Backwards compatibility and theme changes

// Backards compatability from api 25 -> 21
* Created separate menu entries for older api levels that cut off certain features that dont work and lack certain java.nio features
* Cover up config loaders that use java.nio with if cases with api level comparison ( cuts off logcat error screams )
* Fix up required functions that backwards compatible java.nio dep so asset extraction on startup can work

// More MaterialUI work for dialogs and overall app theme
* Replace some more appcompat alertdialogs with MaterialUI dialogs for nicer view
This commit is contained in:
Martin Valba 2023-09-10 17:54:13 +00:00
parent ccea8146c8
commit 8c6c615e86
22 changed files with 284 additions and 78 deletions

View File

@ -15,7 +15,7 @@ android {
externalNativeBuild {
cmake {
cppFlags "-std=c++11"
abiFilters 'arm64-v8a', 'armeabi-v7a'
abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86_64'
}
}
signingConfigs {
@ -80,6 +80,10 @@ dependencies {
implementation 'androidx.preference:preference:1.1.0'
implementation "androidx.compose.material:material:1.0.0"
// Backports for lower api levels
implementation 'com.llamalab.safs:safs-core:0.2.0'
implementation 'me.zhanghai.android.retrofile:library:1.1.1'
implementation project(':chrome-tabs')
implementation project(':NeoLang')
implementation project(':NeoTermBridge')

View File

@ -1,6 +1,7 @@
package com.offsec.nhterm.component.colorscheme
import android.content.Context
import android.os.Build
import io.neolang.frontend.ConfigVisitor
import com.offsec.nhterm.App
import com.offsec.nhterm.R
@ -18,7 +19,7 @@ import java.nio.file.Files
class ColorSchemeComponent : ConfigFileBasedComponent<NeoColorScheme>(NeoTermPath.COLORS_PATH) {
companion object {
fun colorFile(colorName: String): File {
return File("${NeoTermPath.COLORS_PATH}/$colorName.nl")
return File("${NeoTermPath.COLORS_PATH}/$colorName.nl")
}
}
@ -49,18 +50,22 @@ class ColorSchemeComponent : ConfigFileBasedComponent<NeoColorScheme>(NeoTermPat
fun reloadColorSchemes(): Boolean {
colors.clear()
File(baseDir)
.listFiles(NEOLANG_FILTER)
.mapNotNull { this.loadConfigure(it) }
.forEach {
colors.put(it.colorName, it)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
File(baseDir)
.listFiles(NEOLANG_FILTER)
.mapNotNull { this.loadConfigure(it) }
.forEach {
colors.put(it.colorName, it)
}
if (colors.containsKey(DefaultColorScheme.colorName)) {
DEFAULT_COLOR = colors[DefaultColorScheme.colorName]!!
return true
if (colors.containsKey(DefaultColorScheme.colorName)) {
DEFAULT_COLOR = colors[DefaultColorScheme.colorName]!!
return true
}
return false
} else {
return false
}
return false
}
fun applyColorScheme(view: TerminalView?, extraKeysView: ExtraKeysView?, colorScheme: NeoColorScheme?) {
@ -112,7 +117,11 @@ class ColorSchemeComponent : ConfigFileBasedComponent<NeoColorScheme>(NeoTermPat
val content = component.newGenerator(colorScheme).generateCode(colorScheme)
kotlin.runCatching {
Files.write(colorFile.toPath(), content.toByteArray())
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Files.write(colorFile.toPath(), content.toByteArray())
} else {
return
}
}.onFailure {
throw RuntimeException("Failed to save file ${colorFile.absolutePath}")
}

View File

@ -1,5 +1,7 @@
package com.offsec.nhterm.component.colorscheme
import android.os.Build
import com.offsec.nhterm.R
import io.neolang.frontend.ConfigVisitor
import com.offsec.nhterm.backend.TerminalColorScheme
import com.offsec.nhterm.backend.TerminalColors
@ -139,12 +141,16 @@ open class NeoColorScheme : CodeGenObject, ConfigFileBasedObject {
if (session != null && session.emulator != null) {
session.emulator.setColorScheme(scheme)
}
view.setBackgroundColor(TerminalColors.parse(backgroundColor))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
view.setBackgroundColor(TerminalColors.parse(backgroundColor))
}
}
if (extraKeysView != null) {
extraKeysView.setBackgroundColor(TerminalColors.parse(backgroundColor))
extraKeysView.setTextColor(TerminalColors.parse(foregroundColor))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
extraKeysView.setBackgroundColor(TerminalColors.parse(backgroundColor))
extraKeysView.setTextColor(TerminalColors.parse(foregroundColor))
}
}
}

View File

@ -2,6 +2,7 @@ package com.offsec.nhterm.component.config
import android.content.Context
import android.content.SharedPreferences
import android.os.Build
import android.preference.PreferenceManager
import android.system.ErrnoException
import android.system.Os
@ -49,14 +50,17 @@ open class NeoConfigureFile(val configureFile: File) {
fun getVisitor() = configVisitor ?: throw IllegalStateException("Configure file not loaded or parse failed.")
open fun parseConfigure() = kotlin.runCatching {
val programCode = String(Files.readAllBytes(configureFile.toPath()))
configParser.setInputSource(programCode)
val ast = configParser.parse()
val astVisitor = ast.visit().getVisitor(ConfigVisitor::class.java) ?: return false
astVisitor.start()
configVisitor = astVisitor.getCallback()
open fun parseConfigure() = kotlin.runCatching {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val programCode = String(Files.readAllBytes(configureFile.toPath()))
configParser.setInputSource(programCode)
val ast = configParser.parse()
val astVisitor = ast.visit().getVisitor(ConfigVisitor::class.java) ?: return false
astVisitor.start()
configVisitor = astVisitor.getCallback()
}
}.isSuccess
}
@ -85,14 +89,16 @@ object NeoPreference {
MIN_FONT_SIZE = (4f * dipInPixels).toInt()
MAX_FONT_SIZE = 256
// load apt source
val sourceFile = File(NeoTermPath.SOURCE_FILE)
kotlin.runCatching {
Files.readAllBytes(sourceFile.toPath())?.let {
val source = String(it).trim().trimEnd()
val array = source.split(" ")
if (array.size >= 2 && array[0] == "deb") {
store(R.string.key_package_source, array[1])
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// load apt source
val sourceFile = File(NeoTermPath.SOURCE_FILE)
kotlin.runCatching {
Files.readAllBytes(sourceFile.toPath())?.let {
val source = String(it).trim().trimEnd()
val array = source.split(" ")
if (array.size >= 2 && array[0] == "deb") {
store(R.string.key_package_source, array[1])
}
}
}
}

View File

@ -1,6 +1,7 @@
package com.offsec.nhterm.component.extrakey
import android.content.Context
import android.os.Build
import io.neolang.frontend.ConfigVisitor
import com.offsec.nhterm.App
import com.offsec.nhterm.component.ConfigFileBasedComponent
@ -57,12 +58,14 @@ class ExtraKeyComponent : ConfigFileBasedComponent<NeoExtraKey>(NeoTermPath.EKS_
private fun reloadExtraKeyConfig() {
extraKeys.clear()
File(baseDir)
.listFiles(NEOLANG_FILTER)
.filter { it.absolutePath != NeoTermPath.EKS_DEFAULT_FILE }
.mapNotNull { this.loadConfigure(it) }
.forEach {
registerShortcutKeys(it)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
File(baseDir)
.listFiles(NEOLANG_FILTER)
.filter { it.absolutePath != NeoTermPath.EKS_DEFAULT_FILE }
.mapNotNull { this.loadConfigure(it) }
.forEach {
registerShortcutKeys(it)
}
}
}
}

View File

@ -16,8 +16,8 @@ class UserScript(val scriptFile: File)
class UserScriptComponent : NeoComponent {
var userScripts = listOf<UserScript>()
var binFiles = listOf<UserScript>()
private val scriptDir = File(NeoTermPath.USER_SCRIPT_PATH)
private val binDir = File(NeoTermPath.BIN_PATH)
val scriptDir = File(NeoTermPath.USER_SCRIPT_PATH)
val binDir = File(NeoTermPath.BIN_PATH)
override fun onServiceInit() = checkForFiles()

View File

@ -6,6 +6,7 @@ import android.content.DialogInterface
import android.view.LayoutInflater
import android.view.View
import androidx.appcompat.app.AlertDialog
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.offsec.nhterm.R
import com.offsec.nhterm.backend.TerminalSession
import com.offsec.nhterm.component.config.DefaultValues.initialCommand
@ -42,7 +43,7 @@ class TerminalDialog(val context: Context) {
terminalSession?.finishIfRunning()
}
dialog = AlertDialog.Builder(context)
dialog = MaterialAlertDialogBuilder(context, R.style.DialogStyle)
.setView(termWindowView.rootView)
.setOnCancelListener {
terminalSession?.finishIfRunning()

View File

@ -2,6 +2,7 @@ package com.offsec.nhterm.frontend.session.view.extrakey
import android.content.Context
import android.graphics.Typeface
import android.os.Build
import android.os.VibrationEffect
import android.os.Vibrator
import android.util.AttributeSet
@ -29,6 +30,7 @@ class ExtraKeysView(context: Context, attrs: AttributeSet) : LinearLayout(contex
private val ARROW_DOWN = ArrowButton(IExtraButton.KEY_ARROW_DOWN)
private val ARROW_LEFT = ArrowButton(IExtraButton.KEY_ARROW_LEFT)
private val ARROW_RIGHT = ArrowButton(IExtraButton.KEY_ARROW_RIGHT)
private val SLASH = ControlButton(IExtraButton.KEY_SLASH)
private val TOGGLE_IME = object : ControlButton(KEY_TOGGLE_IME) {
override fun onClick(view: View) {
EventBus.getDefault().post(ToggleImeEvent())
@ -55,6 +57,7 @@ class ExtraKeysView(context: Context, attrs: AttributeSet) : LinearLayout(contex
private val SHIFT = StatedControlButton(IExtraButton.KEY_SHIFT)
private var buttonPanelExpanded = false
private val EXPAND_BUTTONS = object : ControlButton(IExtraButton.KEY_SHOW_ALL_BUTTONS) {
override fun onClick(view: View) {
expandButtonPanel()
@ -241,7 +244,12 @@ class ExtraKeysView(context: Context, attrs: AttributeSet) : LinearLayout(contex
addBuiltinKey(HOME)
addBuiltinKey(ARROW_UP)
addBuiltinKey(END)
addBuiltinKey(EXPAND_BUTTONS)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
addBuiltinKey(EXPAND_BUTTONS)
} else {
addBuiltinKey(SLASH)
}
}
private fun calculateButtonWidth(): Int {

View File

@ -50,6 +50,7 @@ abstract class IExtraButton : View.OnClickListener {
const val KEY_ARROW_LEFT_TEXT = "Left"
const val KEY_ARROW_RIGHT_TEXT = "Right"
const val KEY_SHOW_ALL_BUTTONS = "···"
const val KEY_SLASH = "/"
const val KEY_TOGGLE_IME = ""
const val KEY_ARROW_UP = ""
@ -100,6 +101,7 @@ abstract class IExtraButton : View.OnClickListener {
KEY_END -> keyCode = KeyEvent.KEYCODE_MOVE_END
KEY_FN -> keyCode = KeyEvent.KEYCODE_FUNCTION
KEY_SHIFT -> keyCode = KeyEvent.KEYCODE_SHIFT_LEFT
KEY_SLASH -> keyCode = KeyEvent.KEYCODE_SLASH
"" -> chars = "-"
// Function keys

View File

@ -15,6 +15,7 @@ import androidx.appcompat.widget.Toolbar
import androidx.core.view.MenuItemCompat
import androidx.recyclerview.widget.LinearLayoutManager
import com.github.wrdlbrnft.sortedlistadapter.SortedListAdapter
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.offsec.nhterm.R
import com.offsec.nhterm.component.ComponentManager
import com.offsec.nhterm.component.config.NeoPreference
@ -51,7 +52,7 @@ class PackageManagerActivity : AppCompatActivity(), SearchView.OnQueryTextListen
recyclerView.setHasFixedSize(true)
adapter = PackageAdapter(this, comparator, object : PackageAdapter.Listener {
override fun onModelClicked(model: PackageModel) {
AlertDialog.Builder(this@PackageManagerActivity)
MaterialAlertDialogBuilder(this@PackageManagerActivity, R.style.DialogStyle)
.setTitle(model.packageInfo.packageName)
.setMessage(model.getPackageDetails(this@PackageManagerActivity))
.setPositiveButton(R.string.install) { _, _ ->
@ -121,7 +122,7 @@ class PackageManagerActivity : AppCompatActivity(), SearchView.OnQueryTextListen
val repoEditor = view.findViewById<EditText>(R.id.dialog_edit_text2_editor)
repoEditor.setText("kali-rolling main")
AlertDialog.Builder(this)
MaterialAlertDialogBuilder(this, R.style.DialogStyle)
.setTitle(R.string.pref_package_source)
.setView(view)
.setNegativeButton(android.R.string.no, null)

View File

@ -16,14 +16,20 @@
package com.offsec.nhterm.ui.settings
import android.content.res.Configuration
import android.content.res.Resources.Theme
import android.os.Bundle
import android.preference.PreferenceActivity
import android.view.MenuInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import androidx.annotation.StyleRes
import androidx.appcompat.app.ActionBar
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.content.res.ResourcesCompat.ThemeCompat
import androidx.preference.Preference
import androidx.preference.PreferenceScreen
import com.offsec.nhterm.R
/**
* A [android.preference.PreferenceActivity] which implements and proxies the necessary calls
@ -39,6 +45,7 @@ abstract class BasePreferenceActivity : PreferenceActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
delegate.installViewFactory()
delegate.onCreate(savedInstanceState)
delegate.setTheme(R.style.AppTheme)
super.onCreate(savedInstanceState)
}

View File

@ -1,7 +1,9 @@
package com.offsec.nhterm.ui.settings
import android.os.Bundle
import android.preference.PreferenceActivity
import android.view.MenuItem
import androidx.preference.Preference
import com.offsec.nhterm.R
/**
@ -16,7 +18,7 @@ class GeneralSettingsActivity : BasePreferenceActivity() {
addPreferencesFromResource(R.xml.setting_general)
}
override fun onBuildHeaders(target: MutableList<Header>?) {
override fun onBuildHeaders(target: MutableList<PreferenceActivity.Header>?) {
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {

View File

@ -1,5 +1,6 @@
package com.offsec.nhterm.ui.settings
import android.os.Build
import android.os.Bundle
import android.view.MenuItem
import com.offsec.nhterm.R
@ -13,7 +14,11 @@ class SettingActivity : BasePreferenceActivity() {
super.onCreate(savedInstanceState)
supportActionBar?.title = getString(R.string.settings)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
addPreferencesFromResource(R.xml.settings_main)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
addPreferencesFromResource(R.xml.settings_main)
} else {
addPreferencesFromResource(R.xml.older_settings_main)
}
}
override fun onBuildHeaders(target: MutableList<Header>?) {

View File

@ -143,7 +143,11 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu_main, menu)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
menuInflater.inflate(R.menu.menu_main, menu)
} else {
menuInflater.inflate(R.menu.older_menu_main, menu)
}
TabSwitcher.setupWithMenu(
tabSwitcher, toolbar.menu,
@ -170,15 +174,19 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
true
}
R.id.menu_item_new_session -> {
addNewNetHunterSession("KALI LINUX")
addNewNetHunterSession("Kali Shell")
true
}
R.id.menu_item_new_system_session -> {
addNewAndroidSession("Android")
R.id.menu_item_new_emergency_session -> {
addNewEmergencySession("Emergency Shell")
true
}
R.id.menu_item_new_bash_session -> {
addNewAndroidSession("Android Shell")
true
}
R.id.menu_item_new_root_session -> {
addNewRootSession("Android SU")
addNewRootSession("Root Shell")
true
}
R.id.menu_item_package_settings -> {
@ -489,11 +497,11 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
}
private fun addNewSession() {
addNewNetHunterSession("KALI LINUX")
addNewNetHunterSession("Kali Shell")
}
private fun addNewSession(sessionName: String?, systemShell: Boolean, animation: Animation) {
addNewNetHunterSession("KALI LINUX")
addNewNetHunterSession("Kali Shell")
}
private fun addNewSessionWithProfile(profile: ShellProfile) {
@ -519,7 +527,7 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
.profile(profile)
val session = termService!!.createTermSession(parameter)
session.mSessionName = sessionName ?: generateSessionName("Kali Linux")
session.mSessionName = sessionName ?: generateSessionName("Kali Shell")
val tab = createTab(session.mSessionName) as TermTab
tab.termData.initializeSessionWith(session, sessionCallback, viewClient)
@ -528,6 +536,27 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
switchToSession(tab)
}
@SuppressLint("SdCardPath")
private fun addNewEmergencySession(sessionName: String?) {
val sessionCallback = TermSessionCallback()
val viewClient = TermViewClient(this)
val parameter = ShellParameter()
.callback(sessionCallback)
.executablePath("/system/bin/sh")
.systemShell(true)
val session = termService!!.createTermSession(parameter)
session.mSessionName = sessionName ?: generateSessionName("Emergency Shell")
val tab = createTab(session.mSessionName) as TermTab
tab.termData.initializeSessionWith(session, sessionCallback, viewClient)
addNewTab(tab, createRevealAnimation())
switchToSession(tab)
}
@SuppressLint("SdCardPath")
private fun addNewAndroidSession(sessionName: String?) {
val sessionCallback = TermSessionCallback()
@ -540,7 +569,7 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
val session = termService!!.createTermSession(parameter)
session.mSessionName = sessionName ?: generateSessionName("Android")
session.mSessionName = sessionName ?: generateSessionName("Android Shell")
val tab = createTab(session.mSessionName) as TermTab
tab.termData.initializeSessionWith(session, sessionCallback, viewClient)
@ -558,7 +587,7 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
.executablePath("/data/data/com.offsec.nhterm/files/usr/bin/kali")
val session = termService!!.createTermSession(parameter)
session.mSessionName = sessionName ?: generateSessionName("KALI LINUX")
session.mSessionName = sessionName ?: generateSessionName("Kali Shell")
val tab = createTab(session.mSessionName) as TermTab
tab.termData.initializeSessionWith(session, sessionCallback, viewClient)
@ -580,7 +609,7 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
val session = termService!!.createTermSession(parameter)
generateSessionName("Android")
session.mSessionName = sessionName ?: generateSessionName("ANDROID SU")
session.mSessionName = sessionName ?: generateSessionName("Root Shell")
val tab = createTab(session.mSessionName) as TermTab
tab.termData.initializeSessionWith(session, sessionCallback, viewClient)
@ -699,7 +728,7 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference
}
private fun createXTab(tabTitle: String?): Tab {
return postTabCreated(XSessionTab(tabTitle ?: "Kali Linux"))
return postTabCreated(XSessionTab(tabTitle ?: "Kali Shell"))
}
private fun <T : NeoTab> postTabCreated(tab: T): T {

View File

@ -3,6 +3,7 @@ package com.offsec.nhterm.ui.term
import android.content.Context
import android.content.res.Configuration
import android.graphics.Rect
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
@ -60,10 +61,12 @@ class NeoTabDecorator(val context: NeoTermActivity) : TabSwitcherDecorator() {
Terminals.setupExtraKeysView(extraKeysView)
val colorSchemeManager = ComponentManager.getComponent<ColorSchemeComponent>()
colorSchemeManager.applyColorScheme(
terminalView, extraKeysView,
colorSchemeManager.getCurrentColorScheme()
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
colorSchemeManager.applyColorScheme(
terminalView, extraKeysView,
colorSchemeManager.getCurrentColorScheme()
)
}
view
}

View File

@ -3,6 +3,7 @@ package com.offsec.nhterm.utils
import android.content.ContentUris
import android.content.Context
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.DocumentsContract
import android.provider.MediaStore
@ -37,17 +38,33 @@ fun Long.formatSizeInKB(): String {
}
fun Context.extractAssetsDir(assetDir: String, extractDir: String) = kotlin.runCatching {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val targetDir = Paths.get(extractDir)
Files.createDirectories(targetDir)
val assets = this.assets
assets.list(assetDir)?.let {
it.map { targetDir.resolve(it) }
.takeWhile { !Files.exists(it) }
.forEach { targetPath ->
assets.open("$assetDir/${targetPath.fileName}").use {
Files.copy(it, targetPath)
Paths.get(extractDir)
Files.createDirectories(targetDir)
val assets = this.assets
assets.list(assetDir)?.let {
it.map { targetDir.resolve(it) }
.takeWhile { !Files.exists(it) }
.forEach { targetPath ->
assets.open("$assetDir/${targetPath.fileName}").use {
Files.copy(it, targetPath)
}
}
}
}
} else {
val targetDir = com.llamalab.safs.Paths.get(extractDir)
com.llamalab.safs.Files.createDirectories(targetDir)
val assets = this.assets
assets.list(assetDir)?.let {
it.map { targetDir.resolve(it) }
.takeWhile { !com.llamalab.safs.Files.exists(it) }
.forEach { targetPath ->
assets.open("$assetDir/${targetPath.fileName}").use {
com.llamalab.safs.Files.copy(it, targetPath)
}
}
}
}
}

View File

@ -6,7 +6,7 @@
android:background="@color/terminal_background"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/terminal_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"

View File

@ -18,8 +18,12 @@
app:showAsAction="never">
<menu>
<item
android:id="@+id/menu_item_new_system_session"
android:title="@string/new_system_session"
android:id="@+id/menu_item_new_emergency_session"
android:title="@string/new_emergency_session"
app:showAsAction="never"/>
<item
android:id="@+id/menu_item_new_bash_session"
android:title="@string/new_bash_session"
app:showAsAction="never"/>
<item

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/toggle_tab_switcher_menu_item"
android:title="@string/toggle_tab_switcher_menu_item"
app:actionLayout="@layout/tab_switcher_menu_item"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/menu_item_new_session"
android:title="@string/new_session"
app:showAsAction="never"/>
<item
android:title="@string/new_session_more"
app:showAsAction="never">
<menu>
<item
android:id="@+id/menu_item_new_emergency_session"
android:title="@string/new_emergency_session"
app:showAsAction="never"/>
<item
android:id="@+id/menu_item_new_bash_session"
android:title="@string/new_bash_session"
app:showAsAction="never"/>
<item
android:id="@+id/menu_item_new_root_session"
android:title="@string/new_root_session"
app:showAsAction="never"/>
</menu>
</item>
<item
android:id="@+id/menu_item_settings"
android:title="@string/settings"
app:showAsAction="never"/>
</menu>

View File

@ -8,7 +8,8 @@
<string name="toggle_tab_switcher_menu_item">Toggle Tabs</string>
<string name="new_session">New Session</string>
<string name="new_session_more">New Session…</string>
<string name="new_system_session">New System Shell</string>
<string name="new_emergency_session">New Emergency Shell</string>
<string name="new_bash_session">New Bash Shell</string>
<string name="new_root_session">New Root Shell</string>
<string name="service_status_text">%d session(s)</string>
<string name="service_lock_acquired">(Wake Locked)</string>
@ -47,6 +48,7 @@
<string name="package_settings">Package Settings</string>
<string name="package_settings_desc">Source, Updates, Upgrades</string>
<string name="customization_settings_desc">Font, ColorScheme</string>
<string name="older_customization_settings_desc">Disabled as of no required functions available by old android api</string>
<string name="customization_settings">Customization</string>
<string name="toggle_ime">Toggle Keyboard</string>
@ -61,7 +63,7 @@
<string name="source_changed">APT source changed, you may get it updated by executing: apt update</string>
<string name="done">Done</string>
<string name="install">Install</string>
<string name="package_details">Package: %s\nVersion: %s\nDepends: %s\nInstalled Size: %s\nDescription: %s\nHome
<string name="package_details">Package: %s\n\nVersion: %s\n\nDepends: %s\n\nInstalled Size: %s\n\nDescription: %s\n\nHome
Page: %s
</string>
<string name="package_list_empty">Package list is empty, please check your source.</string>

View File

@ -9,6 +9,8 @@
<item name="android:actionBarStyle">@style/AppTheme.ActionBar</item>
<item name="actionBarStyle">@style/AppTheme.ActionBar</item>
<item name="android:dialogPreferenceStyle">@style/DialogStyleCompat</item>
</style>
<style name="AppTheme.NoActionBar" parent="@style/AppTheme">
@ -16,8 +18,9 @@
<item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.ActionBar" parent="@style/AppTheme">
<style name="AppTheme.ActionBar" parent="@style/Widget.Material3.ActionBar.Solid">
<item name="windowNoTitle">false</item>
<item name="windowActionBar">true</item>
<item name="android:height">55dp</item>
<item name="height">55dp</item>
<item name="titleTextStyle">@style/AppTheme.ActionBar.TitleText</item>
@ -25,7 +28,7 @@
</style>
<style name="AppTheme.ActionBar.TitleText" parent="@style/AppTheme">
<item name="android:textSize">12sp</item>
<item name="android:textSize">16sp</item>
</style>
<style name="AppTheme.PopupOverlay" parent="@style/Theme.Material3.Dark"/>
@ -70,7 +73,20 @@
<item name="android:buttonBarNegativeButtonStyle">@style/Alert.Button.Neutral</item>
<item name="buttonBarNeutralButtonStyle">@style/Alert.Button.Neutral</item>
<item name="android:buttonBarNeutralButtonStyle">@style/Alert.Button.Neutral</item>
</style>
<style name="DialogStyleCompat" parent="@style/ThemeOverlay.Material3.MaterialAlertDialog">
<item name="android:windowEnterAnimation">@android:anim/fade_in</item>
<item name="android:windowExitAnimation">@android:anim/fade_out</item>
<item name="colorPrimary">#547383</item>
<item name="android:textColor">@color/textColor</item>
<item name="android:textColorSecondary">@color/textColor</item>
<item name="android:textColorLink">#2D55A3</item>
<item name="buttonBarPositiveButtonStyle">@style/Alert.Button.Positive</item>
<item name="buttonBarNegativeButtonStyle">@style/Alert.Button.Neutral</item>
<item name="buttonBarNeutralButtonStyle">@style/Alert.Button.Neutral</item>
</style>
<style name="Alert.Button.Positive" parent="@style/Widget.Material3.Button.TextButton">

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<Preference
android:icon="@drawable/ic_general_white_36dp"
android:summary="@string/general_settings_desc"
android:title="@string/general_settings">
<intent
android:targetClass="com.offsec.nhterm.ui.settings.GeneralSettingsActivity"
android:targetPackage="com.offsec.nhterm"/>
</Preference>
<Preference
android:icon="@drawable/ic_ui_white_36dp"
android:summary="@string/ui_settings_desc"
android:title="@string/ui_settings">
<intent
android:targetClass="com.offsec.nhterm.ui.settings.UISettingsActivity"
android:targetPackage="com.offsec.nhterm"/>
</Preference>
<Preference
android:icon="@drawable/ic_customization_white_36dp"
android:summary="@string/older_customization_settings_desc"
android:title="@string/customization_settings"
android:enabled="false">
<intent
android:targetClass="com.offsec.nhterm.ui.customize.CustomizeActivity"
android:targetPackage="com.offsec.nhterm"/>
</Preference>
<Preference
android:icon="@drawable/ic_info_white_36dp"
android:title="@string/about">
<intent
android:targetClass="com.offsec.nhterm.ui.other.AboutActivity"
android:targetPackage="com.offsec.nhterm"/>
</Preference>
</PreferenceScreen>