Feat: dev settings
This commit is contained in:
parent
584e5e8b3b
commit
eba0fbf29c
13 changed files with 126 additions and 36 deletions
|
@ -24,7 +24,7 @@ class PreferenceManager(private val context: Context) :
|
|||
|
||||
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)
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ fun SettingsTextField(
|
|||
disabled: Boolean = false,
|
||||
pref: String,
|
||||
error: Boolean = false,
|
||||
supportingText: String? = null,
|
||||
onPrefChange: (String) -> Unit,
|
||||
) {
|
||||
Box(modifier = Modifier.padding(horizontal = 18.dp, vertical = 10.dp)) {
|
||||
|
@ -23,7 +24,8 @@ fun SettingsTextField(
|
|||
enabled = !disabled,
|
||||
label = { Text(label) },
|
||||
isError = error,
|
||||
singleLine = true
|
||||
singleLine = true,
|
||||
supportingText = if (supportingText != null) { -> Text(supportingText) } else null
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,9 +1,7 @@
|
|||
package dev.beefers.vendetta.manager.ui.screen.about
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
|
@ -16,7 +14,6 @@ import androidx.compose.foundation.shape.CircleShape
|
|||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.material3.Divider
|
||||
import androidx.compose.material3.ElevatedCard
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
|
@ -30,29 +27,32 @@ import androidx.compose.material3.TopAppBar
|
|||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||
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.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import cafe.adriel.voyager.core.screen.Screen
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import coil.compose.AsyncImage
|
||||
import dev.beefers.vendetta.manager.BuildConfig
|
||||
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.ListItem
|
||||
import dev.beefers.vendetta.manager.ui.widgets.about.UserEntry
|
||||
import dev.beefers.vendetta.manager.utils.Constants
|
||||
import dev.beefers.vendetta.manager.utils.getBitmap
|
||||
import dev.beefers.vendetta.manager.utils.showToast
|
||||
import org.koin.androidx.compose.get
|
||||
|
||||
class AboutScreen : Screen {
|
||||
|
||||
|
@ -60,11 +60,15 @@ class AboutScreen: Screen {
|
|||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
override fun Content() {
|
||||
val uriHandler = LocalUriHandler.current
|
||||
val prefs: PreferenceManager = get()
|
||||
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
|
||||
val ctx = LocalContext.current
|
||||
val bitmap = remember {
|
||||
ctx.getBitmap(R.drawable.ic_launcher, 60).asImageBitmap()
|
||||
}
|
||||
var tapCount by remember {
|
||||
mutableStateOf(0)
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
topBar = { TitleBar(scrollBehavior) },
|
||||
|
@ -100,7 +104,20 @@ class AboutScreen: Screen {
|
|||
text = "v${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})",
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
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(
|
||||
|
|
|
@ -20,7 +20,6 @@ import androidx.compose.material.icons.filled.Home
|
|||
import androidx.compose.material.icons.filled.Info
|
||||
import androidx.compose.material.icons.filled.OpenInNew
|
||||
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.Info
|
||||
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.installer.InstallerScreen
|
||||
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.utils.DiscordVersion
|
||||
import dev.beefers.vendetta.manager.utils.ManagerTab
|
||||
|
@ -75,6 +73,10 @@ class HomeScreen : ManagerTab {
|
|||
val nav = LocalNavigator.currentOrThrow
|
||||
val prefs: PreferenceManager = get()
|
||||
val viewModel: HomeViewModel = getScreenModel()
|
||||
val latestVersion = when {
|
||||
prefs.discordVersion.isBlank() -> viewModel.discordVersions?.get(prefs.channel)
|
||||
else -> DiscordVersion.fromVersionCode(prefs.discordVersion)
|
||||
}
|
||||
val iconColor = when {
|
||||
prefs.patchIcon -> Color(0xFF3AB8BA)
|
||||
prefs.channel == DiscordVersion.Type.ALPHA -> Color(0xFFFBB33C)
|
||||
|
@ -106,18 +108,18 @@ class HomeScreen : ManagerTab {
|
|||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
AnimatedVisibility(visible = viewModel.discordVersions != null) {
|
||||
AnimatedVisibility(visible = viewModel.installManager.current != null) {
|
||||
Text(
|
||||
text = "Latest: ${viewModel.discordVersions?.get(prefs.channel)}",
|
||||
text = "Current: ${viewModel.installManager.current?.versionName}",
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
color = LocalContentColor.current.copy(alpha = 0.5f),
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
}
|
||||
|
||||
AnimatedVisibility(visible = viewModel.installManager.current != null) {
|
||||
AnimatedVisibility(visible = latestVersion != null) {
|
||||
Text(
|
||||
text = "Current: ${viewModel.installManager.current?.versionName}",
|
||||
text = "Latest: $latestVersion",
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
color = LocalContentColor.current.copy(alpha = 0.5f),
|
||||
textAlign = TextAlign.Center
|
||||
|
@ -135,10 +137,7 @@ class HomeScreen : ManagerTab {
|
|||
) {
|
||||
val label = when {
|
||||
viewModel.installManager.current == null -> R.string.action_install
|
||||
viewModel.installManager.current?.versionName == viewModel.discordVersions?.get(
|
||||
prefs.channel
|
||||
).toString() -> R.string.action_reinstall
|
||||
|
||||
viewModel.installManager.current?.versionName == latestVersion.toString() -> R.string.action_reinstall
|
||||
else -> R.string.action_update
|
||||
}
|
||||
Text(stringResource(label))
|
||||
|
|
|
@ -9,18 +9,21 @@ import androidx.compose.material3.NavigationBarItem
|
|||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.compositionLocalOf
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import cafe.adriel.voyager.core.screen.Screen
|
||||
import cafe.adriel.voyager.koin.getScreenModel
|
||||
import com.google.accompanist.pager.ExperimentalPagerApi
|
||||
import com.google.accompanist.pager.HorizontalPager
|
||||
import com.google.accompanist.pager.PagerState
|
||||
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.widgets.updater.UpdateDialog
|
||||
import dev.beefers.vendetta.manager.utils.MainTab
|
||||
|
@ -31,6 +34,7 @@ class MainScreen : Screen {
|
|||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalPagerApi::class)
|
||||
@Composable
|
||||
override fun Content() {
|
||||
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
|
||||
val viewModel: MainViewModel = getScreenModel()
|
||||
val pagerState = rememberPagerState()
|
||||
|
||||
|
@ -39,8 +43,10 @@ class MainScreen : Screen {
|
|||
) {
|
||||
Scaffold(
|
||||
bottomBar = { NavBar() },
|
||||
topBar = { TitleBar() },
|
||||
modifier = Modifier.fillMaxSize()
|
||||
topBar = { TitleBar(scrollBehavior) },
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.nestedScroll(scrollBehavior.nestedScrollConnection)
|
||||
) { pv ->
|
||||
if (viewModel.showUpdateDialog && viewModel.release != null) {
|
||||
UpdateDialog(
|
||||
|
@ -71,18 +77,21 @@ class MainScreen : Screen {
|
|||
|
||||
@OptIn(ExperimentalPagerApi::class, ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun TitleBar() {
|
||||
private fun TitleBar(
|
||||
scrollBehavior: TopAppBarScrollBehavior
|
||||
) {
|
||||
val pagerState = LocalPagerState.current
|
||||
val tab = MainTab.values()[pagerState.currentPage].tab
|
||||
|
||||
TopAppBar(
|
||||
title = { Text(tab.options.title) },
|
||||
actions = { tab.Actions() }
|
||||
actions = { tab.Actions() },
|
||||
scrollBehavior = if (tab is HomeScreen) null else scrollBehavior
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
@OptIn(ExperimentalPagerApi::class)
|
||||
@OptIn(ExperimentalPagerApi::class, ExperimentalMaterial3Api::class)
|
||||
private fun NavBar() {
|
||||
val pagerState = LocalPagerState.current
|
||||
val scope = rememberCoroutineScope()
|
||||
|
|
|
@ -11,6 +11,10 @@ import androidx.compose.material.icons.outlined.Settings
|
|||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
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.platform.LocalContext
|
||||
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.tab.TabOptions
|
||||
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.ui.components.settings.SettingsButton
|
||||
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.screen.about.AboutScreen
|
||||
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.TabOptions
|
||||
import dev.beefers.vendetta.manager.utils.navigate
|
||||
|
@ -44,6 +50,7 @@ class SettingsScreen : ManagerTab {
|
|||
override fun Content() {
|
||||
val viewModel: SettingsViewModel = getScreenModel()
|
||||
val prefs: PreferenceManager = get()
|
||||
val installManager: InstallManager = get()
|
||||
val ctx = LocalContext.current
|
||||
|
||||
Column(
|
||||
|
@ -103,6 +110,51 @@ class SettingsScreen : ManagerTab {
|
|||
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 }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil.compose.AsyncImage
|
||||
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
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.Row
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.SystemUpdate
|
||||
|
|
|
@ -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.main.LocalPagerState
|
||||
import dev.beefers.vendetta.manager.ui.screen.settings.SettingsScreen
|
||||
import dev.beefers.vendetta.manager.ui.viewmodel.main.MainViewModel
|
||||
|
||||
enum class MainTab(val tab: ManagerTab) {
|
||||
HOME(HomeScreen()),
|
||||
|
|
|
@ -8,7 +8,7 @@ data class DiscordVersion(
|
|||
val major: Int,
|
||||
val minor: Int,
|
||||
val type: Type
|
||||
) : Serializable {
|
||||
) : Serializable, Comparable<DiscordVersion> {
|
||||
|
||||
enum class Type(val label: String, @StringRes val labelRes: Int) {
|
||||
STABLE("Stable", R.string.channel_stable),
|
||||
|
@ -16,6 +16,9 @@ data class DiscordVersion(
|
|||
ALPHA("Alpha", R.string.channel_alpha)
|
||||
}
|
||||
|
||||
override fun compareTo(other: DiscordVersion): Int =
|
||||
toVersionCode().toInt() - other.toVersionCode().toInt()
|
||||
|
||||
override fun toString() = "$major.$minor - ${type.label}"
|
||||
|
||||
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) {
|
||||
if (length < 4) return@with null
|
||||
if (toIntOrNull() == null) return@with null
|
||||
if (toInt() <= 126021) return@with null
|
||||
val codeReversed = toCharArray().reversed().joinToString("")
|
||||
val typeInt = codeReversed[2].toString().toInt()
|
||||
val type = Type.values().getOrNull(typeInt) ?: return@with null
|
||||
|
|
|
@ -4,6 +4,11 @@
|
|||
<string name="msg_cleared_cache">Cache cleared successfully</string>
|
||||
<string name="msg_load_fail">Failed to load commits</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_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_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="channel_stable">Stable</string>
|
||||
|
|
Loading…
Reference in a new issue