MISC: enhance code step 2 (runApt)

This commit is contained in:
imkiva 2021-05-08 16:41:20 +08:00 committed by Kiva Oyama
parent cc1fe9de00
commit dc694aad9c
5 changed files with 55 additions and 110 deletions

View File

@ -11,28 +11,24 @@ import io.neoterm.frontend.session.shell.client.BasicSessionCallback
import io.neoterm.frontend.session.shell.client.BasicViewClient import io.neoterm.frontend.session.shell.client.BasicViewClient
import io.neoterm.utils.Terminals import io.neoterm.utils.Terminals
typealias DialogSessionFinished = (TerminalDialog, TerminalSession?) -> Unit
/** /**
* @author kiva * @author kiva
*/ */
class TerminalDialog(val context: Context) { class TerminalDialog(val context: Context) {
private val termWindowView = WindowTermView(context)
interface SessionFinishedCallback { private val terminalSessionCallback: BasicSessionCallback
fun onSessionFinished(dialog: TerminalDialog, finishedSession: TerminalSession?)
}
private var termWindowView = WindowTermView(context)
private var terminalSessionCallback: BasicSessionCallback
private var dialog: AlertDialog? = null private var dialog: AlertDialog? = null
private var terminalSession: TerminalSession? = null private var terminalSession: TerminalSession? = null
private var sessionFinishedCallback: SessionFinishedCallback? = null private var sessionFinishedCallback: DialogSessionFinished? = null
private var cancelListener: DialogInterface.OnCancelListener? = null private var cancelListener: DialogInterface.OnCancelListener? = null
init { init {
termWindowView.setTerminalViewClient(BasicViewClient(termWindowView.terminalView)) termWindowView.setTerminalViewClient(BasicViewClient(termWindowView.terminalView))
terminalSessionCallback = object : BasicSessionCallback(termWindowView.terminalView) { terminalSessionCallback = object : BasicSessionCallback(termWindowView.terminalView) {
override fun onSessionFinished(finishedSession: TerminalSession?) { override fun onSessionFinished(finishedSession: TerminalSession?) {
sessionFinishedCallback?.onSessionFinished(this@TerminalDialog, finishedSession) sessionFinishedCallback?.let { it(this@TerminalDialog, finishedSession) }
super.onSessionFinished(finishedSession) super.onSessionFinished(finishedSession)
} }
} }
@ -74,7 +70,7 @@ class TerminalDialog(val context: Context) {
return this return this
} }
fun onFinish(finishedCallback: SessionFinishedCallback): TerminalDialog { fun onFinish(finishedCallback: DialogSessionFinished): TerminalDialog {
this.sessionFinishedCallback = finishedCallback this.sessionFinishedCallback = finishedCallback
return this return this
} }

View File

@ -16,12 +16,9 @@ import androidx.core.view.MenuItemCompat
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.github.wrdlbrnft.sortedlistadapter.SortedListAdapter import com.github.wrdlbrnft.sortedlistadapter.SortedListAdapter
import io.neoterm.R import io.neoterm.R
import io.neoterm.backend.TerminalSession
import io.neoterm.component.pm.* import io.neoterm.component.pm.*
import io.neoterm.frontend.component.ComponentManager import io.neoterm.frontend.component.ComponentManager
import io.neoterm.frontend.config.NeoPreference import io.neoterm.frontend.config.NeoPreference
import io.neoterm.frontend.config.NeoTermPath
import io.neoterm.frontend.floating.TerminalDialog
import io.neoterm.ui.pm.adapter.PackageAdapter import io.neoterm.ui.pm.adapter.PackageAdapter
import io.neoterm.ui.pm.model.PackageModel import io.neoterm.ui.pm.model.PackageModel
import io.neoterm.ui.pm.utils.StringDistance import io.neoterm.ui.pm.utils.StringDistance
@ -57,9 +54,9 @@ class PackageManagerActivity : AppCompatActivity(), SearchView.OnQueryTextListen
AlertDialog.Builder(this@PackageManagerActivity) AlertDialog.Builder(this@PackageManagerActivity)
.setTitle(model.packageInfo.packageName) .setTitle(model.packageInfo.packageName)
.setMessage(model.getPackageDetails(this@PackageManagerActivity)) .setMessage(model.getPackageDetails(this@PackageManagerActivity))
.setPositiveButton(R.string.install, { _, _ -> .setPositiveButton(R.string.install) { _, _ ->
installPackage(model.packageInfo.packageName) installPackage(model.packageInfo.packageName)
}) }
.setNegativeButton(android.R.string.no, null) .setNegativeButton(android.R.string.no, null)
.show() .show()
} }
@ -74,21 +71,9 @@ class PackageManagerActivity : AppCompatActivity(), SearchView.OnQueryTextListen
refreshPackageList() refreshPackageList()
} }
private fun installPackage(packageName: String?) { private fun installPackage(packageName: String?) = packageName?.let {
if (packageName != null) { runApt("install", "-y", it, autoClose = false) {
TerminalDialog(this@PackageManagerActivity) it.onSuccess { it.setTitle(getString(R.string.done)) }
.execute(
NeoTermPath.APT_BIN_PATH,
arrayOf("apt", "install", "-y", packageName)
)
.onFinish(object : TerminalDialog.SessionFinishedCallback {
override fun onSessionFinished(dialog: TerminalDialog, finishedSession: TerminalSession?) {
dialog.setTitle(getString(R.string.done))
}
})
.imeEnabled(true)
.show("Installing $packageName")
Toast.makeText(this, R.string.installing_topic, Toast.LENGTH_LONG).show()
} }
} }
@ -115,18 +100,15 @@ class PackageManagerActivity : AppCompatActivity(), SearchView.OnQueryTextListen
val sourceManager = ComponentManager.getComponent<PackageComponent>().sourceManager val sourceManager = ComponentManager.getComponent<PackageComponent>().sourceManager
val sourceList = sourceManager.getAllSources() val sourceList = sourceManager.getAllSources()
val items = sourceList.map { "${it.url} :: ${it.repo}" }.toTypedArray()
val selection = sourceList.map { it.enabled }.toBooleanArray()
AlertDialog.Builder(this) AlertDialog.Builder(this)
.setTitle(R.string.pref_package_source) .setTitle(R.string.pref_package_source)
.setMultiChoiceItems(sourceList.map { "${it.url} :: ${it.repo}" }.toTypedArray(), .setMultiChoiceItems(items, selection) { _, which, isChecked ->
sourceList.map { it.enabled }.toBooleanArray(), { dialog, which, isChecked ->
sourceList[which].enabled = isChecked sourceList[which].enabled = isChecked
}) }
.setPositiveButton(android.R.string.yes, { _, _ -> .setPositiveButton(android.R.string.yes) { _, _ -> changeSourceInternal(sourceManager, sourceList) }
changeSourceInternal(sourceManager, sourceList) .setNeutralButton(R.string.new_source) { _, _ -> changeSourceToUserInput(sourceManager) }
})
.setNeutralButton(R.string.new_source, { _, _ ->
changeSourceToUserInput(sourceManager)
})
.setNegativeButton(android.R.string.no, null) .setNegativeButton(android.R.string.no, null)
.show() .show()
} }
@ -145,7 +127,7 @@ class PackageManagerActivity : AppCompatActivity(), SearchView.OnQueryTextListen
.setTitle(R.string.pref_package_source) .setTitle(R.string.pref_package_source)
.setView(view) .setView(view)
.setNegativeButton(android.R.string.no, null) .setNegativeButton(android.R.string.no, null)
.setPositiveButton(android.R.string.yes, { _, _ -> .setPositiveButton(android.R.string.yes) { _, _ ->
val url = urlEditor.text.toString() val url = urlEditor.text.toString()
val repo = repoEditor.text.toString() val repo = repoEditor.text.toString()
var errored = false var errored = false
@ -163,7 +145,7 @@ class PackageManagerActivity : AppCompatActivity(), SearchView.OnQueryTextListen
val source = urlEditor.text.toString() val source = urlEditor.text.toString()
sourceManager.addSource(source, repo, true) sourceManager.addSource(source, repo, true)
postChangeSource(sourceManager) postChangeSource(sourceManager)
}) }
.show() .show()
} }
@ -179,30 +161,15 @@ class PackageManagerActivity : AppCompatActivity(), SearchView.OnQueryTextListen
executeAptUpdate() executeAptUpdate()
} }
private fun executeAptUpdate() = runApt("update", null) { exitStatus, dialog -> private fun executeAptUpdate() = runApt("update") {
if (exitStatus != 0) { it.onSuccess { refreshPackageList() }
dialog.setTitle(getString(R.string.error))
return@runApt
}
Toast.makeText(this, R.string.apt_update_ok, Toast.LENGTH_SHORT).show()
dialog.dismiss()
refreshPackageList()
} }
private fun executeAptUpgrade() = runApt("update", null) { exitStatus, dialog -> private fun executeAptUpgrade() = runApt("update") { update ->
if (exitStatus != 0) { update.onSuccess {
dialog.setTitle(getString(R.string.error)) runApt("upgrade", "-y") {
return@runApt it.onSuccess { Toast.makeText(this, R.string.apt_upgrade_ok, Toast.LENGTH_SHORT).show() }
} }
dialog.dismiss()
runApt("upgrade", arrayOf("-y")) aptUpgrade@{ exitStatus, dialog ->
if (exitStatus != 0) {
dialog.setTitle(getString(R.string.error))
return@aptUpgrade
}
Toast.makeText(this, R.string.apt_upgrade_ok, Toast.LENGTH_SHORT).show()
dialog.dismiss()
} }
} }

