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 1dc38c0..2e9d038 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 @@ -37,6 +37,9 @@ private fun PatchOptionsScreenPreview( enabledPatchCount = KnownPatch.All.size, isPatchEnabled = { true }, onTogglePatch = { _, _ -> }, + patchLockState = { PatchLock.Free }, + variantIndex = { 0 }, + onSelectVariant = { _, _ -> }, isConfigValid = parameters.isConfigValid, onInstall = {}, ) 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 3176276..7eb6fdc 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 @@ -3,6 +3,11 @@ package com.meowarex.rlmobile.ui.screens.patchopts import androidx.annotation.StringRes import com.meowarex.rlmobile.R +data class PatchVariant( + @StringRes val titleRes: Int, + val fileNames: List, +) + enum class KnownPatch( /** * Numeric display order in the patch options list. Lower = higher up. @@ -18,6 +23,8 @@ enum class KnownPatch( @StringRes val descRes: Int, val requires: List = emptyList(), val disables: List = emptyList(), + val variants: List = emptyList(), + val defaultVariantIndex: Int = 0, ) { // Dependency-first order (later refs need backward resolution). // The `order` field controls display order; declaration order doesn't matter. @@ -89,6 +96,27 @@ enum class KnownPatch( descRes = R.string.patch_lyrics_progress_pill_desc, requires = listOf(LyricsDisableCover, LyricsReplaceLyricsButton, LyricsReplaceShareButton), ), + MiniPlayerRedesign( + order = 50, + fileNames = emptyList(), + titleRes = R.string.patch_mini_player_redesign_title, + descRes = R.string.patch_mini_player_redesign_desc, + defaultVariantIndex = 2, + variants = listOf( + PatchVariant( + titleRes = R.string.patch_mini_player_variant_floating_title, + fileNames = listOf("mini-player-floating.patch"), + ), + PatchVariant( + titleRes = R.string.patch_mini_player_variant_square_grey_title, + fileNames = listOf("mini-player-grey.patch"), + ), + PatchVariant( + titleRes = R.string.patch_mini_player_variant_square_black_title, + fileNames = listOf("mini-player-black.patch"), + ), + ), + ), EnableLegacyUi( order = 10, fileNames = listOf("enable-legacy-ui.patch"), @@ -107,13 +135,16 @@ enum class KnownPatch( ), ); + val allVariantFileNames: Set + get() = variants.flatMapTo(mutableSetOf()) { it.fileNames } + companion object { /** * Sorted by `order` ascending. Tie-breaks fall back to the first filename * (alphabetical) so the order is always deterministic. */ val All: List = entries.sortedWith( - compareBy({ it.order }, { it.fileNames.first() }) + compareBy({ it.order }, { it.fileNames.firstOrNull() ?: it.name }) ) } } diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/PatchOptions.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/PatchOptions.kt index 168e2e1..e19df17 100644 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/PatchOptions.kt +++ b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/PatchOptions.kt @@ -33,15 +33,26 @@ data class PatchOptions( val customPatches: PatchComponent? = null, val disabledPatches: Set = emptySet(), + + val selectedVariants: Map = emptyMap(), ) : Parcelable { companion object { - val Default = PatchOptions( - appName = "TIDAL", - packageName = "com.aspiro.tidal", - debuggable = false, - customTidalApk = null, - customPatches = null, - disabledPatches = (KnownPatch.DebugMenuUnlock.fileNames + KnownPatch.EnableLegacyUi.fileNames).toSet(), - ) + val Default: PatchOptions = run { + val miniPlayerFiles = KnownPatch.MiniPlayerRedesign.allVariantFileNames + val disabled = ( + KnownPatch.DebugMenuUnlock.fileNames + + KnownPatch.EnableLegacyUi.fileNames + + miniPlayerFiles + ).toSet() + + PatchOptions( + appName = "TIDAL", + packageName = "com.aspiro.tidal", + debuggable = false, + customTidalApk = null, + customPatches = null, + disabledPatches = disabled, + ) + } } } 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 87c6346..a06a21f 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 @@ -50,10 +50,32 @@ class PatchOptionsModel( var disabledPatches by mutableStateOf(prefilledOptions.disabledPatches) private set - fun isPatchEnabled(patch: KnownPatch): Boolean = - patch.fileNames.none { it in disabledPatches } + var selectedVariants by mutableStateOf(prefilledOptions.selectedVariants) + private set + + fun variantIndex(patch: KnownPatch): Int = selectedVariants[patch.name] + ?.coerceIn(0, patch.variants.lastIndex.coerceAtLeast(0)) + ?: patch.defaultVariantIndex.coerceIn(0, patch.variants.lastIndex.coerceAtLeast(0)) + + fun isPatchEnabled(patch: KnownPatch): Boolean = if (patch.variants.isNotEmpty()) { + val v = patch.variants[variantIndex(patch)] + v.fileNames.isNotEmpty() && v.fileNames.none { it in disabledPatches } + } else { + patch.fileNames.isNotEmpty() && patch.fileNames.none { it in disabledPatches } + } fun setPatchEnabled(patch: KnownPatch, enabled: Boolean) { + if (patch.variants.isNotEmpty()) { + val all = patch.allVariantFileNames + val selected = patch.variants[variantIndex(patch)].fileNames.toSet() + disabledPatches = if (enabled) { + (disabledPatches + all) - selected + } else { + disabledPatches + all + } + return + } + fun closure(seed: KnownPatch, step: (KnownPatch) -> List): Set = buildSet { fun walk(p: KnownPatch) { if (add(p)) step(p).forEach(::walk) } @@ -78,6 +100,37 @@ class PatchOptionsModel( disabledPatches = (disabledPatches - enableFiles) + disableFiles } + fun selectVariant(patch: KnownPatch, index: Int) { + if (patch.variants.isEmpty() || index !in patch.variants.indices) return + val wasOn = isPatchEnabled(patch) + selectedVariants = selectedVariants + (patch.name to index) + if (wasOn) setPatchEnabled(patch, true) + } + + fun lockState(patch: KnownPatch): PatchLock { + if (patch.variants.isNotEmpty()) return PatchLock.Free + + fun closure(seed: KnownPatch, step: (KnownPatch) -> List): Set = + buildSet { + fun walk(p: KnownPatch) { if (add(p)) step(p).forEach(::walk) } + walk(seed) + } + + for (other in KnownPatch.All) { + if (other == patch || !isPatchEnabled(other)) continue + + val requiresClosure = closure(other) { it.requires } + if (patch in requiresClosure - other) return PatchLock.LockedOn(other) + + val disablesClosure = requiresClosure.flatMap { it.disables } + .flatMapTo(mutableSetOf()) { d -> + closure(d) { dep -> KnownPatch.All.filter { dep in it.requires } } + } + if (patch in disablesClosure) return PatchLock.LockedOff(other) + } + return PatchLock.Free + } + val enabledPatchCount: Int get() = KnownPatch.All.count { isPatchEnabled(it) } @@ -123,6 +176,7 @@ class PatchOptionsModel( customTidalApk = customTidalApk, customPatches = customPatches, disabledPatches = disabledPatches, + selectedVariants = selectedVariants, ) } @@ -147,7 +201,16 @@ class PatchOptionsModel( mainThread { packageNameState = state } } + private fun validatePatchSelection() { + for (patch in KnownPatch.All) { + if (isPatchEnabled(patch)) { + setPatchEnabled(patch, true) + } + } + } + init { + validatePatchSelection() screenModelScope.launchBlock { fetchPkgNameState() } } @@ -162,3 +225,9 @@ enum class PackageNameState { Invalid, Taken, } + +sealed class PatchLock { + object Free : PatchLock() + data class LockedOn(val by: KnownPatch) : PatchLock() + data class LockedOff(val by: KnownPatch) : 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 b437bf3..bd3eb26 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 @@ -63,6 +63,9 @@ class PatchOptionsScreen( enabledPatchCount = model.enabledPatchCount, isPatchEnabled = model::isPatchEnabled, onTogglePatch = model::setPatchEnabled, + patchLockState = model::lockState, + variantIndex = model::variantIndex, + onSelectVariant = model::selectVariant, isConfigValid = model.isConfigValid, onInstall = { @@ -96,6 +99,9 @@ fun PatchOptionsScreenContent( enabledPatchCount: Int, isPatchEnabled: (KnownPatch) -> Boolean, onTogglePatch: (KnownPatch, Boolean) -> Unit, + patchLockState: (KnownPatch) -> PatchLock, + variantIndex: (KnownPatch) -> Int, + onSelectVariant: (KnownPatch, Int) -> Unit, isConfigValid: Boolean, onInstall: () -> Unit, @@ -162,6 +168,9 @@ fun PatchOptionsScreenContent( totalCount = KnownPatch.All.size, isEnabled = isPatchEnabled, onToggle = onTogglePatch, + lockState = patchLockState, + variantIndex = variantIndex, + onSelectVariant = onSelectVariant, modifier = Modifier.padding(top = 4.dp), ) 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 724c316..c706022 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 @@ -18,9 +18,14 @@ import androidx.compose.ui.draw.rotate import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.Role +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.fromHtml import androidx.compose.ui.unit.dp import com.meowarex.rlmobile.R import com.meowarex.rlmobile.ui.screens.patchopts.KnownPatch +import com.meowarex.rlmobile.ui.screens.patchopts.PatchLock + +private data class LockInfo(val patch: KnownPatch, val lock: PatchLock) @Composable fun PatchSelectionAccordion( @@ -28,6 +33,9 @@ fun PatchSelectionAccordion( totalCount: Int, isEnabled: (KnownPatch) -> Boolean, onToggle: (KnownPatch, Boolean) -> Unit, + lockState: (KnownPatch) -> PatchLock, + variantIndex: (KnownPatch) -> Int, + onSelectVariant: (KnownPatch, Int) -> Unit, modifier: Modifier = Modifier, ) { var expanded by rememberSaveable { mutableStateOf(false) } @@ -36,6 +44,8 @@ fun PatchSelectionAccordion( label = "patch-accordion-arrow", ) + var lockInfo by remember { mutableStateOf(null) } + Column( modifier = modifier .fillMaxWidth() @@ -80,6 +90,7 @@ fun PatchSelectionAccordion( AnimatedVisibility(visible = expanded) { Column( + verticalArrangement = Arrangement.spacedBy(4.dp), modifier = Modifier .fillMaxWidth() .background(MaterialTheme.colorScheme.background.copy(0.4f)) @@ -94,45 +105,73 @@ fun PatchSelectionAccordion( ) for (patch in KnownPatch.All) key(patch) { - PatchCheckboxRow( + val checked = isEnabled(patch) + val lock = lockState(patch) + PatchSwitchRow( title = stringResource(patch.titleRes), description = stringResource(patch.descRes), - checked = isEnabled(patch), + checked = checked, + lock = lock, onCheckedChange = { onToggle(patch, it) }, + onLockedTap = { lockInfo = LockInfo(patch, lock) }, ) + + if (patch.variants.isNotEmpty()) { + AnimatedVisibility(visible = checked) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(start = 4.dp, end = 4.dp, top = 4.dp, bottom = 4.dp), + ) { + PatchVariantSelector( + variants = patch.variants, + selectedIndex = variantIndex(patch), + onSelect = { idx -> onSelectVariant(patch, idx) }, + ) + } + } + } } } } } + + lockInfo?.let { info -> + PatchLockDialog( + thisPatch = info.patch, + lock = info.lock, + onDismiss = { lockInfo = null }, + ) + } } @Composable -private fun PatchCheckboxRow( +private fun PatchSwitchRow( title: String, description: String, checked: Boolean, + lock: PatchLock, onCheckedChange: (Boolean) -> Unit, + onLockedTap: () -> Unit, ) { val interactionSource = remember(::MutableInteractionSource) + val isLocked = lock !is PatchLock.Free Row( verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp), + horizontalArrangement = Arrangement.spacedBy(12.dp), modifier = Modifier .fillMaxWidth() .clickable( interactionSource = interactionSource, indication = null, - role = Role.Checkbox, - ) { onCheckedChange(!checked) } - .padding(vertical = 4.dp), + role = Role.Switch, + ) { + if (isLocked) onLockedTap() else onCheckedChange(!checked) + } + .alpha(if (isLocked) 0.45f else 1f) + .padding(vertical = 6.dp), ) { - Checkbox( - checked = checked, - onCheckedChange = onCheckedChange, - interactionSource = interactionSource, - ) - Column( verticalArrangement = Arrangement.spacedBy(2.dp), modifier = Modifier.weight(1f), @@ -147,5 +186,77 @@ private fun PatchCheckboxRow( modifier = Modifier.alpha(.7f), ) } + + Box { + Switch( + checked = checked, + enabled = !isLocked, + onCheckedChange = onCheckedChange, + interactionSource = interactionSource, + ) + if (isLocked) { + Box( + modifier = Modifier + .matchParentSize() + .clickable( + interactionSource = remember(::MutableInteractionSource), + indication = null, + role = Role.Switch, + ) { onLockedTap() } + ) + } + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun PatchLockDialog( + thisPatch: KnownPatch, + lock: PatchLock, + onDismiss: () -> Unit, +) { + val (titleRes, msgRes, blockerTitle) = when (lock) { + is PatchLock.LockedOn -> Triple( + R.string.patch_lock_required_title, + R.string.patch_lock_required_msg, + stringResource(lock.by.titleRes), + ) + is PatchLock.LockedOff -> Triple( + R.string.patch_lock_blocked_title, + R.string.patch_lock_blocked_msg, + stringResource(lock.by.titleRes), + ) + PatchLock.Free -> return + } + + 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(titleRes), + style = MaterialTheme.typography.titleLarge, + ) + Text( + text = AnnotatedString.fromHtml(stringResource(msgRes, blockerTitle)), + style = MaterialTheme.typography.titleMedium, + ) + Box(modifier = Modifier.fillMaxWidth()) { + TextButton( + onClick = onDismiss, + modifier = Modifier.align(Alignment.CenterEnd), + ) { + Text(stringResource(R.string.action_got_it)) + } + } + } + } } } diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/components/PatchVariantSelector.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/components/PatchVariantSelector.kt new file mode 100644 index 0000000..9f9274d --- /dev/null +++ b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/components/PatchVariantSelector.kt @@ -0,0 +1,44 @@ +package com.meowarex.rlmobile.ui.screens.patchopts.components + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import com.meowarex.rlmobile.ui.screens.patchopts.PatchVariant + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun PatchVariantSelector( + variants: List, + selectedIndex: Int, + onSelect: (Int) -> Unit, + modifier: Modifier = Modifier, +) { + SingleChoiceSegmentedButtonRow( + modifier = modifier.fillMaxWidth(), + ) { + variants.forEachIndexed { index, variant -> + SegmentedButton( + selected = index == selectedIndex, + onClick = { onSelect(index) }, + shape = SegmentedButtonDefaults.itemShape( + index = index, + count = variants.size, + ), + icon = {}, + label = { + Text( + text = stringResource(variant.titleRes), + maxLines = 1, + overflow = TextOverflow.Ellipsis, + textAlign = TextAlign.Center, + style = MaterialTheme.typography.labelMedium, + ) + }, + ) + } + } +} diff --git a/Manager/app/src/main/res/values/strings.xml b/Manager/app/src/main/res/values/strings.xml index 07d2f44..e99ce5f 100644 --- a/Manager/app/src/main/res/values/strings.xml +++ b/Manager/app/src/main/res/values/strings.xml @@ -283,6 +283,18 @@ name="patch_enable_legacy_ui_desc" >[This patch will stop working soon] - Replaces the New Compose based UI with the Legacy UI (disables player-market-ui feature flag) + Redesigned Mini-Player + Integrates the Seekbar into the control panel at the bottom of the screen. + Floating + Grey + Black + + Patch Required! + Patch Blocked! + Patch Required by <b>%s</b>. + Patch Blocked by <b>%s</b>. + Got it + Custom Component (%s) Select a custom build that was imported by Manager. Latest diff --git a/patches/data.json b/patches/data.json index 0c2c3ea..c24b8c9 100644 --- a/patches/data.json +++ b/patches/data.json @@ -1,5 +1,5 @@ { "tidalVersionCode": 9090, "tidalApkUrl": "https://github.com/meowarex/rl-mobile/releases/download/latest/tidal-stock.apk", - "patchesVersion": "0.9.1" + "patchesVersion": "0.9.5" } diff --git a/patches/extension/radiant/MiniSeekerFloating.smali b/patches/extension/radiant/MiniSeekerFloating.smali new file mode 100644 index 0000000..9957695 --- /dev/null +++ b/patches/extension/radiant/MiniSeekerFloating.smali @@ -0,0 +1,436 @@ +.class public final Lradiant/MiniSeekerFloating; +.super Ljava/lang/Object; + +.implements Lyl0/l; + + +# static fields +.field public static final INSTANCE:Lradiant/MiniSeekerFloating; + + +# direct methods +.method static constructor ()V + .locals 1 + + new-instance v0, Lradiant/MiniSeekerFloating; # singleton + + invoke-direct {v0}, Lradiant/MiniSeekerFloating;->()V # ctor + + sput-object v0, Lradiant/MiniSeekerFloating;->INSTANCE:Lradiant/MiniSeekerFloating; # publish + + return-void +.end method + + +.method private constructor ()V + .locals 0 + + invoke-direct {p0}, Ljava/lang/Object;->()V + + return-void +.end method + + +.method public final invoke(Ljava/lang/Object;)Ljava/lang/Object; + .locals 2 + + check-cast p1, Landroidx/compose/ui/graphics/drawscope/ContentDrawScope; # narrow type + + invoke-interface {p1}, Landroidx/compose/ui/graphics/drawscope/ContentDrawScope;->drawContent()V # draw pill content + + invoke-static {}, Lradiant/MiniSeekerLine;->start()V # lazy subscribe + + :try_start + invoke-static {p1}, Lradiant/MiniSeekerFloating;->drawBorder(Landroidx/compose/ui/graphics/drawscope/ContentDrawScope;)V # draw progress + :try_end + .catch Ljava/lang/Throwable; {:try_start .. :try_end} :swallow + + :swallow + sget-object v0, Lkotlin/u;->a:Lkotlin/u; # Unit + + return-object v0 +.end method + + +.method private static drawBorder(Landroidx/compose/ui/graphics/drawscope/ContentDrawScope;)V + .locals 60 + + sget-object v0, Lradiant/MiniSeekerLine;->progressState:Landroidx/compose/runtime/MutableFloatState; # state + + invoke-interface {v0}, Landroidx/compose/runtime/MutableFloatState;->getFloatValue()F # read tracked + + move-result v0 # raw progress + + const/4 v1, 0x0 # lower bound + + invoke-static {v0, v1}, Ljava/lang/Math;->max(FF)F # clamp low + + move-result v0 # clamped low + + const/high16 v1, 0x3f800000 # 1.0f upper + + invoke-static {v0, v1}, Ljava/lang/Math;->min(FF)F # clamp high + + move-result v0 # final progress + + const/4 v1, 0x0 # zero + + cmpg-float v2, v0, v1 # compare to zero + + if-lez v2, :done # skip if empty + + move/from16 v16, v0 # stash progress + + invoke-interface/range {p0 .. p0}, Landroidx/compose/ui/graphics/drawscope/DrawScope;->getSize-NH-jbRc()J # size long + + move-result-wide v0 # size pair + + invoke-static {v0, v1}, Landroidx/compose/ui/geometry/Size;->getWidth-impl(J)F # extract width + + move-result v2 # width px + + move/from16 v17, v2 # stash width + + invoke-static {v0, v1}, Landroidx/compose/ui/geometry/Size;->getHeight-impl(J)F # extract height + + move-result v2 # height px + + move/from16 v18, v2 # stash height + + invoke-interface/range {p0 .. p0}, Landroidx/compose/ui/unit/Density;->getDensity()F # density + + move-result v2 # px per dp + + move/from16 v19, v2 # stash density + + const/high16 v0, 0x42100000 # 36.0f dp + + move/from16 v1, v19 # density + + mul-float v2, v0, v1 # to px + + move/from16 v20, v2 # stash r + + const/high16 v0, 0x40000000 # 2.0f + + move/from16 v1, v20 # r + + mul-float v2, v1, v0 # 2*r + + move/from16 v21, v2 # stash 2r + + move/from16 v0, v17 # w + + move/from16 v1, v20 # r + + sub-float v2, v0, v1 # w-r + + move/from16 v22, v2 # stash w-r + + move/from16 v0, v18 # h + + move/from16 v1, v20 # r + + sub-float v2, v0, v1 # h-r + + move/from16 v23, v2 # stash h-r + + move/from16 v0, v17 # w + + move/from16 v1, v21 # 2r + + sub-float v2, v0, v1 # w-2r + + move/from16 v24, v2 # stash w-2r + + move/from16 v0, v18 # h + + move/from16 v1, v21 # 2r + + sub-float v2, v0, v1 # h-2r + + move/from16 v25, v2 # stash h-2r + + move/from16 v0, v17 # w + + const/high16 v1, 0x40000000 # 2.0f + + div-float v2, v0, v1 # w/2 + + move/from16 v26, v2 # stash top-center x + + const/high16 v0, 0x42b40000 # 90.0f + + move/from16 v27, v0 # stash 90 + + const/4 v0, 0x0 # zero + + move/from16 v1, v27 # 90 + + sub-float v2, v0, v1 # -90 + + move/from16 v28, v2 # stash -90 + + const/high16 v0, 0x43340000 # 180.0f + + move/from16 v29, v0 # stash 180 + + invoke-static {}, Landroidx/compose/ui/graphics/AndroidPath_androidKt;->Path()Landroidx/compose/ui/graphics/Path; # new path + + move-result-object v0 # path + + move-object/from16 v30, v0 # stash path + + move-object/from16 v0, v30 # path + + move/from16 v1, v26 # w/2 + + const/4 v2, 0x0 # 0 + + invoke-interface {v0, v1, v2}, Landroidx/compose/ui/graphics/Path;->moveTo(FF)V # start top-center + + move-object/from16 v0, v30 # path + + move/from16 v1, v22 # w-r + + const/4 v2, 0x0 # 0 + + invoke-interface {v0, v1, v2}, Landroidx/compose/ui/graphics/Path;->lineTo(FF)V # top edge right + + new-instance v3, Landroidx/compose/ui/geometry/Rect; # arc bounds + + move/from16 v4, v24 # w-2r + + const/4 v5, 0x0 # 0 + + move/from16 v6, v17 # w + + move/from16 v7, v21 # 2r + + invoke-direct {v3, v4, v5, v6, v7}, Landroidx/compose/ui/geometry/Rect;->(FFFF)V # TR rect + + move-object/from16 v0, v30 # path + + move/from16 v4, v28 # -90 + + move/from16 v5, v27 # 90 + + const/4 v6, 0x0 # false + + invoke-interface {v0, v3, v4, v5, v6}, Landroidx/compose/ui/graphics/Path;->arcTo(Landroidx/compose/ui/geometry/Rect;FFZ)V # TR corner + + move-object/from16 v0, v30 # path + + move/from16 v1, v17 # w + + move/from16 v2, v23 # h-r + + invoke-interface {v0, v1, v2}, Landroidx/compose/ui/graphics/Path;->lineTo(FF)V # right edge + + new-instance v3, Landroidx/compose/ui/geometry/Rect; # arc bounds + + move/from16 v4, v24 # w-2r + + move/from16 v5, v25 # h-2r + + move/from16 v6, v17 # w + + move/from16 v7, v18 # h + + invoke-direct {v3, v4, v5, v6, v7}, Landroidx/compose/ui/geometry/Rect;->(FFFF)V # BR rect + + move-object/from16 v0, v30 # path + + const/4 v4, 0x0 # 0 deg + + move/from16 v5, v27 # 90 + + const/4 v6, 0x0 # false + + invoke-interface {v0, v3, v4, v5, v6}, Landroidx/compose/ui/graphics/Path;->arcTo(Landroidx/compose/ui/geometry/Rect;FFZ)V # BR corner + + move-object/from16 v0, v30 # path + + move/from16 v1, v20 # r + + move/from16 v2, v18 # h + + invoke-interface {v0, v1, v2}, Landroidx/compose/ui/graphics/Path;->lineTo(FF)V # bottom edge + + new-instance v3, Landroidx/compose/ui/geometry/Rect; # arc bounds + + const/4 v4, 0x0 # 0 + + move/from16 v5, v25 # h-2r + + move/from16 v6, v21 # 2r + + move/from16 v7, v18 # h + + invoke-direct {v3, v4, v5, v6, v7}, Landroidx/compose/ui/geometry/Rect;->(FFFF)V # BL rect + + move-object/from16 v0, v30 # path + + move/from16 v4, v27 # 90 + + move/from16 v5, v27 # 90 + + const/4 v6, 0x0 # false + + invoke-interface {v0, v3, v4, v5, v6}, Landroidx/compose/ui/graphics/Path;->arcTo(Landroidx/compose/ui/geometry/Rect;FFZ)V # BL corner + + move-object/from16 v0, v30 # path + + const/4 v1, 0x0 # 0 + + move/from16 v2, v20 # r + + invoke-interface {v0, v1, v2}, Landroidx/compose/ui/graphics/Path;->lineTo(FF)V # left edge + + new-instance v3, Landroidx/compose/ui/geometry/Rect; # arc bounds + + const/4 v4, 0x0 # 0 + + const/4 v5, 0x0 # 0 + + move/from16 v6, v21 # 2r + + move/from16 v7, v21 # 2r + + invoke-direct {v3, v4, v5, v6, v7}, Landroidx/compose/ui/geometry/Rect;->(FFFF)V # TL rect + + move-object/from16 v0, v30 # path + + move/from16 v4, v29 # 180 + + move/from16 v5, v27 # 90 + + const/4 v6, 0x0 # false + + invoke-interface {v0, v3, v4, v5, v6}, Landroidx/compose/ui/graphics/Path;->arcTo(Landroidx/compose/ui/geometry/Rect;FFZ)V # TL corner + + move-object/from16 v0, v30 # path + + move/from16 v1, v26 # w/2 + + const/4 v2, 0x0 # 0 + + invoke-interface {v0, v1, v2}, Landroidx/compose/ui/graphics/Path;->lineTo(FF)V # close to start + + const/high16 v0, 0x40000000 # 2.0f + + move/from16 v1, v24 # w-2r + + mul-float v2, v1, v0 # 2*(w-2r) + + move/from16 v1, v25 # h-2r + + mul-float v3, v1, v0 # 2*(h-2r) + + add-float v4, v2, v3 # straight edges + + const v5, 0x40c90fdb # 2*pi + + move/from16 v6, v20 # r + + mul-float v7, v6, v5 # arc length + + add-float v8, v4, v7 # total perim + + move/from16 v31, v8 # stash perim + + move/from16 v0, v16 # progress + + move/from16 v1, v31 # perim + + mul-float v2, v0, v1 # visible length + + move/from16 v32, v2 # stash visible + + sget-object v0, Landroidx/compose/ui/graphics/PathEffect;->Companion:Landroidx/compose/ui/graphics/PathEffect$Companion; # companion + + const/4 v1, 0x2 # length 2 + + new-array v1, v1, [F # intervals + + const/4 v2, 0x0 # index 0 + + move/from16 v3, v32 # visible + + aput v3, v1, v2 # dash length + + const/4 v2, 0x1 # index 1 + + move/from16 v3, v31 # perim + + aput v3, v1, v2 # gap length + + const/4 v2, 0x0 # phase int + + int-to-float v2, v2 # phase float + + invoke-virtual {v0, v1, v2}, Landroidx/compose/ui/graphics/PathEffect$Companion;->dashPathEffect([FF)Landroidx/compose/ui/graphics/PathEffect; # dash effect + + move-result-object v0 # effect + + move-object/from16 v33, v0 # stash effect + + const/high16 v0, 0x40000000 # 2.0f + + move/from16 v1, v19 # density + + mul-float v2, v0, v1 # stroke px + + move/from16 v34, v2 # stash stroke width + + new-instance v40, Landroidx/compose/ui/graphics/drawscope/Stroke; # stroke obj + + move/from16 v41, v34 # width + + const/16 v42, 0x0 # miter default + + const/16 v43, 0x0 # cap default + + const/16 v44, 0x0 # join default + + move-object/from16 v45, v33 # effect + + const/16 v46, 0xe # default mask + + const/16 v47, 0x0 # marker null + + invoke-direct/range {v40 .. v47}, Landroidx/compose/ui/graphics/drawscope/Stroke;->(FFIILandroidx/compose/ui/graphics/PathEffect;ILkotlin/jvm/internal/DefaultConstructorMarker;)V # stroke ctor + + move-object/from16 v35, v40 # stash stroke + + const v0, -0x1 # white ARGB + + invoke-static {v0}, Landroidx/compose/ui/graphics/ColorKt;->Color(I)J # pack color + + move-result-wide v0 # color long + + move-wide/from16 v36, v0 # stash color + + move-object/from16 v50, p0 # scope + + move-object/from16 v51, v30 # path + + move-wide/from16 v52, v36 # color + + const/16 v54, 0x0 # alpha default + + move-object/from16 v55, v35 # style + + const/16 v56, 0x0 # filter null + + const/16 v57, 0x0 # blend default + + const/16 v58, 0x34 # default mask + + const/16 v59, 0x0 # marker null + + invoke-static/range {v50 .. v59}, Landroidx/compose/ui/graphics/drawscope/DrawScope;->drawPath-LG529CI$default(Landroidx/compose/ui/graphics/drawscope/DrawScope;Landroidx/compose/ui/graphics/Path;JFLandroidx/compose/ui/graphics/drawscope/DrawStyle;Landroidx/compose/ui/graphics/ColorFilter;IILjava/lang/Object;)V # draw stroke + + :done + return-void +.end method diff --git a/patches/extension/radiant/MiniSeekerLine.smali b/patches/extension/radiant/MiniSeekerLine.smali new file mode 100644 index 0000000..5db041f --- /dev/null +++ b/patches/extension/radiant/MiniSeekerLine.smali @@ -0,0 +1,200 @@ +.class public final Lradiant/MiniSeekerLine; +.super Ljava/lang/Object; + + +# static fields +.field public static progressState:Landroidx/compose/runtime/MutableFloatState; + +.field public static volatile vm:Ljh/h; + +.field public static volatile sub:Lio/reactivex/disposables/Disposable; + + +# direct methods +.method static constructor ()V + .locals 1 + + const/4 v0, 0x0 # initial progress + + invoke-static {v0}, Landroidx/compose/runtime/PrimitiveSnapshotStateKt;->mutableFloatStateOf(F)Landroidx/compose/runtime/MutableFloatState; # state holder + + move-result-object v0 # state instance + + sput-object v0, Lradiant/MiniSeekerLine;->progressState:Landroidx/compose/runtime/MutableFloatState; # publish state + + return-void +.end method + + +.method private constructor ()V + .locals 0 + + invoke-direct {p0}, Ljava/lang/Object;->()V + + return-void +.end method + + +.method private static dlog(Ljava/lang/String;)V + .locals 1 + + const-string v0, "RLProgressLine" # log tag + + invoke-static {v0, p0}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I # info log + + return-void +.end method + + +.method public static start()V + .locals 3 + + sget-object v0, Lradiant/MiniSeekerLine;->sub:Lio/reactivex/disposables/Disposable; # current sub + + if-eqz v0, :start_block # only run once + + return-void + + :start_block + :try_start + sget-object v0, Lradiant/MiniSeekerLine;->vm:Ljh/h; # cached vm + + if-nez v0, :got_vm # reuse if present + + invoke-static {}, Lcom/aspiro/wamp/App$a;->a()Lcom/aspiro/wamp/App; # app singleton + + move-result-object v0 # app + + invoke-virtual {v0}, Lcom/aspiro/wamp/App;->e()Lf5/c; # dagger component + + move-result-object v0 # component + + check-cast v0, Lf5/d0$n2; # narrow type + + iget-object v0, v0, Lf5/d0$n2;->z0:Ldagger/internal/j; # playqueue provider + + invoke-interface {v0}, Lol0/a;->get()Ljava/lang/Object; # resolve + + move-result-object v0 # playqueue + + check-cast v0, Lcom/aspiro/wamp/playqueue/z0; # narrow type + + new-instance v1, Ljh/h; # build vm + + invoke-direct {v1, v0}, Ljh/h;->(Lcom/aspiro/wamp/playqueue/z0;)V # ctor + + sput-object v1, Lradiant/MiniSeekerLine;->vm:Ljh/h; # cache + + :got_vm + sget-object v0, Lradiant/MiniSeekerLine;->vm:Ljh/h; # vm ref + + invoke-virtual {v0}, Ljh/h;->a()V # activate emission + + iget-object v0, v0, Ljh/h;->d:Lio/reactivex/subjects/BehaviorSubject; # position subject + + invoke-static {}, Lio/reactivex/android/schedulers/AndroidSchedulers;->mainThread()Lio/reactivex/Scheduler; # main scheduler + + move-result-object v1 # scheduler + + invoke-virtual {v0, v1}, Lio/reactivex/Observable;->observeOn(Lio/reactivex/Scheduler;)Lio/reactivex/Observable; # observe main + + move-result-object v0 # observable + + new-instance v1, Lradiant/SeekerConsumer; # consumer + + invoke-direct {v1}, Lradiant/SeekerConsumer;->()V # ctor + + invoke-virtual {v0, v1}, Lio/reactivex/Observable;->subscribe(Lio/reactivex/functions/Consumer;)Lio/reactivex/disposables/Disposable; # subscribe + + move-result-object v0 # disposable + + sput-object v0, Lradiant/MiniSeekerLine;->sub:Lio/reactivex/disposables/Disposable; # cache + + const-string v0, "started" # log msg + + invoke-static {v0}, Lradiant/MiniSeekerLine;->dlog(Ljava/lang/String;)V # info log + + return-void + :try_end + .catch Ljava/lang/Throwable; {:try_start .. :try_end} :swallow + + :swallow + move-exception v0 # error + + const-string v1, "start failed" # log msg + + invoke-static {v1}, Lradiant/MiniSeekerLine;->dlog(Ljava/lang/String;)V # info log + + return-void +.end method + + +.method public static render(Landroidx/compose/runtime/Composer;I)V + .locals 5 + .annotation build Landroidx/compose/runtime/Composable; + .end annotation + + invoke-static {}, Lradiant/MiniSeekerLine;->start()V # lazy subscribe + + sget-object v0, Lradiant/MiniSeekerLine;->progressState:Landroidx/compose/runtime/MutableFloatState; # state + + invoke-interface {v0}, Landroidx/compose/runtime/MutableFloatState;->getFloatValue()F # read tracked + + move-result v0 # raw progress + + const/4 v1, 0x0 # lower bound + + invoke-static {v0, v1}, Ljava/lang/Math;->max(FF)F # clamp low + + move-result v0 # clamped low + + const/high16 v1, 0x3f800000 # 1.0f upper + + invoke-static {v0, v1}, Ljava/lang/Math;->min(FF)F # clamp high + + move-result v0 # final progress + + const v1, 0x52414c49 # 'RALI' slot key + + invoke-interface {p0, v1}, Landroidx/compose/runtime/Composer;->startReplaceGroup(I)V # open group + + sget-object v1, Landroidx/compose/ui/Modifier;->Companion:Landroidx/compose/ui/Modifier$Companion; # base modifier + + invoke-static {v1, v0}, Landroidx/compose/foundation/layout/SizeKt;->fillMaxWidth(Landroidx/compose/ui/Modifier;F)Landroidx/compose/ui/Modifier; # width fraction + + move-result-object v0 # filled modifier + + const/4 v1, 0x2 # 2 dp + + int-to-float v1, v1 # to float + + invoke-static {v1}, Landroidx/compose/ui/unit/Dp;->constructor-impl(F)F # box as Dp + + move-result v1 # dp value + + invoke-static {v0, v1}, Landroidx/compose/foundation/layout/SizeKt;->height-3ABfNKs(Landroidx/compose/ui/Modifier;F)Landroidx/compose/ui/Modifier; # 2dp tall + + move-result-object v0 # sized modifier + + const v1, -0x1 # 0xFFFFFFFF white + + invoke-static {v1}, Landroidx/compose/ui/graphics/ColorKt;->Color(I)J # pack color + + move-result-wide v1 # color long + + invoke-static {}, Landroidx/compose/ui/graphics/RectangleShapeKt;->getRectangleShape()Landroidx/compose/ui/graphics/Shape; # rect shape + + move-result-object v3 # shape + + invoke-static {v0, v1, v2, v3}, Landroidx/compose/foundation/BackgroundKt;->background-bw27NRU(Landroidx/compose/ui/Modifier;JLandroidx/compose/ui/graphics/Shape;)Landroidx/compose/ui/Modifier; # white bg + + move-result-object v0 # final modifier + + const/4 v1, 0x0 # composer $changed + + invoke-static {v0, p0, v1}, Landroidx/compose/foundation/layout/SpacerKt;->Spacer(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)V # draw line + + invoke-interface {p0}, Landroidx/compose/runtime/Composer;->endReplaceGroup()V # close group + + return-void +.end method diff --git a/patches/extension/radiant/SeekerConsumer.smali b/patches/extension/radiant/SeekerConsumer.smali new file mode 100644 index 0000000..3b21120 --- /dev/null +++ b/patches/extension/radiant/SeekerConsumer.smali @@ -0,0 +1,60 @@ +.class public final Lradiant/SeekerConsumer; +.super Ljava/lang/Object; + +.implements Lio/reactivex/functions/Consumer; + + +# direct methods +.method public constructor ()V + .locals 0 + + invoke-direct {p0}, Ljava/lang/Object;->()V + + return-void +.end method + + +# virtual methods +.method public final accept(Ljava/lang/Object;)V + .locals 3 + + if-eqz p1, :ret # null guard + + instance-of v0, p1, Ljh/b; # type guard + + if-eqz v0, :ret # skip if wrong type + + check-cast p1, Ljh/b; # narrow type + + iget v0, p1, Ljh/b;->b:F # raw progress + + invoke-static {v0}, Ljava/lang/Float;->isNaN(F)Z # nan check + + move-result v1 # nan flag + + if-eqz v1, :not_nan # skip clamp if finite + + const/4 v0, 0x0 # default to zero + + :not_nan + const/4 v1, 0x0 # lower bound + + invoke-static {v0, v1}, Ljava/lang/Math;->max(FF)F # clamp low + + move-result v0 # clamped low + + const/high16 v2, 0x3f800000 # 1.0f upper bound + + invoke-static {v0, v2}, Ljava/lang/Math;->min(FF)F # clamp high + + move-result v0 # final value + + sget-object v1, Lradiant/MiniSeekerLine;->progressState:Landroidx/compose/runtime/MutableFloatState; # shared state + + if-eqz v1, :ret # safety + + invoke-interface {v1, v0}, Landroidx/compose/runtime/MutableFloatState;->setFloatValue(F)V # publish + + :ret + return-void +.end method diff --git a/patches/mini-player-black.patch b/patches/mini-player-black.patch new file mode 100644 index 0000000..c325af8 --- /dev/null +++ b/patches/mini-player-black.patch @@ -0,0 +1,69 @@ +--- a/com/tidal/android/feature/appscaffold/ui/composable/a.smali ++++ b/com/tidal/android/feature/appscaffold/ui/composable/a.smali +@@ -116,7 +116,7 @@ + + .line 46 + .line 47 +- const/16 v0, 0x24 ++ const/16 v0, 0x0 # zero pill corner radius + + .line 48 + .line 49 +@@ -162,7 +162,7 @@ + + .line 68 + .line 69 +- const/16 v0, 0x8 ++ const/16 v0, 0x0 # zero bottom padding + + .line 70 + .line 71 +--- a/com/tidal/android/feature/appscaffold/ui/composable/i.smali ++++ b/com/tidal/android/feature/appscaffold/ui/composable/i.smali +@@ -2756,12 +2756,7 @@ + invoke-static {v0, v8, v11, v12}, Landroidx/compose/foundation/layout/SizeKt;->fillMaxWidth$default(Landroidx/compose/ui/Modifier;FILjava/lang/Object;)Landroidx/compose/ui/Modifier; + + move-result-object v0 +- +- .line 140 +- invoke-static {v0}, Landroidx/compose/foundation/layout/WindowInsetsPadding_androidKt;->navigationBarsPadding(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier; +- +- move-result-object v0 +- ++ # flush bottom; skip nav inset + .line 141 + invoke-interface/range {v17 .. v17}, Landroidx/compose/runtime/State;->getValue()Ljava/lang/Object; + +@@ -2773,6 +2768,8 @@ + + move-result v10 + ++ const/4 v10, 0x0 # zero horizontal padding ++ + const/4 v11, 0x2 + + .line 142 +@@ -2816,6 +2813,12 @@ + + move-result-wide v10 + ++ const v8, -0x1000000 # 0xFF000000 opaque black ++ ++ invoke-static {v8}, Landroidx/compose/ui/graphics/ColorKt;->Color(I)J # pack to color long ++ ++ move-result-wide v10 # override theme color ++ + .line 147 + sget-object v8, Lcom/tidal/android/feature/appscaffold/ui/composable/a;->c:Landroidx/compose/foundation/shape/RoundedCornerShape; + +@@ -2969,6 +2972,10 @@ + + invoke-static {v12, v0, v8}, Landroidx/compose/runtime/Updater;->set-impl(Landroidx/compose/runtime/Composer;Ljava/lang/Object;Lyl0/p;)V + ++ const/4 v8, 0x0 # composer $changed flags ++ ++ invoke-static {v15, v8}, Lradiant/MiniSeekerLine;->render(Landroidx/compose/runtime/Composer;I)V # draw top-edge seeker ++ + .line 172 + sget-object v0, Landroidx/compose/foundation/layout/ColumnScopeInstance;->INSTANCE:Landroidx/compose/foundation/layout/ColumnScopeInstance; + diff --git a/patches/mini-player-floating.patch b/patches/mini-player-floating.patch new file mode 100644 index 0000000..eca1011 --- /dev/null +++ b/patches/mini-player-floating.patch @@ -0,0 +1,15 @@ +--- a/com/tidal/android/feature/appscaffold/ui/composable/i.smali ++++ b/com/tidal/android/feature/appscaffold/ui/composable/i.smali +@@ -2829,6 +2829,12 @@ + + move-result-object v0 + ++ sget-object v8, Lradiant/MiniSeekerFloating;->INSTANCE:Lradiant/MiniSeekerFloating; # draw lambda ++ ++ invoke-static {v0, v8}, Landroidx/compose/ui/draw/DrawModifierKt;->drawWithContent(Landroidx/compose/ui/Modifier;Lyl0/l;)Landroidx/compose/ui/Modifier; # overlay perimeter stroke ++ ++ move-result-object v0 # updated modifier ++ + .line 150 + sget-object v8, Lkotlin/u;->a:Lkotlin/u; + diff --git a/patches/mini-player-grey.patch b/patches/mini-player-grey.patch new file mode 100644 index 0000000..3855a98 --- /dev/null +++ b/patches/mini-player-grey.patch @@ -0,0 +1,56 @@ +--- a/com/tidal/android/feature/appscaffold/ui/composable/a.smali ++++ b/com/tidal/android/feature/appscaffold/ui/composable/a.smali +@@ -116,7 +116,7 @@ + + .line 46 + .line 47 +- const/16 v0, 0x24 ++ const/16 v0, 0x0 # zero pill corner radius + + .line 48 + .line 49 +@@ -162,7 +162,7 @@ + + .line 68 + .line 69 +- const/16 v0, 0x8 ++ const/16 v0, 0x0 # zero bottom padding + + .line 70 + .line 71 +--- a/com/tidal/android/feature/appscaffold/ui/composable/i.smali ++++ b/com/tidal/android/feature/appscaffold/ui/composable/i.smali +@@ -2756,12 +2756,7 @@ + invoke-static {v0, v8, v11, v12}, Landroidx/compose/foundation/layout/SizeKt;->fillMaxWidth$default(Landroidx/compose/ui/Modifier;FILjava/lang/Object;)Landroidx/compose/ui/Modifier; + + move-result-object v0 +- +- .line 140 +- invoke-static {v0}, Landroidx/compose/foundation/layout/WindowInsetsPadding_androidKt;->navigationBarsPadding(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier; +- +- move-result-object v0 +- ++ # flush bottom; skip nav inset + .line 141 + invoke-interface/range {v17 .. v17}, Landroidx/compose/runtime/State;->getValue()Ljava/lang/Object; + +@@ -2773,6 +2768,8 @@ + + move-result v10 + ++ const/4 v10, 0x0 # zero horizontal padding ++ + const/4 v11, 0x2 + + .line 142 +@@ -2969,6 +2966,10 @@ + + invoke-static {v12, v0, v8}, Landroidx/compose/runtime/Updater;->set-impl(Landroidx/compose/runtime/Composer;Ljava/lang/Object;Lyl0/p;)V + ++ const/4 v8, 0x0 # composer $changed flags ++ ++ invoke-static {v15, v8}, Lradiant/MiniSeekerLine;->render(Landroidx/compose/runtime/Composer;I)V # draw top-edge seeker ++ + .line 172 + sget-object v0, Landroidx/compose/foundation/layout/ColumnScopeInstance;->INSTANCE:Landroidx/compose/foundation/layout/ColumnScopeInstance; +