mirror of
https://github.com/rhunk/SnapEnhance.git
synced 2025-05-16 14:17:09 +02:00
feat: property translation
- add top bar
This commit is contained in:
parent
9aef7a1b86
commit
c88abd70d4
@ -39,15 +39,14 @@ class MainActivity : ComponentActivity() {
|
||||
|
||||
setContent {
|
||||
val navController = rememberNavController()
|
||||
val navigation = remember { Navigation() }
|
||||
val navigation = remember { Navigation(sections, navController) }
|
||||
AppMaterialTheme {
|
||||
Scaffold(
|
||||
containerColor = MaterialTheme.colorScheme.background,
|
||||
bottomBar = { navigation.NavBar(navController = navController) }
|
||||
topBar = { navigation.TopBar() },
|
||||
bottomBar = { navigation.NavBar() }
|
||||
) { innerPadding ->
|
||||
navigation.NavigationHost(
|
||||
sections = sections,
|
||||
navController = navController,
|
||||
innerPadding = innerPadding,
|
||||
startDestination = startDestination
|
||||
)
|
||||
|
@ -6,15 +6,20 @@ import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.requiredWidth
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.NavigationBar
|
||||
import androidx.compose.material3.NavigationBarItem
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavDestination
|
||||
import androidx.navigation.NavDestination.Companion.hierarchy
|
||||
import androidx.navigation.NavGraph.Companion.findStartDestination
|
||||
import androidx.navigation.NavHostController
|
||||
@ -22,30 +27,55 @@ import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||
|
||||
|
||||
class Navigation{
|
||||
class Navigation(
|
||||
private val sections: Map<EnumSection, Section>,
|
||||
private val navHostController: NavHostController
|
||||
){
|
||||
@Composable
|
||||
fun NavigationHost(
|
||||
sections: Map<EnumSection, Section>,
|
||||
startDestination: EnumSection,
|
||||
navController: NavHostController,
|
||||
innerPadding: PaddingValues
|
||||
) {
|
||||
NavHost(navController, startDestination = startDestination.route, Modifier.padding(innerPadding)) {
|
||||
NavHost(navHostController, startDestination = startDestination.route, Modifier.padding(innerPadding)) {
|
||||
sections.forEach { (_, instance) ->
|
||||
instance.navController = navController
|
||||
instance.navController = navHostController
|
||||
instance.build(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getCurrentSection(navDestination: NavDestination) = sections.firstNotNullOf { (section, instance) ->
|
||||
if (navDestination.hierarchy.any { it.route == section.route }) {
|
||||
instance
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun NavBar(
|
||||
navController: NavController
|
||||
) {
|
||||
fun TopBar() {
|
||||
val navBackStackEntry by navHostController.currentBackStackEntryAsState()
|
||||
val currentDestination = navBackStackEntry?.destination ?: return
|
||||
val currentSection = getCurrentSection(currentDestination)
|
||||
|
||||
TopAppBar(title = {
|
||||
Text(text = currentSection.sectionTopBarName())
|
||||
}, navigationIcon = {
|
||||
if (currentSection.canGoBack()) {
|
||||
IconButton(onClick = { navHostController.popBackStack() }) {
|
||||
Icon(Icons.Filled.ArrowBack, contentDescription = null)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun NavBar() {
|
||||
NavigationBar {
|
||||
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
||||
val navBackStackEntry by navHostController.currentBackStackEntryAsState()
|
||||
val currentDestination = navBackStackEntry?.destination
|
||||
EnumSection.values().toList().forEach { section ->
|
||||
sections.keys.forEach { section ->
|
||||
fun selected() = currentDestination?.hierarchy?.any { it.route == section.route } == true
|
||||
|
||||
NavigationBarItem(
|
||||
@ -73,8 +103,8 @@ class Navigation{
|
||||
},
|
||||
selected = selected(),
|
||||
onClick = {
|
||||
navController.navigate(section.route) {
|
||||
popUpTo(navController.graph.findStartDestination().id) {
|
||||
navHostController.navigate(section.route) {
|
||||
popUpTo(navHostController.graph.findStartDestination().id) {
|
||||
saveState = true
|
||||
}
|
||||
launchSingleTop = true
|
||||
|
@ -70,6 +70,9 @@ open class Section {
|
||||
open fun init() {}
|
||||
open fun onResumed() {}
|
||||
|
||||
open fun sectionTopBarName(): String = context.translation["manager.routes.${enumSection.route}"]
|
||||
open fun canGoBack(): Boolean = false
|
||||
|
||||
@Composable
|
||||
open fun Content() { NotImplemented() }
|
||||
|
||||
|
@ -23,8 +23,6 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import me.rhunk.snapenhance.Logger
|
||||
import me.rhunk.snapenhance.ui.manager.Section
|
||||
import me.rhunk.snapenhance.ui.manager.data.InstallationSummary
|
||||
import me.rhunk.snapenhance.ui.setup.Requirements
|
||||
@ -91,13 +89,14 @@ class HomeSection : Section() {
|
||||
}
|
||||
|
||||
override fun onResumed() {
|
||||
Logger.debug("HomeSection resumed")
|
||||
if (!context.mappings.isMappingsLoaded()) {
|
||||
context.mappings.init()
|
||||
}
|
||||
installationSummary.value = context.getInstallationSummary()
|
||||
}
|
||||
|
||||
override fun sectionTopBarName() = "SnapEnhance"
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
override fun Content() {
|
||||
@ -106,12 +105,6 @@ class HomeSection : Section() {
|
||||
.fillMaxSize()
|
||||
.verticalScroll(ScrollState(0))
|
||||
) {
|
||||
Text(
|
||||
"SnapEnhance",
|
||||
fontSize = 32.sp,
|
||||
modifier = Modifier.padding(32.dp)
|
||||
)
|
||||
|
||||
Text(
|
||||
text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec euismod, nisl eget ultricies ultrices, nunc nisl aliquam nunc, quis aliquam nisl nunc eu nisl. Donec euismod, nisl eget ultricies ultrices, nunc nisl aliquam nunc, quis aliquam nisl nunc eu nisl.",
|
||||
modifier = Modifier.padding(16.dp)
|
||||
|
@ -6,6 +6,7 @@ import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
@ -20,7 +21,6 @@ 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.FolderOpen
|
||||
import androidx.compose.material.icons.filled.OpenInNew
|
||||
import androidx.compose.material.icons.rounded.Save
|
||||
@ -34,7 +34,6 @@ 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
|
||||
@ -43,7 +42,6 @@ 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
|
||||
@ -63,18 +61,75 @@ class FeaturesSection : Section() {
|
||||
private val dialogs by lazy { Dialogs() }
|
||||
|
||||
companion object {
|
||||
private const val MAIN_ROUTE = "root"
|
||||
const val MAIN_ROUTE = "feature_root"
|
||||
const val FEATURE_CONTAINER_ROOT = "feature_container/{name}"
|
||||
}
|
||||
|
||||
private lateinit var openFolderCallback: (uri: String) -> Unit
|
||||
private lateinit var openFolderLauncher: () -> Unit
|
||||
|
||||
private val featuresRouteName by lazy { context.translation["manager.routes.features"] }
|
||||
|
||||
private val allContainers by lazy {
|
||||
val containers = mutableMapOf<String, PropertyPair<*>>()
|
||||
fun queryContainerRecursive(container: ConfigContainer) {
|
||||
container.properties.forEach {
|
||||
if (it.key.dataType.type == DataProcessors.Type.CONTAINER) {
|
||||
containers[it.key.name] = PropertyPair(it.key, it.value)
|
||||
queryContainerRecursive(it.value.get() as ConfigContainer)
|
||||
}
|
||||
}
|
||||
}
|
||||
queryContainerRecursive(context.config.root)
|
||||
containers
|
||||
}
|
||||
|
||||
override fun init() {
|
||||
openFolderLauncher = ChooseFolderHelper.createChooseFolder(context.activity!! as ComponentActivity) {
|
||||
openFolderCallback(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun canGoBack() = sectionTopBarName() != featuresRouteName
|
||||
|
||||
override fun sectionTopBarName(): String {
|
||||
navController.currentBackStackEntry?.arguments?.getString("name")?.let { routeName ->
|
||||
val currentContainerPair = allContainers[routeName]
|
||||
val propertyTree = run {
|
||||
var key = currentContainerPair?.key
|
||||
val tree = mutableListOf<String>()
|
||||
while (key != null) {
|
||||
tree.add(key.propertyTranslationPath())
|
||||
key = key.parentKey
|
||||
}
|
||||
tree
|
||||
}
|
||||
|
||||
val translatedKey = propertyTree.reversed().joinToString(" > ") {
|
||||
context.translation["$it.name"]
|
||||
}
|
||||
|
||||
return "$featuresRouteName > $translatedKey"
|
||||
}
|
||||
return featuresRouteName
|
||||
}
|
||||
|
||||
override fun build(navGraphBuilder: NavGraphBuilder) {
|
||||
navGraphBuilder.navigation(route = "features", startDestination = MAIN_ROUTE) {
|
||||
composable(MAIN_ROUTE) {
|
||||
Container(context.config.root)
|
||||
}
|
||||
|
||||
composable(FEATURE_CONTAINER_ROOT) { backStackEntry ->
|
||||
backStackEntry.arguments?.getString("name")?.let { containerName ->
|
||||
allContainers[containerName]?.let {
|
||||
Container(it.value.get() as ConfigContainer)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PropertyAction(property: PropertyPair<*>, registerClickCallback: RegisterClickCallback) {
|
||||
val showDialog = remember { mutableStateOf(false) }
|
||||
@ -130,7 +185,7 @@ class FeaturesSection : Section() {
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
modifier = Modifier.widthIn(0.dp, 120.dp),
|
||||
text = (propertyValue.getNullable() as? String) ?: "Disabled",
|
||||
text = (propertyValue.getNullable() as? String) ?: context.translation["manager.features.disabled"],
|
||||
)
|
||||
}
|
||||
|
||||
@ -168,7 +223,7 @@ class FeaturesSection : Section() {
|
||||
val container = propertyValue.get() as ConfigContainer
|
||||
|
||||
registerClickCallback {
|
||||
navController.navigate("container/${property.name}")
|
||||
navController.navigate(FEATURE_CONTAINER_ROOT.replace("{name}", property.name))
|
||||
}
|
||||
|
||||
if (container.globalState == null) return
|
||||
@ -183,7 +238,10 @@ class FeaturesSection : Section() {
|
||||
Box(modifier = Modifier
|
||||
.height(50.dp)
|
||||
.width(1.dp)
|
||||
.background(color = MaterialTheme.colors.onBackground.copy(alpha = 0.12f), shape = RoundedCornerShape(5.dp)))
|
||||
.background(
|
||||
color = MaterialTheme.colors.onBackground.copy(alpha = 0.12f),
|
||||
shape = RoundedCornerShape(5.dp)
|
||||
))
|
||||
}
|
||||
|
||||
Switch(
|
||||
@ -222,12 +280,12 @@ class FeaturesSection : Section() {
|
||||
.padding(all = 10.dp)
|
||||
) {
|
||||
Text(
|
||||
text = property.name,
|
||||
text = context.translation["${property.key.propertyTranslationPath()}.name"],
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
Text(
|
||||
text = property.name,
|
||||
text = context.translation["${property.key.propertyTranslationPath()}.description"],
|
||||
fontSize = 12.sp,
|
||||
lineHeight = 15.sp
|
||||
)
|
||||
@ -252,7 +310,6 @@ class FeaturesSection : Section() {
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun Container(
|
||||
containerName: String,
|
||||
configContainer: ConfigContainer
|
||||
) {
|
||||
val properties = remember {
|
||||
@ -264,20 +321,6 @@ class FeaturesSection : Section() {
|
||||
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 = {
|
||||
@ -302,6 +345,8 @@ class FeaturesSection : Section() {
|
||||
modifier = Modifier
|
||||
.fillMaxHeight()
|
||||
.padding(innerPadding),
|
||||
//save button space
|
||||
contentPadding = PaddingValues(top = 10.dp, bottom = 110.dp),
|
||||
verticalArrangement = Arrangement.Center
|
||||
) {
|
||||
items(properties) {
|
||||
@ -310,36 +355,6 @@ class FeaturesSection : Section() {
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
override fun build(navGraphBuilder: NavGraphBuilder) {
|
||||
val allContainers by lazy {
|
||||
val containers = mutableMapOf<String, ConfigContainer>()
|
||||
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(context.config.root)
|
||||
containers
|
||||
}
|
||||
|
||||
navGraphBuilder.navigation(route = "features", startDestination = MAIN_ROUTE) {
|
||||
composable(MAIN_ROUTE) {
|
||||
Container(MAIN_ROUTE, context.config.root)
|
||||
}
|
||||
|
||||
composable("container/{name}") { backStackEntry ->
|
||||
backStackEntry.arguments?.getString("name")?.let { containerName ->
|
||||
allContainers[containerName]?.let {
|
||||
Container(containerName, it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -16,13 +16,16 @@
|
||||
}
|
||||
},
|
||||
|
||||
"category": {
|
||||
"spying_privacy": "Spying & Privacy",
|
||||
"media_manager": "Media Manager",
|
||||
"ui_tweaks": "UI & Tweaks",
|
||||
"camera": "Camera",
|
||||
"updates": "Updates",
|
||||
"experimental_debugging": "Experimental"
|
||||
"manager": {
|
||||
"routes": {
|
||||
"downloads": "Downloads",
|
||||
"features": "Features",
|
||||
"friends": "Friends",
|
||||
"debug": "Debug"
|
||||
},
|
||||
"features": {
|
||||
"disabled": "Disabled"
|
||||
}
|
||||
},
|
||||
|
||||
"action": {
|
||||
@ -34,228 +37,270 @@
|
||||
"export_chat_messages": "Export chat messages"
|
||||
},
|
||||
|
||||
"property": {
|
||||
"message_logger": {
|
||||
"name": "Message Logger",
|
||||
"description": "Prevents messages from being deleted"
|
||||
"features": {
|
||||
"spoof": {
|
||||
"name": "Spoof",
|
||||
"description": "Spoof your information",
|
||||
"properties": {
|
||||
"location": {
|
||||
"name": "Location",
|
||||
"description": "Spoof your location"
|
||||
},
|
||||
"device": {
|
||||
"name": "Device",
|
||||
"description": "Spoof your device"
|
||||
}
|
||||
}
|
||||
},
|
||||
"prevent_read_receipts": {
|
||||
"name": "Prevent Read Receipts",
|
||||
"description": "Prevent anyone from knowing you've opened their Snaps"
|
||||
"downloader": {
|
||||
"name": "Downloader",
|
||||
"description": "Download Snaps and Stories",
|
||||
"properties": {
|
||||
"save_folder": {
|
||||
"name": "Save Folder",
|
||||
"description": "The directory where all media is saved"
|
||||
},
|
||||
"auto_download_options": {
|
||||
"name": "Auto Download Options",
|
||||
"description": "Select which medias to auto download"
|
||||
}
|
||||
}
|
||||
},
|
||||
"hide_bitmoji_presence": {
|
||||
"name": "Hide Bitmoji Presence",
|
||||
"description": "Hides your Bitmoji presence from the chat"
|
||||
"user_interface": {
|
||||
"name": "User Interface",
|
||||
"description": "Change the look and feel of Snapchat",
|
||||
"properties": {
|
||||
"enable_app_appearance": {
|
||||
"name": "Enable App Appearance Settings",
|
||||
"description": "Enables the hidden app appearance settings"
|
||||
},
|
||||
"amoled_dark_mode": {
|
||||
"name": "AMOLED Dark Mode",
|
||||
"description": "Enables AMOLED dark mode\nMake sure Snapchat's dark mode is enabled"
|
||||
},
|
||||
"map_friend_nametags": {
|
||||
"name": "Enhanced Friend Map Nametags",
|
||||
"description": "Enhances the nametags of friends on the map"
|
||||
},
|
||||
"streak_expiration_info": {
|
||||
"name": "Show Streak Expiration Info",
|
||||
"description": "Shows Streak expiration info next to streaks"
|
||||
},
|
||||
"hide_story_section": {
|
||||
"name": "Hide Story Section",
|
||||
"description": "Hide certain UI Elements shown in the story section"
|
||||
},
|
||||
"hide_ui_components": {
|
||||
"name": "Hide UI Components",
|
||||
"description": "Select which UI components to hide"
|
||||
},
|
||||
"disable_spotlight": {
|
||||
"name": "Disable Spotlight",
|
||||
"description": "Disables the Spotlight page"
|
||||
},
|
||||
"startup_tab": {
|
||||
"name": "Startup Tab",
|
||||
"description": "Change the tab that opens on startup"
|
||||
},
|
||||
"story_viewer_override": {
|
||||
"name": "Story Viewer Override",
|
||||
"description": "Turns on certain features which Snapchat hid"
|
||||
},
|
||||
"friend_feed_menu_buttons": {
|
||||
"name": "Friend Feed Menu Buttons",
|
||||
"description": "Select which buttons to show in the Friend Feed Menu Bar"
|
||||
},
|
||||
"friend_feed_menu_position": {
|
||||
"name": "Friend Feed Position Index",
|
||||
"description": "The position of the Friend Feed Menu component"
|
||||
},
|
||||
"enable_friend_feed_menu_bar": {
|
||||
"name": "Friend Feed Menu Bar",
|
||||
"description": "Enables the new Friend Feed Menu Bar"
|
||||
}
|
||||
}
|
||||
},
|
||||
"better_notifications": {
|
||||
"name": "Better Notifications",
|
||||
"description": "Shows more information in notifications"
|
||||
"messaging": {
|
||||
"name": "Messaging",
|
||||
"description": "Change how you interact with friends"
|
||||
},
|
||||
"notification_blacklist": {
|
||||
"name": "Notification Blacklist",
|
||||
"description": "Hides selected notification type"
|
||||
"global": {
|
||||
"name": "Global",
|
||||
"description": "Tweak Snapchat globally"
|
||||
},
|
||||
"disable_metrics": {
|
||||
"name": "Disable Metrics",
|
||||
"description": "Disables metrics sent to Snapchat"
|
||||
"camera": {
|
||||
"name": "Camera",
|
||||
"description": "Adjust the right settings for the perfect snap"
|
||||
},
|
||||
"block_ads": {
|
||||
"name": "Block Ads",
|
||||
"description": "Blocks ads from being displayed"
|
||||
},
|
||||
"unlimited_snap_view_time": {
|
||||
"name": "Unlimited Snap View Time",
|
||||
"description": "Removes the time limit for viewing Snaps"
|
||||
},
|
||||
"prevent_sending_messages": {
|
||||
"name": "Prevent Sending Messages",
|
||||
"description": "Prevents sending certain types of messages"
|
||||
},
|
||||
"anonymous_story_view": {
|
||||
"name": "Anonymous Story View",
|
||||
"description": "Prevents anyone from knowing you've seen their story"
|
||||
},
|
||||
"hide_typing_notification": {
|
||||
"name": "Hide Typing Notification",
|
||||
"description": "Prevents typing notifications being sent"
|
||||
"experimental": {
|
||||
"name": "Experimental",
|
||||
"description": "Experimental features"
|
||||
},
|
||||
|
||||
"save_folder": {
|
||||
"name": "Save Folder",
|
||||
"description": "The directory where all media is saved"
|
||||
},
|
||||
"auto_download_options": {
|
||||
"name": "Auto Download Options",
|
||||
"description": "Select which medias to auto download"
|
||||
},
|
||||
"download_options": {
|
||||
"name": "Download Options",
|
||||
"description": "Specify the file path format"
|
||||
},
|
||||
"chat_download_context_menu": {
|
||||
"name": "Chat Download Context Menu",
|
||||
"description": "Enable the chat download context menu"
|
||||
},
|
||||
"gallery_media_send_override": {
|
||||
"name": "Gallery Media Send Override",
|
||||
"description": "Overrides media sent from the gallery"
|
||||
},
|
||||
"auto_save_messages": {
|
||||
"name": "Auto Save Messages",
|
||||
"description": "Select which type of messages to auto save"
|
||||
},
|
||||
"force_media_source_quality": {
|
||||
"name": "Force Media Source Quality",
|
||||
"description": "Overrides the media source quality"
|
||||
},
|
||||
"download_logging": {
|
||||
"name": "Download Logging",
|
||||
"description": "Show a toast when media is downloading"
|
||||
},
|
||||
"properties": {
|
||||
"message_logger": {
|
||||
"name": "Message Logger",
|
||||
"description": "Prevents messages from being deleted"
|
||||
},
|
||||
"prevent_read_receipts": {
|
||||
"name": "Prevent Read Receipts",
|
||||
"description": "Prevent anyone from knowing you've opened their Snaps"
|
||||
},
|
||||
"hide_bitmoji_presence": {
|
||||
"name": "Hide Bitmoji Presence",
|
||||
"description": "Hides your Bitmoji presence from the chat"
|
||||
},
|
||||
"better_notifications": {
|
||||
"name": "Better Notifications",
|
||||
"description": "Shows more information in notifications"
|
||||
},
|
||||
"notification_blacklist": {
|
||||
"name": "Notification Blacklist",
|
||||
"description": "Hides selected notification type"
|
||||
},
|
||||
"disable_metrics": {
|
||||
"name": "Disable Metrics",
|
||||
"description": "Disables metrics sent to Snapchat"
|
||||
},
|
||||
"block_ads": {
|
||||
"name": "Block Ads",
|
||||
"description": "Blocks ads from being displayed"
|
||||
},
|
||||
"unlimited_snap_view_time": {
|
||||
"name": "Unlimited Snap View Time",
|
||||
"description": "Removes the time limit for viewing Snaps"
|
||||
},
|
||||
"prevent_sending_messages": {
|
||||
"name": "Prevent Sending Messages",
|
||||
"description": "Prevents sending certain types of messages"
|
||||
},
|
||||
"anonymous_story_view": {
|
||||
"name": "Anonymous Story View",
|
||||
"description": "Prevents anyone from knowing you've seen their story"
|
||||
},
|
||||
"hide_typing_notification": {
|
||||
"name": "Hide Typing Notification",
|
||||
"description": "Prevents typing notifications being sent"
|
||||
},
|
||||
|
||||
"enable_friend_feed_menu_bar": {
|
||||
"name": "Friend Feed Menu Bar",
|
||||
"description": "Enables the new Friend Feed Menu Bar"
|
||||
},
|
||||
"friend_feed_menu_buttons": {
|
||||
"name": "Friend Feed Menu Buttons",
|
||||
"description": "Select which buttons to show in the Friend Feed Menu Bar"
|
||||
},
|
||||
"friend_feed_menu_buttons_position": {
|
||||
"name": "Friend Feed Buttons Position Index",
|
||||
"description": "The position of the Friend Feed Menu Buttons"
|
||||
},
|
||||
"hide_ui_elements": {
|
||||
"name": "Hide UI Elements",
|
||||
"description": "Select which UI elements to hide"
|
||||
},
|
||||
"hide_story_section": {
|
||||
"name": "Hide Story Section",
|
||||
"description": "Hide certain UI Elements shown in the story section"
|
||||
},
|
||||
"story_viewer_override": {
|
||||
"name": "Story Viewer Override",
|
||||
"description": "Turns on certain features which Snapchat hid"
|
||||
},
|
||||
"streak_expiration_info": {
|
||||
"name": "Show Streak Expiration Info",
|
||||
"description": "Shows Streak expiration info next to streaks"
|
||||
},
|
||||
"disable_snap_splitting": {
|
||||
"name": "Disable Snap Splitting",
|
||||
"description": "Prevents Snaps from being split into multiple parts"
|
||||
},
|
||||
"disable_video_length_restriction": {
|
||||
"name": "Disable Video Length Restriction",
|
||||
"description": "Disables video length restrictions"
|
||||
},
|
||||
"snapchat_plus": {
|
||||
"name": "Snapchat Plus",
|
||||
"description": "Enables Snapchat Plus features"
|
||||
},
|
||||
"new_map_ui": {
|
||||
"name": "New Map UI",
|
||||
"description": "Enables the new map UI"
|
||||
},
|
||||
"location_spoof": {
|
||||
"name": "Snapmap Location Spoofer",
|
||||
"description": "Spoofs your location on the Snapmap"
|
||||
},
|
||||
"message_preview_length": {
|
||||
"name": "Message Preview Length",
|
||||
"description": "Specify the amount of messages to be previewed"
|
||||
},
|
||||
"unlimited_conversation_pinning": {
|
||||
"name": "Unlimited Conversation Pinning",
|
||||
"description": "Enables the ability to pin unlimited conversations"
|
||||
},
|
||||
"disable_spotlight": {
|
||||
"name": "Disable Spotlight",
|
||||
"description": "Disables the Spotlight page"
|
||||
},
|
||||
"enable_app_appearance": {
|
||||
"name": "Enable App Appearance Settings",
|
||||
"description": "Enables the hidden app appearance settings"
|
||||
},
|
||||
"startup_page_override": {
|
||||
"name": "Override Startup Page",
|
||||
"description": "Overrides the startup page"
|
||||
},
|
||||
"disable_google_play_dialogs": {
|
||||
"name": "Disable Google Play Services Dialogs",
|
||||
"description": "Prevent Google Play Services availability dialogs from being shown"
|
||||
},
|
||||
"download_options": {
|
||||
"name": "Download Options",
|
||||
"description": "Specify the file path format"
|
||||
},
|
||||
"chat_download_context_menu": {
|
||||
"name": "Chat Download Context Menu",
|
||||
"description": "Enable the chat download context menu"
|
||||
},
|
||||
"gallery_media_send_override": {
|
||||
"name": "Gallery Media Send Override",
|
||||
"description": "Overrides media sent from the gallery"
|
||||
},
|
||||
"auto_save_messages": {
|
||||
"name": "Auto Save Messages",
|
||||
"description": "Select which type of messages to auto save"
|
||||
},
|
||||
"force_media_source_quality": {
|
||||
"name": "Force Media Source Quality",
|
||||
"description": "Overrides the media source quality"
|
||||
},
|
||||
"download_logging": {
|
||||
"name": "Download Logging",
|
||||
"description": "Show a toast when media is downloading"
|
||||
},
|
||||
|
||||
"auto_updater": {
|
||||
"name": "Auto Updater",
|
||||
"description": "The interval of checking for updates"
|
||||
},
|
||||
"disable_snap_splitting": {
|
||||
"name": "Disable Snap Splitting",
|
||||
"description": "Prevents Snaps from being split into multiple parts"
|
||||
},
|
||||
"disable_video_length_restriction": {
|
||||
"name": "Disable Video Length Restriction",
|
||||
"description": "Disables video length restrictions"
|
||||
},
|
||||
"snapchat_plus": {
|
||||
"name": "Snapchat Plus",
|
||||
"description": "Enables Snapchat Plus features"
|
||||
},
|
||||
"location_spoof": {
|
||||
"name": "Snapmap Location Spoofer",
|
||||
"description": "Spoofs your location on the Snapmap"
|
||||
},
|
||||
"message_preview_length": {
|
||||
"name": "Message Preview Length",
|
||||
"description": "Specify the amount of messages to be previewed"
|
||||
},
|
||||
"unlimited_conversation_pinning": {
|
||||
"name": "Unlimited Conversation Pinning",
|
||||
"description": "Enables the ability to pin unlimited conversations"
|
||||
},
|
||||
"disable_google_play_dialogs": {
|
||||
"name": "Disable Google Play Services Dialogs",
|
||||
"description": "Prevent Google Play Services availability dialogs from being shown"
|
||||
},
|
||||
|
||||
"disable_camera": {
|
||||
"name": "Disable Camera",
|
||||
"description": "Prevents Snapchat from being able to use the camera"
|
||||
},
|
||||
"immersive_camera_preview": {
|
||||
"name": "Immersive Camera Preview",
|
||||
"description": "Stops Snapchat from cropping the camera preview"
|
||||
},
|
||||
"preview_resolution": {
|
||||
"name": "Preview Resolution",
|
||||
"description": "Overrides the camera preview resolution"
|
||||
},
|
||||
"picture_resolution": {
|
||||
"name": "Picture Resolution",
|
||||
"description": "Overrides the picture resolution"
|
||||
},
|
||||
"force_highest_frame_rate": {
|
||||
"name": "Force Highest Frame Rate",
|
||||
"description": "Forces the highest possible frame rate"
|
||||
},
|
||||
"force_camera_source_encoding": {
|
||||
"name": "Force Camera Source Encoding",
|
||||
"description": "Forces the camera source encoding"
|
||||
},
|
||||
"auto_updater": {
|
||||
"name": "Auto Updater",
|
||||
"description": "The interval of checking for updates"
|
||||
},
|
||||
|
||||
"app_passcode": {
|
||||
"name": "Set App Passcode",
|
||||
"description": "Sets a passcode to lock the app"
|
||||
},
|
||||
"app_lock_on_resume": {
|
||||
"name": "App Lock On Resume",
|
||||
"description": "Locks the app when it's reopened"
|
||||
},
|
||||
"infinite_story_boost": {
|
||||
"name": "Infinite Story Boost",
|
||||
"description": "Infinitely boosts your story"
|
||||
},
|
||||
"meo_passcode_bypass": {
|
||||
"name": "My Eyes Only Passcode Bypass",
|
||||
"description": "Bypass the My Eyes Only passcode\nThis will only work if the passcode has been entered correctly before"
|
||||
},
|
||||
"amoled_dark_mode": {
|
||||
"name": "AMOLED Dark Mode",
|
||||
"description": "Enables AMOLED dark mode\nMake sure Snapchat's dark mode is enabled"
|
||||
},
|
||||
"unlimited_multi_snap": {
|
||||
"name": "Unlimited Multi Snap",
|
||||
"description": "Allows you to take an unlimited amount of multi snaps"
|
||||
},
|
||||
"device_spoof": {
|
||||
"name": "Spoof Device Values",
|
||||
"description": "Spoofs the devices values"
|
||||
},
|
||||
"device_fingerprint": {
|
||||
"name": "Device Fingerprint",
|
||||
"description": "Spoofs the device fingerprint"
|
||||
},
|
||||
"android_id": {
|
||||
"name": "Android ID",
|
||||
"description": "Spoofs the devices Android ID"
|
||||
}
|
||||
},
|
||||
"disable_camera": {
|
||||
"name": "Disable Camera",
|
||||
"description": "Prevents Snapchat from being able to use the camera"
|
||||
},
|
||||
"immersive_camera_preview": {
|
||||
"name": "Immersive Camera Preview",
|
||||
"description": "Stops Snapchat from cropping the camera preview"
|
||||
},
|
||||
"preview_resolution": {
|
||||
"name": "Preview Resolution",
|
||||
"description": "Overrides the camera preview resolution"
|
||||
},
|
||||
"picture_resolution": {
|
||||
"name": "Picture Resolution",
|
||||
"description": "Overrides the picture resolution"
|
||||
},
|
||||
"force_highest_frame_rate": {
|
||||
"name": "Force Highest Frame Rate",
|
||||
"description": "Forces the highest possible frame rate"
|
||||
},
|
||||
"force_camera_source_encoding": {
|
||||
"name": "Force Camera Source Encoding",
|
||||
"description": "Forces the camera source encoding"
|
||||
},
|
||||
|
||||
"option": {
|
||||
"property": {
|
||||
"app_passcode": {
|
||||
"name": "Set App Passcode",
|
||||
"description": "Sets a passcode to lock the app"
|
||||
},
|
||||
"app_lock_on_resume": {
|
||||
"name": "App Lock On Resume",
|
||||
"description": "Locks the app when it's reopened"
|
||||
},
|
||||
"infinite_story_boost": {
|
||||
"name": "Infinite Story Boost",
|
||||
"description": "Infinitely boosts your story"
|
||||
},
|
||||
"meo_passcode_bypass": {
|
||||
"name": "My Eyes Only Passcode Bypass",
|
||||
"description": "Bypass the My Eyes Only passcode\nThis will only work if the passcode has been entered correctly before"
|
||||
},
|
||||
"unlimited_multi_snap": {
|
||||
"name": "Unlimited Multi Snap",
|
||||
"description": "Allows you to take an unlimited amount of multi snaps"
|
||||
},
|
||||
"device_spoof": {
|
||||
"name": "Spoof Device Values",
|
||||
"description": "Spoofs the devices values"
|
||||
},
|
||||
"device_fingerprint": {
|
||||
"name": "Device Fingerprint",
|
||||
"description": "Spoofs the device fingerprint"
|
||||
},
|
||||
"android_id": {
|
||||
"name": "Android ID",
|
||||
"description": "Spoofs the devices Android ID"
|
||||
}
|
||||
},
|
||||
"option": {
|
||||
"better_notifications": {
|
||||
"chat": "Show chat messages",
|
||||
"snap": "Show medias",
|
||||
|
@ -8,16 +8,19 @@ typealias ConfigParamsBuilder = ConfigParams.() -> Unit
|
||||
open class ConfigContainer(
|
||||
var globalState: Boolean? = null
|
||||
) {
|
||||
var parentContainerKey: PropertyKey<*>? = null
|
||||
val properties = mutableMapOf<PropertyKey<*>, PropertyValue<*>>()
|
||||
|
||||
private inline fun <T> registerProperty(
|
||||
key: String,
|
||||
type: DataProcessors.PropertyDataProcessor<*>,
|
||||
defaultValue: PropertyValue<T>,
|
||||
params: ConfigParams.() -> Unit = {}
|
||||
params: ConfigParams.() -> Unit = {},
|
||||
propertyKeyCallback: (PropertyKey<*>) -> Unit = {}
|
||||
): PropertyValue<T> {
|
||||
val propertyKey = PropertyKey(key, type, ConfigParams().also { it.params() })
|
||||
val propertyKey = PropertyKey({ parentContainerKey }, key, type, ConfigParams().also { it.params() })
|
||||
properties[propertyKey] = defaultValue
|
||||
propertyKeyCallback(propertyKey)
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
@ -51,7 +54,9 @@ open class ConfigContainer(
|
||||
protected fun <T : ConfigContainer> container(
|
||||
key: String,
|
||||
container: T
|
||||
) = registerProperty(key, DataProcessors.container(container), PropertyValue(container)).get()
|
||||
) = registerProperty(key, DataProcessors.container(container), PropertyValue(container)) {
|
||||
container.parentContainerKey = it
|
||||
}.get()
|
||||
|
||||
fun toJson(): JsonObject {
|
||||
val json = JsonObject()
|
||||
|
@ -12,7 +12,7 @@ data class PropertyPair<T>(
|
||||
|
||||
class ConfigParams(
|
||||
var shouldTranslate: Boolean = false,
|
||||
var hidden: Boolean = false,
|
||||
var isHidden: Boolean = false,
|
||||
var isFolder: Boolean = false,
|
||||
val disabledKey: String? = null
|
||||
)
|
||||
@ -40,9 +40,20 @@ class PropertyValue<T>(
|
||||
operator fun setValue(t: Any?, property: KProperty<*>, t1: T?) = set(t1)
|
||||
}
|
||||
|
||||
class PropertyKey<T>(
|
||||
data class PropertyKey<T>(
|
||||
private val _parent: () -> PropertyKey<*>?,
|
||||
val name: String,
|
||||
val dataType: DataProcessors.PropertyDataProcessor<T>,
|
||||
val params: ConfigParams = ConfigParams(),
|
||||
)
|
||||
) {
|
||||
val parentKey by lazy { _parent() }
|
||||
|
||||
fun propertyTranslationPath(): String {
|
||||
return if (parentKey != null) {
|
||||
"${parentKey!!.propertyTranslationPath()}.properties.$name"
|
||||
} else {
|
||||
"features.$name"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,8 +27,7 @@ class UserInterfaceTweaks : ConfigContainer() {
|
||||
"ngs_search_icon_container"
|
||||
)
|
||||
val storyViewerOverride = unique("story_viewer_override", "DISCOVER_PLAYBACK_SEEKBAR", "VERTICAL_STORY_VIEWER")
|
||||
|
||||
val friendFeedMenuButtons = multiple("friend_feed_menu_buttons", "auto_download_blacklist", "anti_auto_save", "stealth_mode", "conversation_info")
|
||||
val enableFriendFeedMenuBar = boolean("enable_friend_feed_menu_bar")
|
||||
val friendFeedMenuPosition = integer("friend_feed_menu_position", defaultValue = 1)
|
||||
val enableFriendFeedMenuBar = boolean("enable_friend_feed_menu_bar")
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user