commit 0b0220ce848afee9a65dc225d8b47909816031ef
parent fcb84661a6fe8af93f55deceffc3ab3d459873fb
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date:   Wed,  3 Jan 2024 01:33:49 +0100

feat(app/ui): home section redesign

Diffstat:
Mapp/src/main/kotlin/me/rhunk/snapenhance/ui/manager/Navigation.kt | 2+-
Mapp/src/main/kotlin/me/rhunk/snapenhance/ui/manager/Section.kt | 4++++
Mapp/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/home/HomeSection.kt | 200+++++++++++++++++++++++++++++++------------------------------------------------
Mapp/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/home/HomeSubSection.kt | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Mapp/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/home/SettingsSection.kt | 10+++++++++-
Aapp/src/main/res/drawable/ic_github.xml | 11+++++++++++
Aapp/src/main/res/drawable/ic_telegram.xml | 4++++
Mcommon/src/main/kotlin/me/rhunk/snapenhance/common/action/EnumAction.kt | 4++--
8 files changed, 164 insertions(+), 129 deletions(-)

diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/Navigation.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/Navigation.kt @@ -65,7 +65,7 @@ class Navigation( val currentSection = getCurrentSection(currentDestination) TopAppBar(title = { - Text(text = currentSection.sectionTopBarName()) + currentSection.Title() }, navigationIcon = { val backButtonAnimation by animateFloatAsState(if (currentSection.canGoBack()) 1f else 0f, label = "backButtonAnimation" diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/Section.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/Section.kt @@ -3,6 +3,7 @@ package me.rhunk.snapenhance.ui.manager import androidx.compose.foundation.layout.RowScope import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.* +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.vector.ImageVector import androidx.navigation.NavController @@ -71,6 +72,9 @@ open class Section { open fun canGoBack(): Boolean = false @Composable + open fun Title() { Text(text = sectionTopBarName()) } + + @Composable open fun Content() { NotImplemented() } @Composable 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 @@ -4,16 +4,15 @@ import android.content.Intent import android.net.Uri import androidx.compose.foundation.Image import androidx.compose.foundation.ScrollState +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.* +import androidx.compose.material.icons.filled.BugReport +import androidx.compose.material.icons.filled.Settings import androidx.compose.material3.* import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.scale @@ -21,7 +20,11 @@ import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.text.font.Font +import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp @@ -30,12 +33,11 @@ import androidx.navigation.compose.composable import androidx.navigation.navigation import kotlinx.coroutines.launch import me.rhunk.snapenhance.R +import me.rhunk.snapenhance.common.BuildConfig import me.rhunk.snapenhance.ui.manager.Section import me.rhunk.snapenhance.ui.manager.data.InstallationSummary import me.rhunk.snapenhance.ui.manager.data.Updater -import me.rhunk.snapenhance.ui.setup.Requirements import me.rhunk.snapenhance.ui.util.ActivityLauncherHelper -import me.rhunk.snapenhance.ui.util.saveFile import java.util.Locale class HomeSection : Section() { @@ -57,31 +59,6 @@ class HomeSection : Section() { } @Composable - private fun SummaryCardRow(icon: ImageVector? = null, title: String, action: @Composable () -> Unit) { - Row( - modifier = Modifier.padding(all = 16.dp), - horizontalArrangement = Arrangement.SpaceBetween - ) { - icon?.let { - Icon( - imageVector = it, - contentDescription = null, - modifier = Modifier - .padding(end = 10.dp) - .align(Alignment.CenterVertically) - ) - } - Text(text = title, modifier = Modifier - .weight(1f) - .align(Alignment.CenterVertically) - ) - Column { - action() - } - } - } - - @Composable private fun SummaryCards(installationSummary: InstallationSummary) { val summaryInfo = remember { mapOf( @@ -130,35 +107,6 @@ class HomeSection : Section() { } } } - - OutlinedCard( - modifier = Modifier - .padding(all = cardMargin) - .fillMaxWidth() - ) { - SummaryCardRow( - icon = Icons.Filled.Map, - title = if (installationSummary.modInfo == null || installationSummary.modInfo.mappingsOutdated == true) { - "Mappings ${if (installationSummary.modInfo == null) "not generated" else "outdated"}" - } else { - "Mappings are up-to-date" - } - ) { - Button(onClick = { - context.checkForRequirements(Requirements.MAPPINGS) - }, modifier = Modifier.height(40.dp)) { - Icon(Icons.Filled.Refresh, contentDescription = null) - } - } - - SummaryCardRow(icon = Icons.Filled.Language, title = userLocale ?: "Unknown") { - Button(onClick = { - context.checkForRequirements(Requirements.LANGUAGE) - }, modifier = Modifier.height(40.dp)) { - Icon(Icons.Filled.OpenInNew, contentDescription = null) - } - } - } } override fun onResumed() { @@ -173,7 +121,9 @@ class HomeSection : Section() { context.longToast("SnapEnhance failed to load installation summary: ${it.message}") } runCatching { - latestUpdate = Updater.checkForLatestRelease() + if (!BuildConfig.DEBUG) { + latestUpdate = Updater.checkForLatestRelease() + } }.onFailure { context.longToast("SnapEnhance failed to check for updates: ${it.message}") } @@ -211,48 +161,7 @@ class HomeSection : Section() { } } LOGS_SECTION_ROUTE -> { - var showDropDown by remember { mutableStateOf(false) } - - IconButton(onClick = { - showDropDown = true - }) { - Icon(Icons.Filled.MoreVert, contentDescription = null) - } - - DropdownMenu( - expanded = showDropDown, - onDismissRequest = { showDropDown = false }, - modifier = Modifier.align(Alignment.CenterVertically) - ) { - DropdownMenuItem(onClick = { - context.log.clearLogs() - navController.navigate(LOGS_SECTION_ROUTE) - showDropDown = false - }, text = { - Text( - text = context.translation["manager.sections.home.logs.clear_logs_button"] - ) - }) - - DropdownMenuItem(onClick = { - activityLauncherHelper.saveFile("snapenhance-logs-${System.currentTimeMillis()}.zip", "application/zip") { uri -> - context.androidContext.contentResolver.openOutputStream(Uri.parse(uri))?.use { - runCatching { - context.log.exportLogsToZip(it) - context.longToast("Saved logs to $uri") - }.onFailure { - context.longToast("Failed to save logs to $uri!") - context.log.error("Failed to save logs to $uri!", it) - } - } - } - showDropDown = false - }, text = { - Text( - text = context.translation["manager.sections.home.logs.export_logs_button"] - ) - }) - } + homeSubSection.LogsTopBarButtons(activityLauncherHelper, navController, this) } } } @@ -279,30 +188,84 @@ class HomeSection : Section() { @Composable @Preview override fun Content() { + val avenirNextFontFamily = remember { + FontFamily( + Font(R.font.avenir_next_medium, FontWeight.Medium) + ) + } + Column( modifier = Modifier .verticalScroll(ScrollState(0)) ) { - Column( + + Image( + painter = painterResource(id = R.drawable.launcher_icon_monochrome), + contentDescription = null, + colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.primary), + contentScale = ContentScale.FillHeight, + modifier = Modifier + .fillMaxWidth() + .scale(1.8f) + .height(90.dp) + ) + + Text( + text = arrayOf("\u0020", "\u0065", "\u0063", "\u006e", "\u0061", "\u0068", "\u006e", "\u0045", "\u0070", "\u0061", "\u006e", "\u0053").reversed().joinToString(""), + fontSize = 30.sp, + fontFamily = avenirNextFontFamily, + modifier = Modifier.align(Alignment.CenterHorizontally), + ) + + Text( + text = "v" + BuildConfig.VERSION_NAME + " \u00b7 by rhunk", + fontSize = 12.sp, + fontFamily = avenirNextFontFamily, + modifier = Modifier.align(Alignment.CenterHorizontally), + ) + + Text( + text = "An Xposed module made to enhance your Snapchat experience", modifier = Modifier + .padding(16.dp) .fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally + textAlign = TextAlign.Center, + ) + + Row( + horizontalArrangement = Arrangement.spacedBy(15.dp, Alignment.CenterHorizontally), + modifier = Modifier + .fillMaxWidth() + .padding(all = 10.dp) ) { - Image( - painter = painterResource(id = R.drawable.launcher_icon_monochrome), + Icon( + imageVector = ImageVector.vectorResource(id = R.drawable.ic_github), contentDescription = null, - colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.primary), - contentScale = ContentScale.FillHeight, - modifier = Modifier - .height(120.dp) - .scale(1.75f) + tint = MaterialTheme.colorScheme.onSurfaceVariant, + modifier = Modifier.size(32.dp).clickable { + context.activity?.startActivity( + Intent(Intent.ACTION_VIEW).apply { + data = Uri.parse("https://github.com/rhunk/SnapEnhance") + flags = Intent.FLAG_ACTIVITY_NEW_TASK + } + ) + } ) - Text( - text = arrayOf("\u0065", "\u0063", "\u006e", "\u0061", "\u0068", "\u006e", "\u0045", "\u0070", "\u0061", "\u006e", "\u0053").reversed().joinToString(""), - fontSize = 30.sp, - modifier = Modifier.padding(16.dp), + Icon( + imageVector = ImageVector.vectorResource(id = R.drawable.ic_telegram), + contentDescription = null, + tint = MaterialTheme.colorScheme.onSurfaceVariant, + modifier = Modifier.size(32.dp).clickable { + context.activity?.startActivity( + Intent(Intent.ACTION_VIEW).apply { + data = Uri.parse("https://t.me/snapenhance") + flags = Intent.FLAG_ACTIVITY_NEW_TASK + } + ) + } ) } + Spacer(modifier = Modifier.height(20.dp)) if (latestUpdate != null) { OutlinedCard( @@ -345,11 +308,6 @@ class HomeSection : Section() { } } - Text( - text = "An Xposed module made to enhance your Snapchat experience", - modifier = Modifier.padding(16.dp) - ) - SummaryCards(installationSummary = installationSummary ?: return) } } diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/home/HomeSubSection.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/home/HomeSubSection.kt @@ -1,5 +1,6 @@ package me.rhunk.snapenhance.ui.manager.sections.home +import android.net.Uri import androidx.compose.foundation.ScrollState import androidx.compose.foundation.background import androidx.compose.foundation.gestures.detectTapGestures @@ -10,14 +11,12 @@ import androidx.compose.foundation.lazy.LazyListState import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.KeyboardDoubleArrowDown import androidx.compose.material.icons.filled.KeyboardDoubleArrowUp +import androidx.compose.material.icons.filled.MoreVert import androidx.compose.material.icons.outlined.BugReport import androidx.compose.material.icons.outlined.Info import androidx.compose.material.icons.outlined.Report import androidx.compose.material.icons.outlined.Warning -import androidx.compose.material3.FilledIconButton -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text +import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -28,6 +27,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.navigation.NavController import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -36,8 +36,10 @@ import me.rhunk.snapenhance.LogReader import me.rhunk.snapenhance.RemoteSideContext import me.rhunk.snapenhance.common.logger.LogChannel import me.rhunk.snapenhance.common.logger.LogLevel +import me.rhunk.snapenhance.ui.util.ActivityLauncherHelper import me.rhunk.snapenhance.ui.util.pullrefresh.PullRefreshIndicator import me.rhunk.snapenhance.ui.util.pullrefresh.rememberPullRefreshState +import me.rhunk.snapenhance.ui.util.saveFile class HomeSubSection( private val context: RemoteSideContext @@ -171,6 +173,54 @@ class HomeSubSection( } @Composable + fun LogsTopBarButtons(activityLauncherHelper: ActivityLauncherHelper, navController: NavController, rowScope: RowScope) { + var showDropDown by remember { mutableStateOf(false) } + + IconButton(onClick = { + showDropDown = true + }) { + Icon(Icons.Filled.MoreVert, contentDescription = null) + } + + rowScope.apply { + DropdownMenu( + expanded = showDropDown, + onDismissRequest = { showDropDown = false }, + modifier = Modifier.align(Alignment.CenterVertically) + ) { + DropdownMenuItem(onClick = { + context.log.clearLogs() + navController.navigate(HomeSection.LOGS_SECTION_ROUTE) + showDropDown = false + }, text = { + Text( + text = context.translation["manager.sections.home.logs.clear_logs_button"] + ) + }) + + DropdownMenuItem(onClick = { + activityLauncherHelper.saveFile("snapenhance-logs-${System.currentTimeMillis()}.zip", "application/zip") { uri -> + context.androidContext.contentResolver.openOutputStream(Uri.parse(uri))?.use { + runCatching { + context.log.exportLogsToZip(it) + context.longToast("Saved logs to $uri") + }.onFailure { + context.longToast("Failed to save logs to $uri!") + context.log.error("Failed to save logs to $uri!", it) + } + } + } + showDropDown = false + }, text = { + Text( + text = context.translation["manager.sections.home.logs.export_logs_button"] + ) + }) + } + } + } + + @Composable fun LogsActionButtons() { val coroutineScope = rememberCoroutineScope() Column( diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/home/SettingsSection.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/manager/sections/home/SettingsSection.kt @@ -21,6 +21,7 @@ import me.rhunk.snapenhance.common.Constants import me.rhunk.snapenhance.common.action.EnumAction import me.rhunk.snapenhance.common.bridge.types.BridgeFileType import me.rhunk.snapenhance.ui.manager.Section +import me.rhunk.snapenhance.ui.setup.Requirements import me.rhunk.snapenhance.ui.util.ActivityLauncherHelper import me.rhunk.snapenhance.ui.util.AlertDialogs import me.rhunk.snapenhance.ui.util.saveFile @@ -63,7 +64,7 @@ class SettingsSection( ShiftedRow( modifier = Modifier .fillMaxWidth() - .height(65.dp) + .height(55.dp) .clickable { takeAction() }, @@ -116,6 +117,12 @@ class SettingsSection( launchActionIntent(enumAction) } } + RowAction(title = "Regenerate Mappings") { + context.checkForRequirements(Requirements.MAPPINGS) + } + RowAction(title = "Change Language") { + context.checkForRequirements(Requirements.LANGUAGE) + } RowTitle(title = "Message Logger") ShiftedRow { Column( @@ -227,6 +234,7 @@ class SettingsSection( Text(text = "Clear") } } + Spacer(modifier = Modifier.height(50.dp)) } } } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_github.xml b/app/src/main/res/drawable/ic_github.xml @@ -0,0 +1,11 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:fillColor="#FF000000" + android:pathData="M12,0c-6.626,0 -12,5.373 -12,12 0,5.302 3.438,9.8 8.207,11.387 0.599,0.111 0.793,-0.261 0.793,-0.577v-2.234c-3.338,0.726 -4.033,-1.416 -4.033,-1.416 -0.546,-1.387 -1.333,-1.756 -1.333,-1.756 -1.089,-0.745 0.083,-0.729 0.083,-0.729 1.205,0.084 1.839,1.237 1.839,1.237 1.07,1.834 2.807,1.304 3.492,0.997 0.107,-0.775 0.418,-1.305 0.762,-1.604 -2.665,-0.305 -5.467,-1.334 -5.467,-5.931 0,-1.311 0.469,-2.381 1.236,-3.221 -0.124,-0.303 -0.535,-1.524 0.117,-3.176 0,0 1.008,-0.322 3.301,1.23 0.957,-0.266 1.983,-0.399 3.003,-0.404 1.02,0.005 2.047,0.138 3.006,0.404 2.291,-1.552 3.297,-1.23 3.297,-1.23 0.653,1.653 0.242,2.874 0.118,3.176 0.77,0.84 1.235,1.911 1.235,3.221 0,4.609 -2.807,5.624 -5.479,5.921 0.43,0.372 0.823,1.102 0.823,2.222v3.293c0,0.319 0.192,0.694 0.801,0.576 4.765,-1.589 8.199,-6.086 8.199,-11.386 0,-6.627 -5.373,-12 -12,-12z" + tools:ignore="VectorPath" /> +</vector> diff --git a/app/src/main/res/drawable/ic_telegram.xml b/app/src/main/res/drawable/ic_telegram.xml @@ -0,0 +1,4 @@ +<vector android:height="24dp" android:viewportHeight="32" + android:viewportWidth="32" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> + <path android:fillColor="#FF000000" android:pathData="m16,0.5c-8.563,0 -15.5,6.938 -15.5,15.5s6.938,15.5 15.5,15.5c8.563,0 15.5,-6.938 15.5,-15.5s-6.938,-15.5 -15.5,-15.5zM23.613,11.119 L21.069,23.107c-0.188,0.85 -0.694,1.056 -1.4,0.656l-3.875,-2.856 -1.869,1.8c-0.206,0.206 -0.381,0.381 -0.781,0.381l0.275,-3.944 7.181,-6.488c0.313,-0.275 -0.069,-0.431 -0.482,-0.156l-8.875,5.587 -3.825,-1.194c-0.831,-0.262 -0.85,-0.831 0.175,-1.231l14.944,-5.763c0.694,-0.25 1.3,0.169 1.075,1.219z"/> +</vector> diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/action/EnumAction.kt b/common/src/main/kotlin/me/rhunk/snapenhance/common/action/EnumAction.kt @@ -7,10 +7,10 @@ enum class EnumAction( val exitOnFinish: Boolean = false, val isCritical: Boolean = false, ) { - CLEAN_CACHE("clean_snapchat_cache", exitOnFinish = true), EXPORT_CHAT_MESSAGES("export_chat_messages"), EXPORT_MEMORIES("export_memories"), - BULK_MESSAGING_ACTION("bulk_messaging_action"); + BULK_MESSAGING_ACTION("bulk_messaging_action"), + CLEAN_CACHE("clean_snapchat_cache", exitOnFinish = true); companion object { const val ACTION_PARAMETER = "se_action"