Refactor: Rename NeoService to NeoComponent

This commit is contained in:
zt515
2017-08-14 00:24:01 +08:00
parent 7f61a40e72
commit 6e48d7d574
55 changed files with 781 additions and 193 deletions

View File

@ -140,10 +140,6 @@
<meta-data
android:name="com.sec.android.support.multiwindow"
android:value="true" />
<meta-data
android:name="android.app.shortcuts"
android:resource="@xml/shortcuts" />
</application>
</manifest>

View File

@ -5,8 +5,7 @@ import android.app.Application
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.view.WindowManager
import io.neoterm.customize.NeoInitializer
import io.neoterm.component.NeoInitializer
import io.neoterm.frontend.preference.NeoPreference
import io.neoterm.utils.CrashHandler

View File

@ -0,0 +1,28 @@
package io.neoterm.component
import android.content.Context
import io.neoterm.component.color.ColorSchemeComponent
import io.neoterm.component.completion.CompletionComponent
import io.neoterm.component.config.ConfigureComponent
import io.neoterm.component.eks.ExtraKeysComponent
import io.neoterm.component.font.FontComponent
import io.neoterm.component.pm.NeoPackageComponent
import io.neoterm.component.script.UserScriptComponent
import io.neoterm.frontend.logging.NLog
import io.neoterm.frontend.component.ComponentManager
/**
* @author kiva
*/
object NeoInitializer {
fun initialize(context: Context) {
NLog.init(context)
ComponentManager.registerComponent(ConfigureComponent::class.java)
ComponentManager.registerComponent(ColorSchemeComponent::class.java)
ComponentManager.registerComponent(FontComponent::class.java)
ComponentManager.registerComponent(UserScriptComponent::class.java)
ComponentManager.registerComponent(ExtraKeysComponent::class.java)
ComponentManager.registerComponent(CompletionComponent::class.java)
ComponentManager.registerComponent(NeoPackageComponent::class.java)
}
}

View File

@ -0,0 +1,117 @@
package io.neoterm.component.color
import android.content.Context
import io.neoterm.App
import io.neoterm.R
import io.neoterm.frontend.preference.NeoPreference
import io.neoterm.frontend.preference.NeoTermPath
import io.neoterm.frontend.component.NeoComponent
import io.neoterm.utils.AssetsUtils
import io.neoterm.view.TerminalView
import io.neoterm.view.eks.ExtraKeysView
import java.io.File
/**
* @author kiva
*/
class ColorSchemeComponent : NeoComponent {
override fun onServiceObtained() {
checkForFiles()
}
override fun onServiceInit() {
checkForFiles()
}
override fun onServiceDestroy() {
}
private lateinit var DEFAULT_COLOR: NeoColorScheme
private lateinit var colors: MutableMap<String, NeoColorScheme>
private fun extractDefaultColor(context: Context): Boolean {
try {
AssetsUtils.extractAssetsDir(context, "colors", NeoTermPath.COLORS_PATH)
return true
} catch (e: Exception) {
return false
}
}
fun refreshColorList(): Boolean {
colors.clear()
val colorDir = File(NeoTermPath.COLORS_PATH)
for (file in colorDir.listFiles({ pathname ->
pathname.name.endsWith(".color") || pathname.name.endsWith(".nl")
})) {
val color = NeoColorScheme()
if (color.loadConfigure(file)) {
colors.put(color.colorName, color)
}
}
if (colors.containsKey(DefaultColorScheme.colorName)) {
DEFAULT_COLOR = colors[DefaultColorScheme.colorName]!!
return true
}
return false
}
fun applyColorScheme(view: TerminalView?, extraKeysView: ExtraKeysView?, colorScheme: NeoColorScheme?) {
if (view != null && colorScheme != null) {
colorScheme.applyColors(view, extraKeysView)
}
}
private fun checkForFiles() {
File(NeoTermPath.COLORS_PATH).mkdirs()
colors = mutableMapOf()
val defaultColorFile = colorFile(DefaultColorScheme.colorName)
if (!defaultColorFile.exists()) {
if (!extractDefaultColor(App.get())) {
DEFAULT_COLOR = DefaultColorScheme
colors[DEFAULT_COLOR.colorName] = DEFAULT_COLOR
return
}
}
if (!refreshColorList()) {
DEFAULT_COLOR = DefaultColorScheme
colors[DEFAULT_COLOR.colorName] = DEFAULT_COLOR
}
}
fun getCurrentColorScheme(): NeoColorScheme {
return colors[getCurrentColorName()]!!
}
fun getCurrentColorName(): String {
var currentColorName = NeoPreference.loadString(R.string.key_customization_color_scheme, DefaultColorScheme.colorName)
if (!colors.containsKey(currentColorName)) {
currentColorName = DefaultColorScheme.colorName
NeoPreference.store(R.string.key_customization_color_scheme, DefaultColorScheme.colorName)
}
return currentColorName
}
fun getColor(colorName: String): NeoColorScheme {
return if (colors.containsKey(colorName)) colors[colorName]!! else getCurrentColorScheme()
}
fun getColorNames(): List<String> {
val list = ArrayList<String>()
list += colors.keys
return list
}
fun setCurrentColor(colorName: String) {
NeoPreference.store(R.string.key_customization_color_scheme, colorName)
}
companion object {
fun colorFile(colorName: String): File {
return File("${NeoTermPath.COLORS_PATH}/$colorName.nl")
}
}
}

View File

