DroidFS/app/src/main/java/sushi/hardcore/droidfs/file_viewers/TextEditor.kt

147 lines
5.0 KiB
Kotlin

package sushi.hardcore.droidfs.file_viewers
import android.text.Editable
import android.text.TextWatcher
import android.view.Menu
import android.view.MenuItem
import android.widget.EditText
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.widget.Toolbar
import sushi.hardcore.droidfs.R
import sushi.hardcore.droidfs.util.GocryptfsVolume
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
import java.io.ByteArrayInputStream
import java.io.File
class TextEditor: FileViewerActivity() {
private lateinit var fileName: String
private lateinit var editor: EditText
private lateinit var toolbar: Toolbar
private lateinit var titleText: TextView
private var changedSinceLastSave = false
private var wordWrap = true
override fun hideSystemUi() {
//don't hide system ui
}
override fun viewFile() {
loadWholeFile(filePath)?.let {
fileName = File(filePath).name
try {
loadLayout(String(it))
} catch (e: OutOfMemoryError){
ColoredAlertDialogBuilder(this)
.setTitle(R.string.error)
.setMessage(R.string.outofmemoryerror_msg)
.setCancelable(false)
.setPositiveButton(getString(R.string.ok)) { _, _ -> finish() }
.show()
}
}
}
private fun loadLayout(fileContent: String){
if (wordWrap){
setContentView(R.layout.activity_text_editor_wrap)
} else {
setContentView(R.layout.activity_text_editor)
}
toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar)
title = ""
titleText = findViewById(R.id.title_text)
titleText.text = fileName
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
titleText.text = "*$fileName"
}
}
})
}
private fun save(): Boolean{
var success = false
val content = editor.text.toString().toByteArray()
val handleID = gocryptfsVolume.openWriteMode(filePath)
if (handleID != -1){
val buff = ByteArrayInputStream(content)
var offset: Long = 0
val io_buffer = ByteArray(GocryptfsVolume.DefaultBS)
var length: Int
while (buff.read(io_buffer).also { length = it } > 0) {
val written = gocryptfsVolume.writeFile(handleID, offset, io_buffer, length).toLong()
if (written == length.toLong()) {
offset += written
} else {
break
}
}
if (offset == content.size.toLong()){
success = gocryptfsVolume.truncate(filePath, offset)
}
gocryptfsVolume.closeFile(handleID)
buff.close()
}
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){
ColoredAlertDialogBuilder(this)
.setTitle(R.string.warning)
.setMessage(R.string.ask_save)
.setPositiveButton(getString(R.string.save)) { _, _ ->
if (save()){
finish()
}
}
.setNegativeButton(getString(R.string.discard)){ _, _ -> finish() }
.show()
} else {
finish()
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.text_editor, menu)
toolbar.setNavigationIcon(R.drawable.icon_arrow_back)
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
titleText.text = fileName
}
}
R.id.word_wrap -> {
wordWrap = !item.isChecked
loadLayout(editor.text.toString())
invalidateOptionsMenu()
}
else -> super.onOptionsItemSelected(item)
}
return true
}
override fun onBackPressed() {
checkSaveAndExit()
}
}