mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-10-16 07:49:44 +08:00
fix: add preferences for the termux terminal
This commit is contained in:
@@ -26,11 +26,7 @@ import com.itsaky.androidide.R;
|
||||
import com.itsaky.androidide.app.LimitlessIDEActivity;
|
||||
import com.itsaky.androidide.databinding.ActivityPreferencesBinding;
|
||||
import com.itsaky.androidide.fragments.IDEPreferencesFragment;
|
||||
import com.itsaky.androidide.preferences.AboutPreferences;
|
||||
import com.itsaky.androidide.preferences.ConfigurationPreferences;
|
||||
import com.itsaky.androidide.preferences.DeveloperOptionsPreferences;
|
||||
import com.itsaky.androidide.preferences.IDEPreferences;
|
||||
import com.itsaky.androidide.preferences.PrivacyPreferences;
|
||||
import com.itsaky.androidide.preferences.RootPrefExtsKt;
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.view.ViewGroup
|
||||
import androidx.preference.PreferenceCategory
|
||||
import androidx.preference.PreferenceGroup
|
||||
import com.google.android.material.transition.MaterialSharedAxis
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.preferences.IPreference
|
||||
import com.itsaky.androidide.preferences.IPreferenceGroup
|
||||
import com.itsaky.androidide.preferences.IPreferenceScreen
|
||||
@@ -78,7 +79,6 @@ class IDEPreferencesFragment : BasePreferenceFragment() {
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
const val EXTRA_CHILDREN = "idepref_children"
|
||||
const val EXTRA_CHILDREN = "ide.preferences.fragment.children"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ private class GradleDistrubution(
|
||||
override val icon: Int? = drawable.ic_gradle,
|
||||
) : EditTextPreference() {
|
||||
|
||||
override fun onPreferenceChanged(preferece: Preference, newValue: Any?): Boolean {
|
||||
override fun onPreferenceChanged(preference: Preference, newValue: Any?): Boolean {
|
||||
gradleInstallationDir = newValue as String? ?: ""
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -17,28 +17,34 @@
|
||||
|
||||
package com.itsaky.androidide.preferences
|
||||
|
||||
import android.content.Context
|
||||
import androidx.preference.Preference
|
||||
import com.itsaky.androidide.utils.uncheckedCast
|
||||
import kotlinx.parcelize.IgnoredOnParcel
|
||||
import kotlin.reflect.KMutableProperty0
|
||||
|
||||
internal abstract class PropertyBasedMultiChoicePreference : MultiChoicePreference() {
|
||||
|
||||
@IgnoredOnParcel
|
||||
private val choices by lazy { getProperties() }
|
||||
|
||||
abstract fun getProperties(): Map<String, KMutableProperty0<Boolean>>
|
||||
|
||||
override fun getCheckedItems(choices: Array<String>): BooleanArray {
|
||||
return BooleanArray(choices.size) { this.choices[choices[it]]?.get() == true }
|
||||
override fun getEntries(preference: Preference): Array<PreferenceChoices.Entry> {
|
||||
val properties = getProperties()
|
||||
val entries = Array(properties.size) { PreferenceChoices.Entry.EMPTY }
|
||||
|
||||
var index = 0
|
||||
properties.forEach { (key, property) ->
|
||||
entries[index] = PreferenceChoices.Entry(key, property.get(), property)
|
||||
++index
|
||||
}
|
||||
|
||||
return entries
|
||||
}
|
||||
|
||||
override fun getChoices(context: Context): Array<String> {
|
||||
return choices.keys.toTypedArray()
|
||||
}
|
||||
|
||||
override fun onChoicesConfirmed(selectedPositions: IntArray, selections: Map<String, Boolean>) {
|
||||
selections.forEach { (key, value) ->
|
||||
choices[key]?.set(value)
|
||||
override fun onChoicesConfirmed(
|
||||
preference: Preference,
|
||||
entries: Array<PreferenceChoices.Entry>
|
||||
) {
|
||||
entries.forEach { entry ->
|
||||
uncheckedCast<KMutableProperty0<Boolean>>(entry.data).set(entry.isChecked)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import androidx.preference.Preference
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.databinding.LayoutTextSizeSliderBinding
|
||||
import com.itsaky.androidide.editor.schemes.IDEColorScheme
|
||||
import com.itsaky.androidide.editor.schemes.IDEColorSchemeProvider
|
||||
import com.itsaky.androidide.preferences.internal.AUTO_SAVE
|
||||
import com.itsaky.androidide.preferences.internal.COLOR_SCHEME
|
||||
@@ -176,26 +177,25 @@ private class TabSize(
|
||||
override val dialogCancellable = true
|
||||
|
||||
@IgnoredOnParcel
|
||||
private val choices = arrayOf("2", "4", "6", "8")
|
||||
private val tabSizes = intArrayOf(2, 4, 6, 8)
|
||||
|
||||
override fun getChoices(context: Context): Array<String> {
|
||||
return choices
|
||||
override fun getEntries(preference: Preference): Array<PreferenceChoices.Entry> {
|
||||
val currentTabSize = tabSize
|
||||
return Array(tabSizes.size) { index ->
|
||||
PreferenceChoices.Entry(
|
||||
label = tabSizes[index].toString(),
|
||||
_isChecked = currentTabSize == tabSizes[index],
|
||||
data = tabSizes[index]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getInitiallySelectionItemPosition(context: Context): Int {
|
||||
var current = tabSize / 2 - 1
|
||||
if (current < 0 || current >= choices.size) {
|
||||
current = 1
|
||||
}
|
||||
return current
|
||||
}
|
||||
|
||||
override fun onChoiceConfirmed(position: Int) {
|
||||
var size = (position + 1) * 2
|
||||
if (size < 2 || size > 8) {
|
||||
size = 4
|
||||
}
|
||||
tabSize = size
|
||||
override fun onChoiceConfirmed(
|
||||
preference: Preference,
|
||||
entry: PreferenceChoices.Entry,
|
||||
position: Int
|
||||
) {
|
||||
tabSize = entry.data as Int
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,16 +213,23 @@ private class ColorSchemePreference(
|
||||
@IgnoredOnParcel
|
||||
private val schemes = IDEColorSchemeProvider.list()
|
||||
|
||||
override fun getChoices(context: Context): Array<String> {
|
||||
return schemes.map { it.name }.toTypedArray()
|
||||
override fun getEntries(preference: Preference): Array<PreferenceChoices.Entry> {
|
||||
val currentColorScheme = colorScheme
|
||||
return Array(schemes.size) { index ->
|
||||
PreferenceChoices.Entry(
|
||||
schemes[index].name,
|
||||
currentColorScheme == schemes[index].key,
|
||||
schemes[index]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getInitiallySelectionItemPosition(context: Context): Int {
|
||||
return schemes.indexOfFirst { it.key == colorScheme }
|
||||
}
|
||||
|
||||
override fun onChoiceConfirmed(position: Int) {
|
||||
colorScheme = schemes[position].key
|
||||
override fun onChoiceConfirmed(
|
||||
preference: Preference,
|
||||
entry: PreferenceChoices.Entry,
|
||||
position: Int
|
||||
) {
|
||||
colorScheme = (entry.data as IDEColorScheme).key
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.itsaky.androidide.preferences
|
||||
|
||||
import android.content.Context
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.preference.Preference
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.preferences.internal.CONFIRM_PROJECT_OPEN
|
||||
@@ -38,6 +39,7 @@ import com.itsaky.androidide.resources.R.string
|
||||
import com.itsaky.androidide.resources.localization.LocaleProvider
|
||||
import com.itsaky.androidide.ui.themes.IDETheme
|
||||
import com.itsaky.androidide.ui.themes.IThemeManager
|
||||
import com.itsaky.androidide.ui.themes.ThemeManager
|
||||
import kotlinx.parcelize.IgnoredOnParcel
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@@ -106,28 +108,28 @@ class UiMode(
|
||||
@IgnoredOnParcel
|
||||
override val dialogCancellable = true
|
||||
|
||||
override fun getChoices(context: Context): Array<String> {
|
||||
return arrayOf(
|
||||
context.getString(R.string.uiMode_light),
|
||||
context.getString(R.string.uiMode_dark),
|
||||
context.getString(R.string.uiMode_system)
|
||||
)
|
||||
}
|
||||
override fun getEntries(preference: Preference): Array<PreferenceChoices.Entry> {
|
||||
val context = preference.context
|
||||
val currentUiMode = uiMode
|
||||
|
||||
override fun getInitiallySelectionItemPosition(context: Context): Int {
|
||||
return when (uiMode) {
|
||||
AppCompatDelegate.MODE_NIGHT_NO -> 0
|
||||
AppCompatDelegate.MODE_NIGHT_YES -> 1
|
||||
else -> 2
|
||||
return Array(3) { index ->
|
||||
val (label, mode) = when (index) {
|
||||
0 -> context.getString(R.string.uiMode_light) to AppCompatDelegate.MODE_NIGHT_NO
|
||||
1 -> context.getString(R.string.uiMode_dark) to AppCompatDelegate.MODE_NIGHT_YES
|
||||
2 -> context.getString(R.string.uiMode_system) to AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
|
||||
else -> throw IllegalStateException("Invalid index")
|
||||
}
|
||||
|
||||
PreferenceChoices.Entry(label, currentUiMode == mode, mode)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onChoiceConfirmed(position: Int) {
|
||||
uiMode = when (position) {
|
||||
0 -> AppCompatDelegate.MODE_NIGHT_NO
|
||||
1 -> AppCompatDelegate.MODE_NIGHT_YES
|
||||
else -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
|
||||
}
|
||||
override fun onChoiceConfirmed(
|
||||
preference: Preference,
|
||||
entry: PreferenceChoices.Entry,
|
||||
position: Int
|
||||
) {
|
||||
uiMode = entry.data as Int
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,18 +142,27 @@ class ThemeSelector(
|
||||
) : SingleChoicePreference() {
|
||||
|
||||
@IgnoredOnParcel
|
||||
private val themes = IDETheme.values()
|
||||
private val themes = IDETheme.entries
|
||||
|
||||
override fun getChoices(context: Context): Array<String> {
|
||||
return themes.map { context.getString(it.title) }.toTypedArray()
|
||||
override fun getEntries(preference: Preference): Array<PreferenceChoices.Entry> {
|
||||
val context = preference.context
|
||||
val currentTheme = IThemeManager.getInstance().getCurrentTheme()
|
||||
return Array(themes.size) { index ->
|
||||
val ideTheme = themes[index]
|
||||
PreferenceChoices.Entry(
|
||||
label = ContextCompat.getString(context, ideTheme.title),
|
||||
_isChecked = currentTheme.name == ideTheme.name,
|
||||
data = ideTheme
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getInitiallySelectionItemPosition(context: Context): Int {
|
||||
return themes.indexOf(IThemeManager.getInstance().getCurrentTheme())
|
||||
}
|
||||
|
||||
override fun onChoiceConfirmed(position: Int) {
|
||||
selectedTheme = themes[position].name
|
||||
override fun onChoiceConfirmed(
|
||||
preference: Preference,
|
||||
entry: PreferenceChoices.Entry,
|
||||
position: Int
|
||||
) {
|
||||
selectedTheme = (entry.data as IDETheme).name
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,39 +174,37 @@ class LocaleSelector(
|
||||
override val icon: Int? = R.drawable.ic_translate
|
||||
) : SingleChoicePreference() {
|
||||
|
||||
@IgnoredOnParcel
|
||||
private val locales by lazy {
|
||||
mutableListOf<String>().apply {
|
||||
add("")
|
||||
addAll(LocaleProvider.SUPPORTED_LOCALES.keys)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getChoices(context: Context): Array<String> {
|
||||
return locales.mapIndexed { index, locale ->
|
||||
override fun getEntries(preference: Preference): Array<PreferenceChoices.Entry> {
|
||||
val context = preference.context
|
||||
val currentLocale = selectedLocale
|
||||
val supportedLocales = LocaleProvider.SUPPORTED_LOCALES.keys.toList()
|
||||
return Array(supportedLocales.size + 1) { index ->
|
||||
if (index == 0) {
|
||||
context.getString(R.string.locale_system_default)
|
||||
PreferenceChoices.Entry(
|
||||
label = ContextCompat.getString(context, R.string.locale_system_default),
|
||||
_isChecked = selectedLocale == null,
|
||||
data = 0
|
||||
)
|
||||
} else {
|
||||
LocaleProvider.getLocale(locale)!!.let { it.getDisplayName(it) }
|
||||
val localeKey = supportedLocales[index - 1]
|
||||
val locale = LocaleProvider.getLocale(localeKey)!!
|
||||
PreferenceChoices.Entry(
|
||||
label = locale.getDisplayName(locale),
|
||||
_isChecked = currentLocale == localeKey,
|
||||
data = localeKey
|
||||
)
|
||||
}
|
||||
}.toTypedArray()
|
||||
}
|
||||
|
||||
override fun getInitiallySelectionItemPosition(context: Context): Int {
|
||||
val applicationLocales = AppCompatDelegate.getApplicationLocales()
|
||||
val locale = if (applicationLocales.size() > 0) {
|
||||
applicationLocales.get(0)
|
||||
} else {
|
||||
LocaleProvider.getLocale(selectedLocale)
|
||||
}
|
||||
|
||||
val key = LocaleProvider.getKey(locale) ?: return 0
|
||||
return locales.indexOf(key).coerceAtLeast(0)
|
||||
}
|
||||
|
||||
override fun onChoiceConfirmed(position: Int) {
|
||||
// Reset to null if 'System Default' is selected
|
||||
selectedLocale = if (position == 0) null else locales[position]
|
||||
override fun onChoiceConfirmed(
|
||||
preference: Preference,
|
||||
entry: PreferenceChoices.Entry,
|
||||
position: Int
|
||||
) {
|
||||
selectedLocale = entry.data.let { localeKey ->
|
||||
if (localeKey is Int) null else localeKey as String
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,7 +222,7 @@ class OpenLastProject(
|
||||
return pref
|
||||
}
|
||||
|
||||
override fun onPreferenceChanged(preferece: Preference, newValue: Any?): Boolean {
|
||||
override fun onPreferenceChanged(preference: Preference, newValue: Any?): Boolean {
|
||||
autoOpenProjects = newValue as Boolean? ?: autoOpenProjects
|
||||
return true
|
||||
}
|
||||
@@ -233,7 +242,7 @@ class ConfirmProjectOpen(
|
||||
return pref
|
||||
}
|
||||
|
||||
override fun onPreferenceChanged(preferece: Preference, newValue: Any?): Boolean {
|
||||
override fun onPreferenceChanged(preference: Preference, newValue: Any?): Boolean {
|
||||
confirmProjectOpen = newValue as Boolean? ?: confirmProjectOpen
|
||||
return true
|
||||
}
|
||||
@@ -253,7 +262,7 @@ class UseSytemShell(
|
||||
return pref
|
||||
}
|
||||
|
||||
override fun onPreferenceChanged(preferece: Preference, newValue: Any?): Boolean {
|
||||
override fun onPreferenceChanged(preference: Preference, newValue: Any?): Boolean {
|
||||
useSystemShell = newValue as Boolean? ?: useSystemShell
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
package com.itsaky.androidide.preferences
|
||||
|
||||
import com.itsaky.androidide.resources.R
|
||||
import com.itsaky.androidide.resources.R.string
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@@ -39,6 +38,7 @@ class ConfigurationPreferences(
|
||||
addPreference(GeneralPreferences())
|
||||
addPreference(EditorPreferences())
|
||||
addPreference(BuildAndRunPreferences())
|
||||
addPreference(TermuxPreferences())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ class DeveloperOptionsPreferences(
|
||||
@Parcelize
|
||||
class AboutPreferences(
|
||||
override val key: String = "idepref_category_about",
|
||||
override val title: Int = R.string.about,
|
||||
override val title: Int = string.about,
|
||||
override val children: List<IPreference> = mutableListOf()
|
||||
) : IPreferenceGroup() {
|
||||
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AndroidIDE is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.preferences
|
||||
|
||||
import android.content.Context
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.preference.Preference
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.app.IDEApplication
|
||||
import com.termux.shared.logger.Logger
|
||||
import com.termux.shared.termux.settings.preferences.TermuxAppSharedPreferences
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import kotlin.reflect.KMutableProperty0
|
||||
|
||||
private const val KEY_TERMUX_PREFERENCES = "ide.preferences.terminal"
|
||||
private const val KEY_TERMUX_DEBUGGING_PREFERENCES = "${KEY_TERMUX_PREFERENCES}.debugging"
|
||||
private const val KEY_TERMUX_DEBUGGING_LOG_LEVEL_PREFERENCE = "${KEY_TERMUX_DEBUGGING_PREFERENCES}.logLevel"
|
||||
private const val KEY_TERMUX_DEBUGGING_TERMINAL_VIEW_KEY_LOGGING_PREFERENCE = "${KEY_TERMUX_DEBUGGING_PREFERENCES}.terminalViewKeyLogging"
|
||||
private const val KEY_TERMUX_DEBUGGING_CRASH_REPORT_NOTIFICATIONS_PREFERENCE = "${KEY_TERMUX_DEBUGGING_PREFERENCES}.crashReportNotifications"
|
||||
private const val KEY_TERMUX_KBD_PREFERENCES = "${KEY_TERMUX_PREFERENCES}.keyboard"
|
||||
private const val KEY_TERMUX_KBD_SOFT_KDB_ENABLED_PREFERENCE = "${KEY_TERMUX_KBD_PREFERENCES}.softKeyboardEnabled"
|
||||
private const val KEY_TERMUX_KBD_SOFT_KDB_ONLY_IF_NO_HARD_KBD_PREFERENCE = "${KEY_TERMUX_KBD_PREFERENCES}.softKeyboardEnabled"
|
||||
private const val KEY_TERMUX_VIEW_PREFERENCES = "${KEY_TERMUX_PREFERENCES}.view"
|
||||
private const val KEY_TERMUX_VIEW_MARGIN_ADJUSTMENT_ENABLED_PREFERENCE = "${KEY_TERMUX_VIEW_PREFERENCES}.marginAdjustment"
|
||||
|
||||
abstract class TermuxSwitchPreference(
|
||||
@StringRes private val summaryOn: Int,
|
||||
@StringRes private val summaryOff: Int,
|
||||
property: KMutableProperty0<Boolean>
|
||||
) : SwitchPreference(property) {
|
||||
|
||||
override fun onCreatePreference(context: Context): Preference {
|
||||
return super.onCreatePreference(context).also { preference ->
|
||||
updateSummary(preference)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPreferenceChanged(preference: Preference, newValue: Any?): Boolean {
|
||||
return super.onPreferenceChanged(preference, newValue).also {
|
||||
updateSummary(preference)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateSummary(preference: Preference) {
|
||||
preference.summary = (if (getValue?.invoke() == true) {
|
||||
summaryOn
|
||||
} else {
|
||||
summaryOff
|
||||
}).let { summary ->
|
||||
ContextCompat.getString(preference.context, summary)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
class TermuxPreferences(
|
||||
override val key: String = KEY_TERMUX_PREFERENCES,
|
||||
override val title: Int = R.string.termux_preferences_title,
|
||||
override val summary: Int? = R.string.termux_preferences_summary,
|
||||
override val children: List<IPreference> = mutableListOf()
|
||||
) : IPreferenceScreen() {
|
||||
|
||||
init {
|
||||
addPreference(TermuxDebuggingPreferences())
|
||||
addPreference(TermuxKeyboardPreferences())
|
||||
addPreference(TermuxViewPreferences())
|
||||
}
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
class TermuxDebuggingPreferences(
|
||||
override val key: String = KEY_TERMUX_DEBUGGING_PREFERENCES,
|
||||
override val title: Int = R.string.termux_debugging_preferences_title,
|
||||
override val children: List<IPreference> = mutableListOf()
|
||||
) : IPreferenceGroup() {
|
||||
|
||||
init {
|
||||
addPreference(TermuxDebuggingLogLevelPreference())
|
||||
addPreference(TermuxDebuggingTerminalViewKeyLoggingPreference())
|
||||
addPreference(TermuxDebuggingCrashReportNotificationsPreference())
|
||||
}
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
class TermuxDebuggingLogLevelPreference(
|
||||
override val key: String = KEY_TERMUX_DEBUGGING_LOG_LEVEL_PREFERENCE,
|
||||
override val title: Int = R.string.log_level_title,
|
||||
override val icon: Int? = R.drawable.ic_bug
|
||||
) : SingleChoicePreference() {
|
||||
|
||||
override fun getEntries(preference: Preference): Array<PreferenceChoices.Entry> {
|
||||
val logLevels = Logger.getLogLevelsArray()
|
||||
val logLevelLabels = Logger.getLogLevelLabelsArray(preference.context, logLevels, true)
|
||||
val currentLogLevel = TermuxAppSharedPreferences.build(preference.context, false)?.logLevel
|
||||
?: Logger.DEFAULT_LOG_LEVEL
|
||||
return Array(logLevels.size) {
|
||||
PreferenceChoices.Entry(logLevelLabels[it], currentLogLevel == logLevels[it],
|
||||
logLevels[it])
|
||||
}
|
||||
}
|
||||
|
||||
override fun onChoiceConfirmed(
|
||||
preference: Preference,
|
||||
entry: PreferenceChoices.Entry,
|
||||
position: Int
|
||||
) {
|
||||
val newLevel = entry.data as Int
|
||||
TermuxAppSharedPreferences.build(preference.context, false)
|
||||
?.setLogLevel(preference.context, newLevel)
|
||||
|
||||
preference.summary = Logger.getLogLevelLabel(preference.context, newLevel, true)
|
||||
}
|
||||
|
||||
override fun onCreatePreference(context: Context): Preference {
|
||||
return super.onCreatePreference(context).also { preference ->
|
||||
val currentLogLevel = TermuxAppSharedPreferences.build(preference.context, false)?.logLevel
|
||||
?: Logger.DEFAULT_LOG_LEVEL
|
||||
preference.summary = Logger.getLogLevelLabel(context, currentLogLevel, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var isTerminalViewKeyLoggingEnabled: Boolean
|
||||
get() = TermuxAppSharedPreferences.build(IDEApplication.instance,
|
||||
true).isTerminalViewKeyLoggingEnabled
|
||||
set(value) {
|
||||
TermuxAppSharedPreferences.build(IDEApplication.instance,
|
||||
true).isTerminalViewKeyLoggingEnabled = value
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
class TermuxDebuggingTerminalViewKeyLoggingPreference(
|
||||
override val key: String = KEY_TERMUX_DEBUGGING_TERMINAL_VIEW_KEY_LOGGING_PREFERENCE,
|
||||
override val title: Int = R.string.termux_terminal_view_key_logging_enabled_title,
|
||||
override val icon: Int? = R.drawable.ic_keyboard,
|
||||
) : TermuxSwitchPreference(
|
||||
summaryOn = R.string.termux_terminal_view_key_logging_enabled_on,
|
||||
summaryOff = R.string.termux_terminal_view_key_logging_enabled_off,
|
||||
property = ::isTerminalViewKeyLoggingEnabled
|
||||
)
|
||||
|
||||
private var isTerminalCrashReportNotificationsEnabled: Boolean
|
||||
get() = TermuxAppSharedPreferences.build(IDEApplication.instance,
|
||||
true).areCrashReportNotificationsEnabled(false)
|
||||
set(value) {
|
||||
TermuxAppSharedPreferences.build(IDEApplication.instance,
|
||||
true).setCrashReportNotificationsEnabled(value)
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
class TermuxDebuggingCrashReportNotificationsPreference(
|
||||
override val key: String = KEY_TERMUX_DEBUGGING_CRASH_REPORT_NOTIFICATIONS_PREFERENCE,
|
||||
override val title: Int = R.string.termux_crash_report_notifications_enabled_title,
|
||||
override val icon: Int? = R.drawable.ic_bell,
|
||||
) : TermuxSwitchPreference(
|
||||
summaryOn = R.string.termux_crash_report_notifications_enabled_on,
|
||||
summaryOff = R.string.termux_crash_report_notifications_enabled_off,
|
||||
property = ::isTerminalCrashReportNotificationsEnabled
|
||||
)
|
||||
|
||||
@Parcelize
|
||||
class TermuxKeyboardPreferences(
|
||||
override val key: String = KEY_TERMUX_KBD_PREFERENCES,
|
||||
override val title: Int = R.string.termux_keyboard_header,
|
||||
override val children: List<IPreference> = mutableListOf()
|
||||
) : IPreferenceGroup() {
|
||||
|
||||
init {
|
||||
addPreference(TermuxKbdSoftKbdEnabledPreference())
|
||||
addPreference(TermuxKbdSoftKbdOnlyIfNoHardKbdEnabledPreference())
|
||||
}
|
||||
}
|
||||
|
||||
private var isSoftKbdEnabled: Boolean
|
||||
get() = TermuxAppSharedPreferences.build(IDEApplication.instance,
|
||||
true).isSoftKeyboardEnabled
|
||||
set(value) {
|
||||
TermuxAppSharedPreferences.build(IDEApplication.instance,
|
||||
true).isSoftKeyboardEnabled = value
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
class TermuxKbdSoftKbdEnabledPreference(
|
||||
override val key: String = KEY_TERMUX_KBD_SOFT_KDB_ENABLED_PREFERENCE,
|
||||
override val title: Int = R.string.termux_soft_keyboard_enabled_title,
|
||||
override val icon: Int? = R.drawable.ic_keyboard_soft,
|
||||
) : TermuxSwitchPreference(
|
||||
summaryOn = R.string.termux_soft_keyboard_enabled_on,
|
||||
summaryOff = R.string.termux_soft_keyboard_enabled_off,
|
||||
property = ::isSoftKbdEnabled
|
||||
)
|
||||
|
||||
private var isSoftKbdOnlyIfNoHardKbdEnabled: Boolean
|
||||
get() = TermuxAppSharedPreferences.build(IDEApplication.instance,
|
||||
true).isSoftKeyboardEnabledOnlyIfNoHardware
|
||||
set(value) {
|
||||
TermuxAppSharedPreferences.build(IDEApplication.instance,
|
||||
true).isSoftKeyboardEnabledOnlyIfNoHardware = value
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
class TermuxKbdSoftKbdOnlyIfNoHardKbdEnabledPreference(
|
||||
override val key: String = KEY_TERMUX_KBD_SOFT_KDB_ONLY_IF_NO_HARD_KBD_PREFERENCE,
|
||||
override val title: Int = R.string.termux_soft_keyboard_enabled_only_if_no_hardware_title,
|
||||
override val icon: Int? = R.drawable.ic_keyboard,
|
||||
) : TermuxSwitchPreference(
|
||||
summaryOn = R.string.termux_soft_keyboard_enabled_only_if_no_hardware_on,
|
||||
summaryOff = R.string.termux_soft_keyboard_enabled_only_if_no_hardware_off,
|
||||
property = ::isSoftKbdOnlyIfNoHardKbdEnabled
|
||||
)
|
||||
|
||||
@Parcelize
|
||||
class TermuxViewPreferences(
|
||||
override val key: String = KEY_TERMUX_VIEW_PREFERENCES,
|
||||
override val title: Int = R.string.termux_terminal_view_view_header,
|
||||
override val children: List<IPreference> = mutableListOf()
|
||||
) : IPreferenceGroup() {
|
||||
|
||||
init {
|
||||
addPreference(TermuxViewMarginAdjustmentEnabledPreference())
|
||||
}
|
||||
}
|
||||
|
||||
private var isViewMarginAdjustmentEnabled: Boolean
|
||||
get() = TermuxAppSharedPreferences.build(IDEApplication.instance,
|
||||
true).isTerminalMarginAdjustmentEnabled
|
||||
set(value) {
|
||||
TermuxAppSharedPreferences.build(IDEApplication.instance,
|
||||
true).setTerminalMarginAdjustment(value)
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
class TermuxViewMarginAdjustmentEnabledPreference(
|
||||
override val key: String = KEY_TERMUX_VIEW_MARGIN_ADJUSTMENT_ENABLED_PREFERENCE,
|
||||
override val title: Int = R.string.termux_terminal_view_terminal_margin_adjustment_title,
|
||||
override val icon: Int? = R.drawable.ic_space,
|
||||
) : TermuxSwitchPreference(
|
||||
summaryOn = R.string.termux_terminal_view_terminal_margin_adjustment_on,
|
||||
summaryOff = R.string.termux_terminal_view_terminal_margin_adjustment_off,
|
||||
property = ::isViewMarginAdjustmentEnabled
|
||||
)
|
||||
@@ -18,6 +18,7 @@
|
||||
package com.itsaky.androidide.preferences
|
||||
|
||||
import android.content.Context
|
||||
import androidx.preference.Preference
|
||||
import com.itsaky.androidide.resources.R.string
|
||||
import com.itsaky.androidide.preferences.internal.CLOSING_BRACKET_NEW_LINE
|
||||
import com.itsaky.androidide.preferences.internal.EMPTY_ELEMENTS_BEHAVIOR
|
||||
@@ -230,15 +231,24 @@ private class EmptyElementsBehavior(
|
||||
@IgnoredOnParcel
|
||||
override val dialogCancellable = true
|
||||
|
||||
override fun getInitiallySelectionItemPosition(context: Context): Int {
|
||||
return EmptyElements.valueOf(emptyElementsBehavior).ordinal
|
||||
override fun getEntries(preference: Preference): Array<PreferenceChoices.Entry> {
|
||||
val entries = EmptyElements.entries
|
||||
val currentBehavior = EmptyElements.valueOf(emptyElementsBehavior)
|
||||
|
||||
return Array(entries.size) { index ->
|
||||
PreferenceChoices.Entry(
|
||||
label = entries[index].toString(),
|
||||
_isChecked = currentBehavior == entries[index],
|
||||
data = entries[index]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getChoices(context: Context): Array<String> {
|
||||
return EmptyElements.values().map { it.toString() }.toTypedArray()
|
||||
}
|
||||
|
||||
override fun onChoiceConfirmed(position: Int) {
|
||||
emptyElementsBehavior = EmptyElements.values()[position].toString()
|
||||
override fun onChoiceConfirmed(
|
||||
preference: Preference,
|
||||
entry: PreferenceChoices.Entry,
|
||||
position: Int
|
||||
) {
|
||||
emptyElementsBehavior = (entry.data as EmptyElements).toString()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ abstract class BasePreference : IPreference() {
|
||||
return pref
|
||||
}
|
||||
|
||||
protected open fun onPreferenceChanged(preferece: Preference, newValue: Any?): Boolean {
|
||||
protected open fun onPreferenceChanged(preference: Preference, newValue: Any?): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
+22
-25
@@ -17,49 +17,45 @@
|
||||
|
||||
package com.itsaky.androidide.preferences
|
||||
|
||||
import androidx.annotation.CallSuper
|
||||
import androidx.preference.Preference
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
|
||||
/**
|
||||
* Base class for dialog preferences which allows users to choose from multiple items.
|
||||
* Base class for dialog preferences which allows users to choose from multiple items. Subclasses
|
||||
* must call [onSelectionChanged] to notify about selection changes.
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
abstract class ChoiceBasedDialogPreference : DialogPreference(), PreferenceChoices {
|
||||
|
||||
private var checkedPositions = intArrayOf()
|
||||
private var choices = emptyArray<PreferenceChoices.Entry>()
|
||||
|
||||
final override fun onConfigureDialog(preference: Preference, dialog: MaterialAlertDialogBuilder) {
|
||||
val choices = getChoices(preference.context)
|
||||
val checkedItems = getCheckedItems(choices)
|
||||
choices = getEntries(preference)
|
||||
|
||||
checkedPositions = checkedItems?.map { if(it) 1 else 0 }?.toIntArray() ?: intArrayOf()
|
||||
|
||||
onConfigureDialogChoices(preference, dialog, choices, checkedItems)
|
||||
val selections = BooleanArray(choices.size) { choices[it].isChecked }
|
||||
onConfigureDialogChoices(preference, dialog, choices, selections)
|
||||
|
||||
dialog.setPositiveButton(android.R.string.ok) { dialogInterface, _ ->
|
||||
dialogInterface.dismiss()
|
||||
|
||||
val selections = HashMap<String, Boolean>(choices.size)
|
||||
for (i in 0..checkedPositions.lastIndex) {
|
||||
selections[choices[i]] = checkedPositions[i] == 1
|
||||
}
|
||||
|
||||
onChoicesConfirmed(checkedPositions, selections)
|
||||
onChoicesConfirmed(preference, choices)
|
||||
}
|
||||
|
||||
dialog.setNegativeButton(android.R.string.cancel) { dialogInterface, _ ->
|
||||
dialogInterface.dismiss()
|
||||
onChoicesCancelled()
|
||||
onChoicesCancelled(preference)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSelectionChanged(position: Int, isSelected: Boolean) {
|
||||
if (position < 0 || position >= checkedPositions.size) {
|
||||
return
|
||||
}
|
||||
|
||||
checkedPositions[position] = if (isSelected) 1 else 0
|
||||
@CallSuper
|
||||
override fun onSelectionChanged(
|
||||
preference: Preference,
|
||||
entry: PreferenceChoices.Entry,
|
||||
position: Int,
|
||||
isSelected: Boolean
|
||||
) {
|
||||
entry._isChecked = isSelected
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,11 +64,12 @@ abstract class ChoiceBasedDialogPreference : DialogPreference(), PreferenceChoic
|
||||
protected abstract fun onConfigureDialogChoices(
|
||||
preference: Preference,
|
||||
dialog: MaterialAlertDialogBuilder,
|
||||
choices: Array<String>,
|
||||
checkedItems: BooleanArray?
|
||||
entries: Array<PreferenceChoices.Entry>,
|
||||
selections: BooleanArray
|
||||
)
|
||||
|
||||
override fun onChoicesConfirmed(selectedPositions: IntArray, selections: Map<String, Boolean>) {}
|
||||
override fun onChoicesConfirmed(preference: Preference, entries: Array<PreferenceChoices.Entry>) {
|
||||
}
|
||||
|
||||
override fun onChoicesCancelled() {}
|
||||
override fun onChoicesCancelled(preference: Preference) {}
|
||||
}
|
||||
+7
-5
@@ -34,15 +34,17 @@ abstract class MultiChoicePreference : ChoiceBasedDialogPreference(), Preference
|
||||
override fun onConfigureDialogChoices(
|
||||
preference: Preference,
|
||||
dialog: MaterialAlertDialogBuilder,
|
||||
choices: Array<String>,
|
||||
checkedItems: BooleanArray?
|
||||
entries: Array<PreferenceChoices.Entry>,
|
||||
selections: BooleanArray
|
||||
) {
|
||||
|
||||
val labels = Array(entries.size) { entries[it].label }
|
||||
|
||||
dialog.setMultiChoiceItems(
|
||||
choices,
|
||||
checkedItems!!
|
||||
labels,
|
||||
selections
|
||||
) { _, which, checked ->
|
||||
onSelectionChanged(which, checked)
|
||||
onSelectionChanged(preference, entries[which], which, checked)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ abstract class NumberInputEditTextPreference(
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPreferenceChanged(preferece: Preference, newValue: Any?): Boolean {
|
||||
override fun onPreferenceChanged(preference: Preference, newValue: Any?): Boolean {
|
||||
setValue?.let { it((newValue as String?)?.toInt() ?: 0) }
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
package com.itsaky.androidide.preferences
|
||||
|
||||
import android.content.Context
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import androidx.annotation.RestrictTo
|
||||
import androidx.preference.Preference
|
||||
|
||||
/**
|
||||
* A preference with choices.
|
||||
@@ -27,15 +27,10 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
*/
|
||||
interface PreferenceChoices {
|
||||
|
||||
/** Get the choices to show in the preference. */
|
||||
fun getChoices(context: Context): Array<String>
|
||||
|
||||
/**
|
||||
* Get all checked and unchecked items.
|
||||
*
|
||||
* @see MaterialAlertDialogBuilder.setMultiChoiceItems
|
||||
* Get the entries for this preference.
|
||||
*/
|
||||
fun getCheckedItems(choices: Array<String>): BooleanArray?
|
||||
fun getEntries(preference: Preference): Array<Entry>
|
||||
|
||||
/**
|
||||
* Called when an item is selected from the single choice list.
|
||||
@@ -43,17 +38,46 @@ interface PreferenceChoices {
|
||||
* @param position The position of the selected item.
|
||||
* @param isSelected Whether the item is selected.
|
||||
*/
|
||||
fun onSelectionChanged(position: Int, isSelected: Boolean)
|
||||
fun onSelectionChanged(preference: Preference, entry: Entry, position: Int, isSelected: Boolean)
|
||||
|
||||
/**
|
||||
* Called when the user confirms the selections.
|
||||
*
|
||||
* @param selectedPositions The positions of the selected items.
|
||||
* @param entries The entries.
|
||||
*/
|
||||
fun onChoicesConfirmed(selectedPositions: IntArray, selections: Map<String, Boolean>)
|
||||
fun onChoicesConfirmed(preference: Preference, entries: Array<Entry>)
|
||||
|
||||
/**
|
||||
* Called when the user cancels the selections.
|
||||
*/
|
||||
fun onChoicesCancelled()
|
||||
fun onChoicesCancelled(preference: Preference)
|
||||
|
||||
/**
|
||||
* Entry in [PreferenceChoices].
|
||||
*
|
||||
* @property label The label for the entry.
|
||||
* @property isChecked Whether the item is checked or not.
|
||||
* @property data The data object for the value.
|
||||
*/
|
||||
data class Entry(
|
||||
val label: CharSequence,
|
||||
@Suppress("PropertyName") internal var _isChecked: Boolean,
|
||||
val data: Any,
|
||||
) {
|
||||
|
||||
val isChecked: Boolean
|
||||
get() = _isChecked
|
||||
|
||||
companion object {
|
||||
|
||||
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
|
||||
val EMPTY = Entry("", false, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Map this [PreferenceChoices.Entry] array to entry labels.
|
||||
*/
|
||||
internal val Array<PreferenceChoices.Entry>.labels: Array<CharSequence>
|
||||
get() = Array(size) { this[it].label }
|
||||
+20
-27
@@ -17,10 +17,8 @@
|
||||
|
||||
package com.itsaky.androidide.preferences
|
||||
|
||||
import android.content.Context
|
||||
import androidx.preference.Preference
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import java.lang.IndexOutOfBoundsException
|
||||
|
||||
/**
|
||||
* A preference which allows selecting a single value from a list of values.
|
||||
@@ -39,49 +37,44 @@ abstract class SingleChoicePreference : ChoiceBasedDialogPreference(), Preferenc
|
||||
*/
|
||||
protected open var currentSelection: Int = -1
|
||||
|
||||
/**
|
||||
* Get the index of the selected item.
|
||||
* @see MaterialAlertDialogBuilder.setSingleChoiceItems
|
||||
*/
|
||||
abstract fun getInitiallySelectionItemPosition(context: Context): Int
|
||||
|
||||
final override fun getCheckedItems(choices: Array<String>): BooleanArray? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun onConfigureDialogChoices(
|
||||
preference: Preference,
|
||||
dialog: MaterialAlertDialogBuilder,
|
||||
choices: Array<String>,
|
||||
checkedItems: BooleanArray?
|
||||
entries: Array<PreferenceChoices.Entry>,
|
||||
selections: BooleanArray
|
||||
) {
|
||||
|
||||
this.currentSelection = getInitiallySelectionItemPosition(preference.context)
|
||||
if (currentSelection < 0 || currentSelection >= choices.size) {
|
||||
throw IndexOutOfBoundsException("Initial selection: $currentSelection, size=${choices.size}")
|
||||
val checkedCount = entries.count { it.isChecked }
|
||||
if (checkedCount != 1) {
|
||||
throw IllegalArgumentException(
|
||||
"Entries must have exactly one item checked, however, $checkedCount were checked")
|
||||
}
|
||||
|
||||
currentSelection = entries.indexOfFirst { it.isChecked }
|
||||
|
||||
dialog.setSingleChoiceItems(
|
||||
choices,
|
||||
entries.labels,
|
||||
currentSelection
|
||||
)
|
||||
{ _, position ->
|
||||
|
||||
if (currentSelection != -1) {
|
||||
onSelectionChanged(currentSelection, false)
|
||||
onSelectionChanged(preference, entries[currentSelection], currentSelection, false)
|
||||
}
|
||||
|
||||
currentSelection = position
|
||||
onSelectionChanged(position, true)
|
||||
onSelectionChanged(preference, entries[currentSelection], position, true)
|
||||
}
|
||||
}
|
||||
|
||||
final override fun onChoicesConfirmed(
|
||||
selectedPositions: IntArray,
|
||||
selections: Map<String, Boolean>
|
||||
override fun onChoicesConfirmed(
|
||||
preference: Preference,
|
||||
entries: Array<PreferenceChoices.Entry>
|
||||
) {
|
||||
onChoiceConfirmed(currentSelection)
|
||||
onChoiceConfirmed(preference, entries[currentSelection], currentSelection)
|
||||
}
|
||||
|
||||
protected open fun onChoiceConfirmed(position: Int) {}
|
||||
protected open fun onChoiceConfirmed(
|
||||
preference: Preference,
|
||||
entry: PreferenceChoices.Entry,
|
||||
position: Int
|
||||
) {}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.itsaky.androidide.preferences
|
||||
|
||||
import android.content.Context
|
||||
import androidx.preference.Preference
|
||||
import kotlin.reflect.KMutableProperty0
|
||||
|
||||
/**
|
||||
* A switch preference.
|
||||
@@ -29,13 +30,16 @@ abstract class SwitchPreference
|
||||
@JvmOverloads
|
||||
constructor(val setValue: ((Boolean) -> Unit)? = null, val getValue: (() -> Boolean)? = null) :
|
||||
BasePreference() {
|
||||
|
||||
constructor(property: KMutableProperty0<Boolean>) : this(property::set, property::get)
|
||||
|
||||
override fun onCreatePreference(context: Context): Preference {
|
||||
val pref = androidx.preference.SwitchPreference(context)
|
||||
pref.isChecked = prefValue()
|
||||
return pref
|
||||
}
|
||||
|
||||
override fun onPreferenceChanged(preferece: Preference, newValue: Any?): Boolean {
|
||||
override fun onPreferenceChanged(preference: Preference, newValue: Any?): Boolean {
|
||||
setValue?.let { it(newValue as Boolean? ?: prefValue()) }
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ This file is part of AndroidIDE.
|
||||
~
|
||||
~ AndroidIDE is free software: you can redistribute it and/or modify
|
||||
~ it under the terms of the GNU General Public License as published by
|
||||
~ the Free Software Foundation, either version 3 of the License, or
|
||||
~ (at your option) any later version.
|
||||
~
|
||||
~ AndroidIDE is distributed in the hope that it will be useful,
|
||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
~ GNU General Public License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License
|
||||
~ along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24"
|
||||
android:width="24dp">
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M10 21H14C14 22.1 13.1 23 12 23S10 22.1 10 21M21 19V20H3V19L5 17V11C5 7.9 7 5.2 10 4.3V4C10 2.9 10.9 2 12 2S14 2.9 14 4V4.3C17 5.2 19 7.9 19 11V17L21 19M17 11C17 8.2 14.8 6 12 6S7 8.2 7 11V18H17V11Z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ This file is part of AndroidIDE.
|
||||
~
|
||||
~ AndroidIDE is free software: you can redistribute it and/or modify
|
||||
~ it under the terms of the GNU General Public License as published by
|
||||
~ the Free Software Foundation, either version 3 of the License, or
|
||||
~ (at your option) any later version.
|
||||
~
|
||||
~ AndroidIDE is distributed in the hope that it will be useful,
|
||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
~ GNU General Public License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License
|
||||
~ along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:width="24dp" android:viewportWidth="24" android:viewportHeight="24">
|
||||
<path android:fillColor="#000000" android:pathData="M20,8H17.19C16.74,7.2 16.12,6.5 15.37,6L17,4.41L15.59,3L13.42,5.17C12.96,5.06 12.5,5 12,5C11.5,5 11.05,5.06 10.59,5.17L8.41,3L7,4.41L8.62,6C7.87,6.5 7.26,7.21 6.81,8H4V10H6.09C6.03,10.33 6,10.66 6,11V12H4V14H6V15C6,15.34 6.03,15.67 6.09,16H4V18H6.81C8.47,20.87 12.14,21.84 15,20.18C15.91,19.66 16.67,18.9 17.19,18H20V16H17.91C17.97,15.67 18,15.34 18,15V14H20V12H18V11C18,10.66 17.97,10.33 17.91,10H20V8M16,15A4,4 0 0,1 12,19A4,4 0 0,1 8,15V11A4,4 0 0,1 12,7A4,4 0 0,1 16,11V15M14,10V12H10V10H14M10,14H14V16H10V14Z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ This file is part of AndroidIDE.
|
||||
~
|
||||
~ AndroidIDE is free software: you can redistribute it and/or modify
|
||||
~ it under the terms of the GNU General Public License as published by
|
||||
~ the Free Software Foundation, either version 3 of the License, or
|
||||
~ (at your option) any later version.
|
||||
~
|
||||
~ AndroidIDE is distributed in the hope that it will be useful,
|
||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
~ GNU General Public License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License
|
||||
~ along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24"
|
||||
android:width="24dp">
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M4,5A2,2 0 0,0 2,7V17A2,2 0 0,0 4,19H20A2,2 0 0,0 22,17V7A2,2 0 0,0 20,5H4M4,7H20V17H4V7M5,8V10H7V8H5M8,8V10H10V8H8M11,8V10H13V8H11M14,8V10H16V8H14M17,8V10H19V8H17M5,11V13H7V11H5M8,11V13H10V11H8M11,11V13H13V11H11M14,11V13H16V11H14M17,11V13H19V11H17M8,14V16H16V14H8Z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ This file is part of AndroidIDE.
|
||||
~
|
||||
~ AndroidIDE is free software: you can redistribute it and/or modify
|
||||
~ it under the terms of the GNU General Public License as published by
|
||||
~ the Free Software Foundation, either version 3 of the License, or
|
||||
~ (at your option) any later version.
|
||||
~
|
||||
~ AndroidIDE is distributed in the hope that it will be useful,
|
||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
~ GNU General Public License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License
|
||||
~ along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24"
|
||||
android:width="24dp">
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M6,16H18V18H6V16M6,13V15H2V13H6M7,15V13H10V15H7M11,15V13H13V15H11M14,15V13H17V15H14M18,15V13H22V15H18M2,10H5V12H2V10M19,12V10H22V12H19M18,12H16V10H18V12M8,12H6V10H8V12M12,12H9V10H12V12M15,12H13V10H15V12M2,9V7H4V9H2M5,9V7H7V9H5M8,9V7H10V9H8M11,9V7H13V9H11M14,9V7H16V9H14M17,9V7H22V9H17Z" />
|
||||
</vector>
|
||||
@@ -115,12 +115,9 @@
|
||||
<string name="error_termux_service_start_failed_general">Failed to start TermuxService. Check logcat for exception message.</string>
|
||||
<string name="error_termux_service_start_failed_bg">Failed to start TermuxService while app is in background due to android bg restrictions.</string>
|
||||
|
||||
<!-- Termux Settings -->
|
||||
<string name="title_activity_termux_settings">&TERMUX_APP_NAME; Settings</string>
|
||||
|
||||
<!-- Termux App Preferences -->
|
||||
<string name="termux_preferences_title">&TERMUX_APP_NAME;</string>
|
||||
<string name="termux_preferences_summary">Preferences for &TERMUX_APP_NAME; app</string>
|
||||
<string name="termux_preferences_title">Termux</string>
|
||||
<string name="termux_preferences_summary">Preferences for the Termux terminal.</string>
|
||||
|
||||
<!-- Debugging Preferences -->
|
||||
<string name="termux_debugging_preferences_title">Debugging</string>
|
||||
|
||||
@@ -403,22 +403,22 @@ public class Logger {
|
||||
|
||||
|
||||
|
||||
public static CharSequence[] getLogLevelsArray() {
|
||||
return new CharSequence[]{
|
||||
String.valueOf(LOG_LEVEL_OFF),
|
||||
String.valueOf(LOG_LEVEL_NORMAL),
|
||||
String.valueOf(LOG_LEVEL_DEBUG),
|
||||
String.valueOf(LOG_LEVEL_VERBOSE)
|
||||
public static int[] getLogLevelsArray() {
|
||||
return new int[]{
|
||||
LOG_LEVEL_OFF,
|
||||
LOG_LEVEL_NORMAL,
|
||||
LOG_LEVEL_DEBUG,
|
||||
LOG_LEVEL_VERBOSE
|
||||
};
|
||||
}
|
||||
|
||||
public static CharSequence[] getLogLevelLabelsArray(Context context, CharSequence[] logLevels, boolean addDefaultTag) {
|
||||
public static CharSequence[] getLogLevelLabelsArray(Context context, int[] logLevels, boolean addDefaultTag) {
|
||||
if (logLevels == null) return null;
|
||||
|
||||
CharSequence[] logLevelLabels = new CharSequence[logLevels.length];
|
||||
|
||||
for(int i=0; i<logLevels.length; i++) {
|
||||
logLevelLabels[i] = getLogLevelLabel(context, Integer.parseInt(logLevels[i].toString()), addDefaultTag);
|
||||
logLevelLabels[i] = getLogLevelLabel(context, logLevels[i], addDefaultTag);
|
||||
}
|
||||
|
||||
return logLevelLabels;
|
||||
|
||||
Reference in New Issue
Block a user