Improve: Huge Details
This commit is contained in:
@ -55,6 +55,7 @@ dependencies {
|
|||||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
|
||||||
testCompile 'junit:junit:4.12'
|
testCompile 'junit:junit:4.12'
|
||||||
compile 'com.android.support.constraint:constraint-layout:1.0.2'
|
compile 'com.android.support.constraint:constraint-layout:1.0.2'
|
||||||
|
compile 'org.greenrobot:eventbus:3.0.0'
|
||||||
compile project(':chrome-tabs')
|
compile project(':chrome-tabs')
|
||||||
implementation 'com.android.support:design:25.3.1'
|
implementation 'com.android.support:design:25.3.1'
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,9 @@ object NeoTermPath {
|
|||||||
const val EKS_PATH = "$USR_PATH/share/eks"
|
const val EKS_PATH = "$USR_PATH/share/eks"
|
||||||
const val EKS_DEFAULT_FILE = "$EKS_PATH/default.eks"
|
const val EKS_DEFAULT_FILE = "$EKS_PATH/default.eks"
|
||||||
|
|
||||||
const val SERVER_BASE_URL = "http://mirror.neoterm.studio"
|
const val SOURCE_FILE = "$USR_PATH/etc/apt/sources.list"
|
||||||
|
|
||||||
|
const val DEFAULT_SOURCE = "http://mirror.neoterm.studio"
|
||||||
|
const val SERVER_BASE_URL = DEFAULT_SOURCE
|
||||||
const val SERVER_BOOT_URL = "$SERVER_BASE_URL/boot"
|
const val SERVER_BOOT_URL = "$SERVER_BASE_URL/boot"
|
||||||
}
|
}
|
@ -15,7 +15,7 @@ object ShortcutConfigLoader {
|
|||||||
extraKeysView.loadDefaultUserDefinedExtraKeys()
|
extraKeysView.loadDefaultUserDefinedExtraKeys()
|
||||||
}
|
}
|
||||||
for (button in config.shortcutKeys) {
|
for (button in config.shortcutKeys) {
|
||||||
extraKeysView.addExternalButton(button)
|
extraKeysView.addUserDefinedButton(button)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package io.neoterm.installer;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
|
import android.content.Context;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.system.Os;
|
import android.system.Os;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -10,7 +11,9 @@ import android.util.Pair;
|
|||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -22,6 +25,7 @@ import java.util.zip.ZipInputStream;
|
|||||||
import io.neoterm.R;
|
import io.neoterm.R;
|
||||||
import io.neoterm.backend.EmulatorDebug;
|
import io.neoterm.backend.EmulatorDebug;
|
||||||
import io.neoterm.customize.NeoTermPath;
|
import io.neoterm.customize.NeoTermPath;
|
||||||
|
import io.neoterm.utils.FileUtils;
|
||||||
|
|
||||||
public final class BaseFileInstaller {
|
public final class BaseFileInstaller {
|
||||||
public interface ResultListener {
|
public interface ResultListener {
|
||||||
@ -35,7 +39,11 @@ public final class BaseFileInstaller {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final ProgressDialog progress = ProgressDialog.show(activity, null, activity.getString(R.string.installer_message), true, false);
|
installHomeFiles(activity);
|
||||||
|
|
||||||
|
final ProgressDialog progress = makeProgressDialog(activity);
|
||||||
|
progress.setMax(100);
|
||||||
|
progress.show();
|
||||||
new Thread() {
|
new Thread() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@ -47,13 +55,37 @@ public final class BaseFileInstaller {
|
|||||||
deleteFolder(STAGING_PREFIX_FILE);
|
deleteFolder(STAGING_PREFIX_FILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int totalBytes = 0;
|
||||||
|
int totalReadBytes = 0;
|
||||||
final byte[] buffer = new byte[8096];
|
final byte[] buffer = new byte[8096];
|
||||||
final List<Pair<String, String>> symlinks = new ArrayList<>(50);
|
final List<Pair<String, String>> symlinks = new ArrayList<>(50);
|
||||||
|
|
||||||
final URL zipUrl = determineZipUrl();
|
final URL zipUrl = determineZipUrl();
|
||||||
try (ZipInputStream zipInput = new ZipInputStream(zipUrl.openStream())) {
|
HttpURLConnection connection = (HttpURLConnection) zipUrl.openConnection();
|
||||||
|
totalBytes = connection.getContentLength();
|
||||||
|
|
||||||
|
try (ZipInputStream zipInput = new ZipInputStream(connection.getInputStream())) {
|
||||||
ZipEntry zipEntry;
|
ZipEntry zipEntry;
|
||||||
|
|
||||||
while ((zipEntry = zipInput.getNextEntry()) != null) {
|
while ((zipEntry = zipInput.getNextEntry()) != null) {
|
||||||
|
totalReadBytes += zipEntry.getCompressedSize();
|
||||||
|
|
||||||
|
final int totalReadBytesFinal = totalReadBytes;
|
||||||
|
final int totalBytesFinal = totalBytes;
|
||||||
|
|
||||||
|
activity.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
double progressFloat = ((double) totalReadBytesFinal) / ((double) totalBytesFinal) * 100.0;
|
||||||
|
Log.e("NeoTerm-Installer", "total: " + totalBytesFinal + ", read: " + totalReadBytesFinal + ", " + progressFloat);
|
||||||
|
progress.setProgress((int) progressFloat);
|
||||||
|
} catch (RuntimeException ignore) {
|
||||||
|
// activity dismissed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (zipEntry.getName().equals("SYMLINKS.txt")) {
|
if (zipEntry.getName().equals("SYMLINKS.txt")) {
|
||||||
BufferedReader symlinksReader = new BufferedReader(new InputStreamReader(zipInput));
|
BufferedReader symlinksReader = new BufferedReader(new InputStreamReader(zipInput));
|
||||||
String line;
|
String line;
|
||||||
@ -77,9 +109,10 @@ public final class BaseFileInstaller {
|
|||||||
} else {
|
} else {
|
||||||
try (FileOutputStream outStream = new FileOutputStream(targetFile)) {
|
try (FileOutputStream outStream = new FileOutputStream(targetFile)) {
|
||||||
int readBytes;
|
int readBytes;
|
||||||
while ((readBytes = zipInput.read(buffer)) != -1)
|
while ((readBytes = zipInput.read(buffer)) != -1) {
|
||||||
outStream.write(buffer, 0, readBytes);
|
outStream.write(buffer, 0, readBytes);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (zipEntryName.startsWith("bin/") || zipEntryName.startsWith("libexec") || zipEntryName.startsWith("lib/apt/methods")) {
|
if (zipEntryName.startsWith("bin/") || zipEntryName.startsWith("libexec") || zipEntryName.startsWith("lib/apt/methods")) {
|
||||||
//noinspection OctalInteger
|
//noinspection OctalInteger
|
||||||
Os.chmod(targetFile.getAbsolutePath(), 0700);
|
Os.chmod(targetFile.getAbsolutePath(), 0700);
|
||||||
@ -89,6 +122,8 @@ public final class BaseFileInstaller {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
connection.disconnect();
|
||||||
|
|
||||||
if (symlinks.isEmpty())
|
if (symlinks.isEmpty())
|
||||||
throw new RuntimeException("No SYMLINKS.txt encountered");
|
throw new RuntimeException("No SYMLINKS.txt encountered");
|
||||||
for (Pair<String, String> symlink : symlinks) {
|
for (Pair<String, String> symlink : symlinks) {
|
||||||
@ -133,6 +168,26 @@ public final class BaseFileInstaller {
|
|||||||
}.start();
|
}.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void installHomeFiles(final Activity activity) {
|
||||||
|
File HOME_PATH = new File(NeoTermPath.HOME_PATH);
|
||||||
|
File ZSH_INSTALLER = new File(HOME_PATH, "install-zsh.sh");
|
||||||
|
|
||||||
|
if (!HOME_PATH.exists()) {
|
||||||
|
HOME_PATH.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ZSH_INSTALLER.exists()) {
|
||||||
|
try {
|
||||||
|
InputStream inputStream = activity.getAssets().open("install-zsh.sh");
|
||||||
|
FileUtils.INSTANCE.writeFile(ZSH_INSTALLER, inputStream);
|
||||||
|
inputStream.close();
|
||||||
|
|
||||||
|
Os.chmod(ZSH_INSTALLER.getAbsolutePath(), 0700);
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static URL determineZipUrl() throws MalformedURLException {
|
private static URL determineZipUrl() throws MalformedURLException {
|
||||||
String archName = determineArchName();
|
String archName = determineArchName();
|
||||||
return new URL(NeoTermPath.SERVER_BOOT_URL + "/" + archName + ".zip");
|
return new URL(NeoTermPath.SERVER_BOOT_URL + "/" + archName + ".zip");
|
||||||
@ -166,4 +221,13 @@ public final class BaseFileInstaller {
|
|||||||
throw new RuntimeException("Unable to delete " + (fileOrDirectory.isDirectory() ? "directory " : "file ") + fileOrDirectory.getAbsolutePath());
|
throw new RuntimeException("Unable to delete " + (fileOrDirectory.isDirectory() ? "directory " : "file ") + fileOrDirectory.getAbsolutePath());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ProgressDialog makeProgressDialog(Context context) {
|
||||||
|
ProgressDialog dialog = new ProgressDialog(context);
|
||||||
|
dialog.setMessage(context.getString(R.string.installer_message));
|
||||||
|
dialog.setIndeterminate(false);
|
||||||
|
dialog.setCancelable(false);
|
||||||
|
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
|
||||||
|
return dialog;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,11 @@ package io.neoterm.preference
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.preference.PreferenceManager
|
import android.preference.PreferenceManager
|
||||||
|
import io.neoterm.R
|
||||||
import io.neoterm.backend.TerminalSession
|
import io.neoterm.backend.TerminalSession
|
||||||
import io.neoterm.customize.NeoTermPath
|
import io.neoterm.customize.NeoTermPath
|
||||||
import io.neoterm.services.NeoTermService
|
import io.neoterm.services.NeoTermService
|
||||||
|
import io.neoterm.utils.FileUtils
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
|
||||||
@ -13,7 +15,7 @@ import java.io.File
|
|||||||
* @author kiva
|
* @author kiva
|
||||||
*/
|
*/
|
||||||
|
|
||||||
object NeoTermPreference {
|
object NeoPreference {
|
||||||
const val KEY_FONT_SIZE = "neoterm_general_font_size"
|
const val KEY_FONT_SIZE = "neoterm_general_font_size"
|
||||||
const val KEY_CURRENT_SESSION = "neoterm_service_current_session"
|
const val KEY_CURRENT_SESSION = "neoterm_service_current_session"
|
||||||
|
|
||||||
@ -23,6 +25,17 @@ object NeoTermPreference {
|
|||||||
fun init(context: Context) {
|
fun init(context: Context) {
|
||||||
this.context = context
|
this.context = context
|
||||||
preference = PreferenceManager.getDefaultSharedPreferences(context)
|
preference = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
|
||||||
|
// load apt source
|
||||||
|
val sourceFile = File(NeoTermPath.SOURCE_FILE)
|
||||||
|
val bytes = FileUtils.readFile(sourceFile)
|
||||||
|
if (bytes != null) {
|
||||||
|
val source = String(FileUtils.readFile(sourceFile)!!).trim().trimEnd()
|
||||||
|
val array = source.split(" ")
|
||||||
|
if (array.size >= 2 && array[0] == "deb") {
|
||||||
|
store(R.string.key_package_source, array[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun cleanup() {
|
fun cleanup() {
|
||||||
@ -68,7 +81,7 @@ object NeoTermPreference {
|
|||||||
|
|
||||||
fun storeCurrentSession(session: TerminalSession) {
|
fun storeCurrentSession(session: TerminalSession) {
|
||||||
preference!!.edit()
|
preference!!.edit()
|
||||||
.putString(NeoTermPreference.KEY_CURRENT_SESSION, session.mHandle)
|
.putString(NeoPreference.KEY_CURRENT_SESSION, session.mHandle)
|
||||||
.apply()
|
.apply()
|
||||||
}
|
}
|
||||||
|
|
@ -15,7 +15,7 @@ import io.neoterm.R
|
|||||||
import io.neoterm.backend.EmulatorDebug
|
import io.neoterm.backend.EmulatorDebug
|
||||||
import io.neoterm.backend.TerminalSession
|
import io.neoterm.backend.TerminalSession
|
||||||
import io.neoterm.customize.NeoTermPath
|
import io.neoterm.customize.NeoTermPath
|
||||||
import io.neoterm.preference.NeoTermPreference
|
import io.neoterm.preference.NeoPreference
|
||||||
import io.neoterm.ui.NeoTermActivity
|
import io.neoterm.ui.NeoTermActivity
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -83,7 +83,7 @@ class NeoTermService : Service() {
|
|||||||
executablePath = if (systemShell)
|
executablePath = if (systemShell)
|
||||||
"/system/bin/sh"
|
"/system/bin/sh"
|
||||||
else
|
else
|
||||||
NeoTermPath.USR_PATH + "/bin/" + NeoTermPreference.loadString(R.string.key_general_shell, "sh")
|
NeoTermPath.USR_PATH + "/bin/" + NeoPreference.loadString(R.string.key_general_shell, "sh")
|
||||||
|
|
||||||
if (!File(executablePath).exists()) {
|
if (!File(executablePath).exists()) {
|
||||||
Toast.makeText(this, getString(R.string.shell_not_found, executablePath), Toast.LENGTH_LONG).show()
|
Toast.makeText(this, getString(R.string.shell_not_found, executablePath), Toast.LENGTH_LONG).show()
|
||||||
@ -96,7 +96,7 @@ class NeoTermService : Service() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val session = TerminalSession(executablePath, cwd, arguments,
|
val session = TerminalSession(executablePath, cwd, arguments,
|
||||||
env ?: NeoTermPreference.buildEnvironment(cwd, systemShell, executablePath),
|
env ?: NeoPreference.buildEnvironment(cwd, systemShell, executablePath),
|
||||||
sessionCallback)
|
sessionCallback)
|
||||||
mTerminalSessions.add(session)
|
mTerminalSessions.add(session)
|
||||||
updateNotification()
|
updateNotification()
|
||||||
|
@ -16,7 +16,6 @@ import android.view.View
|
|||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import android.widget.ImageButton
|
import android.widget.ImageButton
|
||||||
import android.widget.Toast
|
|
||||||
import de.mrapp.android.tabswitcher.*
|
import de.mrapp.android.tabswitcher.*
|
||||||
import io.neoterm.R
|
import io.neoterm.R
|
||||||
import io.neoterm.backend.TerminalSession
|
import io.neoterm.backend.TerminalSession
|
||||||
@ -25,15 +24,20 @@ import io.neoterm.customize.shortcut.ShortcutConfigLoader
|
|||||||
import io.neoterm.customize.shortcut.builtin.BuiltinShortcutKeys
|
import io.neoterm.customize.shortcut.builtin.BuiltinShortcutKeys
|
||||||
import io.neoterm.installer.BaseFileInstaller
|
import io.neoterm.installer.BaseFileInstaller
|
||||||
import io.neoterm.preference.NeoPermission
|
import io.neoterm.preference.NeoPermission
|
||||||
import io.neoterm.preference.NeoTermPreference
|
import io.neoterm.preference.NeoPreference
|
||||||
import io.neoterm.services.NeoTermService
|
import io.neoterm.services.NeoTermService
|
||||||
import io.neoterm.ui.settings.SettingActivity
|
import io.neoterm.ui.settings.SettingActivity
|
||||||
import io.neoterm.utils.NeoTermFullScreen
|
import io.neoterm.utils.FullScreenHelper
|
||||||
|
import io.neoterm.view.eks.StatedControlButton
|
||||||
import io.neoterm.view.tab.*
|
import io.neoterm.view.tab.*
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import org.greenrobot.eventbus.Subscribe
|
||||||
|
import org.greenrobot.eventbus.ThreadMode
|
||||||
|
|
||||||
|
|
||||||
class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreferences.OnSharedPreferenceChangeListener {
|
class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
lateinit var tabSwitcher: TabSwitcher
|
lateinit var tabSwitcher: TabSwitcher
|
||||||
|
lateinit var fullScreenToggleButton: StatedControlButton
|
||||||
var systemShell = true
|
var systemShell = true
|
||||||
var termService: NeoTermService? = null
|
var termService: NeoTermService? = null
|
||||||
var restartRequired = false
|
var restartRequired = false
|
||||||
@ -43,16 +47,17 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
|
|||||||
|
|
||||||
NeoPermission.initAppPermission(this, NeoPermission.REQUEST_APP_PERMISSION)
|
NeoPermission.initAppPermission(this, NeoPermission.REQUEST_APP_PERMISSION)
|
||||||
FontManager.init(this)
|
FontManager.init(this)
|
||||||
NeoTermPreference.init(this)
|
NeoPreference.init(this)
|
||||||
|
|
||||||
if (NeoTermPreference.loadBoolean(R.string.key_ui_fullscreen, false)) {
|
val fullscreen = NeoPreference.loadBoolean(R.string.key_ui_fullscreen, false)
|
||||||
|
|
||||||
|
if (fullscreen) {
|
||||||
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||||
WindowManager.LayoutParams.FLAG_FULLSCREEN)
|
WindowManager.LayoutParams.FLAG_FULLSCREEN)
|
||||||
}
|
}
|
||||||
|
|
||||||
setContentView(R.layout.tab_main)
|
setContentView(R.layout.tab_main)
|
||||||
|
FullScreenHelper.injectActivity(this, peekRecreating())
|
||||||
NeoTermFullScreen.injectActivity(this)
|
|
||||||
.setKeyBoardListener({ isShow, _ ->
|
.setKeyBoardListener({ isShow, _ ->
|
||||||
var tab: TermTab? = null
|
var tab: TermTab? = null
|
||||||
|
|
||||||
@ -62,12 +67,24 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
|
|||||||
|
|
||||||
tab?.viewClient?.extraKeysView?.visibility = if (isShow) View.VISIBLE else View.GONE
|
tab?.viewClient?.extraKeysView?.visibility = if (isShow) View.VISIBLE else View.GONE
|
||||||
|
|
||||||
if (NeoTermPreference.loadBoolean(R.string.key_ui_fullscreen, false)
|
if (NeoPreference.loadBoolean(R.string.key_ui_fullscreen, false)
|
||||||
|| NeoTermPreference.loadBoolean(R.string.key_ui_hide_toolbar, false)) {
|
|| NeoPreference.loadBoolean(R.string.key_ui_hide_toolbar, false)) {
|
||||||
tab?.toolbar?.visibility = if (isShow) View.GONE else View.VISIBLE
|
tab?.toolbar?.visibility = if (isShow) View.GONE else View.VISIBLE
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
fullScreenToggleButton = object : StatedControlButton("FS", fullscreen) {
|
||||||
|
override fun onClick(view: View?) {
|
||||||
|
super.onClick(view)
|
||||||
|
if (tabSwitcher.selectedTab is TermTab) {
|
||||||
|
val tab = tabSwitcher.selectedTab as TermTab
|
||||||
|
tab.hideIme()
|
||||||
|
}
|
||||||
|
NeoPreference.store(R.string.key_ui_fullscreen, super.toggleButton.isChecked)
|
||||||
|
this@NeoTermActivity.recreate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tabSwitcher = findViewById(R.id.tab_switcher) as TabSwitcher
|
tabSwitcher = findViewById(R.id.tab_switcher) as TabSwitcher
|
||||||
tabSwitcher.decorator = TermTabDecorator(this)
|
tabSwitcher.decorator = TermTabDecorator(this)
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(tabSwitcher, createWindowInsetsListener())
|
ViewCompat.setOnApplyWindowInsetsListener(tabSwitcher, createWindowInsetsListener())
|
||||||
@ -92,9 +109,8 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
|
|||||||
super.onResume()
|
super.onResume()
|
||||||
if (restartRequired) {
|
if (restartRequired) {
|
||||||
restartRequired = false
|
restartRequired = false
|
||||||
this.recreate()
|
recreate()
|
||||||
}
|
}
|
||||||
|
|
||||||
PreferenceManager.getDefaultSharedPreferences(this)
|
PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
.registerOnSharedPreferenceChangeListener(this)
|
.registerOnSharedPreferenceChangeListener(this)
|
||||||
tabSwitcher.addListener(object : TabSwitcherListener {
|
tabSwitcher.addListener(object : TabSwitcherListener {
|
||||||
@ -123,7 +139,7 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
|
|||||||
|
|
||||||
override fun onSelectionChanged(tabSwitcher: TabSwitcher, selectedTabIndex: Int, selectedTab: Tab?) {
|
override fun onSelectionChanged(tabSwitcher: TabSwitcher, selectedTabIndex: Int, selectedTab: Tab?) {
|
||||||
if (selectedTab is TermTab && selectedTab.termSession != null) {
|
if (selectedTab is TermTab && selectedTab.termSession != null) {
|
||||||
NeoTermPreference.storeCurrentSession(selectedTab.termSession!!)
|
NeoPreference.storeCurrentSession(selectedTab.termSession!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,6 +159,16 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onStart() {
|
||||||
|
super.onStart()
|
||||||
|
EventBus.getDefault().register(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStop() {
|
||||||
|
super.onStop()
|
||||||
|
EventBus.getDefault().unregister(this)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
PreferenceManager.getDefaultSharedPreferences(this)
|
PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
@ -154,7 +180,7 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
|
|||||||
termService = null
|
termService = null
|
||||||
}
|
}
|
||||||
unbindService(this)
|
unbindService(this)
|
||||||
NeoTermPreference.cleanup()
|
NeoPreference.cleanup()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
|
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
|
||||||
@ -185,6 +211,12 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||||
|
if (key == getString(R.string.key_ui_fullscreen)) {
|
||||||
|
restartRequired = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onServiceDisconnected(name: ComponentName?) {
|
override fun onServiceDisconnected(name: ComponentName?) {
|
||||||
if (termService != null) {
|
if (termService != null) {
|
||||||
finish()
|
finish()
|
||||||
@ -227,14 +259,35 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isRecreating()) {
|
||||||
BaseFileInstaller.installBaseFiles(this, resultListener)
|
BaseFileInstaller.installBaseFiles(this, resultListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
|
||||||
if (key == getString(R.string.key_ui_fullscreen)) {
|
|
||||||
Toast.makeText(this, R.string.fullscreen_mode_changed, Toast.LENGTH_SHORT).show()
|
|
||||||
restartRequired = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(outState: Bundle?) {
|
||||||
|
super.onSaveInstanceState(outState)
|
||||||
|
outState?.putBoolean("system_shell", systemShell)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
|
||||||
|
super.onRestoreInstanceState(savedInstanceState)
|
||||||
|
systemShell = savedInstanceState?.getBoolean("system_shell", true) ?: true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun recreate() {
|
||||||
|
NeoPreference.store("recreate", true)
|
||||||
|
super.recreate()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isRecreating(): Boolean {
|
||||||
|
val result = peekRecreating()
|
||||||
|
NeoPreference.store("recreate", !result)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun peekRecreating(): Boolean {
|
||||||
|
val result = NeoPreference.loadBoolean("recreate", false)
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addNewSession(session: TerminalSession?) {
|
private fun addNewSession(session: TerminalSession?) {
|
||||||
@ -299,7 +352,7 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getStoredCurrentSessionOrLast(): TerminalSession? {
|
private fun getStoredCurrentSessionOrLast(): TerminalSession? {
|
||||||
val stored = NeoTermPreference.getCurrentSession(termService)
|
val stored = NeoPreference.getCurrentSession(termService)
|
||||||
if (stored != null) return stored
|
if (stored != null) return stored
|
||||||
val numberOfSessions = termService!!.sessions.size
|
val numberOfSessions = termService!!.sessions.size
|
||||||
if (numberOfSessions == 0) return null
|
if (numberOfSessions == 0) return null
|
||||||
@ -340,24 +393,6 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
|
|||||||
|
|
||||||
private fun createTab(tabTitle: String?): Tab {
|
private fun createTab(tabTitle: String?): Tab {
|
||||||
val tab = TermTab(tabTitle ?: "NeoTerm")
|
val tab = TermTab(tabTitle ?: "NeoTerm")
|
||||||
tab.closeTabProvider = object : CloseTabProvider {
|
|
||||||
override fun closeTab(tab: Tab) {
|
|
||||||
tabSwitcher.showSwitcher()
|
|
||||||
tabSwitcher.removeTab(tab)
|
|
||||||
|
|
||||||
if (tabSwitcher.count > 1) {
|
|
||||||
var index = tabSwitcher.indexOf(tab)
|
|
||||||
if (NeoTermPreference.loadBoolean(R.string.key_ui_next_tab_anim, false)) {
|
|
||||||
// 关闭当前窗口后,向下一个窗口切换
|
|
||||||
if (--index < 0) index = tabSwitcher.count - 1
|
|
||||||
} else {
|
|
||||||
// 关闭当前窗口后,向上一个窗口切换
|
|
||||||
if (++index >= tabSwitcher.count) index = 0
|
|
||||||
}
|
|
||||||
switchToSession(tabSwitcher.getTab(index))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tab.isCloseable = true
|
tab.isCloseable = true
|
||||||
tab.parameters = Bundle()
|
tab.parameters = Bundle()
|
||||||
tab.setBackgroundColor(ContextCompat.getColor(this, R.color.tab_background_color))
|
tab.setBackgroundColor(ContextCompat.getColor(this, R.color.tab_background_color))
|
||||||
@ -408,4 +443,24 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
|
|||||||
insets
|
insets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
|
fun onTabCloseEvent(tabCloseEvent: TabCloseEvent) {
|
||||||
|
val tab = tabCloseEvent.termTab
|
||||||
|
tabSwitcher.showSwitcher()
|
||||||
|
tabSwitcher.removeTab(tab)
|
||||||
|
|
||||||
|
if (tabSwitcher.count > 1) {
|
||||||
|
var index = tabSwitcher.indexOf(tab)
|
||||||
|
if (NeoPreference.loadBoolean(R.string.key_ui_next_tab_anim, false)) {
|
||||||
|
// 关闭当前窗口后,向下一个窗口切换
|
||||||
|
if (--index < 0) index = tabSwitcher.count - 1
|
||||||
|
} else {
|
||||||
|
// 关闭当前窗口后,向上一个窗口切换
|
||||||
|
if (++index >= tabSwitcher.count) index = 0
|
||||||
|
}
|
||||||
|
switchToSession(tabSwitcher.getTab(index))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
package io.neoterm.ui.settings
|
package io.neoterm.ui.settings
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.support.v7.app.AlertDialog
|
||||||
import android.support.v7.app.AppCompatPreferenceActivity
|
import android.support.v7.app.AppCompatPreferenceActivity
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import io.neoterm.R
|
import io.neoterm.R
|
||||||
|
import io.neoterm.customize.NeoTermPath
|
||||||
|
import io.neoterm.preference.NeoPreference
|
||||||
|
import io.neoterm.utils.FileUtils
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author kiva
|
* @author kiva
|
||||||
@ -15,6 +20,33 @@ class PackageSettingsActivity : AppCompatPreferenceActivity() {
|
|||||||
supportActionBar.title = getString(R.string.package_settings)
|
supportActionBar.title = getString(R.string.package_settings)
|
||||||
supportActionBar.setDisplayHomeAsUpEnabled(true)
|
supportActionBar.setDisplayHomeAsUpEnabled(true)
|
||||||
addPreferencesFromResource(R.xml.settings_package)
|
addPreferencesFromResource(R.xml.settings_package)
|
||||||
|
|
||||||
|
val preference = findPreference(getString(R.string.key_package_source))
|
||||||
|
preference.summary = NeoPreference.loadString(R.string.key_package_source, NeoTermPath.DEFAULT_SOURCE)
|
||||||
|
|
||||||
|
preference.setOnPreferenceChangeListener { preference, newValue ->
|
||||||
|
val newSource = newValue as String
|
||||||
|
preference.summary = newSource
|
||||||
|
if (newSource.isNotEmpty()) {
|
||||||
|
val sourceFile = File(NeoTermPath.SOURCE_FILE)
|
||||||
|
FileUtils.writeFile(sourceFile, generateSourceFile(newSource).toByteArray())
|
||||||
|
|
||||||
|
AlertDialog.Builder(this@PackageSettingsActivity)
|
||||||
|
.setMessage(R.string.source_changed)
|
||||||
|
.setPositiveButton(android.R.string.yes, null)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
return@setOnPreferenceChangeListener true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateSourceFile(source: String): String {
|
||||||
|
return StringBuilder().append("# Generated by NeoTerm-Preference\n")
|
||||||
|
.append("deb ")
|
||||||
|
.append(source)
|
||||||
|
.append(" stable main")
|
||||||
|
.append("\n")
|
||||||
|
.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBuildHeaders(target: MutableList<Header>?) {
|
override fun onBuildHeaders(target: MutableList<Header>?) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package io.neoterm.ui.settings
|
package io.neoterm.ui.settings
|
||||||
|
|
||||||
|
import android.app.AlertDialog
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.support.v7.app.AppCompatPreferenceActivity
|
import android.support.v7.app.AppCompatPreferenceActivity
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
@ -16,7 +17,13 @@ class UISettingsActivity : AppCompatPreferenceActivity() {
|
|||||||
supportActionBar.setDisplayHomeAsUpEnabled(true)
|
supportActionBar.setDisplayHomeAsUpEnabled(true)
|
||||||
addPreferencesFromResource(R.xml.settings_ui)
|
addPreferencesFromResource(R.xml.settings_ui)
|
||||||
findPreference(getString(R.string.key_ui_suggestions))
|
findPreference(getString(R.string.key_ui_suggestions))
|
||||||
.setOnPreferenceChangeListener({preference, newValue ->
|
.setOnPreferenceChangeListener({_, newValue ->
|
||||||
|
if (newValue as Boolean) {
|
||||||
|
AlertDialog.Builder(this@UISettingsActivity)
|
||||||
|
.setMessage(R.string.installer_install_zsh_manually)
|
||||||
|
.setPositiveButton(android.R.string.yes, null)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
return@setOnPreferenceChangeListener true
|
return@setOnPreferenceChangeListener true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,31 +1,37 @@
|
|||||||
package io.neoterm.utils
|
package io.neoterm.utils
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.FileInputStream
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.io.OutputStream
|
import java.io.InputStream
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author kiva
|
* @author kiva
|
||||||
*/
|
*/
|
||||||
object FileUtils {
|
object FileUtils {
|
||||||
fun writeFile(path: File, bytes: ByteArray): Boolean {
|
fun writeFile(path: File, bytes: ByteArray): Boolean {
|
||||||
var output: OutputStream? = null
|
return FileOutputStream(path).use {
|
||||||
var success = true
|
it.write(bytes)
|
||||||
try {
|
it.flush()
|
||||||
output = FileOutputStream(path)
|
true
|
||||||
output.write(bytes)
|
|
||||||
output.flush()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
success = false
|
|
||||||
} finally {
|
|
||||||
if (output != null) {
|
|
||||||
try {
|
|
||||||
output.close()
|
|
||||||
} catch (ignore: Exception) {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun writeFile(path: File, inputStream: InputStream): Boolean {
|
||||||
|
val bytes = ByteArray(inputStream.available())
|
||||||
|
inputStream.read(bytes)
|
||||||
|
return writeFile(path, bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun readFile(path: File): ByteArray? {
|
||||||
|
if (!path.canRead()) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return FileInputStream(path).use {
|
||||||
|
val bytes = ByteArray(it.available())
|
||||||
|
it.read(bytes)
|
||||||
|
bytes
|
||||||
}
|
}
|
||||||
return success
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,11 +9,10 @@ import android.widget.FrameLayout;
|
|||||||
/**
|
/**
|
||||||
* Helper class to "adjustResize" Activity when we are in full screen mode and check IME status.
|
* Helper class to "adjustResize" Activity when we are in full screen mode and check IME status.
|
||||||
* Android Bug 5497: https://code.google.com/p/android/issues/detail?id=5497
|
* Android Bug 5497: https://code.google.com/p/android/issues/detail?id=5497
|
||||||
* author @kiva
|
|
||||||
*/
|
*/
|
||||||
public class NeoTermFullScreen {
|
public class FullScreenHelper {
|
||||||
public static NeoTermFullScreen injectActivity(Activity activity) {
|
public static FullScreenHelper injectActivity(Activity activity, boolean isRecreating) {
|
||||||
return new NeoTermFullScreen(activity);
|
return new FullScreenHelper(activity, isRecreating);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface KeyBoardListener {
|
public interface KeyBoardListener {
|
||||||
@ -33,12 +32,14 @@ public class NeoTermFullScreen {
|
|||||||
private int mOriginHeight;
|
private int mOriginHeight;
|
||||||
private int mPreHeight;
|
private int mPreHeight;
|
||||||
private KeyBoardListener mKeyBoardListener;
|
private KeyBoardListener mKeyBoardListener;
|
||||||
|
private boolean shouldSkipFirstTime;
|
||||||
|
|
||||||
public void setKeyBoardListener(KeyBoardListener mKeyBoardListener) {
|
public void setKeyBoardListener(KeyBoardListener mKeyBoardListener) {
|
||||||
this.mKeyBoardListener = mKeyBoardListener;
|
this.mKeyBoardListener = mKeyBoardListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
private NeoTermFullScreen(Activity activity) {
|
private FullScreenHelper(Activity activity, boolean isRecreating) {
|
||||||
|
this.shouldSkipFirstTime = isRecreating;
|
||||||
FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
|
FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
|
||||||
mChildOfContent = content.getChildAt(0);
|
mChildOfContent = content.getChildAt(0);
|
||||||
mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||||
@ -52,10 +53,12 @@ public class NeoTermFullScreen {
|
|||||||
|
|
||||||
private void monitorImeStatus() {
|
private void monitorImeStatus() {
|
||||||
int currHeight = mChildOfContent.getHeight();
|
int currHeight = mChildOfContent.getHeight();
|
||||||
if (currHeight == 0) {
|
if (currHeight == 0 && shouldSkipFirstTime) {
|
||||||
// First time
|
// First time
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shouldSkipFirstTime = false;
|
||||||
boolean hasChange = false;
|
boolean hasChange = false;
|
||||||
if (mPreHeight == 0) {
|
if (mPreHeight == 0) {
|
||||||
mPreHeight = currHeight;
|
mPreHeight = currHeight;
|
@ -50,7 +50,7 @@ public final class ExtraKeysView extends LinearLayout {
|
|||||||
"define | false\n";
|
"define | false\n";
|
||||||
|
|
||||||
public static final int NORMAL_TEXT_COLOR = 0xFFFFFFFF;
|
public static final int NORMAL_TEXT_COLOR = 0xFFFFFFFF;
|
||||||
|
public static final int SELECTED_TEXT_COLOR = 0xFF80DEEA;
|
||||||
|
|
||||||
private List<ExtraButton> builtinExtraKeys;
|
private List<ExtraButton> builtinExtraKeys;
|
||||||
private List<ExtraButton> userDefinedExtraKeys;
|
private List<ExtraButton> userDefinedExtraKeys;
|
||||||
@ -85,7 +85,6 @@ public final class ExtraKeysView extends LinearLayout {
|
|||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean readControlButton() {
|
public boolean readControlButton() {
|
||||||
return CTRL.readState();
|
return CTRL.readState();
|
||||||
}
|
}
|
||||||
@ -94,11 +93,21 @@ public final class ExtraKeysView extends LinearLayout {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addExternalButton(ExtraButton button) {
|
public void addUserDefinedButton(ExtraButton button) {
|
||||||
userDefinedExtraKeys.add(button);
|
addButton(userDefinedExtraKeys, button);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearExternalButton() {
|
public void addBuiltinButton(ExtraButton button) {
|
||||||
|
addButton(builtinExtraKeys, button);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addButton(List<ExtraButton> buttons, ExtraButton button) {
|
||||||
|
if (!buttons.contains(button)) {
|
||||||
|
buttons.add(button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearUserDefinedButton() {
|
||||||
userDefinedExtraKeys.clear();
|
userDefinedExtraKeys.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +118,7 @@ public final class ExtraKeysView extends LinearLayout {
|
|||||||
generateDefaultFile(defaultFile);
|
generateDefaultFile(defaultFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
clearExternalButton();
|
clearUserDefinedButton();
|
||||||
try {
|
try {
|
||||||
ShortcutConfigParser parser = new ShortcutConfigParser();
|
ShortcutConfigParser parser = new ShortcutConfigParser();
|
||||||
parser.setInput(defaultFile);
|
parser.setInput(defaultFile);
|
||||||
@ -153,6 +162,10 @@ public final class ExtraKeysView extends LinearLayout {
|
|||||||
StatedControlButton btn = ((StatedControlButton) extraButton);
|
StatedControlButton btn = ((StatedControlButton) extraButton);
|
||||||
button = btn.toggleButton = new ToggleButton(getContext(), null, android.R.attr.buttonBarButtonStyle);
|
button = btn.toggleButton = new ToggleButton(getContext(), null, android.R.attr.buttonBarButtonStyle);
|
||||||
button.setClickable(true);
|
button.setClickable(true);
|
||||||
|
if (btn.initState) {
|
||||||
|
btn.toggleButton.setChecked(true);
|
||||||
|
btn.toggleButton.setTextColor(SELECTED_TEXT_COLOR);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
button = new Button(getContext(), null, android.R.attr.buttonBarButtonStyle);
|
button = new Button(getContext(), null, android.R.attr.buttonBarButtonStyle);
|
||||||
}
|
}
|
||||||
|
@ -11,15 +11,25 @@ import io.neoterm.view.ExtraKeysView;
|
|||||||
|
|
||||||
public class StatedControlButton extends ControlButton {
|
public class StatedControlButton extends ControlButton {
|
||||||
public ToggleButton toggleButton;
|
public ToggleButton toggleButton;
|
||||||
|
public boolean initState;
|
||||||
|
|
||||||
|
public StatedControlButton(String text, boolean initState) {
|
||||||
|
super(text);
|
||||||
|
this.initState = initState;
|
||||||
|
}
|
||||||
|
|
||||||
public StatedControlButton(String text) {
|
public StatedControlButton(String text) {
|
||||||
super(text);
|
this(text, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
toggleButton.setChecked(toggleButton.isChecked());
|
setStatus(toggleButton.isChecked());
|
||||||
toggleButton.setTextColor(toggleButton.isChecked() ? 0xFF80DEEA : ExtraKeysView.NORMAL_TEXT_COLOR);
|
}
|
||||||
|
|
||||||
|
public void setStatus(boolean status) {
|
||||||
|
toggleButton.setChecked(status);
|
||||||
|
toggleButton.setTextColor(status ? ExtraKeysView.SELECTED_TEXT_COLOR : ExtraKeysView.NORMAL_TEXT_COLOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean readState() {
|
public boolean readState() {
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
package io.neoterm.view.tab
|
|
||||||
|
|
||||||
import de.mrapp.android.tabswitcher.Tab
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author kiva
|
|
||||||
*/
|
|
||||||
interface CloseTabProvider {
|
|
||||||
fun closeTab(tab: Tab)
|
|
||||||
}
|
|
7
app/src/main/java/io/neoterm/view/tab/TabCloseEvent.kt
Normal file
7
app/src/main/java/io/neoterm/view/tab/TabCloseEvent.kt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package io.neoterm.view.tab
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author kiva
|
||||||
|
*/
|
||||||
|
|
||||||
|
class TabCloseEvent(var termTab: TermTab)
|
@ -7,8 +7,7 @@ import android.media.SoundPool
|
|||||||
import android.os.Vibrator
|
import android.os.Vibrator
|
||||||
import io.neoterm.R
|
import io.neoterm.R
|
||||||
import io.neoterm.backend.TerminalSession
|
import io.neoterm.backend.TerminalSession
|
||||||
import io.neoterm.preference.NeoTermPreference
|
import io.neoterm.preference.NeoPreference
|
||||||
import io.neoterm.view.ExtraKeysView
|
|
||||||
import io.neoterm.view.TerminalView
|
import io.neoterm.view.TerminalView
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,7 +46,7 @@ class TermSessionChangedCallback : TerminalSession.SessionChangedCallback {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NeoTermPreference.loadBoolean(R.string.key_general_bell, false)) {
|
if (NeoPreference.loadBoolean(R.string.key_general_bell, false)) {
|
||||||
if (soundPool == null) {
|
if (soundPool == null) {
|
||||||
soundPool = SoundPool.Builder().setMaxStreams(1).build()
|
soundPool = SoundPool.Builder().setMaxStreams(1).build()
|
||||||
bellId = soundPool!!.load(termView!!.context, R.raw.bell, 1)
|
bellId = soundPool!!.load(termView!!.context, R.raw.bell, 1)
|
||||||
@ -55,7 +54,7 @@ class TermSessionChangedCallback : TerminalSession.SessionChangedCallback {
|
|||||||
soundPool?.play(bellId, 1f, 1f, 0, 0, 1f)
|
soundPool?.play(bellId, 1f, 1f, 0, 0, 1f)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NeoTermPreference.loadBoolean(R.string.key_general_vibrate, false)) {
|
if (NeoPreference.loadBoolean(R.string.key_general_vibrate, false)) {
|
||||||
val vibrator = termView!!.context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
|
val vibrator = termView!!.context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
|
||||||
vibrator.vibrate(100)
|
vibrator.vibrate(100)
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
package io.neoterm.view.tab
|
package io.neoterm.view.tab
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.support.v7.widget.Toolbar
|
import android.support.v7.widget.Toolbar
|
||||||
|
import android.view.inputmethod.InputMethodManager
|
||||||
import de.mrapp.android.tabswitcher.Tab
|
import de.mrapp.android.tabswitcher.Tab
|
||||||
import io.neoterm.R
|
import io.neoterm.R
|
||||||
import io.neoterm.backend.TerminalSession
|
import io.neoterm.backend.TerminalSession
|
||||||
import io.neoterm.customize.color.NeoTermColorScheme
|
import io.neoterm.customize.color.NeoTermColorScheme
|
||||||
import io.neoterm.preference.NeoTermPreference
|
import io.neoterm.preference.NeoPreference
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author kiva
|
* @author kiva
|
||||||
@ -18,8 +21,6 @@ class TermTab(title: CharSequence) : Tab(title) {
|
|||||||
var viewClient: TermViewClient? = null
|
var viewClient: TermViewClient? = null
|
||||||
var toolbar: Toolbar? = null
|
var toolbar: Toolbar? = null
|
||||||
|
|
||||||
var closeTabProvider: CloseTabProvider? = null
|
|
||||||
|
|
||||||
fun changeColorScheme(colorScheme: NeoTermColorScheme?) {
|
fun changeColorScheme(colorScheme: NeoTermColorScheme?) {
|
||||||
colorScheme?.apply()
|
colorScheme?.apply()
|
||||||
viewClient?.extraKeysView?.setBackgroundColor(Color.parseColor(colorScheme?.background))
|
viewClient?.extraKeysView?.setBackgroundColor(Color.parseColor(colorScheme?.background))
|
||||||
@ -31,7 +32,6 @@ class TermTab(title: CharSequence) : Tab(title) {
|
|||||||
viewClient?.extraKeysView = null
|
viewClient?.extraKeysView = null
|
||||||
sessionCallback?.termView = null
|
sessionCallback?.termView = null
|
||||||
sessionCallback?.termTab = null
|
sessionCallback?.termTab = null
|
||||||
closeTabProvider = null
|
|
||||||
toolbar = null
|
toolbar = null
|
||||||
termSession = null
|
termSession = null
|
||||||
}
|
}
|
||||||
@ -39,7 +39,7 @@ class TermTab(title: CharSequence) : Tab(title) {
|
|||||||
fun updateTitle(title: String) {
|
fun updateTitle(title: String) {
|
||||||
this.title = title
|
this.title = title
|
||||||
toolbar?.title = title
|
toolbar?.title = title
|
||||||
if (NeoTermPreference.loadBoolean(R.string.key_ui_suggestions, true)) {
|
if (NeoPreference.loadBoolean(R.string.key_ui_suggestions, true)) {
|
||||||
viewClient?.updateSuggestions(title)
|
viewClient?.updateSuggestions(title)
|
||||||
} else {
|
} else {
|
||||||
viewClient?.removeSuggestions()
|
viewClient?.removeSuggestions()
|
||||||
@ -51,6 +51,17 @@ class TermTab(title: CharSequence) : Tab(title) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun requiredCloseTab() {
|
fun requiredCloseTab() {
|
||||||
closeTabProvider?.closeTab(this)
|
hideIme()
|
||||||
|
EventBus.getDefault().post(TabCloseEvent(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hideIme() {
|
||||||
|
val terminalView = viewClient?.termView
|
||||||
|
if (terminalView != null) {
|
||||||
|
val imm = terminalView.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||||
|
if (imm.isActive) {
|
||||||
|
imm.hideSoftInputFromWindow(terminalView.windowToken, InputMethodManager.HIDE_NOT_ALWAYS)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import de.mrapp.android.tabswitcher.Tab
|
|||||||
import de.mrapp.android.tabswitcher.TabSwitcher
|
import de.mrapp.android.tabswitcher.TabSwitcher
|
||||||
import de.mrapp.android.tabswitcher.TabSwitcherDecorator
|
import de.mrapp.android.tabswitcher.TabSwitcherDecorator
|
||||||
import io.neoterm.R
|
import io.neoterm.R
|
||||||
import io.neoterm.preference.NeoTermPreference
|
import io.neoterm.preference.NeoPreference
|
||||||
import io.neoterm.ui.NeoTermActivity
|
import io.neoterm.ui.NeoTermActivity
|
||||||
import io.neoterm.view.ExtraKeysView
|
import io.neoterm.view.ExtraKeysView
|
||||||
import io.neoterm.view.TerminalView
|
import io.neoterm.view.TerminalView
|
||||||
@ -24,8 +24,12 @@ class TermTabDecorator(val context: NeoTermActivity) : TabSwitcherDecorator() {
|
|||||||
override fun onInflateView(inflater: LayoutInflater, parent: ViewGroup?, viewType: Int): View {
|
override fun onInflateView(inflater: LayoutInflater, parent: ViewGroup?, viewType: Int): View {
|
||||||
val view = inflater.inflate(R.layout.term, parent, false)
|
val view = inflater.inflate(R.layout.term, parent, false)
|
||||||
val toolbar = view.findViewById(R.id.terminal_toolbar) as Toolbar
|
val toolbar = view.findViewById(R.id.terminal_toolbar) as Toolbar
|
||||||
toolbar.inflateMenu(R.menu.tab_switcher)
|
val extraKeysView = view.findViewById(R.id.extra_keys) as ExtraKeysView
|
||||||
|
|
||||||
|
extraKeysView.addBuiltinButton(context.fullScreenToggleButton)
|
||||||
|
extraKeysView.updateButtons()
|
||||||
|
|
||||||
|
toolbar.inflateMenu(R.menu.tab_switcher)
|
||||||
toolbar.setOnMenuItemClickListener(context.createToolbarMenuListener())
|
toolbar.setOnMenuItemClickListener(context.createToolbarMenuListener())
|
||||||
val menu = toolbar.menu
|
val menu = toolbar.menu
|
||||||
TabSwitcher.setupWithMenu(context.tabSwitcher, menu, {
|
TabSwitcher.setupWithMenu(context.tabSwitcher, menu, {
|
||||||
@ -64,8 +68,9 @@ class TermTabDecorator(val context: NeoTermActivity) : TabSwitcherDecorator() {
|
|||||||
if (view == null) {
|
if (view == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
view.textSize = NeoTermPreference.loadInt(NeoTermPreference.KEY_FONT_SIZE, 30)
|
view.textSize = NeoPreference.loadInt(NeoPreference.KEY_FONT_SIZE, 30)
|
||||||
view.setTypeface(Typeface.MONOSPACE)
|
view.setTypeface(Typeface.MONOSPACE)
|
||||||
|
context.fullScreenToggleButton.setStatus(NeoPreference.loadBoolean(R.string.key_ui_fullscreen, false))
|
||||||
|
|
||||||
if (tab is TermTab) {
|
if (tab is TermTab) {
|
||||||
val termTab = tab
|
val termTab = tab
|
||||||
|
@ -8,7 +8,7 @@ import android.view.inputmethod.InputMethodManager
|
|||||||
import io.neoterm.R
|
import io.neoterm.R
|
||||||
import io.neoterm.backend.TerminalSession
|
import io.neoterm.backend.TerminalSession
|
||||||
import io.neoterm.customize.shortcut.ShortcutKeysManager
|
import io.neoterm.customize.shortcut.ShortcutKeysManager
|
||||||
import io.neoterm.preference.NeoTermPreference
|
import io.neoterm.preference.NeoPreference
|
||||||
import io.neoterm.view.ExtraKeysView
|
import io.neoterm.view.ExtraKeysView
|
||||||
import io.neoterm.view.TerminalView
|
import io.neoterm.view.TerminalView
|
||||||
import io.neoterm.view.TerminalViewClient
|
import io.neoterm.view.TerminalViewClient
|
||||||
@ -33,7 +33,7 @@ class TermViewClient(val context: Context) : TerminalViewClient {
|
|||||||
val changedSize = (if (increase) 1 else -1) * 2
|
val changedSize = (if (increase) 1 else -1) * 2
|
||||||
val fontSize = termView!!.textSize + changedSize
|
val fontSize = termView!!.textSize + changedSize
|
||||||
termView!!.textSize = fontSize
|
termView!!.textSize = fontSize
|
||||||
NeoTermPreference.store(NeoTermPreference.KEY_FONT_SIZE, fontSize)
|
NeoPreference.store(NeoPreference.KEY_FONT_SIZE, fontSize)
|
||||||
return 1.0f
|
return 1.0f
|
||||||
}
|
}
|
||||||
return scale
|
return scale
|
||||||
@ -45,7 +45,7 @@ class TermViewClient(val context: Context) : TerminalViewClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun shouldBackButtonBeMappedToEscape(): Boolean {
|
override fun shouldBackButtonBeMappedToEscape(): Boolean {
|
||||||
return NeoTermPreference.loadBoolean(R.string.key_generaL_backspace_map_to_esc, false)
|
return NeoPreference.loadBoolean(R.string.key_generaL_backspace_map_to_esc, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun copyModeChanged(copyMode: Boolean) {
|
override fun copyModeChanged(copyMode: Boolean) {
|
||||||
@ -118,7 +118,7 @@ class TermViewClient(val context: Context) : TerminalViewClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun removeSuggestions() {
|
fun removeSuggestions() {
|
||||||
extraKeysView?.clearExternalButton()
|
extraKeysView?.clearUserDefinedButton()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -20,7 +20,8 @@
|
|||||||
android:layout_height="@dimen/eks_height_two_line"
|
android:layout_height="@dimen/eks_height_two_line"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
android:background="@color/terminal_background"
|
android:background="@color/terminal_background"
|
||||||
android:orientation="horizontal" />
|
android:orientation="horizontal"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
<io.neoterm.view.TerminalView
|
<io.neoterm.view.TerminalView
|
||||||
android:id="@+id/terminal_view"
|
android:id="@+id/terminal_view"
|
||||||
|
@ -33,9 +33,11 @@
|
|||||||
<string name="ui_settings">界面设置</string>
|
<string name="ui_settings">界面设置</string>
|
||||||
<string name="shell_not_found">Shell %s 未找到, 请先安装.</string>
|
<string name="shell_not_found">Shell %s 未找到, 请先安装.</string>
|
||||||
<string name="installer_message">正在安装</string>
|
<string name="installer_message">正在安装</string>
|
||||||
|
<string name="installer_install_zsh_manually">你可以通过执行以下命令来配置 zsh 和快捷提示 ~/install-zsh.sh</string>
|
||||||
<string name="fullscreen_mode_changed">全屏模式已改变,请重启 NeoTerm</string>
|
<string name="fullscreen_mode_changed">全屏模式已改变,请重启 NeoTerm</string>
|
||||||
<string name="permission_denied">NeoTerm 无法取得必需的权限,正在退出</string>
|
<string name="permission_denied">NeoTerm 无法取得必需的权限,正在退出</string>
|
||||||
<string name="error">还有这种操作?</string>
|
<string name="error">还有这种操作?</string>
|
||||||
<string name="use_system_shell">使用系统Shell</string>
|
<string name="use_system_shell">使用系统Shell</string>
|
||||||
<string name="retry">重试</string>
|
<string name="retry">重试</string>
|
||||||
|
<string name="source_changed">APT 源已更改,你可能需要执行 apt update 来更新</string>
|
||||||
</resources>
|
</resources>
|
@ -14,6 +14,7 @@
|
|||||||
<string name="package_settings">Package Settings</string>
|
<string name="package_settings">Package Settings</string>
|
||||||
|
|
||||||
<string name="installer_message">Installing</string>
|
<string name="installer_message">Installing</string>
|
||||||
|
<string name="installer_install_zsh_manually">You may install zsh and setup suggestions by executing: ~/install-zsh.sh</string>
|
||||||
|
|
||||||
<string name="pref_general_bell">Bell</string>
|
<string name="pref_general_bell">Bell</string>
|
||||||
<string name="pref_general_bell_desc">Bell when receiving \'\\a\'</string>
|
<string name="pref_general_bell_desc">Bell when receiving \'\\a\'</string>
|
||||||
@ -42,6 +43,7 @@
|
|||||||
<string name="error">Error</string>
|
<string name="error">Error</string>
|
||||||
<string name="use_system_shell">System Shell</string>
|
<string name="use_system_shell">System Shell</string>
|
||||||
<string name="retry">Retry</string>
|
<string name="retry">Retry</string>
|
||||||
|
<string name="source_changed">APT source changed, you may get it updated by executing: apt update</string>
|
||||||
|
|
||||||
<string-array name="pref_ui_color_scheme_entries" translatable="false">
|
<string-array name="pref_ui_color_scheme_entries" translatable="false">
|
||||||
<item>Default</item>
|
<item>Default</item>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:enabled="false"
|
android:defaultValue="http://mirror.neoterm.studio"
|
||||||
android:key="@string/key_package_source"
|
android:key="@string/key_package_source"
|
||||||
android:title="@string/pref_package_source" />
|
android:title="@string/pref_package_source" />
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
Reference in New Issue
Block a user