Skip to content

Commit

Permalink
File change state indication & general improvements, by @harshad1 @gs…
Browse files Browse the repository at this point in the history
…antner (PR gsantner#1516)

* Closes gsantner#1311
* Closes gsantner#1537 

Co-authored-by: Gregor Santner <[email protected]>
  • Loading branch information
harshad1 and gsantner authored Dec 24, 2021
1 parent 6b3f1ec commit ca6f490
Show file tree
Hide file tree
Showing 14 changed files with 241 additions and 220 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,7 @@ protected void onCreate(Bundle savedInstanceState) {
}

setSupportActionBar(_toolbar);
ActionBar ab = getSupportActionBar();
if (ab != null) {
ab.setDisplayHomeAsUpEnabled(true);
ab.setDisplayShowTitleEnabled(false);
}

_toolbar.setOnClickListener(this::onToolbarTitleClicked);

_fragManager = getSupportFragmentManager();
Expand Down Expand Up @@ -283,7 +279,7 @@ public void showTextEditor(@Nullable Document document, @Nullable File file, boo
boolean sameDocumentRequested = false;
if (currentFragment instanceof DocumentEditFragment) {
String reqPath = (reqFile != null) ? reqFile.getPath() : "";
sameDocumentRequested = reqPath.equals(((DocumentEditFragment) currentFragment).getPath());
sameDocumentRequested = reqPath.equals(((DocumentEditFragment) currentFragment).getDocument().getPath());
}

if (!sameDocumentRequested) {
Expand Down Expand Up @@ -369,7 +365,7 @@ private GsFragmentBase getCurrentVisibleFragment() {

public void setDocument(Document document) {
_document = document;
_toolbarTitleText.setText(_document.getTitle());
setDocumentTitle(_document.getTitle());
}

private void onToolbarTitleClicked(View v) {
Expand Down
227 changes: 115 additions & 112 deletions app/src/main/java/net/gsantner/markor/activity/DocumentEditFragment.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ private void showInDocumentActivity(Document document) {
if (getActivity() instanceof DocumentActivity) {
DocumentActivity a = (DocumentActivity) getActivity();
a.setDocument(document);
a.showTextEditor(document, null, false, _appSettings.getDocumentPreviewState(Document.getPath(document)), null);
a.showTextEditor(document, null, false, _appSettings.getDocumentPreviewState(document.getPath()), null);
}
}

Expand Down
89 changes: 42 additions & 47 deletions app/src/main/java/net/gsantner/markor/activity/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ public class MainActivity extends MarkorBaseActivity implements FilesystemViewer
private SectionsPagerAdapter _viewPagerAdapter;

private boolean _doubleBackToExitPressedOnce;
private MenuItem _lastBottomMenuItem;

private AppSettings _appSettings;
private ActivityUtils _contextUtils;
Expand Down Expand Up @@ -136,11 +135,7 @@ protected void onCreate(Bundle savedInstanceState) {

(new ActivityUtils(this)).applySpecialLaunchersVisibility(_appSettings.isSpecialFileLaunchersEnabled());

_bottomNav.postDelayed(() -> {
if (_appSettings.getAppStartupTab() != R.id.nav_notebook) {
_bottomNav.setSelectedItemId(_appSettings.getAppStartupTab());
}
}, 1);
_bottomNav.postDelayed(() -> _bottomNav.setSelectedItemId(_appSettings.getAppStartupTab()), 10);
}

private void optShowRate() {
Expand Down Expand Up @@ -168,7 +163,7 @@ public boolean onOptionsItemSelected(MenuItem item) {
AppSettings as = new AppSettings(this);
switch (item.getItemId()) {
case R.id.action_preview: {
File f = _bottomNav.getSelectedItemId() == R.id.nav_quicknote ? as.getQuickNoteFile() : as.getTodoFile();
final File f = _bottomNav.getSelectedItemId() == R.id.nav_quicknote ? as.getQuickNoteFile() : as.getTodoFile();
DocumentActivity.launch(MainActivity.this, f, false, true, null, null);
return true;
}
Expand Down Expand Up @@ -331,38 +326,12 @@ public void onBackPressed() {

@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
updateFabVisibility(item.getItemId() == R.id.nav_notebook);
PermissionChecker permc = new PermissionChecker(this);

switch (item.getItemId()) {
case R.id.nav_notebook: {
_viewPager.setCurrentItem(0);
_toolbar.setTitle(getFileBrowserTitle());
return true;
}
_viewPager.setCurrentItem(tabIdToPos(item.getItemId()));
return true;
}

case R.id.nav_todo: {
permc.doIfExtStoragePermissionGranted(); // cannot prevent bottom tab selection
restoreDefaultToolbar();
_viewPager.setCurrentItem(1);
_toolbar.setTitle(R.string.todo);
return true;
}
case R.id.nav_quicknote: {
permc.doIfExtStoragePermissionGranted(); // cannot prevent bottom tab selection
restoreDefaultToolbar();
_viewPager.setCurrentItem(2);
_toolbar.setTitle(R.string.quicknote);
return true;
}
case R.id.nav_more: {
restoreDefaultToolbar();
_viewPager.setCurrentItem(3);
_toolbar.setTitle(R.string.more);
return true;
}
}
return false;
public void setMainTitle(final String title) {
_toolbar.setTitle(title);
}

public void updateFabVisibility(boolean visible) {
Expand All @@ -382,17 +351,41 @@ public String getFileBrowserTitle() {
return title;
}

public int tabIdToPos(final int id) {
if (id == R.id.nav_notebook) return 0;
if (id == R.id.nav_todo) return 1;
if (id == R.id.nav_quicknote) return 2;
if (id == R.id.nav_more) return 3;
return 0;
}

public int getCurrentPos() {
return _viewPager.getCurrentItem();
}

public String getPosTitle(final int pos) {
if (pos == 0) return getFileBrowserTitle();
if (pos == 1) return getString(R.string.todo);
if (pos == 2) return getString(R.string.quicknote);
if (pos == 3) return getString(R.string.more);
return "";
}

@OnPageChange(value = R.id.main__view_pager_container, callback = OnPageChange.Callback.PAGE_SELECTED)
public void onViewPagerPageSelected(int pos) {
Menu menu = _bottomNav.getMenu();
PermissionChecker permc = new PermissionChecker(this);
(_lastBottomMenuItem != null ? _lastBottomMenuItem : menu.getItem(0)).setChecked(false);
_lastBottomMenuItem = menu.getItem(pos).setChecked(true);
updateFabVisibility(pos == 0);
_toolbar.setTitle(new String[]{getFileBrowserTitle(), getString(R.string.todo), getString(R.string.quicknote), getString(R.string.more)}[pos]);
_bottomNav.getMenu().getItem(pos).setChecked(true);

updateFabVisibility(pos == tabIdToPos(R.id.nav_notebook));

setMainTitle(getPosTitle(pos));

if (pos > 0 && pos < 3) {
permc.doIfExtStoragePermissionGranted(); // cannot prevent bottom tab selection
if (pos != tabIdToPos(R.id.nav_notebook)) {
restoreDefaultToolbar();
}

if (pos == tabIdToPos(R.id.nav_quicknote) || pos == tabIdToPos(R.id.nav_todo)) {
// cannot prevent bottom tab selection
new PermissionChecker(this).doIfExtStoragePermissionGranted();
}
}

Expand Down Expand Up @@ -422,7 +415,9 @@ public void onFsViewerConfig(FilesystemViewerData.Options dopt) {
public void onFsViewerDoUiUpdate(FilesystemViewerAdapter adapter) {
if (adapter != null && adapter.getCurrentFolder() != null && !TextUtils.isEmpty(adapter.getCurrentFolder().getName())) {
_appSettings.setFileBrowserLastBrowsedFolder(adapter.getCurrentFolder());
_toolbar.setTitle(adapter.areItemsSelected() ? "" : getFileBrowserTitle());
if (getCurrentPos() == tabIdToPos(R.id.nav_notebook)) {
_toolbar.setTitle(adapter.areItemsSelected() ? "" : getFileBrowserTitle());
}
invalidateOptionsMenu();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public String convertMarkupShowInWebView(Document document, String content, WebV
}

String baseFolder = new AppSettings(context).getNotebookDirectoryAsStr();
if (document.getFile() != null && document.getFile().getParentFile() != null) {
if (document.getFile().getParentFile() != null) {
baseFolder = document.getFile().getParent();
}
baseFolder = "file://" + baseFolder + "/";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ public boolean onLongClick(View view) {
case R.string.tmaid_common_indent: {
SearchOrCustomTextDialogCreator.showIndentSizeDialog(_activity, _indent, (size) -> {
_indent = Integer.parseInt(size);
_appSettings.setDocumentIndentSize(getPath(), _indent);
_appSettings.setDocumentIndentSize(_document.getPath(), _indent);
});
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public boolean onLongClick(View v) {
case R.string.tmaid_common_indent: {
SearchOrCustomTextDialogCreator.showIndentSizeDialog(_activity, _indent, (size) -> {
_indent = Integer.parseInt(size);
_appSettings.setDocumentIndentSize(getPath(), _indent);
_appSettings.setDocumentIndentSize(_document.getPath(), _indent);
});
return true;
}
Expand Down
74 changes: 45 additions & 29 deletions app/src/main/java/net/gsantner/markor/model/Document.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
import android.text.TextUtils;
import android.util.Log;
Expand All @@ -29,8 +30,11 @@
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.attribute.BasicFileAttributes;
import java.security.SecureRandom;
import java.util.Locale;

Expand All @@ -50,11 +54,15 @@ public class Document implements Serializable {
private final String _fileExtension;
private int _format = TextFormat.FORMAT_UNKNOWN;
private String _title = "";
private String _path = "";
private long _modTime = 0;
private int _intentLineNumber = -1;
private String _lastHash = null;

public Document(File file) {
// Used to check if string changed
private long _lastHash = 0;
private int _lastLength = -1;

public Document(@NonNull final File file) {
_file = file;
final String name = _file.getName();
final int doti = name.lastIndexOf(".");
Expand All @@ -65,9 +73,10 @@ public Document(File file) {
_fileExtension = name.substring(doti).toLowerCase();
_title = name.substring(0, doti);
}
_path = _file.getAbsolutePath();

// Set initial format
final String fnlower = getFile().getName().toLowerCase();
final String fnlower = _file.getName().toLowerCase();
if (TextFormat.CONVERTER_TODOTXT.isFileOutOfThisFormat(fnlower)) {
setFormat(TextFormat.FORMAT_TODOTXT);
} else if (TextFormat.CONVERTER_KEYVALUE.isFileOutOfThisFormat(fnlower)) {
Expand All @@ -82,21 +91,21 @@ public Document(File file) {
}

public String getPath() {
return getPath(this);
return _path;
}

public static String getPath(final Document document) {
if (document != null) {
final File file = document.getFile();
if (file != null) {
return file.getAbsolutePath();
}
}
return null;
public @NonNull File getFile() {
return _file;
}

public File getFile() {
return _file;
public long lastModified() {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return Files.readAttributes(_file.toPath(), BasicFileAttributes.class).lastModifiedTime().toMillis();
}
} catch (IOException ignored) {
}
return _file.lastModified();
}

public String getTitle() {
Expand All @@ -108,7 +117,7 @@ public void setTitle(String title) {
}

public String getName() {
return getFile().getName();
return _file.getName();
}

public int getIntentLineNumber() {
Expand All @@ -119,7 +128,7 @@ public int getIntentLineNumber() {
public boolean equals(Object obj) {
if (obj instanceof Document) {
Document other = ((Document) obj);
return equalsc(getFile(), other.getFile())
return equalsc(_file, other._file)
&& equalsc(getTitle(), other.getTitle())
&& (getFormat() == other.getFormat());
}
Expand Down Expand Up @@ -147,7 +156,7 @@ public static boolean isEncrypted(File file) {
}

public boolean isEncrypted() {
return isEncrypted(getFile());
return isEncrypted(_file);
}

// Try several fallbacks to get a valid file
Expand Down Expand Up @@ -192,28 +201,37 @@ public static Document fromArguments(Context context, Bundle arguments) {
return document;
}

private void setContentHash(final CharSequence s) {
_lastLength = s.length();
_lastHash = FileUtils.crc32(s.toString().getBytes());
}

public boolean isContentSame(final CharSequence s) {
return s != null && s.length() == _lastLength && _lastHash == (FileUtils.crc32(s.toString().getBytes()));
}

public synchronized String loadContent(final Context context) {

String content;
final char[] pw;
if (isEncrypted() && (pw = getPasswordWithWarning(context)) != null) {
try {
final byte[] encryptedContext = FileUtils.readCloseStreamWithSize(new FileInputStream(getFile()), (int) getFile().length());
final byte[] encryptedContext = FileUtils.readCloseStreamWithSize(new FileInputStream(_file), (int) _file.length());
if (encryptedContext.length > JavaPasswordbasedCryption.Version.NAME_LENGTH) {
content = JavaPasswordbasedCryption.getDecryptedText(encryptedContext, pw);
} else {
content = new String(encryptedContext, StandardCharsets.UTF_8);
}
} catch (FileNotFoundException e) {
Log.e(Document.class.getName(), "loadDocument: File " + getFile() + " not found.");
Log.e(Document.class.getName(), "loadDocument: File " + _file + " not found.");
content = "";
} catch (JavaPasswordbasedCryption.EncryptionFailedException | IllegalArgumentException e) {
Toast.makeText(context, R.string.could_not_decrypt_file_content_wrong_password_or_is_the_file_maybe_not_encrypted, Toast.LENGTH_LONG).show();
Log.e(Document.class.getName(), "loadDocument: decrypt failed for File " + getFile() + ". " + e.getMessage(), e);
Log.e(Document.class.getName(), "loadDocument: decrypt failed for File " + _file + ". " + e.getMessage(), e);
content = "";
}
} else {
content = FileUtils.readTextFileFast(getFile());
content = FileUtils.readTextFileFast(_file);
}

if (MainActivity.IS_DEBUG_ENABLED) {
Expand All @@ -227,8 +245,8 @@ public synchronized String loadContent(final Context context) {
}

// Also set hash and time on load - should prevent unnecessary saves
_lastHash = FileUtils.sha512sum(content.getBytes());
_modTime = _file.lastModified();
setContentHash(content);
_modTime = lastModified();

return content;
}
Expand Down Expand Up @@ -272,10 +290,8 @@ public synchronized boolean saveContent(final Context context, final String cont
}
shareUtil = shareUtil != null ? shareUtil : new ShareUtil(context);

final String newHash = FileUtils.sha512sum(content.getBytes());

// Don't write same content if base file not changed
if (newHash != null && newHash.equals(_lastHash) && _modTime >= _file.lastModified()) {
if (isContentSame(content) && _modTime >= lastModified()) {
return true;
}

Expand All @@ -299,7 +315,7 @@ public synchronized boolean saveContent(final Context context, final String cont
});
success = true;
} else {
success = FileUtils.writeFile(getFile(), contentAsBytes);
success = FileUtils.writeFile(_file, contentAsBytes);
}
} catch (JavaPasswordbasedCryption.EncryptionFailedException e) {
Log.e(Document.class.getName(), "writeContent: encrypt failed for File " + getPath() + ". " + e.getMessage(), e);
Expand All @@ -308,8 +324,8 @@ public synchronized boolean saveContent(final Context context, final String cont
}

if (success) {
_lastHash = newHash;
_modTime = _file.lastModified();
setContentHash(content);
_modTime = lastModified();
}

return success;
Expand Down
Loading

0 comments on commit ca6f490

Please sign in to comment.