Feature: Preference

This commit is contained in:
zt515 2017-06-12 20:57:53 +08:00
parent 0e6207b5f3
commit 085c0b95f1
27 changed files with 322 additions and 30 deletions

View File

@ -41,4 +41,5 @@ dependencies {
testCompile 'junit:junit:4.12'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
compile project(':chrome-tabs')
implementation 'com.android.support:design:25.3.1'
}

View File

@ -2,6 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.neoterm">
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:allowBackup="true"
android:extractNativeLibs="true"
@ -22,19 +24,15 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ui.settings.SettingActivity"
android:theme="@style/Theme.AppCompat" />
<activity
android:name=".ui.settings.GeneralSettingsActivity"
android:theme="@style/Theme.AppCompat" />
<activity
android:name=".ui.settings.UISettingsActivity"
android:theme="@style/Theme.AppCompat" />
<activity
android:name=".ui.settings.PackageSettingsActivity"
android:theme="@style/Theme.AppCompat" />
@ -42,6 +40,11 @@
<service
android:name=".services.NeoTermService"
android:enabled="true" />
<activity
android:name=".ui.AboutActivity"
android:label="@string/about"
android:theme="@style/AppTheme.NoActionBar" />
</application>
</manifest>

View File

@ -1,6 +1,7 @@
package io.neoterm.preference
import android.content.Context
import android.content.SharedPreferences
import android.preference.PreferenceManager
import io.neoterm.backend.TerminalSession
import io.neoterm.services.NeoTermService
@ -10,17 +11,66 @@ import io.neoterm.services.NeoTermService
*/
object NeoTermPreference {
var CURRENT_SESSION_KEY = "neoterm_current_session"
const val KEY_FONT_SIZE = "neoterm_general_font_size"
const val KEY_CURRENT_SESSION = "neoterm_service_current_session"
fun storeCurrentSession(context: Context, session: TerminalSession) {
PreferenceManager.getDefaultSharedPreferences(context)
.edit()
.putString(NeoTermPreference.CURRENT_SESSION_KEY, session.mHandle)
var preference: SharedPreferences? = null
var context: Context? = null
fun init(context: Context) {
this.context = context
preference = PreferenceManager.getDefaultSharedPreferences(context)
}
fun cleanup() {
preference = null
context = null
}
fun store(key: Int, value: Any) {
store(context!!.getString(key), value)
}
fun store(key: String, value: Any) {
when (value) {
is Int -> preference!!.edit().putInt(key, value).apply()
is String -> preference!!.edit().putString(key, value).apply()
is Boolean -> preference!!.edit().putBoolean(key, value).apply()
}
}
fun loadInt(key: Int, defaultValue: Int): Int {
return loadInt(context!!.getString(key), defaultValue)
}
fun loadString(key: Int, defaultValue: String?): String {
return loadString(context!!.getString(key), defaultValue)
}
fun loadBoolean(key: Int, defaultValue: Boolean): Boolean {
return loadBoolean(context!!.getString(key), defaultValue)
}
fun loadInt(key: String, defaultValue: Int): Int {
return preference!!.getInt(key, defaultValue)
}
fun loadString(key: String, defaultValue: String?): String {
return preference!!.getString(key, defaultValue)
}
fun loadBoolean(key: String, defaultValue: Boolean): Boolean {
return preference!!.getBoolean(key, defaultValue)
}
fun storeCurrentSession(session: TerminalSession) {
preference!!.edit()
.putString(NeoTermPreference.KEY_CURRENT_SESSION, session.mHandle)
.apply()
}
fun getCurrentSession(termService: NeoTermService?): TerminalSession? {
val sessionHandle = PreferenceManager.getDefaultSharedPreferences(termService!!).getString(CURRENT_SESSION_KEY, "")
val sessionHandle = PreferenceManager.getDefaultSharedPreferences(termService!!).getString(KEY_CURRENT_SESSION, "")
var i = 0
val len = termService.sessions.size
while (i < len) {

View File

@ -0,0 +1,25 @@
package io.neoterm.ui
import android.os.Bundle
import android.support.design.widget.FloatingActionButton
import android.support.design.widget.Snackbar
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar
import io.neoterm.R
class AboutActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_about)
val toolbar = findViewById(R.id.about_toolbar) as Toolbar
setSupportActionBar(toolbar)
val fab = findViewById(R.id.about_fab) as FloatingActionButton
fab.setOnClickListener({ view ->
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
})
}
}

View File

@ -12,6 +12,7 @@ import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar
import android.view.KeyEvent
import android.view.View
import android.view.WindowManager
import android.widget.ImageButton
import de.mrapp.android.tabswitcher.*
import de.mrapp.android.tabswitcher.view.TabSwitcherButton
@ -45,11 +46,20 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection {
addNewSession(session)
}
switchToSession(getStoredCurrentSessionOrLast())
} else {
tabSwitcher.showSwitcher()
addNewSession("NeoTerm #0", createRevealAnimation())
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
NeoTermPreference.init(this)
if (NeoTermPreference.loadBoolean(R.string.key_ui_fullscreen, false)) {
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN)
}
setContentView(R.layout.tab_main)
tabSwitcher = findViewById(R.id.tab_switcher) as TabSwitcher
@ -68,16 +78,16 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection {
override fun onResume() {
super.onResume()
tabSwitcher.addListener(object : TabSwitcherListener {
private var tabSwitcherButtonInited = false
private var tabSwitcherButtonInit = false
override fun onSwitcherShown(tabSwitcher: TabSwitcher) {
if (tabSwitcherButtonInited) {
if (tabSwitcherButtonInit) {
return
}
val menu = tabSwitcher.toolbarMenu
if (menu != null) {
tabSwitcherButtonInited = true
tabSwitcherButtonInit = true
val tabSwitcherButton = menu.findItem(R.id.toggle_tab_switcher_menu_item).actionView as TabSwitcherButton
tabSwitcherButton.setOnClickListener {
if (tabSwitcher.isSwitcherShown) {
@ -94,7 +104,7 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection {
override fun onSelectionChanged(tabSwitcher: TabSwitcher, selectedTabIndex: Int, selectedTab: Tab?) {
if (selectedTab is TermTab && selectedTab.termSession != null) {
NeoTermPreference.storeCurrentSession(this@NeoTermActivity, selectedTab.termSession!!)
NeoTermPreference.storeCurrentSession(selectedTab.termSession!!)
}
}
@ -125,6 +135,7 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection {
termService = null
}
unbindService(this)
NeoTermPreference.cleanup()
}
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {

View File

@ -3,7 +3,11 @@ package io.neoterm.view.tab
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.media.SoundPool
import android.os.Vibrator
import io.neoterm.R
import io.neoterm.backend.TerminalSession
import io.neoterm.preference.NeoTermPreference
import io.neoterm.view.TerminalView
/**
@ -13,6 +17,9 @@ class TermSessionChangedCallback : TerminalSession.SessionChangedCallback {
var termView: TerminalView? = null
var termTab: TermTab? = null
var bellId: Int = 0
var soundPool: SoundPool? = null
override fun onTextChanged(changedSession: TerminalSession?) {
termView?.onScreenUpdated()
}
@ -35,6 +42,22 @@ class TermSessionChangedCallback : TerminalSession.SessionChangedCallback {
}
override fun onBell(session: TerminalSession?) {
if (termView == null) {
return
}
if (NeoTermPreference.loadBoolean(R.string.key_general_bell, false)) {
if (soundPool == null) {
soundPool = SoundPool.Builder().setMaxStreams(1).build()
bellId = soundPool!!.load(termView!!.context, R.raw.bell, 1)
}
soundPool?.play(bellId, 1f, 1f, 0, 0, 1f)
}
if (NeoTermPreference.loadBoolean(R.string.key_general_vibrate, false)) {
val vibrator = termView!!.context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
vibrator.vibrate(100)
}
}
override fun onColorsChanged(session: TerminalSession?) {

View File

@ -10,9 +10,9 @@ import android.view.ViewGroup
import de.mrapp.android.tabswitcher.Tab
import de.mrapp.android.tabswitcher.TabSwitcher
import de.mrapp.android.tabswitcher.TabSwitcherDecorator
import io.neoterm.ui.NeoTermActivity
import io.neoterm.R
import io.neoterm.customize.color.builtin.MaterialColorScheme
import io.neoterm.preference.NeoTermPreference
import io.neoterm.ui.NeoTermActivity
import io.neoterm.view.ExtraKeysView
import io.neoterm.view.TerminalView
@ -59,7 +59,7 @@ class TermTabDecorator(val context: NeoTermActivity) : TabSwitcherDecorator() {
if (view == null) {
return
}
view.textSize = 30
view.textSize = NeoTermPreference.loadInt(NeoTermPreference.KEY_FONT_SIZE, 30)
view.setTypeface(Typeface.MONOSPACE)
if (tab is TermTab) {

View File

@ -5,7 +5,9 @@ import android.view.InputDevice
import android.view.KeyEvent
import android.view.MotionEvent
import android.view.inputmethod.InputMethodManager
import io.neoterm.R
import io.neoterm.backend.TerminalSession
import io.neoterm.preference.NeoTermPreference
import io.neoterm.view.ExtraKeysView
import io.neoterm.view.TerminalView
import io.neoterm.view.TerminalViewClient
@ -27,7 +29,9 @@ class TermViewClient(val context: Context) : TerminalViewClient {
if (scale < 0.9f || scale > 1.1f) {
val increase = scale > 1f
val changedSize = (if (increase) 1 else -1) * 2
termView!!.textSize = termView!!.textSize + changedSize
val fontSize = termView!!.textSize + changedSize
termView!!.textSize = fontSize
NeoTermPreference.store(NeoTermPreference.KEY_FONT_SIZE, fontSize)
return 1.0f
}
return scale
@ -39,7 +43,7 @@ class TermViewClient(val context: Context) : TerminalViewClient {
}
override fun shouldBackButtonBeMappedToEscape(): Boolean {
return false
return NeoTermPreference.loadBoolean(R.string.key_generaL_backspace_map_to_esc, false)
}
override fun copyModeChanged(copyMode: Boolean) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 500 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

View File

@ -0,0 +1,33 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="48dp"
android:width="48dp"
android:viewportWidth="48"
android:viewportHeight="48">
<!--
https://material.google.com/style/icons.html
-->
<!-- Screen border. -->
<path android:fillColor="#fafafa"
android:strokeColor="#212121"
android:strokeWidth="3"
android:pathData="M7,4
l34,0
q3 0,3 3
l0,34
q0 3, -3 3
l-34,0
q-3 0, -3-3
l0 -34
q0 -3, 3 -3"
/>
<!-- Block cursor. -->
<path android:fillColor="#000"
android:pathData="M14,14
l5,0
l0,10
l-5,0"
/>
</vector>

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="io.neoterm.ui.AboutActivity">
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="@dimen/app_bar_height"
android:fitsSystemWindows="true"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:toolbarId="@+id/about_toolbar">
<android.support.v7.widget.Toolbar
android:id="@+id/about_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_about" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/about_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/fab_margin"
app:layout_anchor="@id/app_bar"
app:layout_anchorGravity="bottom|end"
app:srcCompat="@drawable/ic_terminal_running_white" />
</android.support.design.widget.CoordinatorLayout>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="io.neoterm.ui.AboutActivity"
tools:showIn="@layout/activity_about">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin"
android:text="@string/large_text" />
</android.support.v4.widget.NestedScrollView>

View File

@ -5,7 +5,7 @@
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ff14181c"
android:background="@color/terminal_background"
custom:layoutPolicy="auto"
custom:tabBackgroundColor="@color/tab_background_color"
custom:tabIcon="@drawable/ic_tab_icon"

BIN
app/src/main/res/raw/bell.ogg Executable file

Binary file not shown.

View File

@ -2,6 +2,6 @@
<resources>
<color name="colorPrimary">#607D8B</color>
<color name="colorPrimaryDark">#455A64</color>
<color name="colorAccent">#03A9F4</color>
<color name="terminal_background">#13181a</color>
<color name="colorAccent">#FF5252</color>
<color name="terminal_background">#ff14181c</color>
</resources>

View File

@ -0,0 +1,5 @@
<resources>
<dimen name="app_bar_height">180dp</dimen>
<dimen name="fab_margin">16dp</dimen>
<dimen name="text_margin">16dp</dimen>
</resources>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="key_general_bell" translatable="false">neoterm_general_bell</string>
<string name="key_general_vibrate" translatable="false">neoterm_general_vibrate</string>
<string name="key_generaL_backspace_map_to_esc">neoterm_general_backspace_map_to_esc</string>
<string name="key_ui_fullscreen" translatable="false">neoterm_ui_fullscreen</string>
<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_package_source" translatable="false">neoterm_package_source</string>
</resources>

View File

@ -12,4 +12,17 @@
<string name="general_settings">General Settings</string>
<string name="ui_settings">UI Settings</string>
<string name="package_settings">Package Settings</string>
<string name="large_text">Hello NeoTerm.</string>
<string name="pref_general_bell">Bell</string>
<string name="pref_general_bell_desc">Bell when receiving \'\\a\'</string>
<string name="pref_general_vibrate">Vibrate</string>
<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_ui_fullscreen">Full Screen</string>
<string name="pref_ui_font">Font</string>
<string name="pref_ui_color_scheme">Color Scheme</string>
<string name="pref_package_source">Source</string>
</resources>

View File

@ -1,7 +1,7 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar" >
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorAccent">@color/colorAccent</item>
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
@ -12,4 +12,8 @@
<item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
</resources>

View File

@ -1,4 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:defaultValue="false"
android:key="@string/key_general_bell"
android:summary="@string/pref_general_bell_desc"
android:title="@string/pref_general_bell" />
<CheckBoxPreference
android:defaultValue="false"
android:key="@string/key_general_vibrate"
android:summary="@string/pref_general_vibrate_desc"
android:title="@string/pref_general_vibrate" />
<CheckBoxPreference
android:defaultValue="false"
android:key="@string/key_generaL_backspace_map_to_esc"
android:summary="@string/pref_general_backspace_map_to_esc_desc"
android:title="@string/pref_general_backspace_map_to_esc" />
</PreferenceScreen>

View File

@ -1,25 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<Preference android:title="@string/general_settings">
<Preference
android:icon="@drawable/ic_general_white_36dp"
android:title="@string/general_settings">
<intent
android:targetClass="io.neoterm.ui.settings.GeneralSettingsActivity"
android:targetPackage="io.neoterm" />
</Preference>
<Preference android:title="@string/ui_settings" >
<Preference
android:icon="@drawable/ic_ui_white_36dp"
android:title="@string/ui_settings">
<intent
android:targetClass="io.neoterm.ui.settings.UISettingsActivity"
android:targetPackage="io.neoterm" />
</Preference>
<Preference android:title="@string/package_settings" >
<Preference
android:icon="@drawable/ic_apps_white_36dp"
android:title="@string/package_settings">
<intent
android:targetClass="io.neoterm.ui.settings.PackageSettingsActivity"
android:targetPackage="io.neoterm" />
</Preference>
<Preference android:title="@string/about" >
<Preference
android:icon="@drawable/ic_info_white_36dp"
android:title="@string/about">
<intent
android:targetClass="io.neoterm.ui.AboutActivity"
android:targetPackage="io.neoterm" />

View File

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<EditTextPreference
android:key="@string/key_package_source"
android:title="@string/pref_package_source" />
</PreferenceScreen>

View File

@ -1,4 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:defaultValue="false"
android:key="@string/key_ui_fullscreen"
android:title="@string/pref_ui_fullscreen" />
<EditTextPreference
android:key="@string/key_ui_font"
android:title="@string/pref_ui_font" />
<ListPreference
android:entries="@null"
android:entryValues="@null"
android:key="@string/key_ui_color_scheme"
android:title="@string/pref_ui_color_scheme" />
</PreferenceScreen>

View File

@ -1418,7 +1418,7 @@ public class TabSwitcher extends FrameLayout implements TabSwitcherLayout, Model
savedState.modelState = new Bundle();
Pair<Integer, Float> pair = null;
if (getCount() > 0) {
if (getCount() > 0 && layout != null) {
pair = layout.detachLayout(true);
}
@ -1434,8 +1434,10 @@ public class TabSwitcher extends FrameLayout implements TabSwitcherLayout, Model
model.setFirstVisibleTabIndex(-1);
}
if (layout != null) {
model.removeListener(layout);
layout = null;
}
executePendingAction();
getViewTreeObserver().addOnGlobalLayoutListener(
new LayoutListenerWrapper(this, createGlobalLayoutListener(true)));