@ -1,4 +1,4 @@
package io.neoterm.customize.color
package io.neoterm.component.color
/**
* @author kiva

View File

@ -1,12 +1,12 @@
package io.neoterm.customize.color
package io.neoterm.component.color
import io.neoterm.backend.TerminalColorScheme
import io.neoterm.backend.TerminalColors
import io.neoterm.customize.config.ConfigureService
import io.neoterm.component.config.ConfigureComponent
import io.neolang.visitor.ConfigVisitor
import io.neoterm.frontend.config.NeoConfigureFile
import io.neoterm.frontend.logging.NLog
import io.neoterm.frontend.service.ServiceManager
import io.neoterm.frontend.component.ComponentManager
import io.neoterm.view.TerminalView
import io.neoterm.view.eks.ExtraKeysView
import java.io.File
@ -78,7 +78,7 @@ open class NeoColorScheme {
fun loadConfigure(file: File): Boolean {
// TODO: Refactor with NeoExtraKey#loadConfigure
val loaderService = ServiceManager.getService<ConfigureService>()
val loaderService = ComponentManager.getService<ConfigureComponent>()
val configure: NeoConfigureFile?
try {

View File

@ -0,0 +1,22 @@
package io.neoterm.component.completion
import io.neoterm.component.completion.provider.FileCompletionProvider
import io.neoterm.component.completion.provider.ProgramCompletionProvider
import io.neoterm.frontend.completion.CompletionManager
import io.neoterm.frontend.component.NeoComponent
/**
* @author kiva
*/
class CompletionComponent : NeoComponent {
override fun onServiceInit() {
CompletionManager.registerProvider(FileCompletionProvider())
CompletionManager.registerProvider(ProgramCompletionProvider())
}
override fun onServiceDestroy() {
}
override fun onServiceObtained() {
}
}

View File

@ -1,4 +1,4 @@
package io.neoterm.customize.completion.provider
package io.neoterm.component.completion.provider
import io.neoterm.frontend.completion.model.CompletionCandidate
import io.neoterm.frontend.completion.provider.ICandidateProvider

View File

@ -1,4 +1,4 @@
package io.neoterm.customize.completion.provider
package io.neoterm.component.completion.provider
import java.io.File

View File

@ -0,0 +1,27 @@
package io.neoterm.component.config
import io.neoterm.component.config.loader.NeoLangConfigureLoader
import io.neoterm.component.config.loader.OldConfigureLoader
import io.neoterm.frontend.component.NeoComponent
import java.io.File
/**
* @author kiva
*/
class ConfigureComponent : NeoComponent {
override fun onServiceInit() {
}
override fun onServiceDestroy() {
}
override fun onServiceObtained() {
}
fun newLoader(configFile: File): IConfigureFileLoader {
return when (configFile.extension) {
"nl" -> NeoLangConfigureLoader(configFile)
else -> OldConfigureLoader(configFile)
}
}
}

View File

@ -1,7 +1,6 @@
package io.neoterm.customize.config
package io.neoterm.component.config
import io.neoterm.frontend.config.NeoConfigureFile
import java.io.File
/**
* @author kiva

View File

@ -1,6 +1,6 @@
package io.neoterm.customize.config.loader
package io.neoterm.component.config.loader
import io.neoterm.customize.config.IConfigureFileLoader
import io.neoterm.component.config.IConfigureFileLoader
import io.neoterm.frontend.config.NeoConfigureFile
import java.io.File

View File

@ -1,7 +1,7 @@
package io.neoterm.customize.config.loader
package io.neoterm.component.config.loader
import io.neolang.runtime.type.NeoLangValue
import io.neoterm.customize.color.NeoColorScheme
import io.neoterm.component.color.NeoColorScheme
import io.neolang.visitor.ConfigVisitor
import io.neoterm.frontend.config.NeoConfigureFile
import io.neoterm.frontend.logging.NLog

View File

@ -1,6 +1,6 @@
package io.neoterm.customize.config.loader
package io.neoterm.component.config.loader
import io.neoterm.customize.config.IConfigureFileLoader
import io.neoterm.component.config.IConfigureFileLoader
import io.neoterm.frontend.config.NeoConfigureFile
import java.io.File

View File

@ -1,8 +1,8 @@
package io.neoterm.customize.config.loader
package io.neoterm.component.config.loader
import io.neolang.runtime.type.NeoLangValue
import io.neolang.visitor.ConfigVisitor
import io.neoterm.customize.eks.NeoExtraKey
import io.neoterm.component.eks.NeoExtraKey
import io.neoterm.frontend.config.NeoConfigureFile
import io.neoterm.view.eks.button.TextButton
import java.io.BufferedReader

View File

@ -0,0 +1,85 @@
package io.neoterm.component.eks
import android.content.Context
import io.neoterm.App
import io.neoterm.frontend.logging.NLog
import io.neoterm.frontend.preference.NeoTermPath
import io.neoterm.frontend.component.NeoComponent
import io.neoterm.utils.AssetsUtils
import io.neoterm.view.eks.ExtraKeysView
import java.io.File
import java.io.FileFilter
/**
* @author kiva
*/
class ExtraKeysComponent : NeoComponent {
companion object {
private val FILTER = FileFilter {
it.extension == "nl"
}
}
override fun onServiceInit() {
checkForFiles()
}
override fun onServiceDestroy() {
}
override fun onServiceObtained() {
checkForFiles()
}
val extraKeys: MutableMap<String, NeoExtraKey> = mutableMapOf()
fun showShortcutKeys(program: String, extraKeysView: ExtraKeysView?) {
if (extraKeysView == null) {
return
}
val extraKey = extraKeys[program]
if (extraKey != null) {
extraKey.applyExtraKeys(extraKeysView)
return
}
extraKeysView.loadDefaultUserKeys()
}
fun registerShortcutKeys(extraKey: NeoExtraKey) {
extraKey.programNames.forEach {
extraKeys[it] = extraKey
}
}
private fun checkForFiles() {
File(NeoTermPath.EKS_PATH).mkdirs()
val defaultFile = File(NeoTermPath.EKS_DEFAULT_FILE)
if (!defaultFile.exists()) {
extractDefaultConfig(App.get())
}
loadConfigure()
}
private fun extractDefaultConfig(context: Context) {
try {
AssetsUtils.extractAssetsDir(context, "eks", NeoTermPath.EKS_PATH)
} catch (e: Exception) {
NLog.e("ExtraKey", "Failed to extract configure: ${e.localizedMessage}")
}
}
private fun loadConfigure() {
val configDir = File(NeoTermPath.EKS_PATH)
configDir.listFiles(FILTER).forEach {
if (it.absolutePath != NeoTermPath.EKS_DEFAULT_FILE) {
val extraKey = NeoExtraKey()
if (extraKey.loadConfigure(it)) {
registerShortcutKeys(extraKey)
}
}
}
}
}

