131 lines
4.4 KiB
Kotlin
131 lines
4.4 KiB
Kotlin
package sushi.hardcore.droidfs.file_viewers
|
|
|
|
import android.annotation.SuppressLint
|
|
import android.text.Editable
|
|
import android.text.TextWatcher
|
|
import android.view.Menu
|
|
import android.view.MenuItem
|
|
import android.widget.EditText
|
|
import android.widget.Toast
|
|
import androidx.activity.addCallback
|
|
import sushi.hardcore.droidfs.R
|
|
import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder
|
|
import java.io.File
|
|
|
|
class TextEditor: FileViewerActivity() {
|
|
private lateinit var fileName: String
|
|
private lateinit var editor: EditText
|
|
private var changedSinceLastSave = false
|
|
private var wordWrap = true
|
|
|
|
override fun getFileType(): String {
|
|
return "text"
|
|
}
|
|
|
|
override fun viewFile() {
|
|
fileName = File(filePath).name
|
|
title = fileName
|
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
|
loadWholeFile(filePath) {
|
|
try {
|
|
loadLayout(String(it))
|
|
onBackPressedDispatcher.addCallback(this) {
|
|
checkSaveAndExit()
|
|
}
|
|
} catch (e: OutOfMemoryError){
|
|
CustomAlertDialogBuilder(this, theme)
|
|
.setTitle(R.string.error)
|
|
.setMessage(R.string.outofmemoryerror_msg)
|
|
.setCancelable(false)
|
|
.setPositiveButton(R.string.ok) { _, _ -> goBackToExplorer()}
|
|
.show()
|
|
}
|
|
}
|
|
}
|
|
private fun loadLayout(fileContent: String){
|
|
if (wordWrap){
|
|
setContentView(R.layout.activity_text_editor_wrap)
|
|
} else {
|
|
setContentView(R.layout.activity_text_editor)
|
|
}
|
|
editor = findViewById(R.id.text_editor)
|
|
editor.setText(fileContent)
|
|
editor.addTextChangedListener(object: TextWatcher {
|
|
override fun afterTextChanged(s: Editable?) {
|
|
}
|
|
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
|
|
}
|
|
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
|
if (!changedSinceLastSave){
|
|
changedSinceLastSave = true
|
|
@SuppressLint("SetTextI18n")
|
|
title = "*$fileName"
|
|
}
|
|
}
|
|
})
|
|
}
|
|
private fun save(): Boolean{
|
|
var success = false
|
|
val content = editor.text.toString().toByteArray()
|
|
val fileHandle = encryptedVolume.openFile(filePath)
|
|
if (fileHandle != -1L) {
|
|
var offset: Long = 0
|
|
while (offset < content.size && encryptedVolume.write(fileHandle, offset, content, offset, content.size.toLong()).also { offset += it } > 0) {}
|
|
if (offset == content.size.toLong()){
|
|
success = encryptedVolume.truncate(filePath, offset)
|
|
}
|
|
encryptedVolume.closeFile(fileHandle)
|
|
}
|
|
if (success){
|
|
Toast.makeText(this, getString(R.string.file_saved), Toast.LENGTH_SHORT).show()
|
|
} else {
|
|
Toast.makeText(this, getString(R.string.save_failed), Toast.LENGTH_SHORT).show()
|
|
}
|
|
return success
|
|
}
|
|
|
|
private fun checkSaveAndExit(){
|
|
if (changedSinceLastSave){
|
|
CustomAlertDialogBuilder(this, theme)
|
|
.setTitle(R.string.warning)
|
|
.setMessage(R.string.ask_save)
|
|
.setPositiveButton(R.string.save) { _, _ ->
|
|
if (save()){
|
|
goBackToExplorer()
|
|
}
|
|
}
|
|
.setNegativeButton(R.string.discard){ _, _ -> goBackToExplorer()}
|
|
.show()
|
|
} else {
|
|
goBackToExplorer()
|
|
}
|
|
}
|
|
|
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
|
menuInflater.inflate(R.menu.text_editor, menu)
|
|
menu.findItem(R.id.word_wrap).isChecked = wordWrap
|
|
return true
|
|
}
|
|
|
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
when (item.itemId){
|
|
android.R.id.home -> {
|
|
checkSaveAndExit()
|
|
}
|
|
R.id.menu_save -> {
|
|
if (save()){
|
|
changedSinceLastSave = false
|
|
title = fileName
|
|
}
|
|
}
|
|
R.id.word_wrap -> {
|
|
wordWrap = !item.isChecked
|
|
loadLayout(editor.text.toString())
|
|
invalidateOptionsMenu()
|
|
}
|
|
else -> super.onOptionsItemSelected(item)
|
|
}
|
|
return true
|
|
}
|
|
}
|