diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 48d16183..63e45933 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -50,16 +50,6 @@ android:name=".ui.map.MapActivity" android:exported="true" android:excludeFromRecents="true" /> - - + }.onEach { (section, instance) -> + instance.enumSection = section instance.manager = context instance.navController = navController } } NavHost(navController, startDestination = startDestination.route, Modifier.padding(innerPadding)) { - sections.forEach { (section, instance) -> - composable(section.route) { - instance.Content() - } + sections.forEach { (_, instance) -> + instance.build(this) } } } diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/manager/Section.kt b/app/src/main/kotlin/me/rhunk/snapenhance/manager/Section.kt index 8cf1d226..ab9d338c 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/manager/Section.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/manager/Section.kt @@ -9,10 +9,12 @@ import androidx.compose.material.icons.filled.Stars import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.vector.ImageVector import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.compose.composable import me.rhunk.snapenhance.manager.data.ManagerContext -import me.rhunk.snapenhance.manager.sections.FeaturesSection import me.rhunk.snapenhance.manager.sections.HomeSection import me.rhunk.snapenhance.manager.sections.NotImplemented +import me.rhunk.snapenhance.manager.sections.features.FeaturesSection import kotlin.reflect.KClass enum class EnumSection( @@ -59,9 +61,16 @@ enum class EnumSection( open class Section { + lateinit var enumSection: EnumSection lateinit var manager: ManagerContext lateinit var navController: NavController @Composable open fun Content() { NotImplemented() } + + open fun build(navGraphBuilder: NavGraphBuilder) { + navGraphBuilder.composable(enumSection.route) { + Content() + } + } } \ No newline at end of file diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/manager/data/ManagerContext.kt b/app/src/main/kotlin/me/rhunk/snapenhance/manager/data/ManagerContext.kt index ab6863e2..c8643a7c 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/manager/data/ManagerContext.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/manager/data/ManagerContext.kt @@ -1,7 +1,6 @@ package me.rhunk.snapenhance.manager.data import android.content.Context -import me.rhunk.snapenhance.bridge.wrapper.ConfigWrapper import me.rhunk.snapenhance.bridge.wrapper.MappingsWrapper import me.rhunk.snapenhance.bridge.wrapper.TranslationWrapper import me.rhunk.snapenhance.core.config.ModConfig diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/manager/sections/FeaturesSection.kt b/app/src/main/kotlin/me/rhunk/snapenhance/manager/sections/FeaturesSection.kt deleted file mode 100644 index b0c60b7b..00000000 --- a/app/src/main/kotlin/me/rhunk/snapenhance/manager/sections/FeaturesSection.kt +++ /dev/null @@ -1,235 +0,0 @@ -package me.rhunk.snapenhance.manager.sections - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.widthIn -import androidx.compose.foundation.layout.wrapContentWidth -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.MaterialTheme -import androidx.compose.material.SnackbarHost -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.OpenInNew -import androidx.compose.material.icons.rounded.Save -import androidx.compose.material.rememberScaffoldState -import androidx.compose.material3.Card -import androidx.compose.material3.FilledIconButton -import androidx.compose.material3.FloatingActionButton -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Switch -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.compose.ui.window.Dialog -import androidx.compose.ui.window.DialogProperties -import kotlinx.coroutines.launch -import me.rhunk.snapenhance.Logger -import me.rhunk.snapenhance.config.ConfigProperty -import me.rhunk.snapenhance.config.impl.ConfigIntegerValue -import me.rhunk.snapenhance.config.impl.ConfigStateListValue -import me.rhunk.snapenhance.config.impl.ConfigStateSelection -import me.rhunk.snapenhance.config.impl.ConfigStateValue -import me.rhunk.snapenhance.config.impl.ConfigStringValue -import me.rhunk.snapenhance.manager.Dialogs -import me.rhunk.snapenhance.manager.Section - -typealias ClickCallback = (Boolean) -> Unit -typealias RegisterClickCallback = (ClickCallback) -> ClickCallback - -class FeaturesSection : Section() { - private val dialogs by lazy { Dialogs(manager) } - - @Composable - private fun PropertyAction(item: ConfigProperty, registerClickCallback: RegisterClickCallback) { - val showDialog = remember { mutableStateOf(false) } - val dialogComposable = remember { mutableStateOf<@Composable () -> Unit>({})} - - fun registerDialogOnClickCallback() = registerClickCallback { - showDialog.value = true - } - - if (showDialog.value) { - Dialog(onDismissRequest = { showDialog.value = false }, properties = DialogProperties()) { - dialogComposable.value() - } - } - - when (val container = remember { item.valueContainer }) { - is ConfigStateValue -> { - val state = remember { mutableStateOf(container.value()) } - Switch( - checked = state.value, - onCheckedChange = registerClickCallback { - state.value = state.value.not() - container.writeFrom(state.value.toString()) - } - ) - } - - is ConfigStateSelection -> { - registerDialogOnClickCallback() - dialogComposable.value = { - dialogs.StateSelectionDialog(item) - } - Text( - overflow = TextOverflow.Ellipsis, - maxLines = 1, - modifier = Modifier.widthIn(0.dp, 120.dp), - text = if (item.disableValueLocalization) container.value() else { - manager.translation.propertyOption(item, container.value()) - }, - ) - } - - is ConfigStateListValue, is ConfigStringValue, is ConfigIntegerValue -> { - dialogComposable.value = { - when (container) { - is ConfigStateListValue -> { - dialogs.StateListDialog(item) - } - is ConfigStringValue, is ConfigIntegerValue -> { - dialogs.KeyboardInputDialog(item) { showDialog.value = false } - } - } - } - - registerDialogOnClickCallback().let { { it.invoke(true) } }.also { - if (container is ConfigIntegerValue) { - FilledIconButton(onClick = it) { - Text(text = container.value().toString(), modifier = Modifier.wrapContentWidth(), overflow = TextOverflow.Ellipsis) - } - } else { - IconButton(onClick = it) { - Icon(Icons.Filled.OpenInNew, contentDescription = null) - } - } - } - } - } - } - - @Composable - private fun PropertyCard(item: ConfigProperty) { - val clickCallback = remember { mutableStateOf(null) } - Card( - modifier = Modifier - .fillMaxWidth() - .clickable { - clickCallback.value?.invoke(true) - } - .padding(start = 10.dp, end = 10.dp, top = 5.dp, bottom = 5.dp) - ) { - Row( - modifier = Modifier - .fillMaxSize() - .padding(all = 4.dp), - horizontalArrangement = Arrangement.SpaceBetween - ) { - Column( - modifier = Modifier - .align(Alignment.CenterVertically) - .weight(1f, fill = true) - .padding(all = 10.dp) - ) { - Text(text = manager.translation.propertyName(item), fontSize = 16.sp, fontWeight = FontWeight.Bold) - Text( - text = manager.translation.propertyDescription(item), - fontSize = 12.sp, - lineHeight = 15.sp - ) - } - - Column( - modifier = Modifier - .align(Alignment.CenterVertically) - .padding(all = 10.dp) - ) { - PropertyAction(item, registerClickCallback = { callback -> - clickCallback.value = callback - callback - }) - } - } - } - } - - @Composable - private fun PropertyContainer() { - val properties = remember { - val items by manager.config - items.properties.map { it.key to it.value } - } - - LazyColumn( - modifier = Modifier - .fillMaxHeight(), - verticalArrangement = Arrangement.Center - ) { - items(properties) { (key, value) -> - // Logger.debug("key: $key, value: $value") - } - } - } - - - @Composable - @Preview - override fun Content() { - val scope = rememberCoroutineScope() - val scaffoldState = rememberScaffoldState() - Scaffold( - snackbarHost = { SnackbarHost(scaffoldState.snackbarHostState) }, - floatingActionButton = { - FloatingActionButton( - onClick = { - //manager.config.writeConfig() - scope.launch { - scaffoldState.snackbarHostState.showSnackbar("Saved") - } - }, - containerColor = MaterialTheme.colors.primary, - contentColor = MaterialTheme.colors.onPrimary, - shape = RoundedCornerShape(16.dp), - ) { - Icon( - imageVector = Icons.Rounded.Save, - contentDescription = null - ) - } - }, - modifier = Modifier.fillMaxSize(), - content = { innerPadding -> - Column( - modifier = Modifier - .fillMaxSize() - .padding(innerPadding) - ) { - Text( - text = "Features", - modifier = Modifier.padding(all = 10.dp), - fontSize = 20.sp - ) - PropertyContainer() - } - } - ) - } -} \ No newline at end of file diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/manager/sections/features/CallbackAlias.kt b/app/src/main/kotlin/me/rhunk/snapenhance/manager/sections/features/CallbackAlias.kt new file mode 100644 index 00000000..9e93b545 --- /dev/null +++ b/app/src/main/kotlin/me/rhunk/snapenhance/manager/sections/features/CallbackAlias.kt @@ -0,0 +1,4 @@ +package me.rhunk.snapenhance.manager.sections.features + +typealias ClickCallback = (Boolean) -> Unit +typealias RegisterClickCallback = (ClickCallback) -> ClickCallback \ No newline at end of file diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/manager/Dialogs.kt b/app/src/main/kotlin/me/rhunk/snapenhance/manager/sections/features/Dialogs.kt similarity index 71% rename from app/src/main/kotlin/me/rhunk/snapenhance/manager/Dialogs.kt rename to app/src/main/kotlin/me/rhunk/snapenhance/manager/sections/features/Dialogs.kt index 586c9b66..5e07232e 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/manager/Dialogs.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/manager/sections/features/Dialogs.kt @@ -1,4 +1,4 @@ -package me.rhunk.snapenhance.manager +package me.rhunk.snapenhance.manager.sections.features import androidx.compose.foundation.ScrollState import androidx.compose.foundation.clickable @@ -29,16 +29,11 @@ import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.unit.dp -import me.rhunk.snapenhance.config.ConfigProperty -import me.rhunk.snapenhance.config.impl.ConfigIntegerValue -import me.rhunk.snapenhance.config.impl.ConfigStateListValue -import me.rhunk.snapenhance.config.impl.ConfigStateSelection -import me.rhunk.snapenhance.manager.data.ManagerContext +import me.rhunk.snapenhance.core.config.DataProcessors +import me.rhunk.snapenhance.core.config.PropertyPair -class Dialogs( - private val context: ManagerContext -) { +class Dialogs { @Composable fun DefaultDialogCard(content: @Composable ColumnScope.() -> Unit) { Card( @@ -65,17 +60,25 @@ class Dialogs( } @Composable - fun StateSelectionDialog(config: ConfigProperty) { - assert(config.valueContainer is ConfigStateSelection) - val keys = (config.valueContainer as ConfigStateSelection).keys() - val selectedValue = remember { - mutableStateOf(config.valueContainer.value()) + @Suppress("UNCHECKED_CAST") + fun UniqueSelectionDialog(property: PropertyPair<*>) { + val keys = (property.value.defaultValues as List).toMutableList().apply { + add(0, "disabled") } + + val selectedValue = remember { + mutableStateOf(property.value.getNullable()?.toString() ?: "disabled") + } + DefaultDialogCard { - keys.forEach { item -> + keys.forEachIndexed { index, item -> fun select() { selectedValue.value = item - config.valueContainer.writeFrom(item) + property.value.setAny(if (index == 0) { + null + } else { + item + }) } Row( @@ -83,9 +86,7 @@ class Dialogs( verticalAlignment = Alignment.CenterVertically ) { DefaultEntryText( - text = if (config.disableValueLocalization) - item - else context.translation.propertyOption(config, item), + text = item, modifier = Modifier.weight(1f) ) RadioButton( @@ -98,12 +99,12 @@ class Dialogs( } @Composable - fun KeyboardInputDialog(config: ConfigProperty, dismiss: () -> Unit = {}) { + fun KeyboardInputDialog(property: PropertyPair<*>, dismiss: () -> Unit = {}) { val focusRequester = remember { FocusRequester() } DefaultDialogCard { val fieldValue = remember { - mutableStateOf(config.valueContainer.read().let { + mutableStateOf(property.value.get().toString().let { TextFieldValue( text = it, selection = TextRange(it.length) @@ -123,8 +124,8 @@ class Dialogs( onValueChange = { fieldValue.value = it }, - keyboardOptions = when (config.valueContainer) { - is ConfigIntegerValue -> { + keyboardOptions = when (property.key.dataType.type) { + DataProcessors.Type.INTEGER -> { KeyboardOptions(keyboardType = KeyboardType.Number) } else -> { @@ -142,7 +143,15 @@ class Dialogs( Text(text = "Cancel") } Button(onClick = { - config.valueContainer.writeFrom(fieldValue.value.text) + if (property.key.dataType.type == DataProcessors.Type.INTEGER) { + runCatching { + property.value.setAny(fieldValue.value.text.toInt()) + }.onFailure { + property.value.setAny(0) + } + } else { + property.value.setAny(fieldValue.value.text) + } dismiss() }) { Text(text = "Ok") @@ -152,18 +161,23 @@ class Dialogs( } @Composable - fun StateListDialog(config: ConfigProperty) { - assert(config.valueContainer is ConfigStateListValue) - val stateList = (config.valueContainer as ConfigStateListValue).value() + @Suppress("UNCHECKED_CAST") + fun MultipleSelectionDialog(property: PropertyPair<*>) { + val defaultItems = property.value.defaultValues as List + val toggledStates = property.value.get() as MutableList DefaultDialogCard { - stateList.keys.forEach { key -> + defaultItems.forEach { key -> val state = remember { - mutableStateOf(stateList[key] ?: false) + mutableStateOf(toggledStates.contains(key)) } fun toggle(value: Boolean? = null) { state.value = value ?: !state.value - stateList[key] = state.value + if (state.value) { + toggledStates.add(key) + } else { + toggledStates.remove(key) + } } Row( @@ -171,9 +185,7 @@ class Dialogs( verticalAlignment = Alignment.CenterVertically ) { DefaultEntryText( - text = if (config.disableValueLocalization) - key - else context.translation.propertyOption(config, key), + text = key, modifier = Modifier .weight(1f) ) diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/manager/sections/features/FeaturesSection.kt b/app/src/main/kotlin/me/rhunk/snapenhance/manager/sections/features/FeaturesSection.kt new file mode 100644 index 00000000..75629241 --- /dev/null +++ b/app/src/main/kotlin/me/rhunk/snapenhance/manager/sections/features/FeaturesSection.kt @@ -0,0 +1,293 @@ +package me.rhunk.snapenhance.manager.sections.features + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.widthIn +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.MaterialTheme +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowBack +import androidx.compose.material.icons.filled.OpenInNew +import androidx.compose.material.icons.rounded.Save +import androidx.compose.material3.Card +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.FilledIconButton +import androidx.compose.material3.FloatingActionButton +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Scaffold +import androidx.compose.material3.SnackbarHost +import androidx.compose.material3.Switch +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.rememberBottomSheetScaffoldState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.window.Dialog +import androidx.compose.ui.window.DialogProperties +import androidx.navigation.NavGraphBuilder +import androidx.navigation.compose.composable +import androidx.navigation.navigation +import kotlinx.coroutines.launch +import me.rhunk.snapenhance.core.config.ConfigContainer +import me.rhunk.snapenhance.core.config.DataProcessors +import me.rhunk.snapenhance.core.config.PropertyPair +import me.rhunk.snapenhance.manager.Section + +class FeaturesSection : Section() { + private val dialogs by lazy { Dialogs() } + + companion object { + private const val MAIN_ROUTE = "root" + } + + @Composable + private fun PropertyAction(property: PropertyPair<*>, registerClickCallback: RegisterClickCallback) { + val showDialog = remember { mutableStateOf(false) } + val dialogComposable = remember { mutableStateOf<@Composable () -> Unit>({}) } + + fun registerDialogOnClickCallback() = registerClickCallback { + showDialog.value = true + } + + if (showDialog.value) { + Dialog( + onDismissRequest = { showDialog.value = false }, + properties = DialogProperties() + ) { + dialogComposable.value() + } + } + + val propertyValue = property.value + + when (val dataType = remember { property.key.dataType.type }) { + DataProcessors.Type.BOOLEAN -> { + val state = remember { mutableStateOf(propertyValue.get() as Boolean) } + Switch( + checked = state.value, + onCheckedChange = registerClickCallback { + state.value = state.value.not() + propertyValue.setAny(state.value) + } + ) + } + + DataProcessors.Type.STRING_UNIQUE_SELECTION -> { + registerDialogOnClickCallback() + + dialogComposable.value = { + dialogs.UniqueSelectionDialog(property) + } + + Text( + overflow = TextOverflow.Ellipsis, + maxLines = 1, + modifier = Modifier.widthIn(0.dp, 120.dp), + text = (propertyValue.getNullable() as? String) ?: "Disabled", + ) + } + + DataProcessors.Type.STRING_MULTIPLE_SELECTION, DataProcessors.Type.STRING, DataProcessors.Type.INTEGER -> { + dialogComposable.value = { + when (dataType) { + DataProcessors.Type.STRING_MULTIPLE_SELECTION -> { + dialogs.MultipleSelectionDialog(property) + } + DataProcessors.Type.STRING, DataProcessors.Type.INTEGER -> { + dialogs.KeyboardInputDialog(property) { showDialog.value = false } + } + else -> {} + } + } + + registerDialogOnClickCallback().let { { it.invoke(true) } }.also { + if (dataType == DataProcessors.Type.INTEGER) { + FilledIconButton(onClick = it) { + Text( + text = propertyValue.get().toString(), + modifier = Modifier.wrapContentWidth(), + overflow = TextOverflow.Ellipsis + ) + } + } else { + IconButton(onClick = it) { + Icon(Icons.Filled.OpenInNew, contentDescription = null) + } + } + } + } + else -> {} + } + + } + + @Composable + private fun PropertyCard(property: PropertyPair<*>) { + val clickCallback = remember { mutableStateOf(null) } + Card( + modifier = Modifier + .fillMaxWidth() + .padding(start = 10.dp, end = 10.dp, top = 5.dp, bottom = 5.dp) + ) { + Row( + modifier = Modifier + .fillMaxSize() + .clickable { + clickCallback.value?.invoke(true) + } + .padding(all = 4.dp), + horizontalArrangement = Arrangement.SpaceBetween + ) { + Column( + modifier = Modifier + .align(Alignment.CenterVertically) + .weight(1f, fill = true) + .padding(all = 10.dp) + ) { + Text( + text = property.name, + fontSize = 16.sp, + fontWeight = FontWeight.Bold + ) + Text( + text = property.name, + fontSize = 12.sp, + lineHeight = 15.sp + ) + } + + when (property.key.dataType.type) { + DataProcessors.Type.CONTAINER -> { + clickCallback.value = { + navController.navigate("container/${property.name}") + } + } + else -> { + Column( + modifier = Modifier + .align(Alignment.CenterVertically) + .padding(all = 10.dp) + ) { + PropertyAction(property, registerClickCallback = { callback -> + clickCallback.value = callback + callback + }) + } + } + } + } + } + } + + + @OptIn(ExperimentalMaterial3Api::class) + @Composable + private fun Container( + containerName: String, + configContainer: ConfigContainer + ) { + val properties = remember { + configContainer.properties.map { PropertyPair(it.key, it.value) } + } + + val scope = rememberCoroutineScope() + val scaffoldState = rememberBottomSheetScaffoldState() + Scaffold( + snackbarHost = { SnackbarHost(scaffoldState.snackbarHostState) }, + modifier = Modifier.fillMaxSize(), + topBar = { + TopAppBar( + title = { + Text(text = containerName, textAlign = TextAlign.Center) + }, + navigationIcon = { + if (navController.currentBackStackEntry?.destination?.route != MAIN_ROUTE) { + IconButton(onClick = { navController.popBackStack() }) { + Icon(Icons.Filled.ArrowBack, contentDescription = null) + } + } + } + ) + }, + floatingActionButton = { + FloatingActionButton( + onClick = { + manager.config.writeConfig() + scope.launch { + scaffoldState.snackbarHostState.showSnackbar("Saved") + } + }, + modifier = Modifier.padding(25.dp), + containerColor = MaterialTheme.colors.primary, + contentColor = MaterialTheme.colors.onPrimary, + shape = RoundedCornerShape(16.dp), + ) { + Icon( + imageVector = Icons.Rounded.Save, + contentDescription = null + ) + } + }, + content = { innerPadding -> + LazyColumn( + modifier = Modifier.fillMaxHeight().padding(innerPadding), + verticalArrangement = Arrangement.Center + ) { + items(properties) { + PropertyCard(it) + } + } + } + ) + + } + + override fun build(navGraphBuilder: NavGraphBuilder) { + val allContainers by lazy { + val containers = mutableMapOf() + fun queryContainerRecursive(container: ConfigContainer) { + container.properties.forEach { + if (it.key.dataType.type == DataProcessors.Type.CONTAINER) { + containers[it.key.name] = it.value.get() as ConfigContainer + queryContainerRecursive(it.value.get() as ConfigContainer) + } + } + } + queryContainerRecursive(manager.config.root) + containers + } + + navGraphBuilder.navigation(route = "features", startDestination = MAIN_ROUTE) { + composable(MAIN_ROUTE) { + Container(MAIN_ROUTE, manager.config.root) + } + + composable("container/{name}") { backStackEntry -> + backStackEntry.arguments?.getString("name")?.let { containerName -> + allContainers[containerName]?.let { + Container(containerName, it) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/manager/util/SaveFolderChecker.kt b/app/src/main/kotlin/me/rhunk/snapenhance/manager/util/SaveFolderChecker.kt index 757b903b..47601295 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/manager/util/SaveFolderChecker.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/manager/util/SaveFolderChecker.kt @@ -6,7 +6,6 @@ import android.content.Intent import android.widget.Toast import androidx.activity.ComponentActivity import androidx.activity.result.contract.ActivityResultContracts -import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.core.config.PropertyValue import kotlin.system.exitProcess diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/ModContext.kt b/core/src/main/kotlin/me/rhunk/snapenhance/ModContext.kt index 9ece2f56..7fa0f779 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/ModContext.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/ModContext.kt @@ -14,7 +14,6 @@ import kotlinx.coroutines.asCoroutineDispatcher import me.rhunk.snapenhance.bridge.BridgeClient import me.rhunk.snapenhance.bridge.wrapper.TranslationWrapper import me.rhunk.snapenhance.core.config.ModConfig -import me.rhunk.snapenhance.core.config.impl.RootConfig import me.rhunk.snapenhance.data.MessageSender import me.rhunk.snapenhance.database.DatabaseAccess import me.rhunk.snapenhance.features.Feature diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/SharedContext.kt b/core/src/main/kotlin/me/rhunk/snapenhance/SharedContext.kt index 2b1904ac..77d3a289 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/SharedContext.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/SharedContext.kt @@ -7,7 +7,6 @@ import android.content.Intent import android.os.Build import android.os.Environment import android.provider.Settings -import me.rhunk.snapenhance.bridge.wrapper.ConfigWrapper import me.rhunk.snapenhance.bridge.wrapper.TranslationWrapper import me.rhunk.snapenhance.download.DownloadTaskManager import kotlin.system.exitProcess @@ -18,7 +17,6 @@ import kotlin.system.exitProcess object SharedContext { lateinit var downloadTaskManager: DownloadTaskManager lateinit var translation: TranslationWrapper - lateinit var config: ConfigWrapper private fun askForStoragePermission(context: Context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { @@ -76,10 +74,6 @@ object SharedContext { loadFromContext(context) } } - if (!this::config.isInitialized) { - config = ConfigWrapper().apply { loadFromContext(context) } - } - //askForPermissions(context) } } \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/action/AbstractAction.kt b/core/src/main/kotlin/me/rhunk/snapenhance/action/AbstractAction.kt index 4bc21cc0..6026691c 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/action/AbstractAction.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/action/AbstractAction.kt @@ -1,12 +1,10 @@ package me.rhunk.snapenhance.action import me.rhunk.snapenhance.ModContext -import me.rhunk.snapenhance.config.ConfigProperty import java.io.File abstract class AbstractAction( - val nameKey: String, - val dependsOnProperty: ConfigProperty? = null, + val nameKey: String ) { lateinit var context: ModContext diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/CheckForUpdates.kt b/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/CheckForUpdates.kt index c142d1fa..3a8e2094 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/CheckForUpdates.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/CheckForUpdates.kt @@ -1,10 +1,9 @@ package me.rhunk.snapenhance.action.impl import me.rhunk.snapenhance.action.AbstractAction -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.features.impl.AutoUpdater -class CheckForUpdates : AbstractAction("action.check_for_updates", dependsOnProperty = ConfigProperty.AUTO_UPDATER) { +class CheckForUpdates : AbstractAction("action.check_for_updates") { override fun run() { context.executeAsync { runCatching { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/OpenMap.kt b/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/OpenMap.kt index bb5854a0..64180203 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/OpenMap.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/action/impl/OpenMap.kt @@ -3,11 +3,10 @@ package me.rhunk.snapenhance.action.impl import android.content.Intent import android.os.Bundle import me.rhunk.snapenhance.action.AbstractAction -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.core.BuildConfig import me.rhunk.snapenhance.ui.map.MapActivity -class OpenMap: AbstractAction("action.open_map", dependsOnProperty = ConfigProperty.LOCATION_SPOOF) { +class OpenMap: AbstractAction("action.open_map") { override fun run() { context.runOnUiThread { val mapActivityIntent = Intent() diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/bridge/BridgeClient.kt b/core/src/main/kotlin/me/rhunk/snapenhance/bridge/BridgeClient.kt index 6c9dd3f0..b3819ce3 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/bridge/BridgeClient.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/bridge/BridgeClient.kt @@ -10,10 +10,10 @@ import android.os.Handler import android.os.HandlerThread import android.os.IBinder import de.robv.android.xposed.XposedHelpers -import me.rhunk.snapenhance.core.BuildConfig import me.rhunk.snapenhance.Logger.xposedLog import me.rhunk.snapenhance.ModContext import me.rhunk.snapenhance.bridge.types.BridgeFileType +import me.rhunk.snapenhance.core.BuildConfig import me.rhunk.snapenhance.data.LocalePair import java.util.concurrent.CompletableFuture import java.util.concurrent.Executors diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/bridge/wrapper/ConfigWrapper.kt b/core/src/main/kotlin/me/rhunk/snapenhance/bridge/wrapper/ConfigWrapper.kt deleted file mode 100644 index 47c1bc21..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/bridge/wrapper/ConfigWrapper.kt +++ /dev/null @@ -1,73 +0,0 @@ -package me.rhunk.snapenhance.bridge.wrapper - -import android.content.Context -import com.google.gson.GsonBuilder -import com.google.gson.JsonObject -import me.rhunk.snapenhance.Logger -import me.rhunk.snapenhance.bridge.BridgeClient -import me.rhunk.snapenhance.bridge.FileLoaderWrapper -import me.rhunk.snapenhance.bridge.types.BridgeFileType -import me.rhunk.snapenhance.config.ConfigAccessor -import me.rhunk.snapenhance.config.ConfigProperty - -class ConfigWrapper: ConfigAccessor() { - companion object { - private val gson = GsonBuilder().setPrettyPrinting().create() - } - - private val file = FileLoaderWrapper(BridgeFileType.CONFIG, "{}".toByteArray(Charsets.UTF_8)) - - fun load() { - ConfigProperty.sortedByCategory().forEach { key -> - set(key, key.valueContainer) - } - - if (!file.isFileExists()) { - writeConfig() - return - } - - runCatching { - loadConfig() - }.onFailure { - Logger.error("Failed to load config", it) - writeConfig() - } - } - - fun save() { - writeConfig() - } - - private fun loadConfig() { - val configContent = file.read() - - val configObject: JsonObject = gson.fromJson( - configContent.toString(Charsets.UTF_8), - JsonObject::class.java - ) - - entries().forEach { (key, value) -> - value.writeFrom(configObject.get(key.name)?.asString ?: value.read()) - } - } - - fun writeConfig() { - val configObject = JsonObject() - entries().forEach { (key, value) -> - configObject.addProperty(key.name, value.read()) - } - - file.write(gson.toJson(configObject).toByteArray(Charsets.UTF_8)) - } - - fun loadFromContext(context: Context) { - file.loadFromContext(context) - load() - } - - fun loadFromBridge(bridgeClient: BridgeClient) { - file.loadFromBridge(bridgeClient) - load() - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/bridge/wrapper/TranslationWrapper.kt b/core/src/main/kotlin/me/rhunk/snapenhance/bridge/wrapper/TranslationWrapper.kt index 035d47f8..9bd2cc67 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/bridge/wrapper/TranslationWrapper.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/bridge/wrapper/TranslationWrapper.kt @@ -5,7 +5,6 @@ import com.google.gson.JsonObject import com.google.gson.JsonParser import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.bridge.BridgeClient -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.data.LocalePair import java.util.Locale @@ -80,18 +79,6 @@ class TranslationWrapper { return translationMap[key] ?: key.also { Logger.debug("Missing translation for $key") } } - fun propertyName(property: ConfigProperty): String { - return get("property.${property.translationKey}.name") - } - - fun propertyDescription(property: ConfigProperty): String { - return get("property.${property.translationKey}.description") - } - - fun propertyOption(property: ConfigProperty, item: String): String { - return get(property.getOptionTranslationKey(item)) - } - fun format(key: String, vararg args: Pair): String { return args.fold(get(key)) { acc, pair -> acc.replace("{${pair.first}}", pair.second) diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/config/ConfigAccessor.kt b/core/src/main/kotlin/me/rhunk/snapenhance/config/ConfigAccessor.kt deleted file mode 100644 index 2361bab5..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/config/ConfigAccessor.kt +++ /dev/null @@ -1,62 +0,0 @@ -package me.rhunk.snapenhance.config - -open class ConfigAccessor( - private val configMap: MutableMap> = mutableMapOf() -) { - fun bool(key: ConfigProperty): Boolean { - return get(key).value() as Boolean - } - - fun int(key: ConfigProperty): Int { - return get(key).value() as Int - } - - fun string(key: ConfigProperty): String { - return get(key).value() as String - } - - fun double(key: ConfigProperty): Double { - return get(key).value() as Double - } - - fun float(key: ConfigProperty): Float { - return get(key).value() as Float - } - - fun long(key: ConfigProperty): Long { - return get(key).value() as Long - } - - fun short(key: ConfigProperty): Short { - return get(key).value() as Short - } - - fun byte(key: ConfigProperty): Byte { - return get(key).value() as Byte - } - - fun char(key: ConfigProperty): Char { - return get(key).value() as Char - } - - @Suppress("UNCHECKED_CAST") - fun options(key: ConfigProperty): Map { - return get(key).value() as Map - } - - fun state(key: ConfigProperty): String { - return get(key).value() as String - } - - fun get(key: ConfigProperty): ConfigValue<*> { - return configMap[key]!! - } - - fun set(key: ConfigProperty, value: ConfigValue<*>) { - configMap[key] = value - } - - fun entries(): Set>> { - return configMap.entries - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/config/ConfigCategory.kt b/core/src/main/kotlin/me/rhunk/snapenhance/config/ConfigCategory.kt deleted file mode 100644 index 47f3356c..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/config/ConfigCategory.kt +++ /dev/null @@ -1,14 +0,0 @@ -package me.rhunk.snapenhance.config - -enum class ConfigCategory( - val key: String, - val hidden: Boolean = false -) { - SPYING_PRIVACY("spying_privacy"), - MEDIA_MANAGEMENT("media_manager"), - UI_TWEAKS("ui_tweaks"), - UPDATES("updates"), - CAMERA("camera"), - EXPERIMENTAL_DEBUGGING("experimental_debugging"), - DEVICE_SPOOFER("device_spoofer", hidden = true) -} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/config/ConfigProperty.kt b/core/src/main/kotlin/me/rhunk/snapenhance/config/ConfigProperty.kt deleted file mode 100644 index 39fa7390..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/config/ConfigProperty.kt +++ /dev/null @@ -1,417 +0,0 @@ -package me.rhunk.snapenhance.config - -import me.rhunk.snapenhance.config.impl.ConfigIntegerValue -import me.rhunk.snapenhance.config.impl.ConfigStateListValue -import me.rhunk.snapenhance.config.impl.ConfigStateSelection -import me.rhunk.snapenhance.config.impl.ConfigStateValue -import me.rhunk.snapenhance.config.impl.ConfigStringValue -import me.rhunk.snapenhance.data.NotificationType -import me.rhunk.snapenhance.features.impl.tweaks.CameraTweaks - -enum class ConfigProperty( - val translationKey: String, - val category: ConfigCategory, - val valueContainer: ConfigValue<*>, - val valueContainerTranslationKey: String? = null, - val shouldAppearInSettings: Boolean = true, - val disableValueLocalization: Boolean = false -) { - - //SPYING AND PRIVACY - MESSAGE_LOGGER("message_logger", - ConfigCategory.SPYING_PRIVACY, - ConfigStateValue(false) - ), - PREVENT_READ_RECEIPTS( - "prevent_read_receipts", - ConfigCategory.SPYING_PRIVACY, - ConfigStateValue(false) - ), - HIDE_BITMOJI_PRESENCE( - "hide_bitmoji_presence", - ConfigCategory.SPYING_PRIVACY, - ConfigStateValue(false) - ), - BETTER_NOTIFICATIONS( - "better_notifications", - ConfigCategory.SPYING_PRIVACY, - ConfigStateListValue( - listOf("snap", "chat", "reply_button", "download_button"), - mutableMapOf( - "snap" to false, - "chat" to false, - "reply_button" to false, - "download_button" to false - ) - ) - ), - NOTIFICATION_BLACKLIST( - "notification_blacklist", - ConfigCategory.SPYING_PRIVACY, - ConfigStateListValue( - NotificationType.getIncomingValues().map { it.key }, - NotificationType.getIncomingValues().associate { it.key to false }.toMutableMap() - ), - valueContainerTranslationKey = "notifications", - ), - DISABLE_METRICS("disable_metrics", - ConfigCategory.SPYING_PRIVACY, - ConfigStateValue(false) - ), - BLOCK_ADS("block_ads", - ConfigCategory.SPYING_PRIVACY, - ConfigStateValue(false) - ), - UNLIMITED_SNAP_VIEW_TIME("unlimited_snap_view_time", - ConfigCategory.SPYING_PRIVACY, - ConfigStateValue(false) - ), - PREVENT_SENDING_MESSAGES( - "prevent_sending_messages", - ConfigCategory.SPYING_PRIVACY, - ConfigStateListValue( - NotificationType.getOutgoingValues().map { it.key }, - NotificationType.getOutgoingValues().associate { it.key to false }.toMutableMap() - ), - valueContainerTranslationKey = "notifications", - ), - ANONYMOUS_STORY_VIEW( - "anonymous_story_view", - ConfigCategory.SPYING_PRIVACY, - ConfigStateValue(false) - ), - HIDE_TYPING_NOTIFICATION( - "hide_typing_notification", - ConfigCategory.SPYING_PRIVACY, - ConfigStateValue(false) - ), - - //MEDIA MANAGEMENT - SAVE_FOLDER( - "save_folder", - ConfigCategory.MEDIA_MANAGEMENT, - ConfigStringValue("", isFolderPath =true), - ), - AUTO_DOWNLOAD_OPTIONS( - "auto_download_options", - ConfigCategory.MEDIA_MANAGEMENT, - ConfigStateListValue( - listOf("friend_snaps", "friend_stories", "public_stories", "spotlight"), - mutableMapOf( - "friend_snaps" to false, - "friend_stories" to false, - "public_stories" to false, - "spotlight" to false - ) - ) - ), - DOWNLOAD_OPTIONS( - "download_options", - ConfigCategory.MEDIA_MANAGEMENT, - ConfigStateListValue( - listOf( - "allow_duplicate", - "create_user_folder", - "append_hash", - "append_date_time", - "append_type", - "append_username", - "merge_overlay" - ), - mutableMapOf( - "allow_duplicate" to false, - "create_user_folder" to true, - "append_hash" to true, - "append_date_time" to true, - "append_type" to false, - "append_username" to false, - "merge_overlay" to false, - ) - ) - ), - CHAT_DOWNLOAD_CONTEXT_MENU( - "chat_download_context_menu", - ConfigCategory.MEDIA_MANAGEMENT, - ConfigStateValue(false) - ), - GALLERY_MEDIA_SEND_OVERRIDE( - "gallery_media_send_override", - ConfigCategory.MEDIA_MANAGEMENT, - ConfigStateSelection( - listOf("OFF", "NOTE", "SNAP", "LIVE_SNAP"), - "OFF" - ) - ), - AUTO_SAVE_MESSAGES("auto_save_messages", - ConfigCategory.MEDIA_MANAGEMENT, - ConfigStateListValue( - listOf("CHAT", "SNAP", "NOTE", "EXTERNAL_MEDIA", "STICKER") - ) - ), - - FORCE_MEDIA_SOURCE_QUALITY( - "force_media_source_quality", - ConfigCategory.MEDIA_MANAGEMENT, - ConfigStateValue(false) - ), - DOWNLOAD_LOGGING( - "download_logging", - ConfigCategory.MEDIA_MANAGEMENT, - ConfigStateListValue( - listOf("started", "success", "progress", "failure"), - mutableMapOf( - "started" to false, - "success" to true, - "progress" to false, - "failure" to true - ) - ) - ), - - //UI AND TWEAKS - ENABLE_FRIEND_FEED_MENU_BAR( - "enable_friend_feed_menu_bar", - ConfigCategory.UI_TWEAKS, - ConfigStateValue(false) - ), - FRIEND_FEED_MENU_BUTTONS( - "friend_feed_menu_buttons", - ConfigCategory.UI_TWEAKS, - ConfigStateListValue( - listOf("auto_download_blacklist", "anti_auto_save", "stealth_mode", "conversation_info"), - mutableMapOf( - "auto_download_blacklist" to false, - "anti_auto_save" to false, - "stealth_mode" to true, - "conversation_info" to true - ) - ) - ), - FRIEND_FEED_MENU_POSITION("friend_feed_menu_buttons_position", - ConfigCategory.UI_TWEAKS, - ConfigIntegerValue(1) - ), - HIDE_UI_ELEMENTS( - "hide_ui_elements", - ConfigCategory.UI_TWEAKS, - ConfigStateListValue( - listOf("remove_voice_record_button", "remove_stickers_button", "remove_cognac_button", "remove_live_location_share_button", "remove_call_buttons", "remove_camera_borders"), - mutableMapOf( - "remove_voice_record_button" to false, - "remove_stickers_button" to false, - "remove_cognac_button" to false, - "remove_live_location_share_button" to false, - "remove_call_buttons" to false, - "remove_camera_borders" to false - ) - ) - ), - HIDE_STORY_SECTION( - "hide_story_section", - ConfigCategory.UI_TWEAKS, - ConfigStateListValue( - listOf("hide_friend_suggestions", "hide_friends", "hide_following", "hide_for_you"), - mutableMapOf( - "hide_friend_suggestions" to false, - "hide_friends" to false, - "hide_following" to false, - "hide_for_you" to false - ) - ) - ), - STORY_VIEWER_OVERRIDE("story_viewer_override", - ConfigCategory.UI_TWEAKS, - ConfigStateSelection( - listOf("OFF", "DISCOVER_PLAYBACK_SEEKBAR", "VERTICAL_STORY_VIEWER"), - "OFF" - ) - ), - STREAK_EXPIRATION_INFO( - "streak_expiration_info", - ConfigCategory.UI_TWEAKS, - ConfigStateValue(false) - ), - DISABLE_SNAP_SPLITTING( - "disable_snap_splitting", - ConfigCategory.UI_TWEAKS, - ConfigStateValue(false) - ), - DISABLE_VIDEO_LENGTH_RESTRICTION( - "disable_video_length_restriction", - ConfigCategory.UI_TWEAKS, - ConfigStateValue(false) - ), - SNAPCHAT_PLUS("snapchat_plus", - ConfigCategory.UI_TWEAKS, - ConfigStateValue(false) - ), - NEW_MAP_UI("new_map_ui", - ConfigCategory.UI_TWEAKS, - ConfigStateValue(false) - ), - LOCATION_SPOOF( - "location_spoof", - ConfigCategory.UI_TWEAKS, - ConfigStateValue(false) - ), - LATITUDE( - "latitude_value", - ConfigCategory.UI_TWEAKS, - ConfigStringValue("0.0000"), - shouldAppearInSettings = false - ), - LONGITUDE( - "longitude_value", - ConfigCategory.UI_TWEAKS, - ConfigStringValue("0.0000"), - shouldAppearInSettings = false - ), - MESSAGE_PREVIEW_LENGTH( - "message_preview_length", - ConfigCategory.UI_TWEAKS, - ConfigIntegerValue(20) - ), - UNLIMITED_CONVERSATION_PINNING( - "unlimited_conversation_pinning", - ConfigCategory.UI_TWEAKS, - ConfigStateValue(false) - ), - DISABLE_SPOTLIGHT( - "disable_spotlight", - ConfigCategory.UI_TWEAKS, - ConfigStateValue(false) - ), - ENABLE_APP_APPEARANCE( - "enable_app_appearance", - ConfigCategory.UI_TWEAKS, - ConfigStateValue(false) - ), - STARTUP_PAGE_OVERRIDE( - "startup_page_override", - ConfigCategory.UI_TWEAKS, - ConfigStateSelection( - listOf( - "OFF", - "ngs_map_icon_container", - "ngs_chat_icon_container", - "ngs_camera_icon_container", - "ngs_community_icon_container", - "ngs_spotlight_icon_container", - "ngs_search_icon_container" - ), - "OFF" - ) - ), - DISABLE_GOOGLE_PLAY_DIALOGS( - "disable_google_play_dialogs", - ConfigCategory.UI_TWEAKS, - ConfigStateValue(false) - ), - - //CAMERA - CAMERA_DISABLE( - "disable_camera", - ConfigCategory.CAMERA, - ConfigStateValue(false) - ), - IMMERSIVE_CAMERA_PREVIEW( - "immersive_camera_preview", - ConfigCategory.CAMERA, - ConfigStateValue(false) - ), - OVERRIDE_PREVIEW_RESOLUTION( - "preview_resolution", - ConfigCategory.CAMERA, - ConfigStateSelection( - CameraTweaks.resolutions, - "OFF" - ), - disableValueLocalization = true - ), - OVERRIDE_PICTURE_RESOLUTION( - "picture_resolution", - ConfigCategory.CAMERA, - ConfigStateSelection( - CameraTweaks.resolutions, - "OFF" - ), - disableValueLocalization = true - ), - FORCE_HIGHEST_FRAME_RATE( - "force_highest_frame_rate", - ConfigCategory.CAMERA, - ConfigStateValue(false) - ), - FORCE_CAMERA_SOURCE_ENCODING( - "force_camera_source_encoding", - ConfigCategory.CAMERA, - ConfigStateValue(false) - ), - - // UPDATES - AUTO_UPDATER( - "auto_updater", - ConfigCategory.UPDATES, - ConfigStateSelection( - listOf("DISABLED", "EVERY_LAUNCH", "DAILY", "WEEKLY"), - "DAILY" - ) - ), - - // EXPERIMENTAL DEBUGGING - APP_PASSCODE( - "app_passcode", - ConfigCategory.EXPERIMENTAL_DEBUGGING, - ConfigStringValue("", isHidden = true) - ), - APP_LOCK_ON_RESUME( - "app_lock_on_resume", - ConfigCategory.EXPERIMENTAL_DEBUGGING, - ConfigStateValue(false) - ), - INFINITE_STORY_BOOST( - "infinite_story_boost", - ConfigCategory.EXPERIMENTAL_DEBUGGING, - ConfigStateValue(false) - ), - MEO_PASSCODE_BYPASS( - "meo_passcode_bypass", - ConfigCategory.EXPERIMENTAL_DEBUGGING, - ConfigStateValue(false) - ), - AMOLED_DARK_MODE( - "amoled_dark_mode", - ConfigCategory.EXPERIMENTAL_DEBUGGING, - ConfigStateValue(false) - ), - UNLIMITED_MULTI_SNAP( - "unlimited_multi_snap", - ConfigCategory.EXPERIMENTAL_DEBUGGING, - ConfigStateValue(false) - ), - - //DEVICE SPOOFER - DEVICE_SPOOF( - "device_spoof", - ConfigCategory.DEVICE_SPOOFER, - ConfigStateValue(false) - ), - FINGERPRINT( - "device_fingerprint", - ConfigCategory.DEVICE_SPOOFER, - ConfigStringValue("") - ), - ANDROID_ID( - "android_id", - ConfigCategory.DEVICE_SPOOFER, - ConfigStringValue("") - ); - - fun getOptionTranslationKey(key: String) = "option.property.${valueContainerTranslationKey ?: translationKey}.$key" - - companion object { - fun sortedByCategory(): List { - return values().sortedBy { it.category.ordinal } - } - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/config/ConfigValue.kt b/core/src/main/kotlin/me/rhunk/snapenhance/config/ConfigValue.kt deleted file mode 100644 index e12c8f6c..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/config/ConfigValue.kt +++ /dev/null @@ -1,22 +0,0 @@ -package me.rhunk.snapenhance.config - -abstract class ConfigValue { - private val propertyChangeListeners = mutableListOf<(T) -> Unit>() - - fun addPropertyChangeListener(listener: (T) -> Unit) = propertyChangeListeners.add(listener) - fun removePropertyChangeListener(listener: (T) -> Unit) = propertyChangeListeners.remove(listener) - - abstract fun value(): T - abstract fun read(): String - protected abstract fun write(value: String) - - protected fun onValueChanged() { - propertyChangeListeners.forEach { it(value()) } - } - - fun writeFrom(value: String) { - val oldValue = read() - write(value) - if (oldValue != value) onValueChanged() - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/config/impl/ConfigIntegerValue.kt b/core/src/main/kotlin/me/rhunk/snapenhance/config/impl/ConfigIntegerValue.kt deleted file mode 100644 index e02cac04..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/config/impl/ConfigIntegerValue.kt +++ /dev/null @@ -1,17 +0,0 @@ -package me.rhunk.snapenhance.config.impl - -import me.rhunk.snapenhance.config.ConfigValue - -class ConfigIntegerValue( - private var value: Int -) : ConfigValue() { - override fun value() = value - - override fun read(): String { - return value.toString() - } - - override fun write(value: String) { - this.value = value.toInt() - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/config/impl/ConfigStateListValue.kt b/core/src/main/kotlin/me/rhunk/snapenhance/config/impl/ConfigStateListValue.kt deleted file mode 100644 index 005d9aa6..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/config/impl/ConfigStateListValue.kt +++ /dev/null @@ -1,32 +0,0 @@ -package me.rhunk.snapenhance.config.impl - -import me.rhunk.snapenhance.config.ConfigValue - -class ConfigStateListValue( - private val keys: List, - private var states: MutableMap = mutableMapOf() -) : ConfigValue>() { - override fun value() = states - - fun setKey(key: String, state: Boolean) { - states[key] = state - onValueChanged() - } - - operator fun get(key: String) = states[key] ?: false - - override fun read(): String { - return keys.joinToString("|") { "$it:${states[it]}" } - } - - override fun write(value: String) { - value.split("|").forEach { - val (key, state) = it.split(":") - states[key] = state.toBoolean() - } - } - - override fun toString(): String { - return states.filter { it.value }.keys.joinToString(", ") { it } - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/config/impl/ConfigStateSelection.kt b/core/src/main/kotlin/me/rhunk/snapenhance/config/impl/ConfigStateSelection.kt deleted file mode 100644 index 4f9d3f86..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/config/impl/ConfigStateSelection.kt +++ /dev/null @@ -1,22 +0,0 @@ -package me.rhunk.snapenhance.config.impl - -import me.rhunk.snapenhance.config.ConfigValue - -class ConfigStateSelection( - private val keys: List, - private var state: String = "" -) : ConfigValue() { - fun keys(): List { - return keys - } - - override fun value() = state - - override fun read(): String { - return state - } - - override fun write(value: String) { - state = value - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/config/impl/ConfigStateValue.kt b/core/src/main/kotlin/me/rhunk/snapenhance/config/impl/ConfigStateValue.kt deleted file mode 100644 index ef8dfaea..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/config/impl/ConfigStateValue.kt +++ /dev/null @@ -1,17 +0,0 @@ -package me.rhunk.snapenhance.config.impl - -import me.rhunk.snapenhance.config.ConfigValue - -class ConfigStateValue( - private var value: Boolean -) : ConfigValue() { - override fun value() = value - - override fun read(): String { - return value.toString() - } - - override fun write(value: String) { - this.value = value.toBoolean() - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/config/impl/ConfigStringValue.kt b/core/src/main/kotlin/me/rhunk/snapenhance/config/impl/ConfigStringValue.kt deleted file mode 100644 index 5f991adc..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/config/impl/ConfigStringValue.kt +++ /dev/null @@ -1,21 +0,0 @@ -package me.rhunk.snapenhance.config.impl - -import me.rhunk.snapenhance.config.ConfigValue - -class ConfigStringValue( - private var value: String = "", - val isFolderPath: Boolean = false, - val isHidden: Boolean = false -) : ConfigValue() { - override fun value() = value - - fun hiddenValue() = if (isHidden) value.map { '*' }.joinToString("") else value - - override fun read(): String { - return value - } - - override fun write(value: String) { - this.value = value - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/config/ConfigContainer.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/config/ConfigContainer.kt index c806c423..bba5bbfa 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/config/ConfigContainer.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/config/ConfigContainer.kt @@ -1,7 +1,6 @@ package me.rhunk.snapenhance.core.config import com.google.gson.JsonObject -import me.rhunk.snapenhance.Logger import kotlin.reflect.KProperty typealias ConfigParamsBuilder = ConfigParams.() -> Unit @@ -57,7 +56,7 @@ open class ConfigContainer( fun toJson(): JsonObject { val json = JsonObject() properties.forEach { (propertyKey, propertyValue) -> - val serializedValue = propertyValue.getNullable()?.let { propertyKey.dataProcessor.serializeAny(it) } + val serializedValue = propertyValue.getNullable()?.let { propertyKey.dataType.serializeAny(it) } json.add(propertyKey.name, serializedValue) } return json @@ -66,7 +65,7 @@ open class ConfigContainer( fun fromJson(json: JsonObject) { properties.forEach { (key, _) -> val jsonElement = json.get(key.name) ?: return@forEach - key.dataProcessor.deserializeAny(jsonElement)?.let { + key.dataType.deserializeAny(jsonElement)?.let { properties[key]?.setAny(it) } } diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/config/ConfigObjects.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/config/ConfigObjects.kt index b98cc269..dbd4ea6a 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/config/ConfigObjects.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/config/ConfigObjects.kt @@ -1,12 +1,20 @@ package me.rhunk.snapenhance.core.config -import me.rhunk.snapenhance.Logger import kotlin.reflect.KProperty + +data class PropertyPair( + val key: PropertyKey, + val value: PropertyValue<*> +) { + val name get() = key.name +} + class ConfigParams( var shouldTranslate: Boolean = false, var hidden: Boolean = false, - var isFolder: Boolean = false + var isFolder: Boolean = false, + val disabledKey: String? = null ) class PropertyValue( @@ -34,7 +42,7 @@ class PropertyValue( class PropertyKey( val name: String, - val dataProcessor: DataProcessors.PropertyDataProcessor, + val dataType: DataProcessors.PropertyDataProcessor, val params: ConfigParams = ConfigParams(), ) diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/config/DataProcessors.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/config/DataProcessors.kt index 755a5c8f..8c852cb6 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/config/DataProcessors.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/config/DataProcessors.kt @@ -65,7 +65,7 @@ object DataProcessors { type = Type.STRING_MULTIPLE_SELECTION, serialize = { JsonArray().apply { it.forEach { add(it) } } }, deserialize = { obj -> - obj.asJsonArray.map { it.asString } + obj.asJsonArray.map { it.asString }.toMutableList() }, ) diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/Global.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/Global.kt index 321746ef..b8688a85 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/Global.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/Global.kt @@ -5,7 +5,7 @@ import me.rhunk.snapenhance.data.NotificationType class Global : ConfigContainer() { val snapchatPlus = boolean("snapchat_plus") - val autoUpdater = unique("auto_updater", "DAILY","EVERY_LAUNCH", "DAILY", "WEEKLY") + val autoUpdater = unique("auto_updater", "EVERY_LAUNCH", "DAILY", "WEEKLY") val disableMetrics = boolean("disable_metrics") val disableVideoLengthRestrictions = boolean("disable_video_length_restrictions") val disableGooglePlayDialogs = boolean("disable_google_play_dialogs") diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/RootConfig.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/RootConfig.kt index 57cbb875..86f277e2 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/RootConfig.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/RootConfig.kt @@ -1,8 +1,6 @@ package me.rhunk.snapenhance.core.config.impl import me.rhunk.snapenhance.core.config.ConfigContainer -import me.rhunk.snapenhance.data.NotificationType -import me.rhunk.snapenhance.features.impl.tweaks.CameraTweaks class RootConfig : ConfigContainer() { val downloader = container("downloader", DownloaderConfig()) diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/download/DownloadProcessor.kt b/core/src/main/kotlin/me/rhunk/snapenhance/download/DownloadProcessor.kt index d0c52823..9fc7038f 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/download/DownloadProcessor.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/download/DownloadProcessor.kt @@ -18,8 +18,6 @@ import me.rhunk.snapenhance.Constants import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.SharedContext import me.rhunk.snapenhance.bridge.DownloadCallback -import me.rhunk.snapenhance.bridge.wrapper.ConfigWrapper -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.core.config.ModConfig import me.rhunk.snapenhance.data.FileType import me.rhunk.snapenhance.download.data.DownloadMetadata diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/ConfigEnumKeys.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/ConfigEnumKeys.kt index f7069be0..2cc81ee7 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/ConfigEnumKeys.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/ConfigEnumKeys.kt @@ -1,7 +1,6 @@ package me.rhunk.snapenhance.features.impl import android.annotation.SuppressLint -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.hook.HookStage @@ -95,10 +94,6 @@ class ConfigEnumKeys : Feature("Config enum keys", loadParams = FeatureLoadParam } } - ConfigProperty.ENABLE_APP_APPEARANCE.valueContainer.addPropertyChangeListener { - context.softRestartApp(true) - } - val sharedPreferencesImpl = context.androidContext.classLoader.loadClass("android.app.SharedPreferencesImpl") sharedPreferencesImpl.methods.first { it.name == "getBoolean" }.hook(HookStage.BEFORE) { param -> diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/Messaging.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/Messaging.kt index a0e767e9..99096ebe 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/Messaging.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/Messaging.kt @@ -1,14 +1,13 @@ package me.rhunk.snapenhance.features.impl -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.data.wrapper.impl.SnapUUID import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams +import me.rhunk.snapenhance.features.impl.spying.StealthMode import me.rhunk.snapenhance.hook.HookStage import me.rhunk.snapenhance.hook.Hooker import me.rhunk.snapenhance.hook.hook import me.rhunk.snapenhance.util.getObjectField -import me.rhunk.snapenhance.features.impl.spying.StealthMode; class Messaging : Feature("Messaging", loadParams = FeatureLoadParams.ACTIVITY_CREATE_SYNC or FeatureLoadParams.INIT_ASYNC or FeatureLoadParams.INIT_SYNC) { lateinit var conversationManager: Any diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/MediaDownloader.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/MediaDownloader.kt index 4be342ae..9249fe39 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/MediaDownloader.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/MediaDownloader.kt @@ -11,7 +11,6 @@ import me.rhunk.snapenhance.Constants.ARROYO_URL_KEY_PROTO_PATH import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.Logger.xposedLog import me.rhunk.snapenhance.bridge.DownloadCallback -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.data.ContentType import me.rhunk.snapenhance.data.FileType import me.rhunk.snapenhance.data.wrapper.impl.media.MediaInfo diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/AmoledDarkMode.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/AmoledDarkMode.kt index 8d5f1b35..e86c5796 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/AmoledDarkMode.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/AmoledDarkMode.kt @@ -4,7 +4,6 @@ import android.annotation.SuppressLint import android.content.res.TypedArray import android.graphics.drawable.ColorDrawable import me.rhunk.snapenhance.Constants -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.hook.HookStage diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/AppPasscode.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/AppPasscode.kt index 2d20708c..4c752a9c 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/AppPasscode.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/AppPasscode.kt @@ -1,7 +1,6 @@ package me.rhunk.snapenhance.features.impl.experiments import android.annotation.SuppressLint -import android.app.AlertDialog import android.content.Context import android.os.Build import android.text.Editable @@ -9,7 +8,6 @@ import android.text.InputType import android.text.TextWatcher import android.view.inputmethod.InputMethodManager import android.widget.EditText -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.ui.ViewAppearanceHelper diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/DeviceSpooferHook.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/DeviceSpooferHook.kt index 5f9a4839..1b2cbc38 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/DeviceSpooferHook.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/DeviceSpooferHook.kt @@ -1,7 +1,6 @@ package me.rhunk.snapenhance.features.impl.experiments import me.rhunk.snapenhance.Logger -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.hook.HookStage diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/InfiniteStoryBoost.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/InfiniteStoryBoost.kt index c24fcd1a..4d0de897 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/InfiniteStoryBoost.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/InfiniteStoryBoost.kt @@ -1,6 +1,5 @@ package me.rhunk.snapenhance.features.impl.experiments -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.hook.HookStage diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/MeoPasscodeBypass.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/MeoPasscodeBypass.kt index 2e0031b2..1a02e1d3 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/MeoPasscodeBypass.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/MeoPasscodeBypass.kt @@ -1,6 +1,5 @@ package me.rhunk.snapenhance.features.impl.experiments -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.hook.HookStage diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/UnlimitedMultiSnap.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/UnlimitedMultiSnap.kt index a5d749bc..c2514824 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/UnlimitedMultiSnap.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/experiments/UnlimitedMultiSnap.kt @@ -1,6 +1,5 @@ package me.rhunk.snapenhance.features.impl.experiments -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.hook.HookStage diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/privacy/DisableMetrics.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/privacy/DisableMetrics.kt index e4bef80d..257e69d5 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/privacy/DisableMetrics.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/privacy/DisableMetrics.kt @@ -1,10 +1,8 @@ package me.rhunk.snapenhance.features.impl.privacy import de.robv.android.xposed.XposedHelpers -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams -import me.rhunk.snapenhance.hook.HookAdapter import me.rhunk.snapenhance.hook.HookStage import me.rhunk.snapenhance.hook.Hooker diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/privacy/PreventMessageSending.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/privacy/PreventMessageSending.kt index 22008590..ada46e85 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/privacy/PreventMessageSending.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/privacy/PreventMessageSending.kt @@ -1,7 +1,6 @@ package me.rhunk.snapenhance.features.impl.privacy import me.rhunk.snapenhance.Logger -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.data.NotificationType import me.rhunk.snapenhance.data.wrapper.impl.MessageContent import me.rhunk.snapenhance.features.Feature diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/AnonymousStoryViewing.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/AnonymousStoryViewing.kt index f9e9adc5..4d8b1441 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/AnonymousStoryViewing.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/AnonymousStoryViewing.kt @@ -1,6 +1,5 @@ package me.rhunk.snapenhance.features.impl.spying -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.hook.HookStage diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/MessageLogger.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/MessageLogger.kt index 8f50a24c..c4228c0d 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/MessageLogger.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/MessageLogger.kt @@ -4,7 +4,6 @@ import android.os.DeadObjectException import com.google.gson.JsonObject import com.google.gson.JsonParser import me.rhunk.snapenhance.Logger -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.data.ContentType import me.rhunk.snapenhance.data.MessageState import me.rhunk.snapenhance.data.wrapper.impl.Message diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/PreventReadReceipts.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/PreventReadReceipts.kt index 212c53e3..aa530529 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/PreventReadReceipts.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/spying/PreventReadReceipts.kt @@ -1,6 +1,5 @@ package me.rhunk.snapenhance.features.impl.spying -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.data.wrapper.impl.SnapUUID import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/AutoSave.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/AutoSave.kt index 047f9779..22e646c0 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/AutoSave.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/AutoSave.kt @@ -1,7 +1,6 @@ package me.rhunk.snapenhance.features.impl.tweaks import me.rhunk.snapenhance.Logger -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.data.MessageState import me.rhunk.snapenhance.data.wrapper.impl.Message import me.rhunk.snapenhance.data.wrapper.impl.SnapUUID diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/CameraTweaks.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/CameraTweaks.kt index 2efb85f7..09287129 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/CameraTweaks.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/CameraTweaks.kt @@ -5,7 +5,6 @@ import android.annotation.SuppressLint import android.content.ContextWrapper import android.content.pm.PackageManager import android.hardware.camera2.CameraManager -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.data.wrapper.impl.ScSize import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/DisableVideoLengthRestriction.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/DisableVideoLengthRestriction.kt index 568fc32f..f47e641f 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/DisableVideoLengthRestriction.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/DisableVideoLengthRestriction.kt @@ -1,6 +1,5 @@ package me.rhunk.snapenhance.features.impl.tweaks -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.hook.HookStage diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/GalleryMediaSendOverride.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/GalleryMediaSendOverride.kt index 50bf2d26..bdfc2f76 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/GalleryMediaSendOverride.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/GalleryMediaSendOverride.kt @@ -1,7 +1,5 @@ package me.rhunk.snapenhance.features.impl.tweaks -import android.app.AlertDialog -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.data.ContentType import me.rhunk.snapenhance.data.MessageSender import me.rhunk.snapenhance.data.wrapper.impl.MessageContent diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/GooglePlayServicesDialogs.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/GooglePlayServicesDialogs.kt index d564e022..4a5ec561 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/GooglePlayServicesDialogs.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/GooglePlayServicesDialogs.kt @@ -2,7 +2,6 @@ package me.rhunk.snapenhance.features.impl.tweaks import android.app.AlertDialog import me.rhunk.snapenhance.Logger -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.hook.HookStage diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/LocationSpoofer.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/LocationSpoofer.kt index 7e082f6a..8ed9d07e 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/LocationSpoofer.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/LocationSpoofer.kt @@ -1,7 +1,6 @@ package me.rhunk.snapenhance.features.impl.tweaks import android.content.Intent -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.hook.HookStage diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/MediaQualityLevelOverride.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/MediaQualityLevelOverride.kt index 2907594a..d76c7f43 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/MediaQualityLevelOverride.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/MediaQualityLevelOverride.kt @@ -1,6 +1,5 @@ package me.rhunk.snapenhance.features.impl.tweaks -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.hook.HookStage diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/Notifications.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/Notifications.kt index c91664d2..1f117b31 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/Notifications.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/Notifications.kt @@ -14,7 +14,6 @@ import de.robv.android.xposed.XposedBridge import de.robv.android.xposed.XposedHelpers import me.rhunk.snapenhance.Constants import me.rhunk.snapenhance.Logger -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.data.ContentType import me.rhunk.snapenhance.data.MediaReferenceType import me.rhunk.snapenhance.data.wrapper.impl.Message diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/SnapchatPlus.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/SnapchatPlus.kt index 09cba148..1efc1493 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/SnapchatPlus.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/SnapchatPlus.kt @@ -1,6 +1,5 @@ package me.rhunk.snapenhance.features.impl.tweaks -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.hook.HookStage diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/UnlimitedSnapViewTime.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/UnlimitedSnapViewTime.kt index 99dba59e..19a8f5a8 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/UnlimitedSnapViewTime.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/tweaks/UnlimitedSnapViewTime.kt @@ -1,6 +1,5 @@ package me.rhunk.snapenhance.features.impl.tweaks -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.data.ContentType import me.rhunk.snapenhance.data.MessageState import me.rhunk.snapenhance.data.wrapper.impl.Message diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/StartupPageOverride.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/StartupPageOverride.kt index 358c75a2..707d9643 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/StartupPageOverride.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/StartupPageOverride.kt @@ -5,7 +5,6 @@ import android.view.View import android.view.ViewGroup import android.widget.LinearLayout import me.rhunk.snapenhance.Constants -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.hook.HookStage diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/UITweaks.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/UITweaks.kt index 2c0d09c4..b88ed6b5 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/UITweaks.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/UITweaks.kt @@ -8,7 +8,6 @@ import android.view.View import android.view.ViewGroup import android.widget.FrameLayout import me.rhunk.snapenhance.Constants -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.hook.HookAdapter diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/manager/impl/ActionManager.kt b/core/src/main/kotlin/me/rhunk/snapenhance/manager/impl/ActionManager.kt index 4dfc3415..92d91f8d 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/manager/impl/ActionManager.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/manager/impl/ActionManager.kt @@ -1,6 +1,5 @@ package me.rhunk.snapenhance.manager.impl -import me.rhunk.snapenhance.core.BuildConfig import me.rhunk.snapenhance.ModContext import me.rhunk.snapenhance.action.AbstractAction import me.rhunk.snapenhance.action.impl.CheckForUpdates @@ -9,6 +8,7 @@ import me.rhunk.snapenhance.action.impl.ClearMessageLogger import me.rhunk.snapenhance.action.impl.ExportChatMessages import me.rhunk.snapenhance.action.impl.OpenMap import me.rhunk.snapenhance.action.impl.RefreshMappings +import me.rhunk.snapenhance.core.BuildConfig import me.rhunk.snapenhance.manager.Manager import kotlin.reflect.KClass diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/manager/impl/ConfigManager.kt b/core/src/main/kotlin/me/rhunk/snapenhance/manager/impl/ConfigManager.kt deleted file mode 100644 index 7e14570a..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/manager/impl/ConfigManager.kt +++ /dev/null @@ -1,58 +0,0 @@ -package me.rhunk.snapenhance.manager.impl - -import com.google.gson.JsonObject -import me.rhunk.snapenhance.Logger -import me.rhunk.snapenhance.ModContext -import me.rhunk.snapenhance.bridge.types.BridgeFileType -import me.rhunk.snapenhance.config.ConfigAccessor -import me.rhunk.snapenhance.config.ConfigProperty -import me.rhunk.snapenhance.manager.Manager -import java.nio.charset.StandardCharsets - -class ConfigManager( - private val context: ModContext -) : ConfigAccessor(), Manager { - - override fun init() { - ConfigProperty.sortedByCategory().forEach { key -> - set(key, key.valueContainer) - } - - if (!context.bridgeClient.isFileExists(BridgeFileType.CONFIG)) { - writeConfig() - return - } - - runCatching { - loadConfig() - }.onFailure { - Logger.xposedLog("Failed to load config", it) - writeConfig() - } - } - - private fun loadConfig() { - val configContent = context.bridgeClient.createAndReadFile( - BridgeFileType.CONFIG, - "{}".toByteArray(Charsets.UTF_8) - ) - val configObject: JsonObject = context.gson.fromJson( - String(configContent, StandardCharsets.UTF_8), - JsonObject::class.java - ) - entries().forEach { (key, value) -> - value.writeFrom(configObject.get(key.name)?.asString ?: value.read()) - } - } - - fun writeConfig() { - val configObject = JsonObject() - entries().forEach { (key, value) -> - configObject.addProperty(key.name, value.read()) - } - context.bridgeClient.writeFile( - BridgeFileType.CONFIG, - context.gson.toJson(configObject).toByteArray(Charsets.UTF_8) - ) - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/manager/impl/MappingManager.kt b/core/src/main/kotlin/me/rhunk/snapenhance/manager/impl/MappingManager.kt index 86d8ad65..87a6ca8f 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/manager/impl/MappingManager.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/manager/impl/MappingManager.kt @@ -1,6 +1,5 @@ package me.rhunk.snapenhance.manager.impl -import android.app.AlertDialog import com.google.gson.JsonElement import com.google.gson.JsonParser import me.rhunk.snapenhance.Constants diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/ui/ItemHelper.kt b/core/src/main/kotlin/me/rhunk/snapenhance/ui/ItemHelper.kt deleted file mode 100644 index 2d658aa6..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/ui/ItemHelper.kt +++ /dev/null @@ -1,87 +0,0 @@ -package me.rhunk.snapenhance.ui - -import android.app.Activity -import android.app.AlertDialog -import android.content.Context -import android.content.Intent -import android.widget.EditText -import android.widget.TextView -import android.widget.Toast -import me.rhunk.snapenhance.core.R -import me.rhunk.snapenhance.SharedContext -import me.rhunk.snapenhance.config.ConfigProperty -import me.rhunk.snapenhance.util.ActivityResultCallback -import kotlin.math.abs -import kotlin.random.Random - -class ItemHelper( - private val context : Context -) { - val positiveButtonText by lazy { - SharedContext.translation["button.ok"] - } - - val cancelButtonText by lazy { - SharedContext.translation["button.cancel"] - } - - fun longToast(message: String, context: Context) { - Toast.makeText(context, message, Toast.LENGTH_LONG).show() - } - - fun createTranslatedTextView(property: ConfigProperty, shouldTranslatePropertyValue: Boolean = true): TextView { - return object: TextView(context) { - override fun setText(text: CharSequence?, type: BufferType?) { - val newText = text?.takeIf { it.isNotEmpty() }?.let { - if (!shouldTranslatePropertyValue || property.disableValueLocalization) it - else SharedContext.translation[property.getOptionTranslationKey(it.toString())] - }?.let { - if (it.length > 20) { - "...${it.substring(it.length - 20)}" - } else { - it - } - } ?: "" - super.setTextColor(context.getColor(R.color.tertiaryText)) - super.setText(newText, type) - } - } - } - - fun askForValue(property: ConfigProperty, requestedInputType: Int, callback: (String) -> Unit) { - val editText = EditText(context).apply { - inputType = requestedInputType - setText(property.valueContainer.value().toString()) - } - AlertDialog.Builder(context) - .setTitle(SharedContext.translation["property.${property.translationKey}.name"]) - .setView(editText) - .setPositiveButton(positiveButtonText) { _, _ -> - callback(editText.text.toString()) - } - .setNegativeButton(cancelButtonText) { dialog, _ -> - dialog.cancel() - } - .show() - } - - fun askForFolder(activity: Activity, property: ConfigProperty, callback: (String) -> Unit): Pair { - val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) - .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - .addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION) - - val requestCode = abs(Random.nextInt()) - activity.startActivityForResult(intent, requestCode) - - return requestCode to let@{_, resultCode, data -> - if (resultCode != Activity.RESULT_OK) return@let - val uri = data?.data ?: return@let - val value = uri.toString() - activity.contentResolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION) - property.valueContainer.writeFrom(value) - callback(value) - } - } - - -} diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/ui/config/ConfigActivity.kt b/core/src/main/kotlin/me/rhunk/snapenhance/ui/config/ConfigActivity.kt deleted file mode 100644 index 7a47c87a..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/ui/config/ConfigActivity.kt +++ /dev/null @@ -1,279 +0,0 @@ -package me.rhunk.snapenhance.ui.config - -import android.app.Activity -import android.app.AlertDialog -import android.content.Intent -import android.content.res.ColorStateList -import android.os.Bundle -import android.text.Html -import android.text.InputType -import android.view.View -import android.view.ViewGroup -import android.widget.ImageButton -import android.widget.Switch -import android.widget.TextView -import android.widget.Toast -import me.rhunk.snapenhance.core.BuildConfig -import me.rhunk.snapenhance.core.R -import me.rhunk.snapenhance.SharedContext -import me.rhunk.snapenhance.config.ConfigCategory -import me.rhunk.snapenhance.config.ConfigProperty -import me.rhunk.snapenhance.config.impl.ConfigIntegerValue -import me.rhunk.snapenhance.config.impl.ConfigStateListValue -import me.rhunk.snapenhance.config.impl.ConfigStateSelection -import me.rhunk.snapenhance.config.impl.ConfigStateValue -import me.rhunk.snapenhance.config.impl.ConfigStringValue -import me.rhunk.snapenhance.ui.ItemHelper -import me.rhunk.snapenhance.util.ActivityResultCallback -import kotlin.system.exitProcess - - -class ConfigActivity : Activity() { - private val itemHelper = ItemHelper(this) - private val activityResultCallbacks = mutableMapOf() - - @Deprecated("Deprecated in Java") - @Suppress("DEPRECATION") - override fun onBackPressed() { - super.onBackPressed() - finish() - } - - override fun onDestroy() { - super.onDestroy() - SharedContext.config.writeConfig() - } - - override fun onPause() { - super.onPause() - SharedContext.config.writeConfig() - } - - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - activityResultCallbacks[requestCode]?.invoke(requestCode, resultCode, data) - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - SharedContext.ensureInitialized(this) - setContentView(R.layout.config_activity) - - findViewById(R.id.title_bar).let { titleBar -> - titleBar.findViewById(R.id.title).text = SharedContext.translation["config_activity.title"] - titleBar.findViewById(R.id.back_button).visibility = View.GONE - } - - val propertyListLayout = findViewById(R.id.property_list) - - if (intent.getBooleanExtra("lspatched", false) || - applicationInfo.packageName != "me.rhunk.snapenhance" || - BuildConfig.DEBUG) { - propertyListLayout.addView( - layoutInflater.inflate( - R.layout.config_activity_debug_item, - propertyListLayout, - false - ).apply { - findViewById(R.id.debug_item_content).apply { - text = Html.fromHtml( - "You are using a debug/unofficial build!\n" + - "Please consider downloading stable builds from GitHub.", - Html.FROM_HTML_MODE_COMPACT - ) - movementMethod = android.text.method.LinkMovementMethod.getInstance() - } - }) - } - - //check if save folder is set - //TODO: first run activity - run { - val saveFolder = SharedContext.config.string(ConfigProperty.SAVE_FOLDER) - val itemHelper = ItemHelper(this) - - if (saveFolder.isEmpty() || !saveFolder.startsWith("content://")) { - AlertDialog.Builder(this) - .setTitle("Save folder") - .setMessage("Please select a folder where you want to save downloaded files.") - .setPositiveButton("Select") { _, _ -> - val (requestCode, callback) = itemHelper.askForFolder( - this, - ConfigProperty.SAVE_FOLDER - ) {} - activityResultCallbacks[requestCode] = { a1, a2, a3 -> - callback(a1, a2, a3) - Toast.makeText(this, "Save Folder set!", Toast.LENGTH_SHORT).show() - finish() - } - } - .setNegativeButton("Cancel") { _, _ -> - exitProcess(0) - } - .show() - } - } - - var currentCategory: ConfigCategory? = null - - SharedContext.config.entries().filter { !it.key.category.hidden }.forEach { (property, value) -> - val configItem = layoutInflater.inflate(R.layout.config_activity_item, propertyListLayout, false) - - fun addSeparator() { - //add separator - propertyListLayout.addView(View(this).apply { - layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1) - setBackgroundColor(getColor(R.color.tertiaryBackground)) - }) - } - - if (property.category != currentCategory) { - if(!property.shouldAppearInSettings) return@forEach - currentCategory = property.category - with(layoutInflater.inflate(R.layout.config_activity_item, propertyListLayout, false)) { - findViewById(R.id.name).apply { - text = SharedContext.translation["category.${property.category.key}"] - textSize = 20f - typeface = typeface?.let { android.graphics.Typeface.create(it, android.graphics.Typeface.BOLD) } - } - propertyListLayout.addView(this) - } - addSeparator() - } - - if (!property.shouldAppearInSettings) return@forEach - - val propertyName = SharedContext.translation["property.${property.translationKey}.name"] - - configItem.findViewById(R.id.name).text = propertyName - configItem.findViewById(R.id.description).also { - it.text = SharedContext.translation["property.${property.translationKey}.description"] - it.visibility = if (it.text.isEmpty()) View.GONE else View.VISIBLE - } - - fun addValueView(view: View) { - configItem.findViewById(R.id.value).addView(view) - } - - when (value) { - is ConfigStateValue -> { - val switch = Switch(this) - switch.isChecked = value.value() - switch.trackTintList = ColorStateList( - arrayOf( - intArrayOf(android.R.attr.state_checked), - intArrayOf(-android.R.attr.state_checked) - ), - intArrayOf( - switch.highlightColor, - getColor(R.color.tertiaryBackground) - ) - ) - switch.setOnCheckedChangeListener { _, isChecked -> - value.writeFrom(isChecked.toString()) - } - configItem.setOnClickListener { switch.toggle() } - addValueView(switch) - } - is ConfigStringValue, is ConfigIntegerValue -> { - val textView = itemHelper.createTranslatedTextView(property, shouldTranslatePropertyValue = false).also { - it.text = value.value().toString() - } - configItem.setOnClickListener { - if (value is ConfigStringValue && value.isFolderPath) { - val (requestCode, callback) = itemHelper.askForFolder(this, property) { - value.writeFrom(it) - textView.text = value.value() - } - - activityResultCallbacks[requestCode] = callback - return@setOnClickListener - } - - if (value is ConfigIntegerValue) { - itemHelper.askForValue(property, InputType.TYPE_CLASS_NUMBER) { - try { - value.writeFrom(it) - textView.text = value.value().toString() - } catch (e: NumberFormatException) { - itemHelper.longToast(SharedContext.translation["config_activity.invalid_number_toast"], this) - } - } - return@setOnClickListener - } - itemHelper.askForValue(property, InputType.TYPE_CLASS_TEXT) { - value.writeFrom(it) - textView.text = value.value().toString() - } - } - addValueView(textView) - } - is ConfigStateListValue -> { - val textView = itemHelper.createTranslatedTextView(property, shouldTranslatePropertyValue = false) - val values = value.value() - - fun updateText() { - textView.text = SharedContext.translation.format("config_activity.selected_text", "count" to values.filter { it.value }.size.toString()) - } - - updateText() - - configItem.setOnClickListener { - AlertDialog.Builder(this) - .setTitle(propertyName) - .setPositiveButton(itemHelper.positiveButtonText) { _, _ -> - updateText() - } - .setMultiChoiceItems( - values.keys.map { - if (property.disableValueLocalization) it - else SharedContext.translation[property.getOptionTranslationKey(it)] - }.toTypedArray(), - values.map { it.value }.toBooleanArray() - ) { _, which, isChecked -> - value.setKey(values.keys.elementAt(which), isChecked) - } - .show() - } - - addValueView(textView) - } - is ConfigStateSelection -> { - val textView = itemHelper.createTranslatedTextView(property, shouldTranslatePropertyValue = true) - textView.text = value.value() - - configItem.setOnClickListener { - val builder = AlertDialog.Builder(this) - builder.setTitle(propertyName) - - builder.setSingleChoiceItems( - value.keys().toTypedArray().map { - if (property.disableValueLocalization) it - else SharedContext.translation[property.getOptionTranslationKey(it)] - }.toTypedArray(), - value.keys().indexOf(value.value()) - ) { _, which -> - value.writeFrom(value.keys()[which]) - } - - builder.setPositiveButton(itemHelper.positiveButtonText) { _, _ -> - textView.text = value.value() - } - - builder.show() - } - addValueView(textView) - } - } - - propertyListLayout.addView(configItem) - addSeparator() - } - - propertyListLayout.addView(layoutInflater.inflate(R.layout.config_activity_debug_item, propertyListLayout, false).apply { - findViewById(R.id.debug_item_content).apply { - text = Html.fromHtml("Made by rhunk on GitHub", Html.FROM_HTML_MODE_COMPACT) - movementMethod = android.text.method.LinkMovementMethod.getInstance() - } - }) - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/ui/download/DebugSettingsLayoutInflater.kt b/core/src/main/kotlin/me/rhunk/snapenhance/ui/download/DebugSettingsLayoutInflater.kt index 888eb96d..ce720583 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/ui/download/DebugSettingsLayoutInflater.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/ui/download/DebugSettingsLayoutInflater.kt @@ -1,7 +1,6 @@ package me.rhunk.snapenhance.ui.download import android.app.AlertDialog -import android.content.Intent import android.view.View import android.view.ViewGroup import android.widget.ArrayAdapter @@ -9,11 +8,9 @@ import android.widget.ImageButton import android.widget.ListView import android.widget.TextView import android.widget.Toast -import me.rhunk.snapenhance.core.R import me.rhunk.snapenhance.SharedContext import me.rhunk.snapenhance.bridge.types.BridgeFileType -import me.rhunk.snapenhance.ui.config.ConfigActivity -import me.rhunk.snapenhance.ui.spoof.DeviceSpooferActivity +import me.rhunk.snapenhance.core.R import java.io.File class ActionListAdapter( @@ -68,12 +65,6 @@ class DebugSettingsLayoutInflater( debugSettingsLayout.findViewById(R.id.setting_page_list).apply { adapter = ActionListAdapter(activity, R.layout.debug_setting_item, mutableListOf Unit>>().apply { - add(SharedContext.translation["config_activity.title"] to { - activity.startActivity(Intent(activity, ConfigActivity::class.java)) - }) - add(SharedContext.translation["spoof_activity.title"] to { - activity.startActivity(Intent(activity, DeviceSpooferActivity::class.java)) - }) add(debugSettingsTranslation["clear_cache_title"] to { context.cacheDir.listFiles()?.forEach { it.deleteRecursively() diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/ui/download/DownloadListAdapter.kt b/core/src/main/kotlin/me/rhunk/snapenhance/ui/download/DownloadListAdapter.kt index d7351d3e..60231301 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/ui/download/DownloadListAdapter.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/ui/download/DownloadListAdapter.kt @@ -23,8 +23,8 @@ import kotlinx.coroutines.job import kotlinx.coroutines.launch import kotlinx.coroutines.withTimeout import me.rhunk.snapenhance.Logger -import me.rhunk.snapenhance.core.R import me.rhunk.snapenhance.SharedContext +import me.rhunk.snapenhance.core.R import me.rhunk.snapenhance.data.FileType import me.rhunk.snapenhance.download.data.PendingDownload import me.rhunk.snapenhance.download.enums.DownloadStage diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/ui/download/DownloadManagerActivity.kt b/core/src/main/kotlin/me/rhunk/snapenhance/ui/download/DownloadManagerActivity.kt index 1472afd0..be7e1898 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/ui/download/DownloadManagerActivity.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/ui/download/DownloadManagerActivity.kt @@ -15,10 +15,10 @@ import android.widget.ImageButton import android.widget.TextView import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.RecyclerView -import me.rhunk.snapenhance.core.BuildConfig -import me.rhunk.snapenhance.core.R import me.rhunk.snapenhance.SharedContext import me.rhunk.snapenhance.bridge.wrapper.TranslationWrapper +import me.rhunk.snapenhance.core.BuildConfig +import me.rhunk.snapenhance.core.R import me.rhunk.snapenhance.download.data.PendingDownload class DownloadManagerActivity : Activity() { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/ChatActionMenu.kt b/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/ChatActionMenu.kt index bde676f4..e2ec912d 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/ChatActionMenu.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/ChatActionMenu.kt @@ -10,7 +10,6 @@ import android.widget.Button import android.widget.LinearLayout import me.rhunk.snapenhance.Constants import me.rhunk.snapenhance.Constants.VIEW_INJECTED_CODE -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.features.impl.Messaging import me.rhunk.snapenhance.features.impl.downloader.MediaDownloader import me.rhunk.snapenhance.features.impl.spying.MessageLogger diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/FriendFeedInfoMenu.kt b/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/FriendFeedInfoMenu.kt index 98d55864..3d2c3f01 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/FriendFeedInfoMenu.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/FriendFeedInfoMenu.kt @@ -21,7 +21,6 @@ import android.widget.LinearLayout import android.widget.Switch import android.widget.Toast import me.rhunk.snapenhance.Logger -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.data.ContentType import me.rhunk.snapenhance.data.wrapper.impl.FriendActionButton import me.rhunk.snapenhance.database.objects.ConversationMessage diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/MenuViewInjector.kt b/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/MenuViewInjector.kt index a867fb5d..d5191de0 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/MenuViewInjector.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/MenuViewInjector.kt @@ -6,9 +6,7 @@ import android.view.View import android.view.ViewGroup import android.widget.FrameLayout import android.widget.LinearLayout -import de.robv.android.xposed.XC_MethodHook.Unhook import me.rhunk.snapenhance.Constants -import me.rhunk.snapenhance.config.ConfigProperty import me.rhunk.snapenhance.features.Feature import me.rhunk.snapenhance.features.FeatureLoadParams import me.rhunk.snapenhance.features.impl.Messaging diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/OperaContextActionMenu.kt b/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/OperaContextActionMenu.kt index ecf26179..06438382 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/OperaContextActionMenu.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/OperaContextActionMenu.kt @@ -10,8 +10,8 @@ import android.widget.ScrollView import me.rhunk.snapenhance.Constants import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.features.impl.downloader.MediaDownloader -import me.rhunk.snapenhance.ui.menu.AbstractMenu import me.rhunk.snapenhance.ui.ViewAppearanceHelper.applyTheme +import me.rhunk.snapenhance.ui.menu.AbstractMenu @SuppressLint("DiscouragedApi") class OperaContextActionMenu : AbstractMenu() { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/SettingsGearInjector.kt b/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/SettingsGearInjector.kt index 36e0e6d1..a1887caf 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/SettingsGearInjector.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/SettingsGearInjector.kt @@ -6,9 +6,8 @@ import android.view.View import android.view.ViewGroup import android.widget.FrameLayout import android.widget.ImageView -import me.rhunk.snapenhance.core.BuildConfig import me.rhunk.snapenhance.Constants -import me.rhunk.snapenhance.ui.config.ConfigActivity +import me.rhunk.snapenhance.core.BuildConfig import me.rhunk.snapenhance.ui.menu.AbstractMenu import java.io.File diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/SettingsMenu.kt b/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/SettingsMenu.kt index 365f2844..aee3e657 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/SettingsMenu.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/ui/menu/impl/SettingsMenu.kt @@ -1,26 +1,13 @@ package me.rhunk.snapenhance.ui.menu.impl import android.annotation.SuppressLint -import android.app.AlertDialog -import android.graphics.Color -import android.graphics.Typeface -import android.text.InputType import android.view.View import android.widget.Button -import android.widget.EditText -import android.widget.LinearLayout -import android.widget.Switch -import android.widget.TextView -import me.rhunk.snapenhance.config.ConfigProperty -import me.rhunk.snapenhance.config.impl.ConfigIntegerValue -import me.rhunk.snapenhance.config.impl.ConfigStateListValue -import me.rhunk.snapenhance.config.impl.ConfigStateSelection -import me.rhunk.snapenhance.config.impl.ConfigStateValue -import me.rhunk.snapenhance.config.impl.ConfigStringValue -import me.rhunk.snapenhance.ui.menu.AbstractMenu import me.rhunk.snapenhance.ui.ViewAppearanceHelper +import me.rhunk.snapenhance.ui.menu.AbstractMenu class SettingsMenu : AbstractMenu() { + /* @SuppressLint("ClickableViewAccessibility") private fun createCategoryTitle(key: String): TextView { val categoryText = TextView(context.androidContext) @@ -186,7 +173,7 @@ class SettingsMenu : AbstractMenu() { setPadding(0, 0, 0, thickness) setBackgroundColor(color) } - } + }*/ //TODO: quick settings @SuppressLint("SetTextI18n") @@ -194,9 +181,7 @@ class SettingsMenu : AbstractMenu() { val actions = context.actionManager.getActions().map { Pair(it) { val button = Button(viewModel.context) - button.text = (it.dependsOnProperty?.let { property -> - "["+context.translation["property.${property.translationKey}.name"] + "] " - }?: "") + context.translation[it.nameKey] + button.text = context.translation[it.nameKey] button.setOnClickListener { _ -> it.run() diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/ui/spoof/DeviceSpooferActivity.kt b/core/src/main/kotlin/me/rhunk/snapenhance/ui/spoof/DeviceSpooferActivity.kt deleted file mode 100644 index c6b61abf..00000000 --- a/core/src/main/kotlin/me/rhunk/snapenhance/ui/spoof/DeviceSpooferActivity.kt +++ /dev/null @@ -1,111 +0,0 @@ -package me.rhunk.snapenhance.ui.spoof - -import android.app.Activity -import android.content.res.ColorStateList -import android.os.Bundle -import android.text.InputType -import android.view.View -import android.view.ViewGroup -import android.widget.ImageButton -import android.widget.Switch -import android.widget.TextView -import me.rhunk.snapenhance.core.R -import me.rhunk.snapenhance.SharedContext -import me.rhunk.snapenhance.config.ConfigCategory -import me.rhunk.snapenhance.config.impl.ConfigIntegerValue -import me.rhunk.snapenhance.config.impl.ConfigStateValue -import me.rhunk.snapenhance.config.impl.ConfigStringValue -import me.rhunk.snapenhance.ui.ItemHelper - -class DeviceSpooferActivity: Activity() { - private val itemHelper = ItemHelper(this) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - SharedContext.ensureInitialized(this) - setContentView(R.layout.device_spoofer_activity) - - findViewById(R.id.title).text = "Device Spoofer" - findViewById(R.id.back_button).setOnClickListener { finish() } - val propertyListLayout = findViewById(R.id.spoof_property_list) - - SharedContext.config.entries().filter { it.key.category == ConfigCategory.DEVICE_SPOOFER }.forEach { (property, value) -> - val configItem = layoutInflater.inflate(R.layout.config_activity_item, propertyListLayout, false) - - val propertyName = SharedContext.translation["property.${property.translationKey}.name"] - - fun addSeparator() { - //add separator - propertyListLayout.addView(View(this).apply { - layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1) - setBackgroundColor(getColor(R.color.tertiaryBackground)) - }) - } - - configItem.findViewById(R.id.name).text = propertyName - configItem.findViewById(R.id.description).also { - it.text = SharedContext.translation["property.${property.translationKey}.description"] - it.visibility = if (it.text.isEmpty()) View.GONE else View.VISIBLE - } - - fun addValueView(view: View) { - configItem.findViewById(R.id.value).addView(view) - } - - when (value) { - is ConfigStateValue -> { - val switch = Switch(this) - switch.isChecked = value.value() - switch.trackTintList = ColorStateList( - arrayOf( - intArrayOf(android.R.attr.state_checked), - intArrayOf(-android.R.attr.state_checked) - ), - intArrayOf( - switch.highlightColor, - getColor(R.color.tertiaryBackground) - ) - ) - switch.setOnCheckedChangeListener { _, isChecked -> - value.writeFrom(isChecked.toString()) - } - configItem.setOnClickListener { switch.toggle() } - addValueView(switch) - } - is ConfigStringValue, is ConfigIntegerValue -> { - val textView = itemHelper.createTranslatedTextView(property, shouldTranslatePropertyValue = false).also { - it.text = value.value().toString() - } - configItem.setOnClickListener { - if (value is ConfigIntegerValue) { - itemHelper.askForValue(property, InputType.TYPE_CLASS_NUMBER) { - try { - value.writeFrom(it) - textView.text = value.value().toString() - } catch (e: NumberFormatException) { - itemHelper.longToast(SharedContext.translation["config_activity.invalid_number_toast"], this) - } - } - return@setOnClickListener - } - itemHelper.askForValue(property, InputType.TYPE_CLASS_TEXT) { - value.writeFrom(it) - textView.text = value.value().toString() - } - } - addValueView(textView) - } - } - - propertyListLayout.addView(configItem) - addSeparator() - } - } - - @Deprecated("Deprecated in Java") - @Suppress("DEPRECATION") - override fun onBackPressed() { - super.onBackPressed() - finish() - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/util/export/MessageExporter.kt b/core/src/main/kotlin/me/rhunk/snapenhance/util/export/MessageExporter.kt index 53ceb423..8050dec0 100644 --- a/core/src/main/kotlin/me/rhunk/snapenhance/util/export/MessageExporter.kt +++ b/core/src/main/kotlin/me/rhunk/snapenhance/util/export/MessageExporter.kt @@ -10,9 +10,9 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.withContext -import me.rhunk.snapenhance.core.BuildConfig import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.ModContext +import me.rhunk.snapenhance.core.BuildConfig import me.rhunk.snapenhance.data.ContentType import me.rhunk.snapenhance.data.FileType import me.rhunk.snapenhance.data.MediaReferenceType diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 796de5bd..2433cc52 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,10 +1,10 @@ [versions] -agp = "8.2.0-alpha13" +agp = "8.2.0-alpha14" androidx-material = "1.6.0-alpha02" junit = "4.13.2" kotlin = "1.8.22" kotlinx-coroutines-android = "1.7.2" -kotlin-reflect = "1.8.21" +kotlin-reflect = "1.8.22" material-icons-extended = "1.6.0-alpha03" navigation-compose = "2.6.0" recyclerview = "1.3.1"