Feat: dev settings

This commit is contained in:
wingio 2023-03-24 11:59:58 -04:00
parent 584e5e8b3b
commit eba0fbf29c
13 changed files with 126 additions and 36 deletions

View file

@ -24,7 +24,7 @@ class PreferenceManager(private val context: Context) :
var monet by booleanPreference("monet", Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) var monet by booleanPreference("monet", Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
var isDeveloper by booleanPreference("is_developer", true) var isDeveloper by booleanPreference("is_developer", false)
var theme by enumPreference("theme", Theme.SYSTEM) var theme by enumPreference("theme", Theme.SYSTEM)

View file

@ -13,6 +13,7 @@ fun SettingsTextField(
disabled: Boolean = false, disabled: Boolean = false,
pref: String, pref: String,
error: Boolean = false, error: Boolean = false,
supportingText: String? = null,
onPrefChange: (String) -> Unit, onPrefChange: (String) -> Unit,
) { ) {
Box(modifier = Modifier.padding(horizontal = 18.dp, vertical = 10.dp)) { Box(modifier = Modifier.padding(horizontal = 18.dp, vertical = 10.dp)) {
@ -23,7 +24,8 @@ fun SettingsTextField(
enabled = !disabled, enabled = !disabled,
label = { Text(label) }, label = { Text(label) },
isError = error, isError = error,
singleLine = true singleLine = true,
supportingText = if (supportingText != null) { -> Text(supportingText) } else null
) )
} }
} }

View file

