Integrations UI + Package Name Warnings/Gate <3

This commit is contained in:
2026-07-03 20:19:16 +10:00
parent 47c9c37236
commit 08aee155c9
11 changed files with 261 additions and 20 deletions
@@ -35,12 +35,14 @@ private fun PatchOptionsScreenPreview(
packageName = parameters.packageName, packageName = parameters.packageName,
packageNameState = parameters.packageNameState, packageNameState = parameters.packageNameState,
setPackageName = {}, setPackageName = {},
packageNameLocked = parameters.packageName == PatchOptions.Default.packageName,
onUnlockPackageName = {},
onLockPackageName = {},
customTidalApk = parameters.customTidalApk, customTidalApk = parameters.customTidalApk,
onSelectCustomTidalApk = {}, onSelectCustomTidalApk = {},
customPatches = parameters.customPatches, customPatches = parameters.customPatches,
onSelectCustomPatches = {}, onSelectCustomPatches = {},
specs = specs, specs = specs,
enabledPatchCount = specs.size,
isPatchEnabled = { true }, isPatchEnabled = { true },
onTogglePatch = { _, _ -> }, onTogglePatch = { _, _ -> },
patchLockState = { PatchLock.Free }, patchLockState = { PatchLock.Free },
@@ -24,6 +24,8 @@ enum class KnownPatch(
val variants: List<PatchVariant> = emptyList(), val variants: List<PatchVariant> = emptyList(),
val defaultVariantIndex: Int = 0, val defaultVariantIndex: Int = 0,
val advancedOptions: List<PatchOption> = emptyList(), val advancedOptions: List<PatchOption> = emptyList(),
val category: String = PatchSpec.CATEGORY_PATCH,
val pathLocked: Boolean = false,
) { ) {
LyricsDisableCover( LyricsDisableCover(
order = 41, order = 41,
@@ -140,6 +142,8 @@ enum class KnownPatch(
titleRes = R.string.patch_waze_integration_title, titleRes = R.string.patch_waze_integration_title,
descRes = R.string.patch_waze_integration_desc, descRes = R.string.patch_waze_integration_desc,
default = Disabled, default = Disabled,
category = PatchSpec.CATEGORY_INTEGRATION,
pathLocked = true,
advancedOptions = listOf( advancedOptions = listOf(
PatchOption.Choice( PatchOption.Choice(
key = "browse_root", key = "browse_root",
@@ -43,6 +43,24 @@ class PatchOptionsModel(
fetchPkgNameStateDebounced() fetchPkgNameStateDebounced()
} }
/** Patches flagged [PatchSpec.pathLocked] only work under the stock package name. */
fun isBlockedByPackageName(spec: PatchSpec): Boolean =
spec.pathLocked && packageName != PatchOptions.Default.packageName
/** The package-name field starts locked & editing requires confirming the unlock dialog */
var packageNameLocked by mutableStateOf(prefilledOptions.packageName == PatchOptions.Default.packageName)
private set
fun unlockPackageName() {
packageNameLocked = false
}
/** Re-locking snaps the package name back to the stock default */
fun lockPackageName() {
packageNameLocked = true
changePackageName(PatchOptions.Default.packageName)
}
var appName by mutableStateOf(prefilledOptions.appName) var appName by mutableStateOf(prefilledOptions.appName)
private set private set
@@ -83,7 +101,7 @@ class PatchOptionsModel(
.coerceIn(0, spec.variants.lastIndex.coerceAtLeast(0)) .coerceIn(0, spec.variants.lastIndex.coerceAtLeast(0))
fun isPatchEnabled(spec: PatchSpec): Boolean = fun isPatchEnabled(spec: PatchSpec): Boolean =
patchStates[spec.id] ?: spec.defaultEnabled !isBlockedByPackageName(spec) && (patchStates[spec.id] ?: spec.defaultEnabled)
fun setPatchEnabled(spec: PatchSpec, enabled: Boolean) { fun setPatchEnabled(spec: PatchSpec, enabled: Boolean) {
val byId = specs.associateBy { it.id } val byId = specs.associateBy { it.id }
@@ -190,6 +208,7 @@ class PatchOptionsModel(
) )
fun lockState(spec: PatchSpec): PatchLock { fun lockState(spec: PatchSpec): PatchLock {
if (isBlockedByPackageName(spec)) return PatchLock.RequiresDefaultPackage
if (spec.variants.isNotEmpty()) return PatchLock.Free if (spec.variants.isNotEmpty()) return PatchLock.Free
val byId = specs.associateBy { it.id } val byId = specs.associateBy { it.id }
@@ -216,9 +235,6 @@ class PatchOptionsModel(
return PatchLock.Free return PatchLock.Free
} }
val enabledPatchCount: Int
get() = specs.count { isPatchEnabled(it) }
var customTidalApk by mutableStateOf<PatchComponent?>(null) var customTidalApk by mutableStateOf<PatchComponent?>(null)
private set private set
var customPatches by mutableStateOf<PatchComponent?>(null) var customPatches by mutableStateOf<PatchComponent?>(null)
@@ -333,7 +349,10 @@ class PatchOptionsModel(
debuggable = debuggable, debuggable = debuggable,
customTidalApk = customTidalApk, customTidalApk = customTidalApk,
customPatches = customPatches, customPatches = customPatches,
patchStates = patchStates, // Hard-disable package-name-bound patches so the patcher can't apply
patchStates = patchStates.toMutableMap().apply {
specs.filter { isBlockedByPackageName(it) }.forEach { this[it.id] = false }
},
selectedVariants = selectedVariants, selectedVariants = selectedVariants,
optionFloats = optionFloats, optionFloats = optionFloats,
optionBools = optionBools, optionBools = optionBools,
@@ -395,4 +414,7 @@ sealed class PatchLock {
data object Free : PatchLock() data object Free : PatchLock()
data class LockedOn(val by: PatchSpec) : PatchLock() data class LockedOn(val by: PatchSpec) : PatchLock()
data class LockedOff(val by: PatchSpec) : PatchLock() data class LockedOff(val by: PatchSpec) : PatchLock()
/** Locked off because the install uses a non-default package name */
data object RequiresDefaultPackage : PatchLock()
} }
@@ -19,7 +19,9 @@ import com.meowarex.rlmobile.R
import com.meowarex.rlmobile.ui.components.* import com.meowarex.rlmobile.ui.components.*
import com.meowarex.rlmobile.ui.screens.componentopts.PatchComponent import com.meowarex.rlmobile.ui.screens.componentopts.PatchComponent
import com.meowarex.rlmobile.ui.screens.patching.PatchingScreen import com.meowarex.rlmobile.ui.screens.patching.PatchingScreen
import androidx.compose.runtime.saveable.rememberSaveable
import com.meowarex.rlmobile.ui.screens.patchopts.components.PackageNameStateLabel import com.meowarex.rlmobile.ui.screens.patchopts.components.PackageNameStateLabel
import com.meowarex.rlmobile.ui.screens.patchopts.components.PackageNameUnlockDialog
import com.meowarex.rlmobile.ui.screens.patchopts.components.PatchOptionsAppBar import com.meowarex.rlmobile.ui.screens.patchopts.components.PatchOptionsAppBar
import com.meowarex.rlmobile.ui.screens.patchopts.components.PatchSelectionAccordion import com.meowarex.rlmobile.ui.screens.patchopts.components.PatchSelectionAccordion
import com.meowarex.rlmobile.ui.screens.patchopts.components.options.* import com.meowarex.rlmobile.ui.screens.patchopts.components.options.*
@@ -55,13 +57,16 @@ class PatchOptionsScreen(
packageNameState = model.packageNameState, packageNameState = model.packageNameState,
setPackageName = model::changePackageName, setPackageName = model::changePackageName,
packageNameLocked = model.packageNameLocked,
onUnlockPackageName = model::unlockPackageName,
onLockPackageName = model::lockPackageName,
customTidalApk = model.customTidalApk, customTidalApk = model.customTidalApk,
customPatches = model.customPatches, customPatches = model.customPatches,
onSelectCustomTidalApk = { model.selectCustomTidalApk(navigator) }, onSelectCustomTidalApk = { model.selectCustomTidalApk(navigator) },
onSelectCustomPatches = { model.selectCustomPatches(navigator) }, onSelectCustomPatches = { model.selectCustomPatches(navigator) },
specs = model.specs, specs = model.specs,
enabledPatchCount = model.enabledPatchCount,
isPatchEnabled = model::isPatchEnabled, isPatchEnabled = model::isPatchEnabled,
onTogglePatch = model::setPatchEnabled, onTogglePatch = model::setPatchEnabled,
patchLockState = model::lockState, patchLockState = model::lockState,
@@ -93,13 +98,16 @@ fun PatchOptionsScreenContent(
packageNameState: PackageNameState, packageNameState: PackageNameState,
setPackageName: (String) -> Unit, setPackageName: (String) -> Unit,
packageNameLocked: Boolean,
onUnlockPackageName: () -> Unit,
onLockPackageName: () -> Unit,
customTidalApk: PatchComponent?, customTidalApk: PatchComponent?,
onSelectCustomTidalApk: () -> Unit, onSelectCustomTidalApk: () -> Unit,
customPatches: PatchComponent?, customPatches: PatchComponent?,
onSelectCustomPatches: () -> Unit, onSelectCustomPatches: () -> Unit,
specs: List<PatchSpec>, specs: List<PatchSpec>,
enabledPatchCount: Int,
isPatchEnabled: (PatchSpec) -> Boolean, isPatchEnabled: (PatchSpec) -> Boolean,
onTogglePatch: (PatchSpec, Boolean) -> Unit, onTogglePatch: (PatchSpec, Boolean) -> Unit,
patchLockState: (PatchSpec) -> PatchLock, patchLockState: (PatchSpec) -> PatchLock,
@@ -110,6 +118,18 @@ fun PatchOptionsScreenContent(
isConfigValid: Boolean, isConfigValid: Boolean,
onInstall: () -> Unit, onInstall: () -> Unit,
) { ) {
var showPkgUnlockDialog by rememberSaveable { mutableStateOf(false) }
if (showPkgUnlockDialog) {
PackageNameUnlockDialog(
blockedTitles = specs.filter { it.pathLocked }.map { it.title },
onConfirm = {
showPkgUnlockDialog = false
onUnlockPackageName()
},
onDismiss = { showPkgUnlockDialog = false },
)
}
Scaffold( Scaffold(
topBar = { PatchOptionsAppBar(isUpdate = isUpdate) }, topBar = { PatchOptionsAppBar(isUpdate = isUpdate) },
) { paddingValues -> ) { paddingValues ->
@@ -159,6 +179,10 @@ fun PatchOptionsScreenContent(
valueIsDefault = packageNameIsDefault, valueIsDefault = packageNameIsDefault,
onValueChange = setPackageName, onValueChange = setPackageName,
onValueReset = { setPackageName(PatchOptions.Default.packageName) }, onValueReset = { setPackageName(PatchOptions.Default.packageName) },
locked = packageNameLocked,
onLockClick = {
if (packageNameLocked) showPkgUnlockDialog = true else onLockPackageName()
},
) { ) {
PackageNameStateLabel( PackageNameStateLabel(
state = packageNameState, state = packageNameState,
@@ -167,17 +191,40 @@ fun PatchOptionsScreenContent(
} }
} }
val (integrations, patches) = remember(specs) { specs.partition { it.isIntegration } }
if (integrations.isNotEmpty()) {
PatchSelectionAccordion(
iconRes = R.drawable.ic_extension,
titleRes = R.string.patchopts_integrations_title,
descriptionRes = R.string.patchopts_integrations_desc,
specs = integrations,
enabledCount = integrations.count(isPatchEnabled),
totalCount = integrations.size,
isEnabled = isPatchEnabled,
onToggle = onTogglePatch,
lockState = patchLockState,
variantIndex = variantIndex,
onSelectVariant = onSelectVariant,
optionState = optionState,
modifier = Modifier.padding(top = 4.dp),
)
}
PatchSelectionAccordion( PatchSelectionAccordion(
specs = specs, iconRes = R.drawable.ic_healing,
enabledCount = enabledPatchCount, titleRes = R.string.patchopts_patches_title,
totalCount = specs.size, descriptionRes = R.string.patchopts_patches_desc,
specs = patches,
enabledCount = patches.count(isPatchEnabled),
totalCount = patches.size,
isEnabled = isPatchEnabled, isEnabled = isPatchEnabled,
onToggle = onTogglePatch, onToggle = onTogglePatch,
lockState = patchLockState, lockState = patchLockState,
variantIndex = variantIndex, variantIndex = variantIndex,
onSelectVariant = onSelectVariant, onSelectVariant = onSelectVariant,
optionState = optionState, optionState = optionState,
modifier = Modifier.padding(top = 4.dp), modifier = if (integrations.isEmpty()) Modifier.padding(top = 4.dp) else Modifier,
) )
if (isDevMode) { if (isDevMode) {
@@ -29,7 +29,16 @@ data class PatchSpec(
val variants: List<VariantSpec> = emptyList(), val variants: List<VariantSpec> = emptyList(),
val defaultVariantIndex: Int = 0, val defaultVariantIndex: Int = 0,
val advancedOptions: List<OptionSpec> = emptyList(), val advancedOptions: List<OptionSpec> = emptyList(),
) val category: String = CATEGORY_PATCH,
val pathLocked: Boolean = false,
) {
val isIntegration: Boolean get() = category == CATEGORY_INTEGRATION
companion object {
const val CATEGORY_PATCH = "patch"
const val CATEGORY_INTEGRATION = "integration"
}
}
@Immutable @Immutable
@Serializable @Serializable
@@ -163,6 +172,8 @@ fun builtinPatchSpecs(resolve: (Int) -> String): List<PatchSpec> =
variants = patch.variants.map { VariantSpec(resolve(it.titleRes), it.fileNames, it.extensionFiles) }, variants = patch.variants.map { VariantSpec(resolve(it.titleRes), it.fileNames, it.extensionFiles) },
defaultVariantIndex = patch.defaultVariantIndex, defaultVariantIndex = patch.defaultVariantIndex,
advancedOptions = patch.advancedOptions.map { it.toSpec(resolve) }, advancedOptions = patch.advancedOptions.map { it.toSpec(resolve) },
category = patch.category,
pathLocked = patch.pathLocked,
) )
} }
@@ -0,0 +1,88 @@
package com.meowarex.rlmobile.ui.screens.patchopts.components
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
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.material3.BasicAlertDialog
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.fromHtml
import androidx.compose.ui.unit.dp
import com.meowarex.rlmobile.R
import com.meowarex.rlmobile.ui.screens.patchopts.PatchOptions
/**
* Confirms unlocking the package-name field, warning that a custom name
* blocks the listed patches/integrations from working.
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PackageNameUnlockDialog(
blockedTitles: List<String>,
onConfirm: () -> Unit,
onDismiss: () -> Unit,
) {
BasicAlertDialog(onDismissRequest = onDismiss) {
Surface(
shape = MaterialTheme.shapes.large,
color = MaterialTheme.colorScheme.surfaceContainerHigh,
tonalElevation = 6.dp,
) {
Column(
modifier = Modifier.padding(start = 24.dp, end = 12.dp, top = 20.dp, bottom = 8.dp),
verticalArrangement = Arrangement.spacedBy(6.dp),
) {
Text(
text = stringResource(R.string.patchopts_pkgname_warning_title),
style = MaterialTheme.typography.titleLarge,
)
Text(
text = AnnotatedString.fromHtml(
stringResource(R.string.patchopts_pkgname_warning_msg, PatchOptions.Default.packageName),
),
style = MaterialTheme.typography.bodyLarge,
)
if (blockedTitles.isNotEmpty()) {
Column(
verticalArrangement = Arrangement.spacedBy(2.dp),
modifier = Modifier.padding(start = 4.dp),
) {
for (title in blockedTitles) {
Text(
text = "$title",
style = MaterialTheme.typography.bodyLarge,
fontWeight = FontWeight.Bold,
)
}
}
}
Text(
text = stringResource(R.string.patchopts_pkgname_warning_permanent),
style = MaterialTheme.typography.bodyLarge,
)
Box(modifier = Modifier.fillMaxWidth()) {
Row(modifier = Modifier.align(Alignment.CenterEnd)) {
TextButton(onClick = onDismiss) {
Text(stringResource(R.string.action_cancel))
}
TextButton(onClick = onConfirm) {
Text(stringResource(R.string.action_continue))
}
}
}
}
}
}
}
@@ -1,6 +1,8 @@
package com.meowarex.rlmobile.ui.screens.patchopts.components package com.meowarex.rlmobile.ui.screens.patchopts.components
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.background import androidx.compose.foundation.background
@@ -27,6 +29,7 @@ import com.meowarex.rlmobile.R
import com.meowarex.rlmobile.ui.screens.patchopts.OptionSpec import com.meowarex.rlmobile.ui.screens.patchopts.OptionSpec
import com.meowarex.rlmobile.ui.screens.patchopts.PatchLock import com.meowarex.rlmobile.ui.screens.patchopts.PatchLock
import com.meowarex.rlmobile.ui.screens.patchopts.PatchOptionState import com.meowarex.rlmobile.ui.screens.patchopts.PatchOptionState
import com.meowarex.rlmobile.ui.screens.patchopts.PatchOptions
import com.meowarex.rlmobile.ui.screens.patchopts.PatchSpec import com.meowarex.rlmobile.ui.screens.patchopts.PatchSpec
import com.meowarex.rlmobile.ui.screens.patchopts.effectiveVariants import com.meowarex.rlmobile.ui.screens.patchopts.effectiveVariants
import com.meowarex.rlmobile.ui.screens.patchopts.resolveVariantIndex import com.meowarex.rlmobile.ui.screens.patchopts.resolveVariantIndex
@@ -35,6 +38,9 @@ private data class LockInfo(val patch: PatchSpec, val lock: PatchLock)
@Composable @Composable
fun PatchSelectionAccordion( fun PatchSelectionAccordion(
@DrawableRes iconRes: Int,
@StringRes titleRes: Int,
@StringRes descriptionRes: Int,
specs: List<PatchSpec>, specs: List<PatchSpec>,
enabledCount: Int, enabledCount: Int,
totalCount: Int, totalCount: Int,
@@ -69,12 +75,17 @@ fun PatchSelectionAccordion(
.clickable(role = Role.Button) { expanded = !expanded } .clickable(role = Role.Button) { expanded = !expanded }
.padding(horizontal = 16.dp, vertical = 14.dp), .padding(horizontal = 16.dp, vertical = 14.dp),
) { ) {
Icon(
painter = painterResource(iconRes),
contentDescription = null,
)
Column( Column(
verticalArrangement = Arrangement.spacedBy(2.dp), verticalArrangement = Arrangement.spacedBy(2.dp),
modifier = Modifier.weight(1f), modifier = Modifier.weight(1f),
) { ) {
Text( Text(
text = stringResource(R.string.patchopts_patches_title), text = stringResource(titleRes),
style = MaterialTheme.typography.titleMedium, style = MaterialTheme.typography.titleMedium,
) )
Text( Text(
@@ -106,7 +117,7 @@ fun PatchSelectionAccordion(
.padding(horizontal = 16.dp, vertical = 12.dp), .padding(horizontal = 16.dp, vertical = 12.dp),
) { ) {
Text( Text(
text = stringResource(R.string.patchopts_patches_desc), text = stringResource(descriptionRes),
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
modifier = Modifier modifier = Modifier
.alpha(.7f) .alpha(.7f)
@@ -372,6 +383,11 @@ private fun PatchLockDialog(
R.string.patch_lock_blocked_msg, R.string.patch_lock_blocked_msg,
lock.by.title, lock.by.title,
) )
PatchLock.RequiresDefaultPackage -> Triple(
R.string.patch_lock_pkgname_title,
R.string.patch_lock_pkgname_msg,
PatchOptions.Default.packageName,
)
PatchLock.Free -> return PatchLock.Free -> return
} }
@@ -391,7 +407,7 @@ private fun PatchLockDialog(
) )
Text( Text(
text = AnnotatedString.fromHtml(stringResource(msgRes, blockerTitle)), text = AnnotatedString.fromHtml(stringResource(msgRes, blockerTitle)),
style = MaterialTheme.typography.titleMedium, style = MaterialTheme.typography.bodyLarge,
) )
Box(modifier = Modifier.fillMaxWidth()) { Box(modifier = Modifier.fillMaxWidth()) {
TextButton( TextButton(
@@ -3,8 +3,12 @@ package com.meowarex.rlmobile.ui.screens.patchopts.components.options
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.meowarex.rlmobile.R
import com.meowarex.rlmobile.ui.components.Label import com.meowarex.rlmobile.ui.components.Label
import com.meowarex.rlmobile.ui.components.ResetToDefaultButton import com.meowarex.rlmobile.ui.components.ResetToDefaultButton
@@ -18,6 +22,8 @@ fun TextPatchOption(
onValueChange: (String) -> Unit, onValueChange: (String) -> Unit,
onValueReset: () -> Unit, onValueReset: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
locked: Boolean? = null,
onLockClick: () -> Unit = {},
extra: (@Composable ColumnScope.() -> Unit)? = null, extra: (@Composable ColumnScope.() -> Unit)? = null,
) { ) {
Label( Label(
@@ -30,16 +36,41 @@ fun TextPatchOption(
onValueChange = onValueChange, onValueChange = onValueChange,
isError = valueIsError, isError = valueIsError,
singleLine = true, singleLine = true,
enabled = locked != true,
colors = OutlinedTextFieldDefaults.colors( colors = OutlinedTextFieldDefaults.colors(
unfocusedContainerColor = MaterialTheme.colorScheme.surfaceContainerLow, unfocusedContainerColor = MaterialTheme.colorScheme.surfaceContainerLow,
focusedContainerColor = MaterialTheme.colorScheme.surfaceContainerLow, focusedContainerColor = MaterialTheme.colorScheme.surfaceContainerLow,
errorContainerColor = MaterialTheme.colorScheme.surfaceContainerLow, errorContainerColor = MaterialTheme.colorScheme.surfaceContainerLow,
disabledContainerColor = MaterialTheme.colorScheme.surfaceContainerLow,
), ),
trailingIcon = { trailingIcon = {
ResetToDefaultButton( Row(verticalAlignment = Alignment.CenterVertically) {
enabled = !valueIsDefault, if (locked != true) {
onClick = onValueReset, ResetToDefaultButton(
) enabled = !valueIsDefault,
onClick = onValueReset,
)
}
if (locked != null) {
IconButton(
onClick = onLockClick,
modifier = Modifier.size(32.dp),
) {
Icon(
painter = painterResource(
if (locked) R.drawable.ic_lock else R.drawable.ic_lock_open,
),
contentDescription = stringResource(
if (locked) R.string.patchopts_field_unlock else R.string.patchopts_field_lock,
),
tint = if (locked) MaterialTheme.colorScheme.primary
else MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.size(18.dp),
)
}
Spacer(Modifier.width(8.dp))
}
}
}, },
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="#e8eaed"
android:pathData="M218,856L104,742Q81,719 81,686Q81,653 104,630L630,104Q653,81 686,81Q719,81 742,104L856,218Q879,241 879,274Q879,307 856,330L330,856Q307,879 274,879Q241,879 218,856ZM508,734L734,508L856,630Q879,653 879,686Q879,719 856,742L742,856Q719,879 686,879Q653,879 630,856L508,734ZM480,600Q497,600 508.5,588.5Q520,577 520,560Q520,543 508.5,531.5Q497,520 480,520Q463,520 451.5,531.5Q440,543 440,560Q440,577 451.5,588.5Q463,600 480,600ZM400,520Q417,520 428.5,508.5Q440,497 440,480Q440,463 428.5,451.5Q417,440 400,440Q383,440 371.5,451.5Q360,463 360,480Q360,497 371.5,508.5Q383,520 400,520ZM560,520Q577,520 588.5,508.5Q600,497 600,480Q600,463 588.5,451.5Q577,440 560,440Q543,440 531.5,451.5Q520,463 520,480Q520,497 531.5,508.5Q543,520 560,520ZM225,451L104,330Q81,307 81,274Q81,241 104,218L218,104Q241,81 274,81Q307,81 330,104L452,226L225,451ZM480,440Q497,440 508.5,428.5Q520,417 520,400Q520,383 508.5,371.5Q497,360 480,360Q463,360 451.5,371.5Q440,383 440,400Q440,417 451.5,428.5Q463,440 480,440Z" />
</vector>
@@ -252,9 +252,16 @@
<string name="patchopts_patches_title">Patches</string> <string name="patchopts_patches_title">Patches</string>
<string name="patchopts_patches_desc">Toggle which patches are applied during installation. Unchecked patches are skipped entirely.</string> <string name="patchopts_patches_desc">Toggle which patches are applied during installation. Unchecked patches are skipped entirely.</string>
<string name="patchopts_patches_summary">%1$d of %2$d enabled</string> <string name="patchopts_patches_summary">%1$d of %2$d enabled</string>
<string name="patchopts_integrations_title">Integrations</string>
<string name="patchopts_integrations_desc">Connect TIDAL to other systems/apps</string>
<string name="patchopts_pkgname_warning_title">Custom Package Name</string>
<string name="patchopts_pkgname_warning_msg">Installing under a package name other than &lt;b>%s&lt;/b> will block the following from working:</string>
<string name="patchopts_pkgname_warning_permanent">The package name is permanent once installed (requires a fresh install)</string>
<string name="patchopts_advanced_button">Advanced Options</string> <string name="patchopts_advanced_button">Advanced Options</string>
<string name="patchopts_advanced_sheet_label">Advanced Options</string> <string name="patchopts_advanced_sheet_label">Advanced Options</string>
<string name="patchopts_toggle_snap">Toggle snapping to steps</string> <string name="patchopts_toggle_snap">Toggle snapping to steps</string>
<string name="patchopts_field_unlock">Unlock editing</string>
<string name="patchopts_field_lock">Lock and reset to default</string>
<string name="patch_lyrics_disable_cover_title">Disable Lyrics Cover</string> <string name="patch_lyrics_disable_cover_title">Disable Lyrics Cover</string>
<string name="patch_lyrics_disable_cover_desc">Removes the mini track cover from the lyrics screen.</string> <string name="patch_lyrics_disable_cover_desc">Removes the mini track cover from the lyrics screen.</string>
@@ -333,6 +340,8 @@
<string name="patch_lock_blocked_title">Patch Blocked!</string> <string name="patch_lock_blocked_title">Patch Blocked!</string>
<string name="patch_lock_required_msg">Patch Required by &lt;b>%s&lt;/b>.</string> <string name="patch_lock_required_msg">Patch Required by &lt;b>%s&lt;/b>.</string>
<string name="patch_lock_blocked_msg">Patch Blocked by &lt;b>%s&lt;/b>.</string> <string name="patch_lock_blocked_msg">Patch Blocked by &lt;b>%s&lt;/b>.</string>
<string name="patch_lock_pkgname_title">Original Package Name Invalid!</string>
<string name="patch_lock_pkgname_msg">This only works while the app keeps its original &lt;b>%s&lt;/b> package name. Reset the Package Name option to enable it.&lt;br/>&lt;br/>An existing install can\'t be renamed (requires a fresh install)</string>
<string name="patch_opt_lock_title">Option Locked</string> <string name="patch_opt_lock_title">Option Locked</string>
<string name="patch_opt_lock_needs_variant">Requires the &lt;b>%s&lt;/b> style.</string> <string name="patch_opt_lock_needs_variant">Requires the &lt;b>%s&lt;/b> style.</string>
<string name="patch_opt_lock_needs_option">Requires the &lt;b>%s&lt;/b> option.</string> <string name="patch_opt_lock_needs_option">Requires the &lt;b>%s&lt;/b> option.</string>
+2
View File
@@ -215,6 +215,8 @@
{ {
"id": "WazeIntegration", "id": "WazeIntegration",
"order": 90, "order": 90,
"category": "integration",
"pathLocked": true,
"fileNames": ["waze-media-browser.patch"], "fileNames": ["waze-media-browser.patch"],
"extensionFiles": ["radiant/WazeInitReceiver.smali", "radiant/WazeServiceConnection.smali"], "extensionFiles": ["radiant/WazeInitReceiver.smali", "radiant/WazeServiceConnection.smali"],
"title": "Waze Integration", "title": "Waze Integration",