From b11e60a3c583bb7e03b5ab632951c639bfe15ca2 Mon Sep 17 00:00:00 2001 From: Andrii Chubko Date: Sun, 15 Aug 2021 07:31:48 +0300 Subject: [PATCH 1/2] Show save prompt when exiting editor if there are unsaved changes To check if there are unsaved changes, the current text is compared to the original text. If user uses the "Saved as" button to modify this file, the original text is updated. When there are unsaved changes: - If user clicks "Discard", the editor is exited without saving. - If user clicks "Save" and successfully saves the file, the editor is automatically closed afterward. - If user clicks "Save" but then fails to save or closes the save dialog, the editor is not closed. --- .../pro/activities/ReadTextActivity.kt | 53 +++++++++++++++---- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/filemanager/pro/activities/ReadTextActivity.kt b/app/src/main/kotlin/com/simplemobiletools/filemanager/pro/activities/ReadTextActivity.kt index ab6546af..5de340a9 100644 --- a/app/src/main/kotlin/com/simplemobiletools/filemanager/pro/activities/ReadTextActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/filemanager/pro/activities/ReadTextActivity.kt @@ -15,9 +15,11 @@ import android.webkit.WebView import android.webkit.WebViewClient import android.widget.ImageView import android.widget.TextView +import com.simplemobiletools.commons.dialogs.ConfirmationAdvancedDialog import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE import com.simplemobiletools.commons.helpers.REAL_FILE_PATH +import com.simplemobiletools.commons.helpers.SAVE_DISCARD_PROMPT_INTERVAL import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.views.MyEditText import com.simplemobiletools.filemanager.pro.R @@ -31,10 +33,12 @@ import java.io.OutputStream class ReadTextActivity : SimpleActivity() { private val SELECT_SAVE_FILE_INTENT = 1 + private val SELECT_SAVE_FILE_AND_EXIT_INTENT = 2 private var filePath = "" private var originalText = "" private var searchIndex = 0 + private var lastSavePromptTS = 0L private var searchMatches = emptyList() private var isSearchActive = false @@ -83,15 +87,30 @@ class ReadTextActivity : SimpleActivity() { super.onActivityResult(requestCode, resultCode, resultData) if (requestCode == SELECT_SAVE_FILE_INTENT && resultCode == Activity.RESULT_OK && resultData != null && resultData.data != null) { val outputStream = contentResolver.openOutputStream(resultData.data!!) - saveTextContent(outputStream) + saveTextContent(outputStream, shouldExitAfterSaving = requestCode == SELECT_SAVE_FILE_AND_EXIT_INTENT, + shouldOverwriteOriginalText = getRealPathFromURI(intent.data!!) == filePath) } } override fun onBackPressed() { - if (isSearchActive) { - closeSearch() - } else { - super.onBackPressed() + val hasUnsavedChanges = originalText != read_text_view.text.toString() + when { + isSearchActive -> { + closeSearch() + } + hasUnsavedChanges && System.currentTimeMillis() - lastSavePromptTS > SAVE_DISCARD_PROMPT_INTERVAL -> { + lastSavePromptTS = System.currentTimeMillis() + ConfirmationAdvancedDialog(this, "", R.string.save_before_closing, R.string.save, R.string.discard) { + if (it) { + saveText(shouldExitAfterSaving = true) + } else { + super.onBackPressed() + } + } + } + else -> { + super.onBackPressed() + } } } @@ -108,7 +127,7 @@ class ReadTextActivity : SimpleActivity() { }, 250) } - private fun saveText() { + private fun saveText(shouldExitAfterSaving: Boolean = false) { if (filePath.isEmpty()) { filePath = getRealPathFromURI(intent.data!!) ?: "" } @@ -120,7 +139,12 @@ class ReadTextActivity : SimpleActivity() { putExtra(Intent.EXTRA_TITLE, filename) addCategory(Intent.CATEGORY_OPENABLE) - startActivityForResult(this, SELECT_SAVE_FILE_INTENT) + val requestCode = if (shouldExitAfterSaving) { + SELECT_SAVE_FILE_AND_EXIT_INTENT + } else { + SELECT_SAVE_FILE_INTENT + } + startActivityForResult(this, requestCode) } } } else { @@ -129,7 +153,7 @@ class ReadTextActivity : SimpleActivity() { if (it) { val file = File(path) getFileOutputStream(file.toFileDirItem(this), true) { - saveTextContent(it) + saveTextContent(it, shouldExitAfterSaving, shouldOverwriteOriginalText = path == filePath) } } } @@ -137,11 +161,20 @@ class ReadTextActivity : SimpleActivity() { } } - private fun saveTextContent(outputStream: OutputStream?) { + private fun saveTextContent(outputStream: OutputStream?, shouldExitAfterSaving: Boolean, shouldOverwriteOriginalText: Boolean) { if (outputStream != null) { - outputStream.bufferedWriter().use { it.write(read_text_view.text.toString()) } + val currentText = read_text_view.text.toString() + outputStream.bufferedWriter().use { it.write(currentText) } toast(R.string.file_saved) hideKeyboard() + + if (shouldOverwriteOriginalText) { + originalText = currentText + } + + if (shouldExitAfterSaving) { + super.onBackPressed() + } } else { toast(R.string.unknown_error_occurred) } From a706e26df613c3d9e2495ae10c34575c438a4e31 Mon Sep 17 00:00:00 2001 From: Andrii Chubko Date: Sun, 15 Aug 2021 11:41:58 +0300 Subject: [PATCH 2/2] Clean code --- .../pro/activities/ReadTextActivity.kt | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/filemanager/pro/activities/ReadTextActivity.kt b/app/src/main/kotlin/com/simplemobiletools/filemanager/pro/activities/ReadTextActivity.kt index 5de340a9..452ebc20 100644 --- a/app/src/main/kotlin/com/simplemobiletools/filemanager/pro/activities/ReadTextActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/filemanager/pro/activities/ReadTextActivity.kt @@ -87,8 +87,13 @@ class ReadTextActivity : SimpleActivity() { super.onActivityResult(requestCode, resultCode, resultData) if (requestCode == SELECT_SAVE_FILE_INTENT && resultCode == Activity.RESULT_OK && resultData != null && resultData.data != null) { val outputStream = contentResolver.openOutputStream(resultData.data!!) - saveTextContent(outputStream, shouldExitAfterSaving = requestCode == SELECT_SAVE_FILE_AND_EXIT_INTENT, - shouldOverwriteOriginalText = getRealPathFromURI(intent.data!!) == filePath) + + val shouldExitAfterSaving = requestCode == SELECT_SAVE_FILE_AND_EXIT_INTENT + + val selectedFilePath = getRealPathFromURI(intent.data!!) + val shouldOverwriteOriginalText = selectedFilePath == filePath + + saveTextContent(outputStream, shouldExitAfterSaving, shouldOverwriteOriginalText) } } @@ -133,7 +138,7 @@ class ReadTextActivity : SimpleActivity() { } if (filePath.isEmpty()) { - SaveAsDialog(this, filePath, true) { path, filename -> + SaveAsDialog(this, filePath, true) { _, filename -> Intent(Intent.ACTION_CREATE_DOCUMENT).apply { type = "text/plain" putExtra(Intent.EXTRA_TITLE, filename) @@ -148,12 +153,13 @@ class ReadTextActivity : SimpleActivity() { } } } else { - SaveAsDialog(this, filePath, false) { path, filename -> - handlePermission(PERMISSION_WRITE_STORAGE) { - if (it) { + SaveAsDialog(this, filePath, false) { path, _ -> + handlePermission(PERMISSION_WRITE_STORAGE) { isPermissionGranted -> + if (isPermissionGranted) { val file = File(path) getFileOutputStream(file.toFileDirItem(this), true) { - saveTextContent(it, shouldExitAfterSaving, shouldOverwriteOriginalText = path == filePath) + val shouldOverwriteOriginalText = path == filePath + saveTextContent(it, shouldExitAfterSaving, shouldOverwriteOriginalText) } } }