From 08aee155c9283d972caf4ee38b857ecb7b1ee3f9 Mon Sep 17 00:00:00 2001 From: meowarex Date: Fri, 3 Jul 2026 20:19:16 +1000 Subject: [PATCH] Integrations UI + Package Name Warnings/Gate <3 --- .../screens/PatchOptionsScreenPreview.kt | 4 +- .../ui/screens/patchopts/KnownPatch.kt | 4 + .../ui/screens/patchopts/PatchOptionsModel.kt | 32 +++++-- .../screens/patchopts/PatchOptionsScreen.kt | 59 +++++++++++-- .../ui/screens/patchopts/PatchSpec.kt | 13 ++- .../components/PackageNameUnlockDialog.kt | 88 +++++++++++++++++++ .../components/PatchSelectionAccordion.kt | 22 ++++- .../components/options/TextPatchOption.kt | 39 +++++++- .../app/src/main/res/drawable/ic_healing.xml | 9 ++ Manager/app/src/main/res/values/strings.xml | 9 ++ patches/manifest.json | 2 + 11 files changed, 261 insertions(+), 20 deletions(-) create mode 100644 Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/components/PackageNameUnlockDialog.kt create mode 100644 Manager/app/src/main/res/drawable/ic_healing.xml diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/previews/screens/PatchOptionsScreenPreview.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/previews/screens/PatchOptionsScreenPreview.kt index d0c8379..49a95cb 100644 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/previews/screens/PatchOptionsScreenPreview.kt +++ b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/previews/screens/PatchOptionsScreenPreview.kt @@ -35,12 +35,14 @@ private fun PatchOptionsScreenPreview( packageName = parameters.packageName, packageNameState = parameters.packageNameState, setPackageName = {}, + packageNameLocked = parameters.packageName == PatchOptions.Default.packageName, + onUnlockPackageName = {}, + onLockPackageName = {}, customTidalApk = parameters.customTidalApk, onSelectCustomTidalApk = {}, customPatches = parameters.customPatches, onSelectCustomPatches = {}, specs = specs, - enabledPatchCount = specs.size, isPatchEnabled = { true }, onTogglePatch = { _, _ -> }, patchLockState = { PatchLock.Free }, diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/KnownPatch.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/KnownPatch.kt index 5bb3193..bcdf2e1 100644 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/KnownPatch.kt +++ b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/KnownPatch.kt @@ -24,6 +24,8 @@ enum class KnownPatch( val variants: List = emptyList(), val defaultVariantIndex: Int = 0, val advancedOptions: List = emptyList(), + val category: String = PatchSpec.CATEGORY_PATCH, + val pathLocked: Boolean = false, ) { LyricsDisableCover( order = 41, @@ -140,6 +142,8 @@ enum class KnownPatch( titleRes = R.string.patch_waze_integration_title, descRes = R.string.patch_waze_integration_desc, default = Disabled, + category = PatchSpec.CATEGORY_INTEGRATION, + pathLocked = true, advancedOptions = listOf( PatchOption.Choice( key = "browse_root", diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/PatchOptionsModel.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/PatchOptionsModel.kt index 8065d4e..b545efc 100644 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/PatchOptionsModel.kt +++ b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/PatchOptionsModel.kt @@ -43,6 +43,24 @@ class PatchOptionsModel( 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) private set @@ -83,7 +101,7 @@ class PatchOptionsModel( .coerceIn(0, spec.variants.lastIndex.coerceAtLeast(0)) fun isPatchEnabled(spec: PatchSpec): Boolean = - patchStates[spec.id] ?: spec.defaultEnabled + !isBlockedByPackageName(spec) && (patchStates[spec.id] ?: spec.defaultEnabled) fun setPatchEnabled(spec: PatchSpec, enabled: Boolean) { val byId = specs.associateBy { it.id } @@ -190,6 +208,7 @@ class PatchOptionsModel( ) fun lockState(spec: PatchSpec): PatchLock { + if (isBlockedByPackageName(spec)) return PatchLock.RequiresDefaultPackage if (spec.variants.isNotEmpty()) return PatchLock.Free val byId = specs.associateBy { it.id } @@ -216,9 +235,6 @@ class PatchOptionsModel( return PatchLock.Free } - val enabledPatchCount: Int - get() = specs.count { isPatchEnabled(it) } - var customTidalApk by mutableStateOf(null) private set var customPatches by mutableStateOf(null) @@ -333,7 +349,10 @@ class PatchOptionsModel( debuggable = debuggable, customTidalApk = customTidalApk, 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, optionFloats = optionFloats, optionBools = optionBools, @@ -395,4 +414,7 @@ sealed class PatchLock { data object Free : PatchLock() data class LockedOn(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() } diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/PatchOptionsScreen.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/PatchOptionsScreen.kt index 91c204c..628d450 100644 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/PatchOptionsScreen.kt +++ b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/PatchOptionsScreen.kt @@ -19,7 +19,9 @@ import com.meowarex.rlmobile.R import com.meowarex.rlmobile.ui.components.* import com.meowarex.rlmobile.ui.screens.componentopts.PatchComponent 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.PackageNameUnlockDialog 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.options.* @@ -55,13 +57,16 @@ class PatchOptionsScreen( packageNameState = model.packageNameState, setPackageName = model::changePackageName, + packageNameLocked = model.packageNameLocked, + onUnlockPackageName = model::unlockPackageName, + onLockPackageName = model::lockPackageName, + customTidalApk = model.customTidalApk, customPatches = model.customPatches, onSelectCustomTidalApk = { model.selectCustomTidalApk(navigator) }, onSelectCustomPatches = { model.selectCustomPatches(navigator) }, specs = model.specs, - enabledPatchCount = model.enabledPatchCount, isPatchEnabled = model::isPatchEnabled, onTogglePatch = model::setPatchEnabled, patchLockState = model::lockState, @@ -93,13 +98,16 @@ fun PatchOptionsScreenContent( packageNameState: PackageNameState, setPackageName: (String) -> Unit, + packageNameLocked: Boolean, + onUnlockPackageName: () -> Unit, + onLockPackageName: () -> Unit, + customTidalApk: PatchComponent?, onSelectCustomTidalApk: () -> Unit, customPatches: PatchComponent?, onSelectCustomPatches: () -> Unit, specs: List, - enabledPatchCount: Int, isPatchEnabled: (PatchSpec) -> Boolean, onTogglePatch: (PatchSpec, Boolean) -> Unit, patchLockState: (PatchSpec) -> PatchLock, @@ -110,6 +118,18 @@ fun PatchOptionsScreenContent( isConfigValid: Boolean, 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( topBar = { PatchOptionsAppBar(isUpdate = isUpdate) }, ) { paddingValues -> @@ -159,6 +179,10 @@ fun PatchOptionsScreenContent( valueIsDefault = packageNameIsDefault, onValueChange = setPackageName, onValueReset = { setPackageName(PatchOptions.Default.packageName) }, + locked = packageNameLocked, + onLockClick = { + if (packageNameLocked) showPkgUnlockDialog = true else onLockPackageName() + }, ) { PackageNameStateLabel( 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( - specs = specs, - enabledCount = enabledPatchCount, - totalCount = specs.size, + iconRes = R.drawable.ic_healing, + titleRes = R.string.patchopts_patches_title, + descriptionRes = R.string.patchopts_patches_desc, + specs = patches, + enabledCount = patches.count(isPatchEnabled), + totalCount = patches.size, isEnabled = isPatchEnabled, onToggle = onTogglePatch, lockState = patchLockState, variantIndex = variantIndex, onSelectVariant = onSelectVariant, optionState = optionState, - modifier = Modifier.padding(top = 4.dp), + modifier = if (integrations.isEmpty()) Modifier.padding(top = 4.dp) else Modifier, ) if (isDevMode) { diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/PatchSpec.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/PatchSpec.kt index 12bb65e..3467ccf 100644 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/PatchSpec.kt +++ b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/PatchSpec.kt @@ -29,7 +29,16 @@ data class PatchSpec( val variants: List = emptyList(), val defaultVariantIndex: Int = 0, val advancedOptions: List = 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 @Serializable @@ -163,6 +172,8 @@ fun builtinPatchSpecs(resolve: (Int) -> String): List = variants = patch.variants.map { VariantSpec(resolve(it.titleRes), it.fileNames, it.extensionFiles) }, defaultVariantIndex = patch.defaultVariantIndex, advancedOptions = patch.advancedOptions.map { it.toSpec(resolve) }, + category = patch.category, + pathLocked = patch.pathLocked, ) } diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/components/PackageNameUnlockDialog.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/components/PackageNameUnlockDialog.kt new file mode 100644 index 0000000..3b6afdc --- /dev/null +++ b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/components/PackageNameUnlockDialog.kt @@ -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, + 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)) + } + } + } + } + } + } +} diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/components/PatchSelectionAccordion.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/components/PatchSelectionAccordion.kt index 5bfa5b5..70ab32c 100644 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/components/PatchSelectionAccordion.kt +++ b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/components/PatchSelectionAccordion.kt @@ -1,6 +1,8 @@ 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.core.animateFloatAsState 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.PatchLock 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.effectiveVariants import com.meowarex.rlmobile.ui.screens.patchopts.resolveVariantIndex @@ -35,6 +38,9 @@ private data class LockInfo(val patch: PatchSpec, val lock: PatchLock) @Composable fun PatchSelectionAccordion( + @DrawableRes iconRes: Int, + @StringRes titleRes: Int, + @StringRes descriptionRes: Int, specs: List, enabledCount: Int, totalCount: Int, @@ -69,12 +75,17 @@ fun PatchSelectionAccordion( .clickable(role = Role.Button) { expanded = !expanded } .padding(horizontal = 16.dp, vertical = 14.dp), ) { + Icon( + painter = painterResource(iconRes), + contentDescription = null, + ) + Column( verticalArrangement = Arrangement.spacedBy(2.dp), modifier = Modifier.weight(1f), ) { Text( - text = stringResource(R.string.patchopts_patches_title), + text = stringResource(titleRes), style = MaterialTheme.typography.titleMedium, ) Text( @@ -106,7 +117,7 @@ fun PatchSelectionAccordion( .padding(horizontal = 16.dp, vertical = 12.dp), ) { Text( - text = stringResource(R.string.patchopts_patches_desc), + text = stringResource(descriptionRes), style = MaterialTheme.typography.bodySmall, modifier = Modifier .alpha(.7f) @@ -372,6 +383,11 @@ private fun PatchLockDialog( R.string.patch_lock_blocked_msg, lock.by.title, ) + PatchLock.RequiresDefaultPackage -> Triple( + R.string.patch_lock_pkgname_title, + R.string.patch_lock_pkgname_msg, + PatchOptions.Default.packageName, + ) PatchLock.Free -> return } @@ -391,7 +407,7 @@ private fun PatchLockDialog( ) Text( text = AnnotatedString.fromHtml(stringResource(msgRes, blockerTitle)), - style = MaterialTheme.typography.titleMedium, + style = MaterialTheme.typography.bodyLarge, ) Box(modifier = Modifier.fillMaxWidth()) { TextButton( diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/components/options/TextPatchOption.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/components/options/TextPatchOption.kt index 46414d5..5b59819 100644 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/components/options/TextPatchOption.kt +++ b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/components/options/TextPatchOption.kt @@ -3,8 +3,12 @@ package com.meowarex.rlmobile.ui.screens.patchopts.components.options import androidx.compose.foundation.layout.* import androidx.compose.material3.* import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import com.meowarex.rlmobile.R import com.meowarex.rlmobile.ui.components.Label import com.meowarex.rlmobile.ui.components.ResetToDefaultButton @@ -18,6 +22,8 @@ fun TextPatchOption( onValueChange: (String) -> Unit, onValueReset: () -> Unit, modifier: Modifier = Modifier, + locked: Boolean? = null, + onLockClick: () -> Unit = {}, extra: (@Composable ColumnScope.() -> Unit)? = null, ) { Label( @@ -30,16 +36,41 @@ fun TextPatchOption( onValueChange = onValueChange, isError = valueIsError, singleLine = true, + enabled = locked != true, colors = OutlinedTextFieldDefaults.colors( unfocusedContainerColor = MaterialTheme.colorScheme.surfaceContainerLow, focusedContainerColor = MaterialTheme.colorScheme.surfaceContainerLow, errorContainerColor = MaterialTheme.colorScheme.surfaceContainerLow, + disabledContainerColor = MaterialTheme.colorScheme.surfaceContainerLow, ), trailingIcon = { - ResetToDefaultButton( - enabled = !valueIsDefault, - onClick = onValueReset, - ) + Row(verticalAlignment = Alignment.CenterVertically) { + if (locked != true) { + 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 .fillMaxWidth() diff --git a/Manager/app/src/main/res/drawable/ic_healing.xml b/Manager/app/src/main/res/drawable/ic_healing.xml new file mode 100644 index 0000000..6bebe3b --- /dev/null +++ b/Manager/app/src/main/res/drawable/ic_healing.xml @@ -0,0 +1,9 @@ + + + diff --git a/Manager/app/src/main/res/values/strings.xml b/Manager/app/src/main/res/values/strings.xml index f1aa74a..3e92d46 100644 --- a/Manager/app/src/main/res/values/strings.xml +++ b/Manager/app/src/main/res/values/strings.xml @@ -252,9 +252,16 @@ Patches Toggle which patches are applied during installation. Unchecked patches are skipped entirely. %1$d of %2$d enabled + Integrations + Connect TIDAL to other systems/apps + Custom Package Name + Installing under a package name other than <b>%s</b> will block the following from working: + The package name is permanent once installed (requires a fresh install) Advanced Options Advanced Options Toggle snapping to steps + Unlock editing + Lock and reset to default Disable Lyrics Cover Removes the mini track cover from the lyrics screen. @@ -333,6 +340,8 @@ Patch Blocked! Patch Required by <b>%s</b>. Patch Blocked by <b>%s</b>. + Original Package Name Invalid! + This only works while the app keeps its original <b>%s</b> package name. Reset the Package Name option to enable it.<br/><br/>An existing install can\'t be renamed (requires a fresh install) Option Locked Requires the <b>%s</b> style. Requires the <b>%s</b> option. diff --git a/patches/manifest.json b/patches/manifest.json index 23bfda2..4f57621 100644 --- a/patches/manifest.json +++ b/patches/manifest.json @@ -215,6 +215,8 @@ { "id": "WazeIntegration", "order": 90, + "category": "integration", + "pathLocked": true, "fileNames": ["waze-media-browser.patch"], "extensionFiles": ["radiant/WazeInitReceiver.smali", "radiant/WazeServiceConnection.smali"], "title": "Waze Integration",