Refactor: Completion Manager
This commit is contained in:
parent
438e1e4d24
commit
b611b0eaf4
@ -64,6 +64,6 @@ dependencies {
|
||||
compile 'com.github.wrdlbrnft:modular-adapter:0.2.0.6'
|
||||
compile 'com.github.wrdlbrnft:sorted-list-adapter:0.2.0.19'
|
||||
compile 'com.simplecityapps:recyclerview-fastscroll:1.0.16'
|
||||
compile 'com.ramotion.cardslider:card-slider:0.1.0'
|
||||
// compile 'com.ramotion.cardslider:card-slider:0.1.0'
|
||||
compile 'com.github.igalata:Bubble-Picker:v0.2.4'
|
||||
}
|
||||
|
@ -32,9 +32,9 @@
|
||||
|
||||
<activity
|
||||
android:name=".ui.term.NeoTermRemoteInterface"
|
||||
android:theme="@style/AppTheme.Dark"
|
||||
android:excludeFromRecents="true"
|
||||
android:exported="false">
|
||||
android:exported="false"
|
||||
android:theme="@style/AppTheme.Dark">
|
||||
<intent-filter>
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
@ -114,6 +114,10 @@
|
||||
android:name=".services.NeoTermService"
|
||||
android:enabled="true" />
|
||||
|
||||
<service
|
||||
android:name=".services.NeoFloatingTermService"
|
||||
android:enabled="true" />
|
||||
|
||||
<meta-data
|
||||
android:name="com.sec.android.support.multiwindow"
|
||||
android:value="true" />
|
||||
|
@ -2,6 +2,7 @@ package io.neoterm
|
||||
|
||||
import android.app.Application
|
||||
import io.neoterm.customize.color.ColorSchemeManager
|
||||
import io.neoterm.customize.completion.AutoCompletionManager
|
||||
import io.neoterm.customize.font.FontManager
|
||||
import io.neoterm.customize.script.UserScriptManager
|
||||
import io.neoterm.preference.NeoPreference
|
||||
@ -21,6 +22,7 @@ class App : Application() {
|
||||
ColorSchemeManager.init(this)
|
||||
FontManager.init(this)
|
||||
UserScriptManager.init(this)
|
||||
AutoCompletionManager.init(this)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -0,0 +1,14 @@
|
||||
package io.neoterm.customize.completion
|
||||
|
||||
import android.content.Context
|
||||
import io.neoterm.customize.completion.provider.PathProvider
|
||||
import io.neoterm.frontend.completion.CompletionManager
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
object AutoCompletionManager {
|
||||
fun init(context: Context) {
|
||||
CompletionManager.registerProvider(PathProvider())
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package io.neoterm.customize.completion.provider
|
||||
|
||||
import io.neoterm.frontend.completion.model.CompletionCandidate
|
||||
import io.neoterm.frontend.completion.provider.ICandidateProvider
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
|
||||
class PathProvider : ICandidateProvider {
|
||||
override val providerName: String
|
||||
get() = "NeoTermProvider.PathProvider"
|
||||
|
||||
override fun provideCandidates(text: String): List<CompletionCandidate>? {
|
||||
var file = File(text)
|
||||
if (file.isDirectory) {
|
||||
if (file.canRead()) {
|
||||
val candidates = mutableListOf<CompletionCandidate>()
|
||||
file.listFiles().mapTo(candidates, {
|
||||
CompletionCandidate(it.name)
|
||||
})
|
||||
return candidates
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
val partName = file.name
|
||||
file = file.parentFile
|
||||
if (file.canRead()) {
|
||||
val candidates = mutableListOf<CompletionCandidate>()
|
||||
file.listFiles({ pathname -> pathname.name.startsWith(partName) })
|
||||
.mapTo(candidates, {
|
||||
CompletionCandidate(it.name)
|
||||
})
|
||||
return candidates
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun canComplete(text: String): Boolean {
|
||||
return text.startsWith('/')
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package io.neoterm.frontend.completion
|
||||
package io.neoterm.customize.completion.widget
|
||||
|
||||
import android.content.Context
|
||||
import android.view.Gravity
|
||||
@ -12,13 +12,14 @@ import android.widget.TextView
|
||||
import io.neoterm.R
|
||||
import io.neoterm.backend.TerminalColors
|
||||
import io.neoterm.customize.color.ColorSchemeManager
|
||||
import io.neoterm.frontend.completion.model.CompletionCandidate
|
||||
import io.neoterm.view.TerminalView
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
class AutoCompletePopupWindow(val context: Context) {
|
||||
var candidates: List<CompleteCandidate>? = null
|
||||
class CandidatePopupWindow(val context: Context) {
|
||||
var candidates: List<CompletionCandidate>? = null
|
||||
var popupWindow: PopupWindow? = null
|
||||
var wantsToFinish = false
|
||||
var candidateAdapter: CandidateAdapter? = null
|
||||
@ -60,21 +61,21 @@ class AutoCompletePopupWindow(val context: Context) {
|
||||
candidates = null
|
||||
}
|
||||
|
||||
class CandidateAdapter(val autoCompletePopupWindow: AutoCompletePopupWindow) : BaseAdapter() {
|
||||
class CandidateAdapter(val candidatePopupWindow: CandidatePopupWindow) : BaseAdapter() {
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
|
||||
var convertView = convertView
|
||||
val viewHolder: CandidateViewHolder =
|
||||
if (convertView != null) {
|
||||
convertView.tag as CandidateViewHolder
|
||||
} else {
|
||||
convertView = LayoutInflater.from(autoCompletePopupWindow.context)
|
||||
convertView = LayoutInflater.from(candidatePopupWindow.context)
|
||||
.inflate(R.layout.item_complete_candidate, null, false)
|
||||
val viewHolder = CandidateViewHolder(convertView)
|
||||
convertView.tag = viewHolder
|
||||
viewHolder
|
||||
}
|
||||
|
||||
val candidate = getItem(position) as CompleteCandidate
|
||||
val candidate = getItem(position) as CompletionCandidate
|
||||
viewHolder.apply {
|
||||
display.text = candidate.displayName
|
||||
if (candidate.description != null) {
|
||||
@ -90,7 +91,7 @@ class AutoCompletePopupWindow(val context: Context) {
|
||||
}
|
||||
|
||||
override fun getItem(position: Int): Any? {
|
||||
return autoCompletePopupWindow.candidates?.get(position)
|
||||
return candidatePopupWindow.candidates?.get(position)
|
||||
}
|
||||
|
||||
override fun getItemId(position: Int): Long {
|
||||
@ -98,7 +99,7 @@ class AutoCompletePopupWindow(val context: Context) {
|
||||
}
|
||||
|
||||
override fun getCount(): Int {
|
||||
return autoCompletePopupWindow.candidates?.size ?: 0
|
||||
return candidatePopupWindow.candidates?.size ?: 0
|
||||
}
|
||||
}
|
||||
|
@ -2,10 +2,12 @@ package io.neoterm.frontend.client
|
||||
|
||||
import android.util.Log
|
||||
import android.view.KeyEvent
|
||||
import io.neoterm.frontend.completion.AutoCompleteManager
|
||||
import io.neoterm.frontend.completion.CompleteCandidate
|
||||
import io.neoterm.frontend.completion.AutoCompletePopupWindow
|
||||
import io.neoterm.frontend.completion.OnAutoCompleteListener
|
||||
import io.neoterm.BuildConfig
|
||||
import io.neoterm.customize.completion.widget.CandidatePopupWindow
|
||||
import io.neoterm.frontend.completion.CompletionManager
|
||||
import io.neoterm.frontend.completion.listener.OnAutoCompleteListener
|
||||
import io.neoterm.frontend.completion.model.CompletionCandidate
|
||||
import io.neoterm.frontend.completion.model.CompletionResult
|
||||
import io.neoterm.view.TerminalView
|
||||
import java.util.*
|
||||
|
||||
@ -15,7 +17,7 @@ import java.util.*
|
||||
class TermCompleteListener(var terminalView: TerminalView?) : OnAutoCompleteListener {
|
||||
|
||||
private val inputStack = Stack<Char>()
|
||||
private val popupWindow = AutoCompletePopupWindow(terminalView!!.context)
|
||||
private val popupWindow = CandidatePopupWindow(terminalView!!.context)
|
||||
|
||||
override fun onKeyCode(keyCode: Int, keyMod: Int) {
|
||||
when (keyCode) {
|
||||
@ -52,25 +54,39 @@ class TermCompleteListener(var terminalView: TerminalView?) : OnAutoCompleteList
|
||||
return
|
||||
}
|
||||
|
||||
val candidates = AutoCompleteManager.filter(text)
|
||||
Log.e("NeoTerm-AC", "Completing for $text")
|
||||
candidates.forEach {
|
||||
Log.e("NeoTerm-AC", " Candidate: ${it.completeString}")
|
||||
val result = CompletionManager.tryCompleteFor(text)
|
||||
if (!result.hasResult()) {
|
||||
// A provider accepted the task
|
||||
// But no candidates are provided
|
||||
// Give it zero angrily!
|
||||
result.markScore(0)
|
||||
return
|
||||
}
|
||||
if (candidates.isNotEmpty()) {
|
||||
showAutoCompleteCandidates(candidates)
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
val candidates = result.candidates
|
||||
Log.e("NeoTerm-AC", "Completing for $text")
|
||||
candidates.forEach {
|
||||
Log.e("NeoTerm-AC", " Candidate: ${it.completeString}")
|
||||
}
|
||||
}
|
||||
showAutoCompleteCandidates(result)
|
||||
}
|
||||
|
||||
private fun showAutoCompleteCandidates(candidates: List<CompleteCandidate>) {
|
||||
popupWindow.candidates = candidates
|
||||
private fun showAutoCompleteCandidates(result: CompletionResult) {
|
||||
popupWindow.candidates = result.candidates
|
||||
popupWindow.show(terminalView!!)
|
||||
}
|
||||
|
||||
private fun getCurrentEditingText(): String {
|
||||
val builder = StringBuilder()
|
||||
val size = inputStack.size
|
||||
(0..(size - 1))
|
||||
var start = inputStack.lastIndexOf(' ')
|
||||
if (start < 0) {
|
||||
start = 0
|
||||
}
|
||||
|
||||
(start..(size - 1))
|
||||
.map { inputStack[it] }
|
||||
.takeWhile { !(it == 0.toChar() || it == ' ') }
|
||||
.forEach { builder.append(it) }
|
||||
|
@ -2,7 +2,7 @@ package io.neoterm.frontend.client
|
||||
|
||||
import io.neoterm.backend.TerminalSession
|
||||
import io.neoterm.view.ExtraKeysView
|
||||
import io.neoterm.frontend.completion.OnAutoCompleteListener
|
||||
import io.neoterm.frontend.completion.listener.OnAutoCompleteListener
|
||||
import io.neoterm.view.TerminalView
|
||||
|
||||
/**
|
||||
|
@ -1,37 +0,0 @@
|
||||
package io.neoterm.frontend.completion
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
object AutoCompleteManager {
|
||||
private val completeCandidates = mutableListOf<CompleteCandidate>()
|
||||
|
||||
init {
|
||||
val programs = arrayOf("ls", "clean", "exit", "apt", "neoterm-normalize-binary", "less", "ln", "lsof")
|
||||
val desc = arrayOf("List files and directories",
|
||||
"Clear screen",
|
||||
"Exit current executablePath",
|
||||
"Installing, Updating, Upgrading packages",
|
||||
"Fix program error caused by linux shebang",
|
||||
"View files",
|
||||
"Create symlinks or hardlinks",
|
||||
"List opened files")
|
||||
for (i in programs.indices) {
|
||||
val candidate = CompleteCandidate(programs[i])
|
||||
candidate.description = desc[i]
|
||||
completeCandidates.add(candidate)
|
||||
}
|
||||
}
|
||||
|
||||
fun filter(text: String) : List<CompleteCandidate> {
|
||||
val result = mutableListOf<CompleteCandidate>()
|
||||
if (text.isNotEmpty()) {
|
||||
completeCandidates.forEach {
|
||||
if (it.completeString.startsWith(text, ignoreCase = true)) {
|
||||
result.add(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package io.neoterm.frontend.completion
|
||||
|
||||
import io.neoterm.frontend.completion.model.CompletionResult
|
||||
import io.neoterm.frontend.completion.provider.ICandidateProvider
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
object CompletionManager {
|
||||
private val candidateProviders = mutableMapOf<String, ICandidateProvider>()
|
||||
|
||||
fun registerProvider(provider: ICandidateProvider) {
|
||||
this.candidateProviders.put(provider.providerName, provider)
|
||||
}
|
||||
|
||||
fun unregisterProvider(providerName: String) {
|
||||
this.candidateProviders.remove(providerName)
|
||||
}
|
||||
|
||||
fun unregisterProvider(provider: ICandidateProvider) {
|
||||
unregisterProvider(provider.providerName)
|
||||
}
|
||||
|
||||
fun getProvider(providerName: String): ICandidateProvider? {
|
||||
return candidateProviders[providerName]
|
||||
}
|
||||
|
||||
fun tryCompleteFor(text: String): CompletionResult {
|
||||
val detector = detectProviders(text)
|
||||
val provider = detector.detectBest()
|
||||
|
||||
val candidates = provider?.provideCandidates(text) ?: listOf()
|
||||
return CompletionResult(candidates, detector)
|
||||
}
|
||||
|
||||
private fun detectProviders(text: String): ProviderDetector {
|
||||
return ProviderDetector(candidateProviders.values
|
||||
.takeWhile { it.canComplete(text) })
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
package io.neoterm.frontend.completion;
|
||||
|
||||
/**
|
||||
* @author Kiva
|
||||
* @version 1.0
|
||||
*/
|
||||
public interface OnAutoCompleteListener {
|
||||
void onAutoComplete(String newText);
|
||||
|
||||
void onKeyCode(int keyCode, int keyMod);
|
||||
|
||||
void onCleanUp();
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package io.neoterm.frontend.completion
|
||||
|
||||
import io.neoterm.frontend.completion.listener.MarkScoreListener
|
||||
import io.neoterm.frontend.completion.provider.ICandidateProvider
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
class ProviderDetector(val providers: List<ICandidateProvider>) : MarkScoreListener {
|
||||
private var detectedProvider: ICandidateProvider? = null
|
||||
|
||||
override fun onMarkScore(score: Int) {
|
||||
// TODO: Save provider score
|
||||
}
|
||||
|
||||
fun detectBest(): ICandidateProvider? {
|
||||
// TODO: detect best
|
||||
detectedProvider = if (providers.isEmpty())
|
||||
null
|
||||
else
|
||||
providers[0]
|
||||
|
||||
return detectedProvider
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package io.neoterm.frontend.completion.listener
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
|
||||
interface MarkScoreListener {
|
||||
fun onMarkScore(score: Int)
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package io.neoterm.frontend.completion.listener
|
||||
|
||||
/**
|
||||
* @author Kiva
|
||||
* *
|
||||
* @version 1.0
|
||||
*/
|
||||
interface OnAutoCompleteListener {
|
||||
fun onAutoComplete(newText: String?)
|
||||
|
||||
fun onKeyCode(keyCode: Int, keyMod: Int)
|
||||
|
||||
fun onCleanUp()
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
package io.neoterm.frontend.completion
|
||||
package io.neoterm.frontend.completion.model
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
class CompleteCandidate(var completeString: String) {
|
||||
class CompletionCandidate(var completeString: String) {
|
||||
var displayName: String = completeString
|
||||
var description: String? = null
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package io.neoterm.frontend.completion.model
|
||||
|
||||
import io.neoterm.frontend.completion.listener.MarkScoreListener
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
class CompletionResult(val candidates: List<CompletionCandidate>, var scoreMarker: MarkScoreListener) {
|
||||
fun markScore(score: Int) {
|
||||
scoreMarker.onMarkScore(score)
|
||||
}
|
||||
|
||||
fun hasResult(): Boolean {
|
||||
return candidates.isNotEmpty()
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package io.neoterm.frontend.completion.provider
|
||||
|
||||
import io.neoterm.frontend.completion.model.CompletionCandidate
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
|
||||
interface ICandidateProvider {
|
||||
val providerName: String
|
||||
|
||||
fun provideCandidates(text: String): List<CompletionCandidate>?
|
||||
|
||||
fun canComplete(text: String): Boolean
|
||||
}
|
@ -1,18 +1,13 @@
|
||||
package io.neoterm.frontend.floating
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import io.neoterm.R
|
||||
import io.neoterm.backend.TerminalSession
|
||||
import io.neoterm.frontend.ShellParameter
|
||||
import io.neoterm.frontend.tinyclient.BasicSessionCallback
|
||||
import io.neoterm.frontend.tinyclient.BasicViewClient
|
||||
import io.neoterm.frontend.ShellParameter
|
||||
import io.neoterm.utils.TerminalUtils
|
||||
import io.neoterm.view.TerminalView
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
@ -23,9 +18,7 @@ class TerminalDialog(val context: Context) {
|
||||
fun onSessionFinished(dialog: TerminalDialog, finishedSession: TerminalSession?)
|
||||
}
|
||||
|
||||
@SuppressLint("InflateParams")
|
||||
private var view: View = LayoutInflater.from(context).inflate(R.layout.ui_term_dialog, null, false)
|
||||
private var terminalView: TerminalView
|
||||
private var termWindowView = WindowTermView(context)
|
||||
private var terminalSessionCallback: BasicSessionCallback
|
||||
private var dialog: AlertDialog? = null
|
||||
private var terminalSession: TerminalSession? = null
|
||||
@ -33,10 +26,9 @@ class TerminalDialog(val context: Context) {
|
||||
private var cancelListener: DialogInterface.OnCancelListener? = null
|
||||
|
||||
init {
|
||||
terminalView = view.findViewById(R.id.terminal_view_dialog) as TerminalView
|
||||
TerminalUtils.setupTerminalView(terminalView, BasicViewClient(terminalView))
|
||||
termWindowView.setTerminalViewClient(BasicViewClient(termWindowView.terminalView))
|
||||
|
||||
terminalSessionCallback = object : BasicSessionCallback(terminalView) {
|
||||
terminalSessionCallback = object : BasicSessionCallback(termWindowView.terminalView) {
|
||||
override fun onSessionFinished(finishedSession: TerminalSession?) {
|
||||
sessionFinishedCallback?.onSessionFinished(this@TerminalDialog, finishedSession)
|
||||
super.onSessionFinished(finishedSession)
|
||||
@ -50,7 +42,7 @@ class TerminalDialog(val context: Context) {
|
||||
}
|
||||
|
||||
dialog = AlertDialog.Builder(context)
|
||||
.setView(view)
|
||||
.setView(termWindowView.rootView)
|
||||
.setOnCancelListener {
|
||||
terminalSession?.finishIfRunning()
|
||||
cancelListener?.onCancel(it)
|
||||
@ -63,7 +55,7 @@ class TerminalDialog(val context: Context) {
|
||||
.callback(terminalSessionCallback)
|
||||
.systemShell(false)
|
||||
terminalSession = TerminalUtils.createShellSession(context, parameter)
|
||||
terminalView.attachSession(terminalSession)
|
||||
termWindowView.attachSession(terminalSession)
|
||||
return this
|
||||
}
|
||||
|
||||
@ -94,8 +86,7 @@ class TerminalDialog(val context: Context) {
|
||||
|
||||
fun imeEnabled(enabled: Boolean): TerminalDialog {
|
||||
if (enabled) {
|
||||
terminalView.isFocusable = true
|
||||
terminalView.isFocusableInTouchMode = true
|
||||
termWindowView.setInputMethodEnabled(true)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
@ -1,7 +0,0 @@
|
||||
package io.neoterm.frontend.floating
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
class TerminalWindowView {
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package io.neoterm.frontend.floating
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import io.neoterm.R
|
||||
import io.neoterm.backend.TerminalSession
|
||||
import io.neoterm.utils.TerminalUtils
|
||||
import io.neoterm.view.TerminalView
|
||||
import io.neoterm.view.TerminalViewClient
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
class WindowTermView(val context: Context) {
|
||||
@SuppressLint("InflateParams")
|
||||
var rootView: View = LayoutInflater.from(context).inflate(R.layout.ui_term_dialog, null, false)
|
||||
private set
|
||||
var terminalView: TerminalView = rootView.findViewById(R.id.terminal_view_dialog) as TerminalView
|
||||
private set
|
||||
|
||||
init {
|
||||
TerminalUtils.setupTerminalView(terminalView)
|
||||
}
|
||||
|
||||
fun setTerminalViewClient(terminalViewClient: TerminalViewClient?) {
|
||||
terminalView.setTerminalViewClient(terminalViewClient)
|
||||
}
|
||||
|
||||
fun attachSession(terminalSession: TerminalSession?) {
|
||||
terminalView.attachSession(terminalSession)
|
||||
}
|
||||
|
||||
fun setInputMethodEnabled(enabled: Boolean) {
|
||||
terminalView.isFocusable = enabled
|
||||
terminalView.isFocusableInTouchMode = enabled
|
||||
}
|
||||
}
|
@ -19,6 +19,10 @@ object NeoPreference {
|
||||
const val KEY_HAPPY_EGG = "neoterm_fun_happy"
|
||||
const val KEY_FONT_SIZE = "neoterm_general_font_size"
|
||||
const val KEY_CURRENT_SESSION = "neoterm_service_current_session"
|
||||
// const val KEY_FLOATING_WINDOW_X = "neoterm_floating_window_x"
|
||||
// const val KEY_FLOATING_WINDOW_Y = "neoterm_floating_window_y"
|
||||
// const val KEY_FLOATING_WIDTH = "neoterm_floating_window_width"
|
||||
// const val KEY_FLOATING_HEIGHT = "neoterm_floating_window_height"
|
||||
|
||||
const val VALUE_HAPPY_EGG_TRIGGER = 8
|
||||
const val VALUE_NEOTERM_ONLY = "NeoTermOnly"
|
||||
@ -96,6 +100,23 @@ object NeoPreference {
|
||||
return null
|
||||
}
|
||||
|
||||
// fun storeWindowSize(context: Context, width: Int, height: Int) {
|
||||
// store(KEY_FLOATING_WIDTH, width)
|
||||
// store(KEY_FLOATING_HEIGHT, height)
|
||||
// }
|
||||
//
|
||||
// fun storeWindowLocation(context: Context, x: Int, y: Int) {
|
||||
// store(KEY_FLOATING_WINDOW_X, x)
|
||||
// store(KEY_FLOATING_WINDOW_Y, y)
|
||||
// }
|
||||
//
|
||||
// fun applySavedWindowParameter(context: Context, layout: WindowManager.LayoutParams) {
|
||||
// layout.x = loadInt(KEY_FLOATING_WINDOW_X, 200)
|
||||
// layout.y = loadInt(KEY_FLOATING_WINDOW_Y, 200)
|
||||
// layout.width = loadInt(KEY_FLOATING_WIDTH, 500)
|
||||
// layout.height = loadInt(KEY_FLOATING_HEIGHT, 800)
|
||||
// }
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* To print the job name about to be executed in bash:
|
||||
|
@ -150,8 +150,11 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
|
||||
startActivity(Intent(this, PackageManagerActivity::class.java))
|
||||
true
|
||||
}
|
||||
R.id.menu_item_discovery -> {
|
||||
startActivity(Intent(this, SetupActivity::class.java))
|
||||
R.id.menu_item_float_up -> {
|
||||
val tab = tabSwitcher.selectedTab
|
||||
if (tab != null && tab is TermTab) {
|
||||
floatTabUp(tab)
|
||||
}
|
||||
true
|
||||
}
|
||||
R.id.menu_item_new_session -> {
|
||||
@ -325,6 +328,10 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
}
|
||||
|
||||
private fun floatTabUp(tab: TermTab) {
|
||||
|
||||
}
|
||||
|
||||
private fun enterSystemShell() {
|
||||
toggleSwitcher(showSwitcher = true, easterEgg = false)
|
||||
addNewSession("NeoTerm #0", systemShell, createRevealAnimation())
|
||||
|
@ -16,7 +16,7 @@ import io.neoterm.frontend.client.TermCompleteListener
|
||||
import io.neoterm.ui.term.NeoTermActivity
|
||||
import io.neoterm.utils.TerminalUtils
|
||||
import io.neoterm.view.ExtraKeysView
|
||||
import io.neoterm.frontend.completion.OnAutoCompleteListener
|
||||
import io.neoterm.frontend.completion.listener.OnAutoCompleteListener
|
||||
import io.neoterm.view.TerminalView
|
||||
|
||||
/**
|
||||
|
@ -35,7 +35,7 @@ import io.neoterm.backend.KeyHandler;
|
||||
import io.neoterm.backend.TerminalBuffer;
|
||||
import io.neoterm.backend.TerminalEmulator;
|
||||
import io.neoterm.backend.TerminalSession;
|
||||
import io.neoterm.frontend.completion.OnAutoCompleteListener;
|
||||
import io.neoterm.frontend.completion.listener.OnAutoCompleteListener;
|
||||
|
||||
/**
|
||||
* View displaying and interacting with a {@link TerminalSession}.
|
||||
@ -231,12 +231,19 @@ public final class TerminalView extends View {
|
||||
|
||||
/**
|
||||
* @param client Listener for all kinds of key events, both hardware and IME (which makes it different from that
|
||||
* available with {@link View#setOnKeyListener(OnKeyListener)}.
|
||||
* available with {@link View#setOnKeyListener(OnKeyListener)}.
|
||||
*/
|
||||
public void setTerminalViewClient(TerminalViewClient client) {
|
||||
this.mClient = client;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnKeyListener(OnKeyListener l) {
|
||||
if (l instanceof TerminalViewClient) {
|
||||
setTerminalViewClient(((TerminalViewClient) l));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach a {@link TerminalSession} to this view.
|
||||
*
|
||||
|
@ -50,8 +50,7 @@
|
||||
android:layout_marginEnd="@dimen/preview_layout_margin"
|
||||
android:text="@string/setup_next"
|
||||
android:textColor="#9b9b9b"
|
||||
android:textStyle="bold"
|
||||
android:visibility="invisible" />
|
||||
android:textStyle="bold" />
|
||||
|
||||
<com.igalata.bubblepicker.rendering.BubblePicker
|
||||
android:id="@+id/bubble_picker"
|
||||
|
@ -33,8 +33,8 @@ License.
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_item_discovery"
|
||||
android:title="@string/discovery"
|
||||
android:id="@+id/menu_item_float_up"
|
||||
android:title="@string/float_up"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
|
@ -5,13 +5,14 @@
|
||||
<string name="copy_text">复制</string>
|
||||
<string name="general_settings">通用设置</string>
|
||||
<string name="new_session">新建终端</string>
|
||||
<string name="package_settings">软件包设置</string>
|
||||
<string name="package_settings">软件包</string>
|
||||
<string name="paste_text">粘贴</string>
|
||||
<string name="pref_general_backspace_map_to_esc">返回键发送ESC</string>
|
||||
<string name="pref_general_backspace_map_to_esc_desc">当返回键按下时,发送ESC而不是关闭窗口</string>
|
||||
<string name="pref_general_bell">响铃</string>
|
||||
<string name="pref_general_bell_desc">收到 \'\\a\' 时响铃</string>
|
||||
<string name="pref_general_shell_desc">登录时使用指定的 Shell</string>
|
||||
<string name="pref_general_shell">登录程序</string>
|
||||
<string name="pref_general_shell_desc">登录时使用指定的程序</string>
|
||||
<string name="pref_general_vibrate">振动</string>
|
||||
<string name="pref_general_vibrate_desc">收到 \'\\a\' 时振动</string>
|
||||
<string name="pref_general_program_selection">程序选择模式</string>
|
||||
@ -39,7 +40,7 @@
|
||||
<string name="ui_settings">界面设置</string>
|
||||
<string name="shell_not_found">Shell %s 未找到, 请先安装.</string>
|
||||
<string name="installer_message">正在安装</string>
|
||||
<string name="installer_install_zsh_required">将要安装 oh-my-zsh 并将您的登录 executablePath 切换到 zsh</string>
|
||||
<string name="installer_install_zsh_required">将要安装 oh-my-zsh 并将您的登录程序切换到 zsh</string>
|
||||
<string name="fullscreen_mode_changed">全屏模式已改变,请重启 NeoTerm</string>
|
||||
<string name="permission_denied">NeoTerm 无法取得必需的权限,正在退出</string>
|
||||
<string name="error">还有这种操作?</string>
|
||||
@ -50,6 +51,7 @@
|
||||
<string name="package_list_empty">软件包列表为空,请检查你的软件源</string>
|
||||
<string name="menu_refresh_list">刷新</string>
|
||||
<string name="menu_update">更新并刷新</string>
|
||||
<string name="float_up">浮动窗口</string>
|
||||
|
||||
<string-array name="pref_general_program_selection_entries">
|
||||
<item>只使用 NeoTerm</item>
|
||||
|
@ -29,6 +29,7 @@
|
||||
<string name="customization_settings">Customization</string>
|
||||
|
||||
<string name="toggle_ime">Toggle IME</string>
|
||||
<string name="float_up">Float Up</string>
|
||||
<string name="shell_not_found">Shell %s not found, please install it first.</string>
|
||||
<string name="fullscreen_mode_changed">FullScreen mode changed, please restart NeoTerm.</string>
|
||||
<string name="permission_denied">NeoTerm cannot get essential permissions, exiting.</string>
|
||||
@ -51,7 +52,7 @@
|
||||
<string name="crash_stack_trace">Stack Trace</string>
|
||||
|
||||
<string name="installer_message">Installing</string>
|
||||
<string name="installer_install_zsh_required">We are about to install oh-my-zsh and switch your login executablePath to zsh</string>
|
||||
<string name="installer_install_zsh_required">We are about to install oh-my-zsh and switch your login program to zsh</string>
|
||||
|
||||
<string name="pref_general_bell">Bell</string>
|
||||
<string name="pref_general_bell_desc">Bell when receiving \'\\a\'</string>
|
||||
@ -59,8 +60,8 @@
|
||||
<string name="pref_general_vibrate_desc">Vibrate when receiving \'\\a\'</string>
|
||||
<string name="pref_general_backspace_map_to_esc">BackSpace Mapped to Esc</string>
|
||||
<string name="pref_general_backspace_map_to_esc_desc">Send esc when backspace is pressed</string>
|
||||
<string name="pref_general_shell" translatable="false">Shell</string>
|
||||
<string name="pref_general_shell_desc">Which executablePath should we use when login</string>
|
||||
<string name="pref_general_shell">Login Program</string>
|
||||
<string name="pref_general_shell_desc">Which program should we use as shell when login</string>
|
||||
<string name="pref_general_program_selection">Program Selection</string>
|
||||
<string name="pref_general_program_selection_desc">When both Neo Term and your Android OS have a program, which one should we choose?</string>
|
||||
<string name="pref_general_initial_command">Initial Command</string>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<full-backup-content>
|
||||
<!-- See https://developer.android.com/training/backup/autosyncapi.html -->
|
||||
<include domain="file" path="home/auto_backup" />
|
||||
<include domain="file" path="home/.neoterm" />
|
||||
</full-backup-content>
|
@ -37,4 +37,8 @@ public abstract class AbstractTabViewHolder {
|
||||
*/
|
||||
public ImageButton closeButton;
|
||||
|
||||
/**
|
||||
* The custom button of a tab.
|
||||
*/
|
||||
public ImageButton customButton;
|
||||
}
|
Loading…
Reference in New Issue
Block a user