View File

@ -40,17 +40,12 @@ class GeneralSettingsActivity : BasePreferenceActivity() {
.setTitle(getString(R.string.shell_not_found, shellName)) .setTitle(getString(R.string.shell_not_found, shellName))
.setMessage(R.string.shell_not_found_message) .setMessage(R.string.shell_not_found_message)
.setPositiveButton(R.string.install) { _, _ -> .setPositiveButton(R.string.install) { _, _ ->
runApt("install", arrayOf("-y", shellName)) { exitStatus, dialog -> runApt("install", "-y", shellName) {
if (exitStatus == 0) { it.onSuccess { postChangeShell(shellName) }
dialog.dismiss()
postChangeShell(shellName)
} else dialog.setTitle(getString(R.string.error))
} }
} }
.setNegativeButton(android.R.string.no, null) .setNegativeButton(android.R.string.no, null)
.setOnDismissListener { .setOnDismissListener { postChangeShell(currentShell) }
postChangeShell(currentShell)
}
.show() .show()
} }
@ -59,8 +54,7 @@ class GeneralSettingsActivity : BasePreferenceActivity() {
override fun onOptionsItemSelected(item: MenuItem?): Boolean { override fun onOptionsItemSelected(item: MenuItem?): Boolean {
when (item?.itemId) { when (item?.itemId) {
android.R.id.home -> android.R.id.home -> finish()
finish()
} }
return super.onOptionsItemSelected(item) return super.onOptionsItemSelected(item)
} }

View File

@ -234,11 +234,11 @@ class SetupActivity : AppCompatActivity(), View.OnClickListener, ResultListener
} }
} }
private fun executeAptUpdate() = runApt("update") private fun executeAptUpdate() = runApt("update") {
.onSuccess { executeAptUpgrade() } it.onSuccess { executeAptUpgrade() }
.onFailure { Toast.makeText(this, R.string.error, Toast.LENGTH_SHORT).show() } }
private fun executeAptUpgrade() = runApt("upgrade", "-y") private fun executeAptUpgrade() = runApt("upgrade", "-y") {
.onSuccess { finish() } it.onSuccess { finish() }
.onFailure { Toast.makeText(this, R.string.error, Toast.LENGTH_SHORT).show() } }
} }

