Feature: Program Suggestions
This commit is contained in:
parent
ddb663c71a
commit
93d4a29d47
@ -0,0 +1,10 @@
|
||||
package io.neoterm.customize.shortcut
|
||||
|
||||
import io.neoterm.view.ExtraKeysView
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
interface ShortcutKey {
|
||||
fun applyShortcutKeys(extraKeysView: ExtraKeysView)
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package io.neoterm.customize.shortcut
|
||||
|
||||
import io.neoterm.view.ExtraKeysView
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
object ShortcutKeysManager {
|
||||
val shortcutKeys: MutableMap<String, ShortcutKey> = mutableMapOf()
|
||||
|
||||
fun showShortcutKeys(program: String, extraKeysView: ExtraKeysView?) {
|
||||
if (extraKeysView == null) {
|
||||
return
|
||||
}
|
||||
|
||||
if (this.shortcutKeys.containsKey(program)) {
|
||||
val shortcutKey = shortcutKeys[program]
|
||||
shortcutKey?.applyShortcutKeys(extraKeysView)
|
||||
return
|
||||
}
|
||||
|
||||
extraKeysView.resetExternalButtons()
|
||||
}
|
||||
|
||||
fun registerShortcutKeys(program: String, shortcutKey: ShortcutKey?) {
|
||||
if (shortcutKey == null) {
|
||||
if (this.shortcutKeys.containsKey(program)) {
|
||||
this.shortcutKeys.remove(program)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
this.shortcutKeys[program] = shortcutKey
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package io.neoterm.customize.shortcut.builtin
|
||||
|
||||
import io.neoterm.customize.shortcut.ShortcutKey
|
||||
import io.neoterm.customize.shortcut.ShortcutKeysManager
|
||||
import io.neoterm.view.ExtraKeysView
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
*/
|
||||
object BuiltinShortcutKeys {
|
||||
val vim = object : ShortcutKey {
|
||||
override fun applyShortcutKeys(extraKeysView: ExtraKeysView) {
|
||||
extraKeysView.addExternalButton(ExtraKeysView.SLASH) // Search
|
||||
extraKeysView.addExternalButton(ExtraKeysView.TextButton(":w", true)) // Save
|
||||
extraKeysView.addExternalButton(ExtraKeysView.TextButton("dd", true)) // Delete
|
||||
extraKeysView.addExternalButton(ExtraKeysView.TextButton(":q", true)) // Quit
|
||||
}
|
||||
}
|
||||
|
||||
val moreAndLess = object : ShortcutKey {
|
||||
override fun applyShortcutKeys(extraKeysView: ExtraKeysView) {
|
||||
extraKeysView.addExternalButton(ExtraKeysView.TextButton("R", true)) // Rest
|
||||
extraKeysView.addExternalButton(ExtraKeysView.TextButton("Q", true)) // Quit
|
||||
}
|
||||
}
|
||||
|
||||
fun registerAll() {
|
||||
ShortcutKeysManager.registerShortcutKeys("vim", vim)
|
||||
ShortcutKeysManager.registerShortcutKeys("more", moreAndLess)
|
||||
ShortcutKeysManager.registerShortcutKeys("less", moreAndLess)
|
||||
}
|
||||
}
|
@ -1,10 +1,7 @@
|
||||
package io.neoterm.ui
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.ComponentName
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.content.*
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Bundle
|
||||
import android.os.IBinder
|
||||
@ -16,11 +13,13 @@ import android.support.v7.widget.Toolbar
|
||||
import android.view.KeyEvent
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.ImageButton
|
||||
import de.mrapp.android.tabswitcher.*
|
||||
import de.mrapp.android.tabswitcher.view.TabSwitcherButton
|
||||
import io.neoterm.R
|
||||
import io.neoterm.backend.TerminalSession
|
||||
import io.neoterm.customize.shortcut.builtin.BuiltinShortcutKeys
|
||||
import io.neoterm.installer.BaseFileInstaller
|
||||
import io.neoterm.preference.NeoPermission
|
||||
import io.neoterm.preference.NeoTermPreference
|
||||
@ -83,6 +82,8 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection {
|
||||
|
||||
NeoPermission.initAppPermission(this, NeoPermission.REQUEST_APP_PERMISSION)
|
||||
NeoTermPreference.init(this)
|
||||
BuiltinShortcutKeys.registerAll()
|
||||
|
||||
if (NeoTermPreference.loadBoolean(R.string.key_ui_fullscreen, false)) {
|
||||
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN)
|
||||
@ -285,6 +286,11 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection {
|
||||
startActivity(Intent(this, SettingActivity::class.java))
|
||||
true
|
||||
}
|
||||
R.id.menu_item_toggle_ime -> {
|
||||
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0)
|
||||
true
|
||||
}
|
||||
R.id.menu_item_new_session -> {
|
||||
if (!tabSwitcher.isSwitcherShown) {
|
||||
tabSwitcher.showSwitcher()
|
||||
|
@ -2,6 +2,7 @@ package io.neoterm.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.KeyEvent;
|
||||
@ -40,13 +41,23 @@ public final class ExtraKeysView extends GridLayout {
|
||||
}
|
||||
|
||||
public static class TextButton extends ExtraButton {
|
||||
boolean withEnter = false;
|
||||
|
||||
public TextButton(String text) {
|
||||
buttonText = text;
|
||||
this(text, false);
|
||||
}
|
||||
|
||||
public TextButton(String text, boolean withEnter) {
|
||||
this.buttonText = text;
|
||||
this.withEnter = withEnter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
ExtraKeysView.sendKey(view, buttonText);
|
||||
if (withEnter) {
|
||||
ExtraKeysView.sendKey(view, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,10 +107,15 @@ public final class ExtraKeysView extends GridLayout {
|
||||
|
||||
public ExtraKeysView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
try {
|
||||
externalButtons = new ArrayList<>(3);
|
||||
extraButtons = new ArrayList<>();
|
||||
resetExternalButtons();
|
||||
reload();
|
||||
updateButtons();
|
||||
} catch (Throwable e) {
|
||||
Log.e("NeoTerm", e.toString());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendKey(View view, String keyName) {
|
||||
@ -167,6 +183,7 @@ public final class ExtraKeysView extends GridLayout {
|
||||
|
||||
public void resetExternalButtons() {
|
||||
clearExternalButton();
|
||||
externalButtons.add(ALT);
|
||||
externalButtons.add(HORIZONTAL);
|
||||
externalButtons.add(SLASH);
|
||||
externalButtons.add(PIPE);
|
||||
@ -175,7 +192,6 @@ public final class ExtraKeysView extends GridLayout {
|
||||
void loadDefaultButtons(List<ExtraButton> buttons) {
|
||||
buttons.add(ESC);
|
||||
buttons.add(CTRL);
|
||||
buttons.add(ALT);
|
||||
buttons.add(TAB);
|
||||
}
|
||||
|
||||
@ -183,8 +199,7 @@ public final class ExtraKeysView extends GridLayout {
|
||||
buttons.addAll(externalButtons);
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
ALT.toggleButton = CTRL.toggleButton = null;
|
||||
public void updateButtons() {
|
||||
removeAllViews();
|
||||
|
||||
extraButtons.clear();
|
||||
@ -208,6 +223,7 @@ public final class ExtraKeysView extends GridLayout {
|
||||
|
||||
button.setText(extraButton.buttonText);
|
||||
button.setTextColor(TEXT_COLOR);
|
||||
button.setAllCaps(false);
|
||||
|
||||
final Button finalButton = button;
|
||||
button.setOnClickListener(new OnClickListener() {
|
||||
|
@ -16,7 +16,6 @@ import io.neoterm.view.TerminalView
|
||||
*/
|
||||
class TermSessionChangedCallback : TerminalSession.SessionChangedCallback {
|
||||
var termView: TerminalView? = null
|
||||
var extraKeysView: ExtraKeysView? = null
|
||||
var termTab: TermTab? = null
|
||||
|
||||
var bellId: Int = 0
|
||||
|
@ -3,8 +3,10 @@ package io.neoterm.view.tab
|
||||
import android.graphics.Color
|
||||
import android.support.v7.widget.Toolbar
|
||||
import de.mrapp.android.tabswitcher.Tab
|
||||
import io.neoterm.R
|
||||
import io.neoterm.backend.TerminalSession
|
||||
import io.neoterm.customize.color.NeoTermColorScheme
|
||||
import io.neoterm.preference.NeoTermPreference
|
||||
|
||||
/**
|
||||
* @author kiva
|
||||
@ -29,7 +31,6 @@ class TermTab(title: CharSequence) : Tab(title) {
|
||||
viewClient?.extraKeysView = null
|
||||
sessionCallback?.termView = null
|
||||
sessionCallback?.termTab = null
|
||||
sessionCallback?.extraKeysView = null
|
||||
closeTabProvider = null
|
||||
toolbar = null
|
||||
termSession = null
|
||||
@ -38,6 +39,9 @@ class TermTab(title: CharSequence) : Tab(title) {
|
||||
fun updateTitle(title: String) {
|
||||
this.title = title
|
||||
toolbar?.title = title
|
||||
if (NeoTermPreference.loadBoolean(R.string.key_ui_suggestions, true)) {
|
||||
viewClient?.updateSuggestions(title)
|
||||
}
|
||||
}
|
||||
|
||||
fun onSessionFinished() {
|
||||
|
@ -68,13 +68,16 @@ class TermTabDecorator(val context: NeoTermActivity) : TabSwitcherDecorator() {
|
||||
// 复用前一次的 TermSession
|
||||
termTab.sessionCallback?.termView = view
|
||||
termTab.sessionCallback?.termTab = termTab
|
||||
termTab.sessionCallback?.extraKeysView = extraKeysView
|
||||
|
||||
// 复用上一次的 TermViewClient
|
||||
termTab.viewClient?.termTab = termTab
|
||||
termTab.viewClient?.termView = view
|
||||
termTab.viewClient?.extraKeysView = extraKeysView
|
||||
|
||||
if (termTab.termSession != null) {
|
||||
termTab.viewClient?.updateSuggestions(termTab.termSession?.title, true)
|
||||
}
|
||||
|
||||
view.setOnKeyListener(termTab.viewClient)
|
||||
view.attachSession(termTab.termSession)
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import android.view.MotionEvent
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import io.neoterm.R
|
||||
import io.neoterm.backend.TerminalSession
|
||||
import io.neoterm.customize.shortcut.ShortcutKeysManager
|
||||
import io.neoterm.preference.NeoTermPreference
|
||||
import io.neoterm.view.ExtraKeysView
|
||||
import io.neoterm.view.TerminalView
|
||||
@ -18,6 +19,7 @@ import io.neoterm.view.TerminalViewClient
|
||||
class TermViewClient(val context: Context) : TerminalViewClient {
|
||||
private var mVirtualControlKeyDown: Boolean = false
|
||||
private var mVirtualFnKeyDown: Boolean = false
|
||||
private var lastTitle: String = ""
|
||||
|
||||
var sessionFinished: Boolean = false
|
||||
|
||||
@ -102,4 +104,17 @@ class TermViewClient(val context: Context) : TerminalViewClient {
|
||||
return false
|
||||
}
|
||||
|
||||
fun updateSuggestions(title: String?, force: Boolean = false) {
|
||||
if (extraKeysView == null || title == null || title.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
if (lastTitle != title || force) {
|
||||
extraKeysView?.clearExternalButton()
|
||||
ShortcutKeysManager.showShortcutKeys(title, extraKeysView)
|
||||
extraKeysView?.updateButtons()
|
||||
lastTitle = title
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -27,6 +27,11 @@ License.
|
||||
android:title="@string/new_session"
|
||||
app:showAsAction="never"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_item_toggle_ime"
|
||||
android:title="@string/toggle_ime"
|
||||
app:showAsAction="never"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_item_settings"
|
||||
android:title="@string/settings"
|
||||
|
@ -9,6 +9,7 @@
|
||||
<string name="key_ui_font" translatable="false">neoterm_ui_font</string>
|
||||
<string name="key_ui_color_scheme" translatable="false">neoterm_ui_color_scheme</string>
|
||||
<string name="key_ui_next_tab_anim" translatable="false">neoterm_ui_next_tab_anim</string>
|
||||
<string name="key_ui_suggestions" translatable="false">neoterm_ui_suggestions</string>
|
||||
|
||||
<string name="key_package_source" translatable="false">neoterm_package_source</string>
|
||||
</resources>
|
@ -28,7 +28,10 @@
|
||||
<string name="pref_ui_color_scheme">Color Scheme</string>
|
||||
<string name="pref_ui_close_tab_anim_next_tab">Next tab animation</string>
|
||||
<string name="pref_ui_close_tab_anim_next_tab_desc">Switch to next tab instead of previous tab when closing tab</string>
|
||||
<string name="pref_ui_suggestions">Show Suggestions (zsh required)</string>
|
||||
<string name="pref_ui_suggestions_desc">When using some programs, show shortcut keys</string>
|
||||
<string name="pref_package_source">Source</string>
|
||||
<string name="toggle_ime">Toggle IME</string>
|
||||
|
||||
<string-array name="pref_ui_color_scheme_entries" translatable="false">
|
||||
<item>Default</item>
|
||||
|
@ -12,6 +12,12 @@
|
||||
android:summary="@string/pref_ui_close_tab_anim_next_tab_desc"
|
||||
android:title="@string/pref_ui_close_tab_anim_next_tab" />
|
||||
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="true"
|
||||
android:key="@string/key_ui_suggestions"
|
||||
android:summary="@string/pref_ui_suggestions_desc"
|
||||
android:title="@string/pref_ui_suggestions" />
|
||||
|
||||
<EditTextPreference
|
||||
android:key="@string/key_ui_font"
|
||||
android:title="@string/pref_ui_font" />
|
||||
|
@ -324,7 +324,7 @@ public abstract class AbstractDragHandler<CallbackType extends AbstractDragHandl
|
||||
flingDistance = -1 * flingDistance;
|
||||
}
|
||||
|
||||
long duration = Math.round(Math.abs(flingDistance) / flingVelocity * 1000);
|
||||
long duration = Math.round(Math.abs(flingDistance) / flingVelocity * 3000);
|
||||
notifyOnFling(flingDistance, duration);
|
||||
}
|
||||
}
|
||||
|
@ -283,7 +283,7 @@ public class PhoneDragHandler extends AbstractDragHandler<PhoneDragHandler.Callb
|
||||
protected final boolean isSwipeThresholdReached(@NonNull final TabItem swipedTabItem) {
|
||||
View view = swipedTabItem.getView();
|
||||
return Math.abs(getArithmetics().getPosition(Axis.ORTHOGONAL_AXIS, view)) >
|
||||
getArithmetics().getTabContainerSize(Axis.ORTHOGONAL_AXIS) / 6f;
|
||||
getArithmetics().getTabContainerSize(Axis.ORTHOGONAL_AXIS) / 2f;
|
||||
}
|
||||
|
||||
}
|
@ -24,7 +24,7 @@ License.
|
||||
<dimen name="stacked_tab_spacing">4dp</dimen>
|
||||
<dimen name="max_overshoot_distance">48dp</dimen>
|
||||
<dimen name="max_camera_distance">1280dp</dimen>
|
||||
<dimen name="min_swipe_velocity">1024dp</dimen>
|
||||
<dimen name="min_swipe_velocity">2048dp</dimen>
|
||||
<dimen name="drag_threshold">8dp</dimen>
|
||||
<dimen name="swipe_threshold">24dp</dimen>
|
||||
<dimen name="tab_switcher_drawable_size">32dp</dimen>
|
||||
|
Loading…
x
Reference in New Issue
Block a user