@ -1,9 +1,7 @@
package dev.beefers.vendetta.manager.ui.screen.about package dev.beefers.vendetta.manager.ui.screen.about
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@ -16,7 +14,6 @@ import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.material3.Divider import androidx.compose.material3.Divider
import androidx.compose.material3.ElevatedCard import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
@ -30,41 +27,48 @@ import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import cafe.adriel.voyager.core.screen.Screen import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.navigator.currentOrThrow
import coil.compose.AsyncImage
import dev.beefers.vendetta.manager.BuildConfig import dev.beefers.vendetta.manager.BuildConfig
import dev.beefers.vendetta.manager.R import dev.beefers.vendetta.manager.R
import dev.beefers.vendetta.manager.domain.manager.PreferenceManager
import dev.beefers.vendetta.manager.ui.widgets.about.LinkItem import dev.beefers.vendetta.manager.ui.widgets.about.LinkItem
import dev.beefers.vendetta.manager.ui.widgets.about.ListItem import dev.beefers.vendetta.manager.ui.widgets.about.ListItem
import dev.beefers.vendetta.manager.ui.widgets.about.UserEntry import dev.beefers.vendetta.manager.ui.widgets.about.UserEntry
import dev.beefers.vendetta.manager.utils.Constants import dev.beefers.vendetta.manager.utils.Constants
import dev.beefers.vendetta.manager.utils.getBitmap import dev.beefers.vendetta.manager.utils.getBitmap
import dev.beefers.vendetta.manager.utils.showToast
import org.koin.androidx.compose.get
class AboutScreen: Screen { class AboutScreen : Screen {
@Composable @Composable
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
override fun Content() { override fun Content() {
val uriHandler = LocalUriHandler.current val uriHandler = LocalUriHandler.current
val prefs: PreferenceManager = get()
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior() val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
val ctx = LocalContext.current val ctx = LocalContext.current
val bitmap = remember { val bitmap = remember {
ctx.getBitmap(R.drawable.ic_launcher, 60).asImageBitmap() ctx.getBitmap(R.drawable.ic_launcher, 60).asImageBitmap()
} }
var tapCount by remember {
mutableStateOf(0)
}
Scaffold( Scaffold(
topBar = { TitleBar(scrollBehavior) }, topBar = { TitleBar(scrollBehavior) },
@ -100,7 +104,20 @@ class AboutScreen: Screen {
text = "v${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})", text = "v${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})",
style = MaterialTheme.typography.labelLarge, style = MaterialTheme.typography.labelLarge,
color = LocalContentColor.current.copy(alpha = 0.5f), color = LocalContentColor.current.copy(alpha = 0.5f),
modifier = Modifier.clickable { } modifier = Modifier.clickable(
enabled = !prefs.isDeveloper
) {
tapCount++
when (tapCount) {
3 -> ctx.showToast(R.string.msg_seven_left)
5 -> ctx.showToast(R.string.msg_five_left)
8 -> ctx.showToast(R.string.msg_two_left)
10 -> {
ctx.showToast(R.string.msg_unlocked)
prefs.isDeveloper = true
}
}
}
) )
Row( Row(
@ -153,7 +170,7 @@ class AboutScreen: Screen {
uriHandler.openUri("https://github.com/${member.username}") uriHandler.openUri("https://github.com/${member.username}")
} }
) )
if(i != Constants.TEAM_MEMBERS.lastIndex) { if (i != Constants.TEAM_MEMBERS.lastIndex) {
Divider( Divider(
thickness = 0.5.dp, thickness = 0.5.dp,
color = MaterialTheme.colorScheme.outline.copy(alpha = 0.3f), color = MaterialTheme.colorScheme.outline.copy(alpha = 0.3f),

View file

@ -20,7 +20,6 @@ import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Info import androidx.compose.material.icons.filled.Info
import androidx.compose.material.icons.filled.OpenInNew import androidx.compose.material.icons.filled.OpenInNew
import androidx.compose.material.icons.filled.Refresh import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material.icons.filled.RestartAlt
import androidx.compose.material.icons.outlined.Home import androidx.compose.material.icons.outlined.Home
import androidx.compose.material.icons.outlined.Info import androidx.compose.material.icons.outlined.Info
import androidx.compose.material3.Button import androidx.compose.material3.Button
@ -54,7 +53,6 @@ import dev.beefers.vendetta.manager.ui.components.SegmentedButton
import dev.beefers.vendetta.manager.ui.screen.about.AboutScreen import dev.beefers.vendetta.manager.ui.screen.about.AboutScreen
import dev.beefers.vendetta.manager.ui.screen.installer.InstallerScreen import dev.beefers.vendetta.manager.ui.screen.installer.InstallerScreen
import dev.beefers.vendetta.manager.ui.viewmodel.home.HomeViewModel import dev.beefers.vendetta.manager.ui.viewmodel.home.HomeViewModel
import dev.beefers.vendetta.manager.ui.viewmodel.main.MainViewModel
import dev.beefers.vendetta.manager.ui.widgets.home.Commit import dev.beefers.vendetta.manager.ui.widgets.home.Commit
import dev.beefers.vendetta.manager.utils.DiscordVersion import dev.beefers.vendetta.manager.utils.DiscordVersion
import dev.beefers.vendetta.manager.utils.ManagerTab import dev.beefers.vendetta.manager.utils.ManagerTab
@ -75,6 +73,10 @@ class HomeScreen : ManagerTab {
val nav = LocalNavigator.currentOrThrow val nav = LocalNavigator.currentOrThrow
val prefs: PreferenceManager = get() val prefs: PreferenceManager = get()
val viewModel: HomeViewModel = getScreenModel() val viewModel: HomeViewModel = getScreenModel()
val latestVersion = when {
prefs.discordVersion.isBlank() -> viewModel.discordVersions?.get(prefs.channel)
else -> DiscordVersion.fromVersionCode(prefs.discordVersion)
}
val iconColor = when { val iconColor = when {
prefs.patchIcon -> Color(0xFF3AB8BA) prefs.patchIcon -> Color(0xFF3AB8BA)
prefs.channel == DiscordVersion.Type.ALPHA -> Color(0xFFFBB33C) prefs.channel == DiscordVersion.Type.ALPHA -> Color(0xFFFBB33C)
@ -106,18 +108,18 @@ class HomeScreen : ManagerTab {
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) { ) {
AnimatedVisibility(visible = viewModel.discordVersions != null) { AnimatedVisibility(visible = viewModel.installManager.current != null) {
Text( Text(
text = "Latest: ${viewModel.discordVersions?.get(prefs.channel)}", text = "Current: ${viewModel.installManager.current?.versionName}",
style = MaterialTheme.typography.labelLarge, style = MaterialTheme.typography.labelLarge,
color = LocalContentColor.current.copy(alpha = 0.5f), color = LocalContentColor.current.copy(alpha = 0.5f),
textAlign = TextAlign.Center textAlign = TextAlign.Center
) )
} }
AnimatedVisibility(visible = viewModel.installManager.current != null) { AnimatedVisibility(visible = latestVersion != null) {
Text( Text(
text = "Current: ${viewModel.installManager.current?.versionName}", text = "Latest: $latestVersion",
style = MaterialTheme.typography.labelLarge, style = MaterialTheme.typography.labelLarge,
color = LocalContentColor.current.copy(alpha = 0.5f), color = LocalContentColor.current.copy(alpha = 0.5f),
textAlign = TextAlign.Center textAlign = TextAlign.Center
@ -135,10 +137,7 @@ class HomeScreen : ManagerTab {
) { ) {
val label = when { val label = when {
viewModel.installManager.current == null -> R.string.action_install viewModel.installManager.current == null -> R.string.action_install
viewModel.installManager.current?.versionName == viewModel.discordVersions?.get( viewModel.installManager.current?.versionName == latestVersion.toString() -> R.string.action_reinstall
prefs.channel
).toString() -> R.string.action_reinstall
else -> R.string.action_update else -> R.string.action_update
} }
Text(stringResource(label)) Text(stringResource(label))

View file

@ -9,18 +9,21 @@ import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.compositionLocalOf import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import cafe.adriel.voyager.core.screen.Screen import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.koin.getScreenModel import cafe.adriel.voyager.koin.getScreenModel
import com.google.accompanist.pager.ExperimentalPagerApi import com.google.accompanist.pager.ExperimentalPagerApi
import com.google.accompanist.pager.HorizontalPager import com.google.accompanist.pager.HorizontalPager
import com.google.accompanist.pager.PagerState import com.google.accompanist.pager.PagerState
import com.google.accompanist.pager.rememberPagerState import com.google.accompanist.pager.rememberPagerState
import dev.beefers.vendetta.manager.BuildConfig import dev.beefers.vendetta.manager.ui.screen.home.HomeScreen
import dev.beefers.vendetta.manager.ui.viewmodel.main.MainViewModel import dev.beefers.vendetta.manager.ui.viewmodel.main.MainViewModel
import dev.beefers.vendetta.manager.ui.widgets.updater.UpdateDialog import dev.beefers.vendetta.manager.ui.widgets.updater.UpdateDialog
import dev.beefers.vendetta.manager.utils.MainTab import dev.beefers.vendetta.manager.utils.MainTab
@ -31,6 +34,7 @@ class MainScreen : Screen {
@OptIn(ExperimentalMaterial3Api::class, ExperimentalPagerApi::class) @OptIn(ExperimentalMaterial3Api::class, ExperimentalPagerApi::class)
@Composable @Composable
override fun Content() { override fun Content() {
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
val viewModel: MainViewModel = getScreenModel() val viewModel: MainViewModel = getScreenModel()
val pagerState = rememberPagerState() val pagerState = rememberPagerState()
@ -39,8 +43,10 @@ class MainScreen : Screen {
) { ) {
Scaffold( Scaffold(
bottomBar = { NavBar() }, bottomBar = { NavBar() },
topBar = { TitleBar() }, topBar = { TitleBar(scrollBehavior) },
modifier = Modifier.fillMaxSize() modifier = Modifier
.fillMaxSize()
.nestedScroll(scrollBehavior.nestedScrollConnection)
) { pv -> ) { pv ->
if (viewModel.showUpdateDialog && viewModel.release != null) { if (viewModel.showUpdateDialog && viewModel.release != null) {
UpdateDialog( UpdateDialog(
@ -71,18 +77,21 @@ class MainScreen : Screen {
@OptIn(ExperimentalPagerApi::class, ExperimentalMaterial3Api::class) @OptIn(ExperimentalPagerApi::class, ExperimentalMaterial3Api::class)
@Composable @Composable
private fun TitleBar() { private fun TitleBar(
scrollBehavior: TopAppBarScrollBehavior
) {
val pagerState = LocalPagerState.current val pagerState = LocalPagerState.current
val tab = MainTab.values()[pagerState.currentPage].tab val tab = MainTab.values()[pagerState.currentPage].tab
TopAppBar( TopAppBar(
title = { Text(tab.options.title) }, title = { Text(tab.options.title) },
actions = { tab.Actions() } actions = { tab.Actions() },
scrollBehavior = if (tab is HomeScreen) null else scrollBehavior
) )
} }
@Composable @Composable
@OptIn(ExperimentalPagerApi::class) @OptIn(ExperimentalPagerApi::class, ExperimentalMaterial3Api::class)
private fun NavBar() { private fun NavBar() {
val pagerState = LocalPagerState.current val pagerState = LocalPagerState.current
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()

View file

@ -11,6 +11,10 @@ import androidx.compose.material.icons.outlined.Settings
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.runtime.Composable 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.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
@ -19,6 +23,7 @@ import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.navigator.currentOrThrow
import cafe.adriel.voyager.navigator.tab.TabOptions import cafe.adriel.voyager.navigator.tab.TabOptions
import dev.beefers.vendetta.manager.R import dev.beefers.vendetta.manager.R
import dev.beefers.vendetta.manager.domain.manager.InstallManager
import dev.beefers.vendetta.manager.domain.manager.PreferenceManager import dev.beefers.vendetta.manager.domain.manager.PreferenceManager
import dev.beefers.vendetta.manager.ui.components.settings.SettingsButton import dev.beefers.vendetta.manager.ui.components.settings.SettingsButton
import dev.beefers.vendetta.manager.ui.components.settings.SettingsHeader import dev.beefers.vendetta.manager.ui.components.settings.SettingsHeader
@ -27,6 +32,7 @@ import dev.beefers.vendetta.manager.ui.components.settings.SettingsSwitch
import dev.beefers.vendetta.manager.ui.components.settings.SettingsTextField import dev.beefers.vendetta.manager.ui.components.settings.SettingsTextField
import dev.beefers.vendetta.manager.ui.screen.about.AboutScreen import dev.beefers.vendetta.manager.ui.screen.about.AboutScreen
import dev.beefers.vendetta.manager.ui.viewmodel.settings.SettingsViewModel import dev.beefers.vendetta.manager.ui.viewmodel.settings.SettingsViewModel
import dev.beefers.vendetta.manager.utils.DiscordVersion
import dev.beefers.vendetta.manager.utils.ManagerTab import dev.beefers.vendetta.manager.utils.ManagerTab
import dev.beefers.vendetta.manager.utils.TabOptions import dev.beefers.vendetta.manager.utils.TabOptions
import dev.beefers.vendetta.manager.utils.navigate import dev.beefers.vendetta.manager.utils.navigate
@ -44,6 +50,7 @@ class SettingsScreen : ManagerTab {
override fun Content() { override fun Content() {
val viewModel: SettingsViewModel = getScreenModel() val viewModel: SettingsViewModel = getScreenModel()
val prefs: PreferenceManager = get() val prefs: PreferenceManager = get()
val installManager: InstallManager = get()
val ctx = LocalContext.current val ctx = LocalContext.current
Column( Column(
@ -103,6 +110,51 @@ class SettingsScreen : ManagerTab {
viewModel.clearCache() viewModel.clearCache()
} }
) )
if (prefs.isDeveloper) {
SettingsHeader(stringResource(R.string.settings_developer))
SettingsTextField(
label = stringResource(R.string.settings_package_name),
pref = prefs.packageName,
onPrefChange = {
prefs.packageName = it
installManager.getInstalled()
}
)
var version by remember {
mutableStateOf(prefs.discordVersion)
}
var versionError by remember {
mutableStateOf(false)
}
val supportingText = if (versionError)
stringResource(R.string.msg_invalid_version)
else if (version.isNotBlank())
DiscordVersion.fromVersionCode(version).toString()
else
null
SettingsTextField(
label = stringResource(R.string.settings_version),
pref = version,
error = versionError,
supportingText = supportingText,
onPrefChange = {
version = it
if (DiscordVersion.fromVersionCode(it) == null && it.isNotBlank()) {
versionError = true
} else {
versionError = false
prefs.discordVersion = it
}
}
)
SettingsSwitch(
label = stringResource(R.string.settings_debuggable),
secondaryLabel = stringResource(R.string.settings_debuggable_description),
pref = prefs.debuggable,
onPrefChange = { prefs.debuggable = it }
)
}
} }
} }

View file

@ -54,7 +54,7 @@ class MainViewModel(
fun downloadAndInstallUpdate() { fun downloadAndInstallUpdate() {
coroutineScope.launch { coroutineScope.launch {
val update = File(cacheDir, "update.apk") val update = File(cacheDir, "update.apk")
if(update.exists()) update.delete() if (update.exists()) update.delete()
isUpdating = true isUpdating = true
downloadManager.downloadUpdate(update) downloadManager.downloadUpdate(update)
isUpdating = false isUpdating = false

View file

@ -15,7 +15,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage import coil.compose.AsyncImage

View file

@ -44,7 +44,7 @@ fun UserEntry(
) { ) {
AsyncImage( AsyncImage(
modifier = Modifier modifier = Modifier
.size(if(isLarge) 70.dp else 50.dp) .size(if (isLarge) 70.dp else 50.dp)
.clip(CircleShape) .clip(CircleShape)
.background(MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp)), .background(MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp)),
model = "https://github.com/$username.png", model = "https://github.com/$username.png",

View file

@ -1,8 +1,6 @@
package dev.beefers.vendetta.manager.ui.widgets.updater package dev.beefers.vendetta.manager.ui.widgets.updater
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.SystemUpdate import androidx.compose.material.icons.filled.SystemUpdate
@ -46,9 +44,9 @@ fun UpdateDialog(
Box { Box {
Text( Text(
text = stringResource(R.string.action_start_update), text = stringResource(R.string.action_start_update),
color = if(isUpdating) Color.Transparent else LocalContentColor.current color = if (isUpdating) Color.Transparent else LocalContentColor.current
) )
if(isUpdating) { if (isUpdating) {
CircularProgressIndicator( CircularProgressIndicator(
strokeWidth = 3.dp, strokeWidth = 3.dp,
modifier = Modifier modifier = Modifier

View file

@ -13,7 +13,6 @@ import com.google.accompanist.pager.ExperimentalPagerApi
import dev.beefers.vendetta.manager.ui.screen.home.HomeScreen import dev.beefers.vendetta.manager.ui.screen.home.HomeScreen
import dev.beefers.vendetta.manager.ui.screen.main.LocalPagerState import dev.beefers.vendetta.manager.ui.screen.main.LocalPagerState
import dev.beefers.vendetta.manager.ui.screen.settings.SettingsScreen import dev.beefers.vendetta.manager.ui.screen.settings.SettingsScreen
import dev.beefers.vendetta.manager.ui.viewmodel.main.MainViewModel
enum class MainTab(val tab: ManagerTab) { enum class MainTab(val tab: ManagerTab) {
HOME(HomeScreen()), HOME(HomeScreen()),

View file

@ -8,7 +8,7 @@ data class DiscordVersion(
val major: Int, val major: Int,
val minor: Int, val minor: Int,
val type: Type val type: Type
) : Serializable { ) : Serializable, Comparable<DiscordVersion> {
enum class Type(val label: String, @StringRes val labelRes: Int) { enum class Type(val label: String, @StringRes val labelRes: Int) {
STABLE("Stable", R.string.channel_stable), STABLE("Stable", R.string.channel_stable),
@ -16,6 +16,9 @@ data class DiscordVersion(
ALPHA("Alpha", R.string.channel_alpha) ALPHA("Alpha", R.string.channel_alpha)
} }
override fun compareTo(other: DiscordVersion): Int =
toVersionCode().toInt() - other.toVersionCode().toInt()
override fun toString() = "$major.$minor - ${type.label}" override fun toString() = "$major.$minor - ${type.label}"
fun toVersionCode() = "$major${type.ordinal}${if (minor < 10) 0 else ""}${minor}" fun toVersionCode() = "$major${type.ordinal}${if (minor < 10) 0 else ""}${minor}"
@ -25,6 +28,7 @@ data class DiscordVersion(
fun fromVersionCode(string: String): DiscordVersion? = with(string) { fun fromVersionCode(string: String): DiscordVersion? = with(string) {
if (length < 4) return@with null if (length < 4) return@with null
if (toIntOrNull() == null) return@with null if (toIntOrNull() == null) return@with null
if (toInt() <= 126021) return@with null
val codeReversed = toCharArray().reversed().joinToString("") val codeReversed = toCharArray().reversed().joinToString("")
val typeInt = codeReversed[2].toString().toInt() val typeInt = codeReversed[2].toString().toInt()
val type = Type.values().getOrNull(typeInt) ?: return@with null val type = Type.values().getOrNull(typeInt) ?: return@with null

View file

@ -4,6 +4,11 @@
<string name="msg_cleared_cache">Cache cleared successfully</string> <string name="msg_cleared_cache">Cache cleared successfully</string>
<string name="msg_load_fail">Failed to load commits</string> <string name="msg_load_fail">Failed to load commits</string>
<string name="msg_coming_soon">Coming soon</string> <string name="msg_coming_soon">Coming soon</string>
<string name="msg_invalid_version">Invalid Discord version</string>
<string name="msg_seven_left">7 more taps</string>
<string name="msg_five_left">5 more taps</string>
<string name="msg_two_left">2 more taps</string>
<string name="msg_unlocked">You are now a developer</string>
<string name="group_download">Download APKs</string> <string name="group_download">Download APKs</string>
<string name="group_patch">Patching</string> <string name="group_patch">Patching</string>
@ -71,6 +76,12 @@
<string name="settings_app_icon_description">Uses the Vendetta icon instead of Discord\'s</string> <string name="settings_app_icon_description">Uses the Vendetta icon instead of Discord\'s</string>
<string name="settings_channel">Release channel</string> <string name="settings_channel">Release channel</string>
<string name="settings_developer">Developer only</string>
<string name="settings_package_name">Package name</string>
<string name="settings_version">Discord version</string>
<string name="settings_debuggable">Debuggable</string>
<string name="settings_debuggable_description">Enable debuggable flag</string>
<string name="update_description">Vendetta Manager version %1$s is now available!</string> <string name="update_description">Vendetta Manager version %1$s is now available!</string>
<string name="channel_stable">Stable</string> <string name="channel_stable">Stable</string>