View File

@ -6,7 +6,7 @@ import android.net.Uri
import android.os.Environment import android.os.Environment
import android.provider.DocumentsContract import android.provider.DocumentsContract
import android.provider.MediaStore import android.provider.MediaStore
import io.neoterm.backend.TerminalSession import io.neoterm.R
import io.neoterm.frontend.config.NeoTermPath import io.neoterm.frontend.config.NeoTermPath
import io.neoterm.frontend.floating.TerminalDialog import io.neoterm.frontend.floating.TerminalDialog
import java.io.File import java.io.File
@ -49,23 +49,23 @@ fun Context.extractAssetsDir(dirName: String, extractDir: String) {
} }
} }
fun Context.runApt(subCommand: String, vararg extraArgs: String): Result<TerminalDialog> = runAsyncCatching { fun Context.runApt(
val args = arrayOf(NeoTermPath.APT_BIN_PATH, subCommand, *extraArgs) subCommand: String, vararg extraArgs: String,
TerminalDialog(this) autoClose: Boolean = true, block: (Result<TerminalDialog>) -> Unit
.onFinish(object : TerminalDialog.SessionFinishedCallback { ) = TerminalDialog(this)
override fun onSessionFinished(dialog: TerminalDialog, finishedSession: TerminalSession?) { .execute(NeoTermPath.APT_BIN_PATH, arrayOf(NeoTermPath.APT_BIN_PATH, subCommand, *extraArgs))
val exit = finishedSession?.exitStatus ?: 1
if (exit == 0) {
dialog.dismiss()
throw SuccessResult(dialog)
}
else throw RuntimeException()
}
})
.imeEnabled(true) .imeEnabled(true)
.execute(NeoTermPath.APT_BIN_PATH, args) .onFinish { dialog, session ->
val exit = session?.exitStatus ?: 1
if (exit == 0) {
if (autoClose) dialog.dismiss()
block(Result.success(dialog))
} else {
dialog.setTitle(getString(R.string.error))
block(Result.failure(RuntimeException()))
}
}
.show("apt $subCommand") .show("apt $subCommand")
}
/** /**
* Get a file path from a Uri. This will get the the path for Storage Access * Get a file path from a Uri. This will get the the path for Storage Access
@ -121,15 +121,3 @@ private fun getDataColumn(context: Context, uri: Uri, selection: String?, select
private fun isExternalStorageDocument(uri: Uri) = "com.android.externalstorage.documents" == uri.authority private fun isExternalStorageDocument(uri: Uri) = "com.android.externalstorage.documents" == uri.authority
private fun isDownloadsDocument(uri: Uri) = "com.android.providers.downloads.documents" == uri.authority private fun isDownloadsDocument(uri: Uri) = "com.android.providers.downloads.documents" == uri.authority
private fun isMediaDocument(uri: Uri) = "com.android.providers.media.documents" == uri.authority private fun isMediaDocument(uri: Uri) = "com.android.providers.media.documents" == uri.authority
data class SuccessResult(val data: Any) : RuntimeException()
inline fun <reified R> runAsyncCatching(block: () -> Unit): Result<R> = try {
block()
Result.failure(IllegalStateException())
} catch (s: SuccessResult) {
if (s.data is R) Result.success(s.data)
else Result.failure(ClassCastException())
} catch (e: Throwable) {
Result.failure(e)
}