Merge pull request #496 from qwertyfinger/feature/editor-save-prompt

Show save prompt when exiting editor if there are unsaved changes
This commit is contained in:
Tibor Kaputa 2021-08-15 23:06:51 +02:00 committed by GitHub
commit a57569cd86
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 53 additions and 14 deletions

View File

@ -15,9 +15,11 @@ import android.webkit.WebView
import android.webkit.WebViewClient import android.webkit.WebViewClient
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import com.simplemobiletools.commons.dialogs.ConfirmationAdvancedDialog
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE
import com.simplemobiletools.commons.helpers.REAL_FILE_PATH 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.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.views.MyEditText import com.simplemobiletools.commons.views.MyEditText
import com.simplemobiletools.filemanager.pro.R import com.simplemobiletools.filemanager.pro.R
@ -31,10 +33,12 @@ import java.io.OutputStream
class ReadTextActivity : SimpleActivity() { class ReadTextActivity : SimpleActivity() {
private val SELECT_SAVE_FILE_INTENT = 1 private val SELECT_SAVE_FILE_INTENT = 1
private val SELECT_SAVE_FILE_AND_EXIT_INTENT = 2
private var filePath = "" private var filePath = ""
private var originalText = "" private var originalText = ""
private var searchIndex = 0 private var searchIndex = 0
private var lastSavePromptTS = 0L
private var searchMatches = emptyList<Int>() private var searchMatches = emptyList<Int>()
private var isSearchActive = false private var isSearchActive = false
@ -83,17 +87,37 @@ class ReadTextActivity : SimpleActivity() {
super.onActivityResult(requestCode, resultCode, resultData) super.onActivityResult(requestCode, resultCode, resultData)
if (requestCode == SELECT_SAVE_FILE_INTENT && resultCode == Activity.RESULT_OK && resultData != null && resultData.data != null) { if (requestCode == SELECT_SAVE_FILE_INTENT && resultCode == Activity.RESULT_OK && resultData != null && resultData.data != null) {
val outputStream = contentResolver.openOutputStream(resultData.data!!) val outputStream = contentResolver.openOutputStream(resultData.data!!)
saveTextContent(outputStream)
val shouldExitAfterSaving = requestCode == SELECT_SAVE_FILE_AND_EXIT_INTENT
val selectedFilePath = getRealPathFromURI(intent.data!!)
val shouldOverwriteOriginalText = selectedFilePath == filePath
saveTextContent(outputStream, shouldExitAfterSaving, shouldOverwriteOriginalText)
} }
} }
override fun onBackPressed() { override fun onBackPressed() {
if (isSearchActive) { val hasUnsavedChanges = originalText != read_text_view.text.toString()
when {
isSearchActive -> {
closeSearch() 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 { } else {
super.onBackPressed() super.onBackPressed()
} }
} }
}
else -> {
super.onBackPressed()
}
}
}
private fun openSearch() { private fun openSearch() {
isSearchActive = true isSearchActive = true
@ -108,28 +132,34 @@ class ReadTextActivity : SimpleActivity() {
}, 250) }, 250)
} }
private fun saveText() { private fun saveText(shouldExitAfterSaving: Boolean = false) {
if (filePath.isEmpty()) { if (filePath.isEmpty()) {
filePath = getRealPathFromURI(intent.data!!) ?: "" filePath = getRealPathFromURI(intent.data!!) ?: ""
} }
if (filePath.isEmpty()) { if (filePath.isEmpty()) {
SaveAsDialog(this, filePath, true) { path, filename -> SaveAsDialog(this, filePath, true) { _, filename ->
Intent(Intent.ACTION_CREATE_DOCUMENT).apply { Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
type = "text/plain" type = "text/plain"
putExtra(Intent.EXTRA_TITLE, filename) putExtra(Intent.EXTRA_TITLE, filename)
addCategory(Intent.CATEGORY_OPENABLE) 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 { } else {
SaveAsDialog(this, filePath, false) { path, filename -> SaveAsDialog(this, filePath, false) { path, _ ->
handlePermission(PERMISSION_WRITE_STORAGE) { handlePermission(PERMISSION_WRITE_STORAGE) { isPermissionGranted ->
if (it) { if (isPermissionGranted) {
val file = File(path) val file = File(path)
getFileOutputStream(file.toFileDirItem(this), true) { getFileOutputStream(file.toFileDirItem(this), true) {
saveTextContent(it) val shouldOverwriteOriginalText = path == filePath
saveTextContent(it, shouldExitAfterSaving, shouldOverwriteOriginalText)
} }
} }
} }
@ -137,11 +167,20 @@ class ReadTextActivity : SimpleActivity() {
} }
} }
private fun saveTextContent(outputStream: OutputStream?) { private fun saveTextContent(outputStream: OutputStream?, shouldExitAfterSaving: Boolean, shouldOverwriteOriginalText: Boolean) {
if (outputStream != null) { 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) toast(R.string.file_saved)
hideKeyboard() hideKeyboard()
if (shouldOverwriteOriginalText) {
originalText = currentText
}
if (shouldExitAfterSaving) {
super.onBackPressed()
}
} else { } else {
toast(R.string.unknown_error_occurred) toast(R.string.unknown_error_occurred)
} }