MISC: enhance code step 2 (runApt)
This commit is contained in:
parent
cc1fe9de00
commit
dc694aad9c
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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() }
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user