View File

@ -1,10 +1,10 @@
package io.neoterm.customize.eks
package io.neoterm.component.eks
import io.neolang.visitor.ConfigVisitor
import io.neoterm.customize.config.ConfigureService
import io.neoterm.component.config.ConfigureComponent
import io.neoterm.frontend.config.NeoConfigureFile
import io.neoterm.frontend.logging.NLog
import io.neoterm.frontend.service.ServiceManager
import io.neoterm.frontend.component.ComponentManager
import io.neoterm.view.eks.ExtraKeysView
import io.neoterm.view.eks.button.IExtraButton
import io.neoterm.view.eks.button.TextButton
@ -44,7 +44,7 @@ class NeoExtraKey {
fun loadConfigure(file: File): Boolean {
// TODO: Refactor with NeoColorScheme#loadConfigure
val loaderService = ServiceManager.getService<ConfigureService>()
val loaderService = ComponentManager.getService<ConfigureComponent>()
val configure: NeoConfigureFile?
try {

View File

@ -0,0 +1,122 @@
package io.neoterm.component.font
import android.content.Context
import android.graphics.Typeface
import io.neoterm.App
import io.neoterm.R
import io.neoterm.frontend.preference.NeoPreference
import io.neoterm.frontend.preference.NeoTermPath
import io.neoterm.frontend.component.NeoComponent
import io.neoterm.utils.AssetsUtils
import java.io.File
/**
* @author kiva
*/
class FontComponent : NeoComponent {
override fun onServiceInit() {
checkForFiles()
}
override fun onServiceDestroy() {
}
override fun onServiceObtained() {
checkForFiles()
}
private val DEFAULT_FONT_NAME = "SourceCodePro"
private lateinit var DEFAULT_FONT: NeoFont
private lateinit var fonts: MutableMap<String, NeoFont>
fun getDefaultFont(): NeoFont {
return DEFAULT_FONT
}
fun getCurrentFont(): NeoFont {
return fonts[getCurrentFontName()]!!
}
fun setCurrentFont(fontName: String) {
NeoPreference.store(R.string.key_customization_font, fontName)
}
fun getCurrentFontName(): String {
var currentFontName = NeoPreference.loadString(R.string.key_customization_font, DEFAULT_FONT_NAME)
if (!fonts.containsKey(currentFontName)) {
currentFontName = DEFAULT_FONT_NAME
NeoPreference.store(R.string.key_customization_font, DEFAULT_FONT_NAME)
}
return currentFontName
}
fun getFont(fontName: String): NeoFont {
return if (fonts.containsKey(fontName)) fonts[fontName]!! else getCurrentFont()
}
fun getFontNames(): List<String> {
val list = ArrayList<String>()
list += fonts.keys
return list
}
fun refreshFontList(): Boolean {
fonts.clear()
fonts.put("Android Monospace", NeoFont(Typeface.MONOSPACE))
fonts.put("Android Sans Serif", NeoFont(Typeface.SANS_SERIF))
fonts.put("Android Serif", NeoFont(Typeface.SERIF))
val fontDir = File(NeoTermPath.FONT_PATH)
for (file in fontDir.listFiles({ pathname -> pathname.name.endsWith(".ttf") })) {
val fontName = fontName(file)
val font = NeoFont(file)
fonts.put(fontName, font)
}
if (fonts.containsKey(DEFAULT_FONT_NAME)) {
DEFAULT_FONT = fonts[DEFAULT_FONT_NAME]!!
return true
}
return false
}
private fun loadDefaultFontFromAsset(context: Context): NeoFont {
return NeoFont(Typeface.createFromAsset(context.assets, "fonts/$DEFAULT_FONT_NAME.ttf"))
}
private fun extractDefaultFont(context: Context): Boolean {
try {
AssetsUtils.extractAssetsDir(context, "fonts", NeoTermPath.FONT_PATH)
return true
} catch (e: Exception) {
return false
}
}
private fun fontFile(fontName: String): File {
return File("${NeoTermPath.FONT_PATH}/$fontName.ttf")
}
private fun fontName(fontFile: File): String {
return fontFile.nameWithoutExtension
}
private fun checkForFiles() {
File(NeoTermPath.FONT_PATH).mkdirs()
fonts = mutableMapOf()
val context = App.get()
val defaultFontFile = fontFile(DEFAULT_FONT_NAME)
if (!defaultFontFile.exists()) {
if (!extractDefaultFont(context)) {
DEFAULT_FONT = loadDefaultFontFromAsset(context)
fonts.put(DEFAULT_FONT_NAME, DEFAULT_FONT)
return
}
}
if (!refreshFontList()) {
DEFAULT_FONT = loadDefaultFontFromAsset(context)
fonts.put(DEFAULT_FONT_NAME, DEFAULT_FONT)
}
}
}

View File

@ -1,4 +1,4 @@
package io.neoterm.customize.font
package io.neoterm.component.font
import android.graphics.Typeface
import java.io.File

View File

@ -1,4 +1,4 @@
package io.neoterm.customize.pm
package io.neoterm.component.pm
/**
* @author kiva

View File

@ -0,0 +1,116 @@
package io.neoterm.component.pm;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import io.neoterm.frontend.component.NeoComponent;
/**
* @author kiva
*/
public class NeoPackageComponent implements NeoComponent {
private final Object lock = new Object();
private boolean isRefreshing = false;
private boolean queryEnabled = true;
private HashMap<String, NeoPackageInfo> neoPackages;
private NeoPackageInfo getPackageInfo(String packageName) {
return queryEnabled ? neoPackages.get(packageName) : null;
}
public HashMap<String, NeoPackageInfo> getPackages() {
return queryEnabled ? neoPackages : new HashMap<String, NeoPackageInfo>();
}
public int getPackageCount() {
return queryEnabled ? neoPackages.size() : -1;
}
public void refreshPackageList(File packageListFile, boolean clearPrevious) throws IOException {
synchronized (lock) {
if (isRefreshing) {
return;
}
isRefreshing = true;
}
tryParsePackages(packageListFile, clearPrevious);
synchronized (lock) {
isRefreshing = false;
}
}
public void clearPackages() {
if (isRefreshing) {
return;
}
neoPackages.clear();
}
private void tryParsePackages(File packageListFile, final boolean clearPrevious) throws IOException {
NeoPackageParser packageParser = new NeoPackageParser(new FileInputStream(packageListFile));
packageParser.setStateListener(new NeoPackageParser.ParseStateListener() {
@Override
public void onStartState() {
queryEnabled = false;
if (clearPrevious) {
neoPackages.clear();
}
}
@Override
public void onEndState() {
queryEnabled = true;
for (NeoPackageInfo info : neoPackages.values()) {
resolveDepends(info);
}
}
@Override
public NeoPackageInfo onCreatePackageInfo() {
return new NeoPackageInfo();
}
@Override
public void onStartParsePackage(String name, NeoPackageInfo packageInfo) {
}
@Override
public void onEndParsePackage(NeoPackageInfo packageInfo) {
neoPackages.put(packageInfo.getPackageName(), packageInfo);
}
});
packageParser.parse();
}
private void resolveDepends(NeoPackageInfo info) {
String dep = info.getDependenciesString();
if (dep == null) {
return;
}
String[] splits = dep.split(",");
NeoPackageInfo[] depends = new NeoPackageInfo[splits.length];
info.setDependencies(depends);
for (int i = 0; i < splits.length; ++i) {
String item = splits[i].trim();
depends[i] = getPackageInfo(item);
}
}
@Override
public void onServiceInit() {
neoPackages = new HashMap<>();
}
@Override
public void onServiceDestroy() {
}
@Override
public void onServiceObtained() {
}
}

View File

@ -1,4 +1,4 @@
package io.neoterm.customize.pm
package io.neoterm.component.pm
/**
* @author kiva

View File

@ -1,4 +1,4 @@
package io.neoterm.customize.pm
package io.neoterm.component.pm
import io.neoterm.R
import io.neoterm.frontend.preference.NeoPreference

View File

@ -1,4 +1,4 @@
package io.neoterm.customize.pm;
package io.neoterm.component.pm;
import java.io.BufferedReader;
import java.io.IOException;

View File

@ -1,4 +1,4 @@
package io.neoterm.customize.script
package io.neoterm.component.script
import java.io.File

View File

@ -0,0 +1,35 @@
package io.neoterm.component.script
import io.neoterm.frontend.component.NeoComponent
import io.neoterm.frontend.preference.NeoTermPath
import java.io.File
/**
* @author kiva
*/
class UserScriptComponent : NeoComponent {
override fun onServiceInit() {
userScripts = mutableListOf()
reloadScripts()
}
override fun onServiceDestroy() {
}
override fun onServiceObtained() {
reloadScripts()
}
lateinit var userScripts: MutableList<UserScript>
private set
fun reloadScripts() {
val userScriptDir = File(NeoTermPath.USER_SCRIPT_PATH)
userScriptDir.mkdirs()
userScripts.clear()
userScriptDir.listFiles()
.takeWhile { it.canExecute() }
.mapTo(userScripts, { UserScript(it) })
}
}

View File

@ -1,4 +1,4 @@
package io.neoterm.customize.setup;
package io.neoterm.component.setup;
import android.app.Activity;
import android.app.ProgressDialog;

View File

@ -1,28 +0,0 @@
package io.neoterm.customize
import android.content.Context
import io.neoterm.customize.color.ColorSchemeService
import io.neoterm.customize.completion.CompletionService
import io.neoterm.customize.config.ConfigureService
import io.neoterm.customize.eks.ExtraKeysService
import io.neoterm.customize.font.FontService
import io.neoterm.customize.pm.NeoPackageService
import io.neoterm.customize.script.UserScriptService
import io.neoterm.frontend.logging.NLog
import io.neoterm.frontend.service.ServiceManager
/**
* @author kiva
*/
object NeoInitializer {
fun initialize(context: Context) {
NLog.init(context)
ServiceManager.registerService(ConfigureService::class.java)
ServiceManager.registerService(ColorSchemeService::class.java)
ServiceManager.registerService(FontService::class.java)
ServiceManager.registerService(UserScriptService::class.java)
ServiceManager.registerService(ExtraKeysService::class.java)
ServiceManager.registerService(CompletionService::class.java)
ServiceManager.registerService(NeoPackageService::class.java)
}
}

View File

@ -9,9 +9,9 @@ import android.view.inputmethod.InputMethodManager
import io.neoterm.R
import io.neoterm.backend.KeyHandler
import io.neoterm.backend.TerminalSession
import io.neoterm.customize.eks.ExtraKeysService
import io.neoterm.component.eks.ExtraKeysComponent
import io.neoterm.frontend.preference.NeoPreference
import io.neoterm.frontend.service.ServiceManager
import io.neoterm.frontend.component.ComponentManager
import io.neoterm.view.TerminalViewClient
@ -203,7 +203,7 @@ class TermViewClient(val context: Context) : TerminalViewClient {
if (lastTitle != title || force) {
removeSuggestions()
ServiceManager.getService<ExtraKeysService>().showShortcutKeys(title, extraKeysView)
ComponentManager.getService<ExtraKeysComponent>().showShortcutKeys(title, extraKeysView)
extraKeysView.updateButtons()
lastTitle = title
}

View File

@ -11,10 +11,10 @@ import android.widget.PopupWindow
import android.widget.TextView
import io.neoterm.R
import io.neoterm.backend.TerminalColors
import io.neoterm.customize.color.ColorSchemeService
import io.neoterm.component.color.ColorSchemeComponent
import io.neoterm.frontend.completion.listener.OnCandidateSelectedListener
import io.neoterm.frontend.completion.model.CompletionCandidate
import io.neoterm.frontend.service.ServiceManager
import io.neoterm.frontend.component.ComponentManager
import io.neoterm.view.MaxHeightView
import io.neoterm.view.TerminalView
@ -136,7 +136,7 @@ class CandidatePopupWindow(val context: Context) {
val splitView: View = rootView.findViewById(R.id.complete_split)
init {
val colorScheme = ServiceManager.getService<ColorSchemeService>().getCurrentColorScheme()
val colorScheme = ComponentManager.getService<ColorSchemeComponent>().getCurrentColorScheme()
val textColor = TerminalColors.parse(colorScheme.foregroundColor)
display.setTextColor(textColor)
description.setTextColor(textColor)

View File

@ -0,0 +1,6 @@
package io.neoterm.frontend.component
/**
* @author kiva
*/
class ComponentDuplicateException(serviceName: String) : RuntimeException("Service $serviceName duplicate")

View File

@ -0,0 +1,43 @@
package io.neoterm.frontend.component
import java.util.concurrent.ConcurrentHashMap
/**
* @author kiva
*/
object ComponentManager {
val THROW_WHEN_SERVICE_NOT_FOUND = true
val SERVICE_CACHE = ConcurrentHashMap<Class<out NeoComponent>, NeoComponent>()
fun registerComponent(serviceClass: Class<out NeoComponent>) {
if (SERVICE_CACHE.containsKey(serviceClass)) {
throw ComponentDuplicateException(serviceClass.simpleName)
}
val service = createServiceInstance(serviceClass)
SERVICE_CACHE.put(serviceClass, service)
service.onServiceInit()
}
fun unregisterComponent(serviceInterface: Class<out NeoComponent>) {
val service = SERVICE_CACHE[serviceInterface]
if (service != null) {
service.onServiceDestroy()
SERVICE_CACHE.remove(serviceInterface)
}
}
inline fun <reified T : NeoComponent> getService(): T {
val serviceInterface = T::class.java
val service: NeoComponent? = SERVICE_CACHE[serviceInterface]
if (service == null && THROW_WHEN_SERVICE_NOT_FOUND) {
throw ComponentNotFoundException(serviceInterface.simpleName)
}
service?.onServiceObtained()
return service as T
}
private fun createServiceInstance(serviceInterface: Class<out NeoComponent>): NeoComponent {
return serviceInterface.newInstance()
}
}

View File

@ -0,0 +1,7 @@
package io.neoterm.frontend.component
/**
* @author kiva
*/
class ComponentNotFoundException(serviceName: String) : RuntimeException("Service `$serviceName' not found") {
}

View File

@ -0,0 +1,10 @@
package io.neoterm.frontend.component
/**
* @author kiva
*/
interface NeoComponent {
fun onServiceInit()
fun onServiceDestroy()
fun onServiceObtained()
}

View File

@ -1,6 +0,0 @@
package io.neoterm.frontend.service
/**
* @author kiva
*/
class ServiceDuplicateException(serviceName: String) : RuntimeException("Service $serviceName duplicate")

View File

@ -1,7 +0,0 @@
package io.neoterm.frontend.service
/**
* @author kiva
*/
class ServiceNotFoundException(serviceName: String) : RuntimeException("Service `$serviceName' not found") {
}

View File

@ -94,9 +94,8 @@ class NeoTermService : Service() {
}
private fun updateNotification() {
if (sessions.isNotEmpty()) {
(getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).notify(NOTIFICATION_ID, createNotification())
}
val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
service.notify(NOTIFICATION_ID, createNotification())
}
private fun createNotification(): Notification {

View File

@ -0,0 +1,58 @@
package io.neoterm.ui.customize
import android.annotation.SuppressLint
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar
import android.view.MenuItem
import io.neoterm.R
import io.neoterm.backend.TerminalSession
import io.neoterm.frontend.preference.NeoTermPath
import io.neoterm.frontend.shell.ShellParameter
import io.neoterm.frontend.tinyclient.BasicSessionCallback
import io.neoterm.frontend.tinyclient.BasicViewClient
import io.neoterm.utils.TerminalUtils
import io.neoterm.view.TerminalView
import io.neoterm.view.eks.ExtraKeysView
/**
* @author kiva
*/
@SuppressLint("Registered")
open class BaseCustomizeActivity : AppCompatActivity() {
lateinit var terminalView: TerminalView
lateinit var viewClient: BasicViewClient
lateinit var sessionCallback: BasicSessionCallback
lateinit var session: TerminalSession
lateinit var extraKeysView: ExtraKeysView
fun initCustomizationComponent(layoutId: Int) {
setContentView(layoutId)
val toolbar = findViewById<Toolbar>(R.id.custom_toolbar)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
terminalView = findViewById<TerminalView>(R.id.terminal_view)
extraKeysView = findViewById<ExtraKeysView>(R.id.custom_extra_keys)
viewClient = BasicViewClient(terminalView)
sessionCallback = BasicSessionCallback(terminalView)
TerminalUtils.setupTerminalView(terminalView, viewClient)
val parameter = ShellParameter()
.executablePath("${NeoTermPath.USR_PATH}/bin/applets/echo")
.arguments(arrayOf("echo", "Hello NeoTerm."))
.callback(sessionCallback)
.systemShell(false)
session = TerminalUtils.createShellSession(this, parameter)
terminalView.attachSession(session)
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
when (item?.itemId) {
android.R.id.home -> finish()
}
return super.onOptionsItemSelected(item)
}
}

View File

@ -1,20 +1,16 @@
package io.neoterm.ui.customize
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar
import android.view.MenuItem
import io.neoterm.R
/**
* @author kiva
*/
class ColorSchemeActivity : AppCompatActivity() {
class ColorSchemeActivity : BaseCustomizeActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.ui_color_scheme)
setSupportActionBar(findViewById<Toolbar>(R.id.color_scheme_toolbar))
supportActionBar?.setDisplayHomeAsUpEnabled(true)
initCustomizationComponent(R.layout.ui_color_scheme)
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {

View File

@ -1,65 +1,35 @@
package io.neoterm.ui.customize
import android.app.Activity
import android.app.AlertDialog
import android.content.Intent
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar
import android.view.MenuItem
import android.view.View
import android.widget.*
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Spinner
import android.widget.Toast
import io.neoterm.R
import io.neoterm.backend.TerminalSession
import io.neoterm.customize.color.ColorSchemeService
import io.neoterm.component.color.ColorSchemeComponent
import io.neoterm.component.font.FontComponent
import io.neoterm.frontend.preference.NeoTermPath
import io.neoterm.customize.font.FontService
import io.neoterm.frontend.shell.ShellParameter
import io.neoterm.frontend.service.ServiceManager
import io.neoterm.frontend.component.ComponentManager
import io.neoterm.utils.FileUtils
import io.neoterm.utils.MediaUtils
import io.neoterm.utils.TerminalUtils
import io.neoterm.frontend.tinyclient.BasicSessionCallback
import io.neoterm.frontend.tinyclient.BasicViewClient
import io.neoterm.view.eks.ExtraKeysView
import io.neoterm.view.TerminalView
import java.io.File
import java.io.FileInputStream
/**
* @author kiva
*/
class CustomizeActivity : AppCompatActivity() {
lateinit var terminalView: TerminalView
lateinit var viewClient: BasicViewClient
lateinit var sessionCallback: BasicSessionCallback
lateinit var session: TerminalSession
lateinit var extraKeysView: ExtraKeysView
class CustomizeActivity : BaseCustomizeActivity() {
val REQUEST_SELECT_FONT = 22222
val REQUEST_SELECT_COLOR = 22223
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.ui_customize)
val toolbar = findViewById<Toolbar>(R.id.custom_toolbar)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
terminalView = findViewById<TerminalView>(R.id.terminal_view)
extraKeysView = findViewById<ExtraKeysView>(R.id.custom_extra_keys)
viewClient = BasicViewClient(terminalView)
sessionCallback = BasicSessionCallback(terminalView)
TerminalUtils.setupTerminalView(terminalView, viewClient)
val parameter = ShellParameter()
.executablePath("${NeoTermPath.USR_PATH}/bin/applets/echo")
.arguments(arrayOf("echo", "Hello NeoTerm."))
.callback(sessionCallback)
.systemShell(false)
session = TerminalUtils.createShellSession(this, parameter)
terminalView.attachSession(session)
initCustomizationComponent(R.layout.ui_customize)
findViewById<View>(R.id.custom_install_font_button).setOnClickListener {
val intent = Intent()
@ -69,16 +39,25 @@ class CustomizeActivity : AppCompatActivity() {
}
findViewById<View>(R.id.custom_install_color_button).setOnClickListener {
val intent = Intent()
intent.action = Intent.ACTION_GET_CONTENT
intent.type = "*/*"
startActivityForResult(Intent.createChooser(intent, getString(R.string.install_color)), REQUEST_SELECT_COLOR)
AlertDialog.Builder(this)
.setMessage(R.string.pref_customization_font)
.setNeutralButton(android.R.string.no, null)
.setPositiveButton(R.string.install_font, { _, _ ->
val intent = Intent()
intent.action = Intent.ACTION_GET_CONTENT
intent.type = "*/*"
startActivityForResult(Intent.createChooser(intent, getString(R.string.install_color)), REQUEST_SELECT_COLOR)
})
.setNegativeButton(R.string.new_color_scheme, { _, _ ->
startActivity(Intent(this, ColorSchemeActivity::class.java))
})
.show()
}
}
private fun setupSpinners() {
val fontManager = ServiceManager.getService<FontService>()
val colorSchemeManager = ServiceManager.getService<ColorSchemeService>()
val fontManager = ComponentManager.getService<FontComponent>()
val colorSchemeManager = ComponentManager.getService<ColorSchemeComponent>()
setupSpinner(R.id.custom_font_spinner, fontManager.getFontNames(),
fontManager.getCurrentFontName(), object : AdapterView.OnItemSelectedListener {

View File

@ -23,12 +23,12 @@ import com.github.wrdlbrnft.sortedlistadapter.SortedListAdapter
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView
import io.neoterm.R
import io.neoterm.backend.TerminalSession
import io.neoterm.customize.pm.NeoPackageManagerUtils
import io.neoterm.customize.pm.NeoPackageService
import io.neoterm.component.pm.NeoPackageManagerUtils
import io.neoterm.component.pm.NeoPackageComponent
import io.neoterm.frontend.floating.TerminalDialog
import io.neoterm.frontend.preference.NeoPreference
import io.neoterm.frontend.preference.NeoTermPath
import io.neoterm.frontend.service.ServiceManager
import io.neoterm.frontend.component.ComponentManager
import io.neoterm.ui.pm.adapter.PackageAdapter
import io.neoterm.ui.pm.model.PackageModel
import io.neoterm.utils.PackageUtils
@ -213,7 +213,7 @@ class PackageManagerActivity : AppCompatActivity(), SearchView.OnQueryTextListen
progressBar.visibility = View.VISIBLE
progressBar.alpha = 0.0f
Thread {
val pm = ServiceManager.getService<NeoPackageService>()
val pm = ComponentManager.getService<NeoPackageComponent>()
val sourceFiles = NeoPackageManagerUtils.detectSourceFiles()
pm.clearPackages()

View File

@ -4,7 +4,7 @@ import android.content.Context
import com.github.wrdlbrnft.sortedlistadapter.SortedListAdapter
import io.neoterm.R
import io.neoterm.customize.pm.NeoPackageInfo
import io.neoterm.component.pm.NeoPackageInfo
import io.neoterm.utils.FileUtils
/**

View File

@ -4,11 +4,9 @@ import android.app.Activity
import android.os.Bundle
import android.support.v7.app.AlertDialog
import android.support.v7.app.AppCompatActivity
import android.widget.Button
import android.widget.Toast
import io.neoterm.App
import io.neoterm.R
import io.neoterm.customize.setup.BaseFileInstaller
import io.neoterm.component.setup.BaseFileInstaller
import io.neoterm.utils.PackageUtils

View File

@ -24,7 +24,7 @@ import android.widget.Toast
import de.mrapp.android.tabswitcher.*
import io.neoterm.R
import io.neoterm.backend.TerminalSession
import io.neoterm.customize.setup.BaseFileInstaller
import io.neoterm.component.setup.BaseFileInstaller
import io.neoterm.frontend.client.TermSessionCallback
import io.neoterm.frontend.client.TermViewClient
import io.neoterm.frontend.preference.NeoPermission

View File

@ -1,6 +1,5 @@
package io.neoterm.ui.term
import android.app.Activity
import android.content.ComponentName
import android.content.Intent
import android.content.ServiceConnection
@ -10,24 +9,18 @@ import android.os.IBinder
import android.support.v7.app.AlertDialog
import android.support.v7.app.AppCompatActivity
import android.widget.ArrayAdapter
import android.widget.EditText
import android.widget.ListView
import android.widget.Toast
import io.neoterm.App
import io.neoterm.R
import io.neoterm.customize.script.UserScript
import io.neoterm.customize.script.UserScriptService
import io.neoterm.frontend.shell.ShellParameter
import io.neoterm.component.script.UserScript
import io.neoterm.component.script.UserScriptComponent
import io.neoterm.frontend.client.TermSessionCallback
import io.neoterm.frontend.preference.NeoPreference
import io.neoterm.frontend.component.ComponentManager
import io.neoterm.frontend.shell.ShellParameter
import io.neoterm.services.NeoTermService
import io.neoterm.utils.TerminalUtils
import java.io.File
import android.content.Intent.ShortcutIconResource
import android.util.Log
import android.view.View
import io.neoterm.App
import io.neoterm.frontend.logging.NLog
import io.neoterm.frontend.service.ServiceManager
/**
@ -47,8 +40,13 @@ class NeoTermRemoteInterface : AppCompatActivity(), ServiceConnection {
override fun onDestroy() {
super.onDestroy()
termService = null
unbindService(this)
if (termService != null) {
if (termService!!.sessions.isEmpty()) {
termService!!.stopSelf()
}
termService = null
unbindService(this)
}
}
override fun onServiceDisconnected(name: ComponentName?) {
@ -107,7 +105,7 @@ class NeoTermRemoteInterface : AppCompatActivity(), ServiceConnection {
private fun handleUserScript() {
val filesToHandle = mutableListOf<String>()
val userScriptService = ServiceManager.getService<UserScriptService>()
val userScriptService = ComponentManager.getService<UserScriptComponent>()
val userScripts = userScriptService.userScripts
if (userScripts.isEmpty()) {
App.get().errorDialog(this, R.string.no_user_script_found, { finish() })

View File

@ -4,10 +4,10 @@ import android.content.Context
import android.support.v7.widget.Toolbar
import android.view.inputmethod.InputMethodManager
import de.mrapp.android.tabswitcher.Tab
import io.neoterm.customize.color.ColorSchemeService
import io.neoterm.component.color.ColorSchemeComponent
import io.neoterm.frontend.client.TermDataHolder
import io.neoterm.frontend.client.TermUiPresenter
import io.neoterm.frontend.service.ServiceManager
import io.neoterm.frontend.component.ComponentManager
import io.neoterm.ui.term.event.TabCloseEvent
import io.neoterm.ui.term.event.TitleChangedEvent
import io.neoterm.ui.term.event.ToggleFullScreenEvent
@ -22,7 +22,7 @@ class TermTab(title: CharSequence) : Tab(title), TermUiPresenter {
var toolbar: Toolbar? = null
fun updateColorScheme() {
val colorSchemeManager = ServiceManager.getService<ColorSchemeService>()
val colorSchemeManager = ComponentManager.getService<ColorSchemeComponent>()
colorSchemeManager.applyColorScheme(termData.termView, termData.extraKeysView,
colorSchemeManager.getCurrentColorScheme())
}

View File

@ -9,14 +9,14 @@ import de.mrapp.android.tabswitcher.Tab
import de.mrapp.android.tabswitcher.TabSwitcher
import de.mrapp.android.tabswitcher.TabSwitcherDecorator
import io.neoterm.R
import io.neoterm.customize.color.ColorSchemeService
import io.neoterm.component.color.ColorSchemeComponent
import io.neoterm.frontend.preference.NeoPreference
import io.neoterm.frontend.client.TermCompleteListener
import io.neoterm.ui.term.NeoTermActivity
import io.neoterm.utils.TerminalUtils
import io.neoterm.view.eks.ExtraKeysView
import io.neoterm.frontend.completion.listener.OnAutoCompleteListener
import io.neoterm.frontend.service.ServiceManager
import io.neoterm.frontend.component.ComponentManager
import io.neoterm.view.TerminalView
/**
@ -51,7 +51,7 @@ class TermTabDecorator(val context: NeoTermActivity) : TabSwitcherDecorator() {
TerminalUtils.setupTerminalView(view)
TerminalUtils.setupExtraKeysView(extraKeysView)
val colorSchemeManager = ServiceManager.getService<ColorSchemeService>()
val colorSchemeManager = ComponentManager.getService<ColorSchemeComponent>()
colorSchemeManager.applyColorScheme(view, extraKeysView, colorSchemeManager.getCurrentColorScheme())
if (tab is TermTab) {

View File

@ -3,10 +3,10 @@ package io.neoterm.utils
import android.content.Context
import io.neoterm.R
import io.neoterm.backend.TerminalSession
import io.neoterm.customize.font.FontService
import io.neoterm.component.font.FontComponent
import io.neoterm.frontend.shell.ShellParameter
import io.neoterm.frontend.shell.ShellTermSession
import io.neoterm.frontend.service.ServiceManager
import io.neoterm.frontend.component.ComponentManager
import io.neoterm.frontend.preference.NeoPreference
import io.neoterm.view.eks.ExtraKeysView
import io.neoterm.view.TerminalView
@ -18,14 +18,14 @@ import io.neoterm.view.TerminalViewClient
object TerminalUtils {
fun setupTerminalView(terminalView: TerminalView?, terminalViewClient: TerminalViewClient? = null) {
terminalView?.textSize = NeoPreference.loadInt(NeoPreference.KEY_FONT_SIZE, 30)
terminalView?.setTypeface(ServiceManager.getService<FontService>().getCurrentFont().getTypeFace())
terminalView?.setTypeface(ComponentManager.getService<FontComponent>().getCurrentFont().getTypeFace())
if (terminalViewClient != null) {
terminalView?.setTerminalViewClient(terminalViewClient)
}
}
fun setupExtraKeysView(extraKeysView: ExtraKeysView?) {
extraKeysView?.setTypeface(ServiceManager.getService<FontService>().getCurrentFont().getTypeFace())
extraKeysView?.setTypeface(ComponentManager.getService<FontComponent>().getCurrentFont().getTypeFace())
}
fun setupTerminalSession(session: TerminalSession?) {

View File

@ -7,7 +7,7 @@ import android.view.*
import android.widget.GridLayout
import android.widget.LinearLayout
import io.neoterm.R
import io.neoterm.customize.eks.NeoExtraKey
import io.neoterm.component.eks.NeoExtraKey
import io.neoterm.frontend.preference.NeoPreference
import io.neoterm.frontend.preference.NeoTermPath
import io.neoterm.ui.term.event.ToggleImeEvent

View File

@ -6,7 +6,7 @@
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/color_scheme_toolbar"
android:id="@+id/custom_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary"
@ -22,7 +22,7 @@
android:background="@color/terminal_background">
<io.neoterm.view.eks.ExtraKeysView
android:id="@+id/color_scheme_extra_keys"
android:id="@+id/custom_extra_keys"
style="?android:buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="@dimen/eks_height_two_line"

View File

@ -122,4 +122,5 @@
<string name="support_donate_dialog_text">这个app是我在课余时间制作的一个人不仅要维护app还要维护各种软件包和服务器如果能得到你的支持我将更有动力继续将app完善下去</string>
<string name="support_donate_qq">QQ</string>
<string name="support_donate_alipay">支付宝</string>
<string name="new_color_scheme">新建配色方案</string>
</resources>

View File

@ -2,7 +2,7 @@
<resources>
<color name="colorPrimary">#607D8B</color>
<color name="colorPrimaryDark">#455A64</color>
<color name="colorAccent">#FF5252</color>
<color name="colorAccent">#42a5f5</color>
<color name="terminal_background">#ff14181c</color>
<color name="textColor">#fefefe</color>
<color name="textColorSecondary">#ced7db</color>

View File

@ -117,6 +117,7 @@
<string name="about_developers">Kiva for Maintaining\nCrixec for Icon Design</string>
<string name="about_credits_label">Acknowledgements</string>
<string name="about_credits">nullptr for accompanying me\nCoolApk User @NimaQu for providing server\nQQ User @My for providing free network</string>
<string name="new_color_scheme">New Color Scheme</string>
<string-array name="pref_general_shell_entries" translatable="false">
<item>sh</item>

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
<shortcut
android:shortcutId="@string/id_shortcut_create_new_session"
android:enabled="true"
android:icon="@drawable/ic_terminal_running"
android:shortcutShortLabel="@string/new_session">
<intent
android:targetPackage="io.neoterm"
android:targetClass="io.neoterm.ui.term.NeoTermRemoteInterface" />
</shortcut>
</shortcuts>

View File

@ -1,12 +1,11 @@
package io.neoterm
import io.neolang.main.Main
import io.neolang.visitor.ConfigVisitor
import io.neoterm.customize.color.NeoColorScheme
import io.neoterm.customize.config.ConfigureService
import io.neoterm.customize.eks.NeoExtraKey
import io.neoterm.component.color.NeoColorScheme
import io.neoterm.component.config.ConfigureComponent
import io.neoterm.component.eks.NeoExtraKey
import io.neoterm.frontend.config.NeoConfigureFile
import io.neoterm.frontend.service.ServiceManager
import io.neoterm.frontend.component.ComponentManager
import org.junit.Test
import java.io.File
@ -26,7 +25,7 @@ class ConfigureFileTest {
@Test
fun colorConfigureTest() {
try {
ServiceManager.registerService(ConfigureService::class.java)
ComponentManager.registerComponent(ConfigureComponent::class.java)
} catch (ignore: Throwable) {
}
@ -44,7 +43,7 @@ class ConfigureFileTest {
@Test
fun extraKeyConfigureTest() {
try {
ServiceManager.registerService(ConfigureService::class.java)
ComponentManager.registerComponent(ConfigureComponent::class.java)
} catch (ignore: Throwable) {
}