|
|
|
@ -48,6 +48,7 @@ import java.io.InputStreamReader
|
|
|
|
|
import java.lang.Thread.sleep
|
|
|
|
|
import java.net.URLDecoder
|
|
|
|
|
import java.time.Instant
|
|
|
|
|
import kotlin.concurrent.fixedRateTimer
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MainActivity : AppCompatActivity() {
|
|
|
|
@ -62,8 +63,8 @@ class MainActivity : AppCompatActivity() {
|
|
|
|
|
var metaData = mdMeta()
|
|
|
|
|
var mdToAppend: String = ""
|
|
|
|
|
var thisFileUri: Uri? = null
|
|
|
|
|
var truncate = false
|
|
|
|
|
lateinit var tempFile: File
|
|
|
|
|
var emptyFile = false
|
|
|
|
|
lateinit var pickMultipleVisualMedia: ActivityResultLauncher<PickVisualMediaRequest>
|
|
|
|
|
lateinit var ghostSettings: ActivityResultLauncher<Intent>
|
|
|
|
|
lateinit var ghostMetaData: ActivityResultLauncher<Intent>
|
|
|
|
@ -72,6 +73,7 @@ class MainActivity : AppCompatActivity() {
|
|
|
|
|
var ghostConnection = false
|
|
|
|
|
lateinit var credManager: CredentialManager
|
|
|
|
|
var intentScheme = "none"
|
|
|
|
|
var lastSaved = Instant.now().toEpochMilli()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
|
|
@ -120,7 +122,7 @@ class MainActivity : AppCompatActivity() {
|
|
|
|
|
|
|
|
|
|
@JavascriptInterface
|
|
|
|
|
fun triggerOpenFile() {
|
|
|
|
|
openFile(thisFileUri!!)
|
|
|
|
|
openFile()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@JavascriptInterface
|
|
|
|
@ -145,7 +147,7 @@ class MainActivity : AppCompatActivity() {
|
|
|
|
|
|
|
|
|
|
@JavascriptInterface
|
|
|
|
|
fun triggerDisplayName(): String {
|
|
|
|
|
return getDisplayName()
|
|
|
|
|
return getDisplayName(thisFileUri)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@JavascriptInterface
|
|
|
|
@ -172,6 +174,14 @@ class MainActivity : AppCompatActivity() {
|
|
|
|
|
Log.i(javaClass.simpleName,"delivering cursor: $cursor")
|
|
|
|
|
return cursor.toString()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@JavascriptInterface
|
|
|
|
|
fun toggleBar() {
|
|
|
|
|
this@MainActivity.runOnUiThread({
|
|
|
|
|
if (supportActionBar!!.isShowing) supportActionBar!!.hide()
|
|
|
|
|
else supportActionBar!!.show()
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
webView.addJavascriptInterface(jsi, "Android")
|
|
|
|
|
|
|
|
|
@ -200,6 +210,18 @@ class MainActivity : AppCompatActivity() {
|
|
|
|
|
ghostMetaData = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
|
|
|
|
saveFile()
|
|
|
|
|
}
|
|
|
|
|
fixedRateTimer("timer",true,0,5000){
|
|
|
|
|
this@MainActivity.runOnUiThread {
|
|
|
|
|
webView.evaluateJavascript("easyMDE.codemirror.doc.isClean();", {
|
|
|
|
|
if (it == "false" && thisFileUri != null) {
|
|
|
|
|
saveFile()
|
|
|
|
|
this@MainActivity.runOnUiThread {
|
|
|
|
|
webView.evaluateJavascript("easyMDE.codemirror.doc.markClean();", {})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override fun onResume() {
|
|
|
|
@ -305,6 +327,20 @@ class MainActivity : AppCompatActivity() {
|
|
|
|
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
|
|
|
val id = item.itemId
|
|
|
|
|
when (id) {
|
|
|
|
|
R.id.new_file -> {
|
|
|
|
|
truncate = true
|
|
|
|
|
selectFileForSaveAs()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
R.id.open_file -> {
|
|
|
|
|
openFile()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
R.id.save_file -> {
|
|
|
|
|
saveFile()
|
|
|
|
|
selectFileForSaveAs()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
R.id.push_ghost -> {
|
|
|
|
|
webView.evaluateJavascript("getHtml();", {
|
|
|
|
|
val msg = URLDecoder.decode(it.removeSurrounding("\""))
|
|
|
|
@ -323,7 +359,7 @@ class MainActivity : AppCompatActivity() {
|
|
|
|
|
} else {
|
|
|
|
|
Log.i(javaClass.simpleName,"posting $msg")
|
|
|
|
|
updatePost(
|
|
|
|
|
title = metaData.get("title") ?: getDisplayName(),
|
|
|
|
|
title = metaData.get("title") ?: getDisplayName(thisFileUri),
|
|
|
|
|
author = credManager.username,
|
|
|
|
|
html = msg,
|
|
|
|
|
id = metaData.getId()!!
|
|
|
|
@ -514,7 +550,7 @@ class MainActivity : AppCompatActivity() {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
fun sendPosting(html: String, author: String): retrofit2.Response<Any> {
|
|
|
|
|
val title = metaData.get("title") ?: "test" //getDisplayName()
|
|
|
|
|
val title = metaData.get("title") ?: "test"
|
|
|
|
|
val post = sendPost(title, updated_at = Instant.now().toString(), authors = listOf(author), html, feature_image = metaData.get("feature_image"))
|
|
|
|
|
val postings = sendPostList(listOf(post))
|
|
|
|
|
var response: retrofit2.Response<posts> = retrofit2.Response.error(
|
|
|
|
@ -690,33 +726,33 @@ class MainActivity : AppCompatActivity() {
|
|
|
|
|
// Create an image file name
|
|
|
|
|
val storageDir = File(cacheDir, "html")
|
|
|
|
|
storageDir.mkdir()
|
|
|
|
|
tempFile = File(storageDir.path + "/${getDisplayName().split(".")[0]}.html")
|
|
|
|
|
tempFile = File(storageDir.path + "/${getDisplayName(thisFileUri).split(".")[0]}.html")
|
|
|
|
|
if (tempFile.exists()) tempFile.delete()
|
|
|
|
|
tempFile.createNewFile()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun openFile(uri: Uri) {
|
|
|
|
|
fun openFile() {
|
|
|
|
|
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
|
|
|
|
|
addCategory(Intent.CATEGORY_OPENABLE)
|
|
|
|
|
putExtra(DocumentsContract.EXTRA_INITIAL_URI, uri)
|
|
|
|
|
putExtra(DocumentsContract.EXTRA_INITIAL_URI, thisFileUri)
|
|
|
|
|
|
|
|
|
|
type = "text/*"
|
|
|
|
|
getDisplayName().apply { putExtra(Intent.EXTRA_TITLE, getDisplayName()) }
|
|
|
|
|
getDisplayName(thisFileUri).apply { putExtra(Intent.EXTRA_TITLE, getDisplayName(
|
|
|
|
|
thisFileUri)) }
|
|
|
|
|
addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
|
|
|
|
|
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
|
|
|
|
addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
|
|
|
|
}
|
|
|
|
|
startActivityForResult(intent, OPEN_FILE)
|
|
|
|
|
Log.i(javaClass.simpleName, "Buffer gelesen")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@SuppressLint("Range")
|
|
|
|
|
fun getDisplayName(): String {
|
|
|
|
|
fun getDisplayName(uri: Uri?): String {
|
|
|
|
|
// via: https://stackoverflow.com/questions/5568874/how-to-extract-the-file-name-from-uri-returned-from-intent-action-get-content
|
|
|
|
|
var result: String? = null;
|
|
|
|
|
if (thisFileUri == null) return "hauntED.md"
|
|
|
|
|
if (thisFileUri!!.getScheme().equals("content")) {
|
|
|
|
|
val cursor = getContentResolver().query(thisFileUri!!, null, null, null, null);
|
|
|
|
|
if (uri == null) return "hauntED.md"
|
|
|
|
|
if (uri!!.getScheme().equals("content")) {
|
|
|
|
|
val cursor = getContentResolver().query(uri!!, null, null, null, null);
|
|
|
|
|
try {
|
|
|
|
|
if (cursor != null && cursor.moveToFirst()) {
|
|
|
|
|
result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
|
|
|
|
@ -726,7 +762,7 @@ class MainActivity : AppCompatActivity() {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (result == null) {
|
|
|
|
|
result = thisFileUri!!.getPath();
|
|
|
|
|
result = uri!!.getPath();
|
|
|
|
|
val cut = result!!.lastIndexOf('/');
|
|
|
|
|
if (cut != -1) {
|
|
|
|
|
result = result.substring(cut + 1);
|
|
|
|
@ -739,7 +775,7 @@ class MainActivity : AppCompatActivity() {
|
|
|
|
|
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
|
|
|
|
|
addCategory(Intent.CATEGORY_OPENABLE)
|
|
|
|
|
type = "text/*"
|
|
|
|
|
putExtra(Intent.EXTRA_TITLE, getDisplayName())
|
|
|
|
|
putExtra(Intent.EXTRA_TITLE, getDisplayName(thisFileUri))
|
|
|
|
|
addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
|
|
|
|
|
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
|
|
|
|
addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
|
|
|
@ -785,11 +821,9 @@ class MainActivity : AppCompatActivity() {
|
|
|
|
|
uri,
|
|
|
|
|
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
|
|
|
|
)
|
|
|
|
|
thisFileUri = uri
|
|
|
|
|
Log.d(javaClass.simpleName, "Saving to: ${getDisplayName(thisFileUri)}\n${getDisplayName(uri)}")
|
|
|
|
|
if (getDisplayName(thisFileUri) + " (1)" != getDisplayName(uri)) thisFileUri = uri
|
|
|
|
|
saveAs()
|
|
|
|
|
|
|
|
|
|
webView.evaluateJavascript("easyMDE.codemirror.focus()", ValueCallback<String>() {})
|
|
|
|
|
Log.i(javaClass.simpleName, "file newly written")
|
|
|
|
|
}
|
|
|
|
|
} else if (requestCode == OPEN_FILE && resultCode == Activity.RESULT_OK) {
|
|
|
|
|
resultData?.data?.also { uri ->
|
|
|
|
@ -797,8 +831,7 @@ class MainActivity : AppCompatActivity() {
|
|
|
|
|
uri,
|
|
|
|
|
Intent.FLAG_GRANT_READ_URI_PERMISSION and Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
|
|
|
|
)
|
|
|
|
|
thisFileUri = uri
|
|
|
|
|
saveMetaToSharedPrefs()
|
|
|
|
|
readFile(uri)
|
|
|
|
|
|
|
|
|
|
if (metaData.metaData.get("url") == null) {
|
|
|
|
|
deleteVisible = false
|
|
|
|
@ -811,12 +844,8 @@ class MainActivity : AppCompatActivity() {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun getFileContents(): String {
|
|
|
|
|
return metaData.toString() + mdeValue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun saveFile(): Boolean {
|
|
|
|
|
if (thisFileUri == null) return false
|
|
|
|
|
fun saveFile() {
|
|
|
|
|
if (thisFileUri == null) return
|
|
|
|
|
lateinit var textFile: ParcelFileDescriptor
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
@ -835,7 +864,7 @@ class MainActivity : AppCompatActivity() {
|
|
|
|
|
).show()
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
return false
|
|
|
|
|
return
|
|
|
|
|
// TODO: implement workaround for this bug. See: https://stackoverflow.com/q/69248596
|
|
|
|
|
} catch (e: java.io.FileNotFoundException) {
|
|
|
|
|
Log.d(javaClass.simpleName, "File not found. Deleted while loaded?\n${e.stackTraceToString()}")
|
|
|
|
@ -849,7 +878,7 @@ class MainActivity : AppCompatActivity() {
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
selectFileForSaveAs()
|
|
|
|
|
return false
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
catch (e: Exception) {
|
|
|
|
@ -863,77 +892,80 @@ class MainActivity : AppCompatActivity() {
|
|
|
|
|
).show()
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
/* This block is currently actually not needed as the change logic is made in js */
|
|
|
|
|
//TODO: Rework this for change check on network file provider
|
|
|
|
|
Log.d(
|
|
|
|
|
javaClass.simpleName,
|
|
|
|
|
"Size in cache: ${mdeValue.toByteArray().size} Size on disk: ${textFile.statSize}"
|
|
|
|
|
)
|
|
|
|
|
if (getFileContents().length.toLong() == textFile.statSize) {
|
|
|
|
|
Log.d(javaClass.simpleName, "No change on disk, file not saved.")
|
|
|
|
|
return false
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
contentResolver.openFileDescriptor(thisFileUri!!, "wt")?.use {
|
|
|
|
|
FileOutputStream(it.fileDescriptor).use {
|
|
|
|
|
it.write(getFileContents().toByteArray())
|
|
|
|
|
this. runOnUiThread({
|
|
|
|
|
webView.evaluateJavascript("getValue();") {
|
|
|
|
|
mdeValue =
|
|
|
|
|
metaData.toString() + URLDecoder.decode(it.removeSurrounding("\""))
|
|
|
|
|
if (mdeValue.length.toLong() == textFile.statSize) {
|
|
|
|
|
Log.d(javaClass.simpleName, "No change on disk, file not saved.")
|
|
|
|
|
return@evaluateJavascript
|
|
|
|
|
}
|
|
|
|
|
contentResolver.openFileDescriptor(thisFileUri!!, "wt")?.use {
|
|
|
|
|
FileOutputStream(it.fileDescriptor).use {
|
|
|
|
|
it.write(mdeValue.toByteArray())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Log.d(javaClass.simpleName, "File saved: ${thisFileUri}")
|
|
|
|
|
Toast.makeText(
|
|
|
|
|
this,
|
|
|
|
|
"File saved.",
|
|
|
|
|
Toast.LENGTH_SHORT
|
|
|
|
|
).show()
|
|
|
|
|
textFile.close()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
} catch (e: Exception) {
|
|
|
|
|
Toast.makeText(
|
|
|
|
|
this,
|
|
|
|
|
"Error during writing.\n$e",
|
|
|
|
|
Toast.LENGTH_LONG
|
|
|
|
|
).show()
|
|
|
|
|
return false
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
Log.d(javaClass.simpleName, "File saved: ${thisFileUri}")
|
|
|
|
|
this.runOnUiThread({
|
|
|
|
|
Toast.makeText(
|
|
|
|
|
this,
|
|
|
|
|
"File saved.",
|
|
|
|
|
Toast.LENGTH_SHORT
|
|
|
|
|
).show()
|
|
|
|
|
})
|
|
|
|
|
textFile.close()
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun saveAs(): Boolean {
|
|
|
|
|
lateinit var textFile: ParcelFileDescriptor
|
|
|
|
|
private fun saveAs() {
|
|
|
|
|
try {
|
|
|
|
|
textFile = contentResolver.openFileDescriptor(thisFileUri!!, "w")!!
|
|
|
|
|
textFile.checkError()
|
|
|
|
|
} catch (e: Exception) {
|
|
|
|
|
lateinit var textFile: ParcelFileDescriptor
|
|
|
|
|
try {
|
|
|
|
|
textFile = contentResolver.openFileDescriptor(thisFileUri!!, "w")!!
|
|
|
|
|
textFile.checkError()
|
|
|
|
|
} catch (e: Exception) {
|
|
|
|
|
Toast.makeText(
|
|
|
|
|
this,
|
|
|
|
|
"Problem with accessing file\n$e",
|
|
|
|
|
Toast.LENGTH_LONG
|
|
|
|
|
).show()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if (truncate) {
|
|
|
|
|
mdeValue = ""
|
|
|
|
|
truncate = false
|
|
|
|
|
}
|
|
|
|
|
FileOutputStream(textFile.fileDescriptor).use {
|
|
|
|
|
it.write(mdeValue.toByteArray())
|
|
|
|
|
}
|
|
|
|
|
Toast.makeText(
|
|
|
|
|
this,
|
|
|
|
|
"Problem with accessing file\n$e",
|
|
|
|
|
"File saved.",
|
|
|
|
|
Toast.LENGTH_LONG
|
|
|
|
|
).show()
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
FileOutputStream(textFile.fileDescriptor).use {
|
|
|
|
|
it.write(getFileContents().toByteArray())
|
|
|
|
|
}
|
|
|
|
|
Log.i(javaClass.simpleName, "file newly written")
|
|
|
|
|
webView.evaluateJavascript("onRead();", ValueCallback<String>() {})
|
|
|
|
|
|
|
|
|
|
textFile.close()
|
|
|
|
|
saveMetaToSharedPrefs()
|
|
|
|
|
} catch (e: Exception) {
|
|
|
|
|
Toast.makeText(
|
|
|
|
|
this,
|
|
|
|
|
"Error during writing.\n$e",
|
|
|
|
|
Toast.LENGTH_LONG
|
|
|
|
|
).show()
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
Toast.makeText(
|
|
|
|
|
this,
|
|
|
|
|
"File saved.",
|
|
|
|
|
Toast.LENGTH_LONG
|
|
|
|
|
).show()
|
|
|
|
|
textFile.close()
|
|
|
|
|
saveMetaToSharedPrefs()
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Throws(IOException::class)
|
|
|
|
@ -962,10 +994,6 @@ class MainActivity : AppCompatActivity() {
|
|
|
|
|
Toast.LENGTH_LONG
|
|
|
|
|
).show()
|
|
|
|
|
})
|
|
|
|
|
/*
|
|
|
|
|
openFile(uri)
|
|
|
|
|
return false
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
contentResolver.openInputStream(uri)?.use { inputStream ->
|
|
|
|
@ -1004,9 +1032,11 @@ class MainActivity : AppCompatActivity() {
|
|
|
|
|
})
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
thisFileUri = uri
|
|
|
|
|
saveMetaToSharedPrefs()
|
|
|
|
|
this.runOnUiThread({
|
|
|
|
|
webView.evaluateJavascript("onRead();", {})
|
|
|
|
|
})
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1035,7 +1065,7 @@ class MainActivity : AppCompatActivity() {
|
|
|
|
|
override fun onPause() {
|
|
|
|
|
super.onPause()
|
|
|
|
|
/*outState.putString("test", "onSaveInstanceState-String")*/
|
|
|
|
|
webView.evaluateJavascript("saveFile();", ValueCallback<String>() {})
|
|
|
|
|
saveFile()
|
|
|
|
|
webView.evaluateJavascript("easyMDE.codemirror.doc.getCursor();") {
|
|
|
|
|
metaData.cursor=it
|
|
|
|
|
Log.i(javaClass.simpleName,"Cursor: $it")
|
|
|
|
|