Feature: Program Suggestions

This commit is contained in:
zt515 2017-06-14 20:47:36 +08:00
parent ddb663c71a
commit 93d4a29d47
16 changed files with 153 additions and 18 deletions

View File

@ -0,0 +1,10 @@
package io.neoterm.customize.shortcut
import io.neoterm.view.ExtraKeysView
/**
* @author kiva
*/
interface ShortcutKey {
fun applyShortcutKeys(extraKeysView: ExtraKeysView)
}

View File

@ -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
}
}

View File

@ -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)
}
}

View File

@ -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()

View File

@ -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() {

View File

@ -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

View File

@ -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() {

View File

@ -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)
}

View File

@ -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
}
}
}

View File

@ -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"

View File

@ -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>

View File

@ -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>

View File

@ -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" />

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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>