commit 77584d67e21b7b3801017a5220a832be7abb2730
parent e587f4700a491aff805dd5d35e9ebf5630d80f4b
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date:   Sun,  3 Sep 2023 00:11:11 +0200

chore(lang): section translation
- profile picture downloader config

Diffstat:
Mapp/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/NotImplemented.kt | 10+++++++++-
Mapp/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/downloads/DownloadsSection.kt | 8++++++--
Mapp/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/home/HomeSection.kt | 8++++++--
Mapp/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/social/AddFriendDialog.kt | 13++++++++-----
Mapp/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/social/ScopeContent.kt | 21++++++++++-----------
Mapp/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/social/SocialSection.kt | 2+-
Mapp/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/PermissionsScreen.kt | 70+++++++++++++++++++++++++++++++++++++++++++++-------------------------
Mapp/src/main/kotlin/me/rhunk/snapenhance/ui/util/AlertDialogs.kt | 4++--
Mcore/src/main/assets/lang/en_US.json | 64+++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/DownloaderConfig.kt | 1+
Mcore/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/RootConfig.kt | 3++-
Mcore/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/ProfilePictureDownloader.kt | 14+++++++++-----
12 files changed, 150 insertions(+), 68 deletions(-)

diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/NotImplemented.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/NotImplemented.kt @@ -1,14 +1,22 @@ package me.rhunk.snapenhance.ui.manager.sections +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier import me.rhunk.snapenhance.ui.manager.Section class NotImplemented : Section() { @Composable override fun Content() { - Column { + Column( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + ) { Text(text = "Not implemented yet!") } } diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/downloads/DownloadsSection.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/downloads/DownloadsSection.kt @@ -269,9 +269,13 @@ class DownloadsSection : Section() { item { Spacer(Modifier.height(20.dp)) if (loadedDownloads.value.isEmpty()) { - Text(text = "(empty)", fontSize = 20.sp, modifier = Modifier + Text( + text = context.translation["manager.sections.downloads.empty_download_list"], + fontSize = 20.sp, + modifier = Modifier .fillMaxWidth() - .padding(10.dp), textAlign = TextAlign.Center) + .padding(10.dp), textAlign = TextAlign.Center + ) } LaunchedEffect(Unit) { val lastItemIndex = (loadedDownloads.value.size - 1).takeIf { it >= 0 } ?: return@LaunchedEffect diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/home/HomeSection.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/home/HomeSection.kt @@ -250,7 +250,9 @@ class HomeSection : Section() { navController.navigate(LOGS_SECTION_ROUTE) showDropDown = false }, text = { - Text(text = "Clear logs") + Text( + text = context.translation["manager.sections.home.logs.clear_logs_button"] + ) }) DropdownMenuItem(onClick = { @@ -267,7 +269,9 @@ class HomeSection : Section() { } showDropDown = false }, text = { - Text(text = "Export logs") + Text( + text = context.translation["manager.sections.home.logs.export_logs_button"] + ) }) } } diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/social/AddFriendDialog.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/social/AddFriendDialog.kt @@ -53,6 +53,9 @@ class AddFriendDialog( private val context: RemoteSideContext, private val section: SocialSection, ) { + + private val translation by lazy { context.translation.getCategory("manager.dialogs.add_friend")} + @Composable private fun ListCardEntry(name: String, getCurrentState: () -> Boolean, onState: (Boolean) -> Unit = {}) { var currentState by remember { mutableStateOf(getCurrentState()) } @@ -95,7 +98,7 @@ class AddFriendDialog( .padding(10.dp), ) { Text( - text = "Add Friend or Group", + text = translation["title"], fontSize = 23.sp, fontWeight = FontWeight.ExtraBold, modifier = Modifier @@ -113,7 +116,7 @@ class AddFriendDialog( value = searchKeyword.value, onValueChange = { searchKeyword.value = it }, label = { - Text(text = "Search") + Text(text = translation["search_hint"]) }, modifier = Modifier .weight(1f) @@ -184,7 +187,7 @@ class AddFriendDialog( ) { if (hasFetchError) { Text( - text = "Failed to fetch data", + text = translation["fetch_error"], fontSize = 20.sp, fontWeight = FontWeight.Bold, modifier = Modifier.padding(bottom = 10.dp, top = 10.dp) @@ -222,7 +225,7 @@ class AddFriendDialog( ) { item { if (filteredGroups.isEmpty()) return@item - Text(text = "Groups", + Text(text = translation["category_groups"], fontSize = 20.sp, fontWeight = FontWeight.Bold, modifier = Modifier.padding(bottom = 10.dp, top = 10.dp) @@ -248,7 +251,7 @@ class AddFriendDialog( item { if (filteredFriends.isEmpty()) return@item - Text(text = "Friends", + Text(text = translation["category_friends"], fontSize = 20.sp, fontWeight = FontWeight.Bold, modifier = Modifier.padding(bottom = 10.dp, top = 10.dp) diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/social/ScopeContent.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/social/ScopeContent.kt @@ -40,6 +40,8 @@ class ScopeContent( val scope: SocialScope, private val id: String ) { + private val translation by lazy { context.translation.getCategory("manager.sections.social") } + fun deleteScope(coroutineScope: CoroutineScope) { when (scope) { SocialScope.FRIEND -> context.modDatabase.deleteFriend(id) @@ -68,7 +70,7 @@ class ScopeContent( val rules = context.modDatabase.getRules(id) - SectionTitle("Rules") + SectionTitle(translation["rules_title"]) ContentCard { //manager anti features etc @@ -163,7 +165,7 @@ class ScopeContent( private fun Friend() { //fetch the friend from the database val friend = remember { context.modDatabase.getFriendInfo(id) } ?: run { - Text(text = "Friend not found") + Text(text = translation["not_found"]) return } @@ -197,9 +199,6 @@ class ScopeContent( fontSize = 12.sp, fontWeight = FontWeight.Light ) - // Spacer(modifier = Modifier.height(16.dp)) - - //DeleteScopeEntityButton() } Spacer(modifier = Modifier.height(16.dp)) @@ -207,7 +206,7 @@ class ScopeContent( //streaks streaks?.let { var shouldNotify by remember { mutableStateOf(it.notify) } - SectionTitle("Streaks") + SectionTitle(translation["streaks_title"]) ContentCard { Row( verticalAlignment = Alignment.CenterVertically @@ -215,13 +214,13 @@ class ScopeContent( Column( modifier = Modifier.weight(1f), ) { - Text(text = "Length: ${streaks.length}", maxLines = 1) - Text(text = "Expires in: ${computeStreakETA(streaks.expirationTimestamp)}", maxLines = 1) + Text(text = translation.format("streaks_length_text", "count" to streaks.length.toString()), maxLines = 1) + Text(text = translation.format("streaks_expiration_text", "eta" to computeStreakETA(streaks.expirationTimestamp)), maxLines = 1) } Row( verticalAlignment = Alignment.CenterVertically ) { - Text(text = "Reminder", maxLines = 1, modifier = Modifier.padding(end = 10.dp)) + Text(text = translation["reminder_button"], maxLines = 1, modifier = Modifier.padding(end = 10.dp)) Switch(checked = shouldNotify, onCheckedChange = { context.modDatabase.setFriendStreaksNotify(id, it) shouldNotify = it @@ -237,7 +236,7 @@ class ScopeContent( private fun Group() { //fetch the group from the database val group = remember { context.modDatabase.getGroupInfo(id) } ?: run { - Text(text = "Group not found") + Text(text = translation["not_found"]) return } @@ -256,7 +255,7 @@ class ScopeContent( ) Spacer(modifier = Modifier.height(5.dp)) Text( - text = "Participants: ${group.participantsCount}", + text = translation.format("participants_text", "count" to group.participantsCount.toString()), maxLines = 1, fontSize = 12.sp, fontWeight = FontWeight.Light diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/social/SocialSection.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/social/SocialSection.kt @@ -219,7 +219,7 @@ class SocialSection : Section() { MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.primary ) - Text(text = "${streaks.hoursLeft()}h", maxLines = 1, fontWeight = FontWeight.Bold) + Text(text = context.translation.format("context.sections.social.streaks_expiration_short", "hours" to streaks.length.toString()), maxLines = 1, fontWeight = FontWeight.Bold) } } } diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/PermissionsScreen.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/PermissionsScreen.kt @@ -15,7 +15,11 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Check import androidx.compose.material3.Button +import androidx.compose.material3.Icon import androidx.compose.material3.OutlinedCard import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -26,6 +30,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import kotlinx.coroutines.launch import me.rhunk.snapenhance.ui.setup.screens.SetupScreen @@ -38,6 +43,24 @@ class PermissionsScreen : SetupScreen() { activityLauncherHelper = ActivityLauncherHelper(context.activity!!) } + @Composable + private fun RequestButton(onClick: () -> Unit) { + Button(onClick = onClick) { + Text(text = context.translation["setup.permissions.request_button"]) + } + } + + @Composable + private fun GrantedIcon() { + Icon( + imageVector = Icons.Filled.Check, + contentDescription = null, + modifier = Modifier + .size(24.dp) + .padding(5.dp) + ) + } + @SuppressLint("BatteryLife") @Composable override fun Content() { @@ -59,7 +82,7 @@ class PermissionsScreen : SetupScreen() { allowNext(false) } - DialogText(text = "To continue you need to fit the following requirements:") + DialogText(text = context.translation["setup.permissions.dialog"]) OutlinedCard( modifier = Modifier @@ -73,39 +96,36 @@ class PermissionsScreen : SetupScreen() { Row( horizontalArrangement = Arrangement.Absolute.SpaceAround ) { - DialogText(text = "Notification access", modifier = Modifier.weight(1f)) + DialogText(text = context.translation["setup.permissions.dialog"], modifier = Modifier.weight(1f)) if (notificationPermissionGranted) { - DialogText(text = "Granted") - } else { - Button(onClick = { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - activityLauncherHelper.requestPermission(Manifest.permission.POST_NOTIFICATIONS) { resultCode, _ -> - coroutineScope.launch { - notificationPermissionGranted = resultCode == ComponentActivity.RESULT_OK - } + GrantedIcon() + return@Row + } + + RequestButton { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + activityLauncherHelper.requestPermission(Manifest.permission.POST_NOTIFICATIONS) { resultCode, _ -> + coroutineScope.launch { + notificationPermissionGranted = resultCode == ComponentActivity.RESULT_OK } } - }) { - Text(text = "Request") } } } Row { - DialogText(text = "Battery optimisation", modifier = Modifier.weight(1f)) + DialogText(text = context.translation["setup.permissions.battery_optimization"], modifier = Modifier.weight(1f)) if (isBatteryOptimisationIgnored) { - DialogText(text = "Ignored") - } else { - Button(onClick = { - activityLauncherHelper.launch(Intent().apply { - action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS - data = Uri.parse("package:${context.androidContext.packageName}") - }) { resultCode, _ -> - coroutineScope.launch { - isBatteryOptimisationIgnored = resultCode == 0 - } + GrantedIcon() + return@Row + } + RequestButton { + activityLauncherHelper.launch(Intent().apply { + action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS + data = Uri.parse("package:${context.androidContext.packageName}") + }) { resultCode, _ -> + coroutineScope.launch { + isBatteryOptimisationIgnored = resultCode == 0 } - }) { - Text(text = "Request") } } } diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/AlertDialogs.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/util/AlertDialogs.kt @@ -210,7 +210,7 @@ class AlertDialogs( horizontalArrangement = Arrangement.SpaceEvenly, ) { Button(onClick = { dismiss() }) { - Text(text = "Cancel") + Text(text = translation["button.cancel"]) } Button(onClick = { when (property.key.dataType.type) { @@ -232,7 +232,7 @@ class AlertDialogs( } dismiss() }) { - Text(text = "Ok") + Text(text = translation["button.ok"]) } } } diff --git a/core/src/main/assets/lang/en_US.json b/core/src/main/assets/lang/en_US.json @@ -12,6 +12,12 @@ "generate_failure_no_snapchat": "SnapEnhance was unable to detect Snapchat, please try reinstalling Snapchat.", "generate_failure": "An error occurred while trying to generate mappings, please try again.", "generate_success": "Mappings generated successfully." + }, + "permissions": { + "dialog": "To continue you need to fit the following requirements:", + "notification_access": "Notification Access", + "battery_optimization": "Battery Optimization", + "request_button": "Request" } }, @@ -25,8 +31,38 @@ "social": "Social", "plugins": "Plugins" }, - "features": { - "disabled": "Disabled" + "sections": { + "home": { + "logs": { + "clear_logs_button": "Clear Logs", + "export_logs_button": "Export Logs" + } + }, + "downloads": { + "empty_download_list": "(empty)" + }, + "features": { + "disabled": "Disabled" + }, + "social": { + "rules_title": "Rules", + "participants_text": "{count} participants", + "not_found": "Not found", + "streaks_title": "Streaks", + "streaks_length_text": "Length: {length}", + "streaks_expiration_short": "{hours}h", + "streaks_expiration_text": "Expires in {eta}", + "reminder_button": "Set Reminder" + } + }, + "dialogs": { + "add_friend": { + "title": "Add Friend or Group", + "search_hint": "Search", + "fetch_error": "Failed to fetch data", + "category_groups": "Groups", + "category_friends": "Friends" + } } }, @@ -118,6 +154,10 @@ "name": "Force Voice Note Format", "description": "Forces Voice Notes to be saved in a specified Format" }, + "download_profile_pictures": { + "name": "Download Profile Pictures", + "description": "Allows you to download Profile Pictures from the profile page" + }, "chat_download_context_menu": { "name": "Chat Download Context Menu", "description": "Allows you to download media from a conversation by long-pressing them" @@ -577,16 +617,6 @@ "birthday": "Birthday : {month} {day}" }, - "auto_updater": { - "no_update_available": "No Update available!", - "dialog_title": "New Update available!", - "dialog_message": "There is a new Update for SnapEnhance available! ({version})\n\n{body}", - "dialog_positive_button": "Download and Install", - "dialog_negative_button": "Cancel", - "downloading_toast": "Downloading Update...", - "download_manager_notification_title": "Downloading SnapEnhance APK..." - }, - "chat_export": { "select_export_format": "Select the Export Format", "select_media_type": "Select Media Types to export", @@ -610,7 +640,15 @@ "positive": "Yes", "negative": "No", "cancel": "Cancel", - "open": "Open" + "open": "Open", + "download": "Download" + }, + + "profile_picture_downloader": { + "button": "Download Profile Picture", + "title": "Profile Picture Downloader", + "avatar_option": "Avatar", + "background_option": "Background" }, "download_manager_activity": { diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/DownloaderConfig.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/config/impl/DownloaderConfig.kt @@ -41,6 +41,7 @@ class DownloaderConfig : ConfigContainer() { val forceVoiceNoteFormat = unique("force_voice_note_format", "aac", "mp3", "opus") { addFlags(ConfigFlag.NO_TRANSLATE) } + val downloadProfilePictures = boolean("download_profile_pictures") val chatDownloadContextMenu = boolean("chat_download_context_menu") val ffmpegOptions = container("ffmpeg_options", FFMpegOptions()) { addNotices(FeatureNotice.UNSTABLE) } val logging = multiple("logging", "started", "success", "progress", "failure").apply { 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 @@ -11,6 +11,7 @@ class RootConfig : ConfigContainer() { val rules = container("rules", Rules()) { icon = "Rule" } val camera = container("camera", Camera()) { icon = "Camera"} val streaksReminder = container("streaks_reminder", StreaksReminderConfig()) { icon = "Alarm" } - val experimental = container("experimental", Experimental()) { icon = "Science"; addNotices(FeatureNotice.UNSTABLE) + val experimental = container("experimental", Experimental()) { + icon = "Science"; addNotices(FeatureNotice.UNSTABLE) } } \ No newline at end of file diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/ProfilePictureDownloader.kt b/core/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/ProfilePictureDownloader.kt @@ -16,6 +16,8 @@ import java.nio.ByteBuffer class ProfilePictureDownloader : Feature("ProfilePictureDownloader", loadParams = FeatureLoadParams.ACTIVITY_CREATE_ASYNC) { @SuppressLint("SetTextI18n") override fun asyncOnActivityCreate() { + if (!context.config.downloader.downloadProfilePictures.get()) return + var friendUsername: String? = null var backgroundUrl: String? = null var avatarUrl: String? = null @@ -24,7 +26,7 @@ class ProfilePictureDownloader : Feature("ProfilePictureDownloader", loadParams if (event.view::class.java.name != "com.snap.unifiedpublicprofile.UnifiedPublicProfileView") return@subscribe event.parent.addView(Button(event.parent.context).apply { - text = "Download" + text = this@ProfilePictureDownloader.context.translation["profile_picture_downloader.button"] layoutParams = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT).apply { setMargins(0, 200, 0, 0) } @@ -32,12 +34,14 @@ class ProfilePictureDownloader : Feature("ProfilePictureDownloader", loadParams ViewAppearanceHelper.newAlertDialogBuilder( this@ProfilePictureDownloader.context.mainActivity!! ).apply { - setTitle("Download profile picture") + setTitle(this@ProfilePictureDownloader.context.translation["profile_picture_downloader.title"]) val choices = mutableMapOf<String, String>() - backgroundUrl?.let { choices["Background"] = it } - avatarUrl?.let { choices["Avatar"] = it } + backgroundUrl?.let { choices["avatar_option"] = it } + avatarUrl?.let { choices["background_option"] = it } - setItems(choices.keys.toTypedArray()) { _, which -> + setItems(choices.keys.map { + this@ProfilePictureDownloader.context.translation["profile_picture_downloader.$it"] + }.toTypedArray()) { _, which -> runCatching { this@ProfilePictureDownloader.context.feature(MediaDownloader::class).downloadProfilePicture( choices.values.elementAt(which),