From 09f6e8d34f0af2286015cf33a4dafe7c2a085fa6 Mon Sep 17 00:00:00 2001 From: Se7en-dev Date: Thu, 25 Jun 2026 21:58:27 +0200 Subject: [PATCH] feat(mini player gestures): enable drag option --- .../ui/screens/patchopts/KnownPatch.kt | 8 +++++ .../ui/screens/patchopts/PatchOption.kt | 2 ++ .../ui/screens/patchopts/PatchOptions.kt | 16 +++++++--- .../ui/screens/patchopts/PatchSpec.kt | 3 ++ Manager/app/src/main/res/values/strings.xml | 2 ++ patches/data.json | 2 +- .../radiant/MiniPlayerGestures$Gesture.smali | 29 ++++++++++++++++- .../radiant/MiniPlayerGestures.smali | 4 +-- patches/manifest.json | 9 ++++++ patches/mini-player-gestures.patch | 32 ++++++++++--------- 10 files changed, 84 insertions(+), 23 deletions(-) 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 5d2ec5d..6566c49 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 @@ -197,6 +197,14 @@ enum class KnownPatch( "radiant/MiniPlayerGestures\$ApplyPending.smali", ), ), + PatchOption.Toggle( + key = "swipe_up_drag", + titleRes = R.string.patch_mini_player_drag_title, + descRes = R.string.patch_mini_player_drag_desc, + default = true, + requiresOption = "gestures", + token = "RL_MINI_PLAYER_SWIPE_UP_DRAG", + ), // Swipe left/right to skip PatchOption.Toggle( key = "next_prev", diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/PatchOption.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/PatchOption.kt index b32a26e..b8d24bf 100644 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/PatchOption.kt +++ b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/PatchOption.kt @@ -32,6 +32,8 @@ sealed interface PatchOption { val hidesVariants: List = emptyList(), /** Variant title overrides (index -> @StringRes) applied while this toggle is on. */ val relabelVariants: Map = emptyMap(), + /** Placeholder name (without the surrounding `__`) baked into the `.patch` files. */ + val token: String? = null, ) : PatchOption /** A continuous (or stepped) numeric value within [valueRange]. */ 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 0676722..f9069b9 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 @@ -111,10 +111,18 @@ data class PatchOptions( for (spec in specs) { if (!isEnabled(spec)) continue for (option in spec.advancedOptions) { - if (option !is OptionSpec.Slider) continue - val token = option.token ?: continue - val encode = option.encode ?: continue - put("__${token}__", encode.encode(sliderValue(spec, option))) + when (option) { + is OptionSpec.Toggle -> { + val token = option.token ?: continue + put("__${token}__", if (isToggleActive(spec, option)) "0x1" else "0x0") + } + is OptionSpec.Slider -> { + val token = option.token ?: continue + val encode = option.encode ?: continue + put("__${token}__", encode.encode(sliderValue(spec, option))) + } + is OptionSpec.Choice -> Unit + } } } } 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 03a7780..223b8c2 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 @@ -68,6 +68,8 @@ sealed interface OptionSpec { val hidesVariants: List = emptyList(), /** Variant title overrides (index -> title) applied while this toggle is on. */ val relabelVariants: Map = emptyMap(), + /** Placeholder name (without the surrounding `__`) baked into the `.patch` files. */ + val token: String? = null, ) : OptionSpec @Immutable @@ -162,6 +164,7 @@ private fun PatchOption.toSpec(resolve: (Int) -> String): OptionSpec = when (thi requiresOption = requiresOption, hidesVariants = hidesVariants, relabelVariants = relabelVariants.mapValues { resolve(it.value) }, + token = token, ) is PatchOption.Slider -> OptionSpec.Slider( diff --git a/Manager/app/src/main/res/values/strings.xml b/Manager/app/src/main/res/values/strings.xml index 9b7c46e..4cbdea0 100644 --- a/Manager/app/src/main/res/values/strings.xml +++ b/Manager/app/src/main/res/values/strings.xml @@ -295,6 +295,8 @@ Integrates the Seekbar into the control panel at the bottom of the screen. Mini-Player Gestures Swipe up on the mini-player to open the full player. + Enable Drag + Makes player follow your finger when swiping up. Disable if Android gesture navigation conflicts. Next/Previous Gestures Swipe left or right on the mini-player to skip tracks. Mini-Player Dynamic Background diff --git a/patches/data.json b/patches/data.json index d4af060..1ea66ae 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.12" + "patchesVersion": "0.9.13" } diff --git a/patches/extension/radiant/MiniPlayerGestures$Gesture.smali b/patches/extension/radiant/MiniPlayerGestures$Gesture.smali index f7b00e2..8f1a181 100644 --- a/patches/extension/radiant/MiniPlayerGestures$Gesture.smali +++ b/patches/extension/radiant/MiniPlayerGestures$Gesture.smali @@ -38,9 +38,12 @@ # True once horizontal movement wins (prevents later vertical start) .field public j:Z +# Drag option enabled +.field public final k:Z + # direct methods -.method public constructor (Lyl0/l;Landroidx/compose/material3/SheetState;)V +.method public constructor (Lyl0/l;Landroidx/compose/material3/SheetState;Z)V .locals 0 invoke-direct {p0}, Ljava/lang/Object;->()V @@ -49,6 +52,8 @@ iput-object p2, p0, Lradiant/MiniPlayerGestures$Gesture;->f:Landroidx/compose/material3/SheetState; + iput-boolean p3, p0, Lradiant/MiniPlayerGestures$Gesture;->k:Z + return-void .end method @@ -150,6 +155,10 @@ iput-boolean v0, p0, Lradiant/MiniPlayerGestures$Gesture;->e:Z + iget-boolean v0, p0, Lradiant/MiniPlayerGestures$Gesture;->k:Z + + if-eqz v0, :done + iget-object v1, p0, Lradiant/MiniPlayerGestures$Gesture;->f:Landroidx/compose/material3/SheetState; iget v0, p0, Lradiant/MiniPlayerGestures$Gesture;->b:F @@ -158,6 +167,7 @@ invoke-direct {p0}, Lradiant/MiniPlayerGestures$Gesture;->openPlayer()V + :done return-void .end method @@ -253,6 +263,10 @@ if-eqz v3, :maybe_start + iget-boolean v3, p0, Lradiant/MiniPlayerGestures$Gesture;->k:Z + + if-eqz v3, :store_last + invoke-direct {p0, v2, v5, v6}, Lradiant/MiniPlayerGestures$Gesture;->dragSheet(FJ)V goto :store_last @@ -329,6 +343,10 @@ :begin invoke-direct {p0, v2, v5, v6}, Lradiant/MiniPlayerGestures$Gesture;->startSheet(FJ)V + iget-boolean v10, p0, Lradiant/MiniPlayerGestures$Gesture;->k:Z + + if-eqz v10, :store_last + invoke-direct {p0, v2, v5, v6}, Lradiant/MiniPlayerGestures$Gesture;->dragSheet(FJ)V @@ -347,6 +365,10 @@ if-eqz v0, :finish + iget-boolean v0, p0, Lradiant/MiniPlayerGestures$Gesture;->k:Z + + if-eqz v0, :open_simple + invoke-static {p1}, Lradiant/MiniPlayerGestures;->trackMotion(Landroid/view/MotionEvent;)V invoke-virtual {p1}, Landroid/view/MotionEvent;->getRawY()F @@ -367,6 +389,11 @@ invoke-direct {p0, v0}, Lradiant/MiniPlayerGestures$Gesture;->finishSheet(F)V + goto :finish + + :open_simple + invoke-direct {p0}, Lradiant/MiniPlayerGestures$Gesture;->openPlayer()V + :finish invoke-direct {p0}, Lradiant/MiniPlayerGestures$Gesture;->reset()V diff --git a/patches/extension/radiant/MiniPlayerGestures.smali b/patches/extension/radiant/MiniPlayerGestures.smali index 2be4df3..c09e4d7 100644 --- a/patches/extension/radiant/MiniPlayerGestures.smali +++ b/patches/extension/radiant/MiniPlayerGestures.smali @@ -535,12 +535,12 @@ return p0 .end method -.method public static modifier(Landroidx/compose/ui/Modifier;Lyl0/l;Landroidx/compose/material3/SheetState;)Landroidx/compose/ui/Modifier; +.method public static modifier(Landroidx/compose/ui/Modifier;Lyl0/l;Landroidx/compose/material3/SheetState;Z)Landroidx/compose/ui/Modifier; .locals 1 new-instance v0, Lradiant/MiniPlayerGestures$Gesture; - invoke-direct {v0, p1, p2}, Lradiant/MiniPlayerGestures$Gesture;->(Lyl0/l;Landroidx/compose/material3/SheetState;)V + invoke-direct {v0, p1, p2, p3}, Lradiant/MiniPlayerGestures$Gesture;->(Lyl0/l;Landroidx/compose/material3/SheetState;Z)V invoke-static {p0, v0}, Landroidx/compose/ui/input/pointer/PointerInteropFilter_androidKt;->motionEventSpy(Landroidx/compose/ui/Modifier;Lyl0/l;)Landroidx/compose/ui/Modifier; diff --git a/patches/manifest.json b/patches/manifest.json index 273f80d..ee91d50 100644 --- a/patches/manifest.json +++ b/patches/manifest.json @@ -173,6 +173,15 @@ "radiant/MiniPlayerGestures$ApplyPending.smali" ] }, + { + "type": "toggle", + "key": "swipe_up_drag", + "title": "Enable Drag", + "description": "Makes player follow your finger when swiping up. Disable if Android gesture navigation conflicts.", + "default": true, + "requiresOption": "gestures", + "token": "RL_MINI_PLAYER_SWIPE_UP_DRAG" + }, { "type": "toggle", "key": "next_prev", diff --git a/patches/mini-player-gestures.patch b/patches/mini-player-gestures.patch index b9af323..7efb2b4 100644 --- a/patches/mini-player-gestures.patch +++ b/patches/mini-player-gestures.patch @@ -1,6 +1,19 @@ --- a/com/tidal/android/feature/appscaffold/ui/composable/i.smali +++ b/com/tidal/android/feature/appscaffold/ui/composable/i.smali -@@ -2832,27 +2832,5 @@ +@@ -2427,6 +2427,12 @@ + move-object/from16 v16, v9 + + .line 99 ++ move-object/from16 v9, v25 # SheetState ++ ++ invoke-static {v5, v6, v9}, Lradiant/MiniPlayerGestures;->rootModifier(Landroidx/compose/ui/Modifier;Lyl0/l;Landroidx/compose/material3/SheetState;)Landroidx/compose/ui/Modifier; # continue drag after player recomposition ++ ++ move-result-object v5 ++ + invoke-static {v15, v5}, Landroidx/compose/ui/ComposedModifierKt;->materializeModifier(Landroidx/compose/runtime/Composer;Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier; + + move-result-object v9 +@@ -2832,27 +2838,7 @@ - .line 150 - sget-object v8, Lkotlin/u;->a:Lkotlin/u; - @@ -28,22 +41,11 @@ - invoke-static {v0, v8, v10}, Landroidx/compose/ui/input/pointer/SuspendingPointerInputFilterKt;->pointerInput(Landroidx/compose/ui/Modifier;Ljava/lang/Object;Landroidx/compose/ui/input/pointer/PointerInputEventHandler;)Landroidx/compose/ui/Modifier; + move-object/from16 v8, v25 # SheetState from AppScaffold + -+ invoke-static {v0, v6, v8}, Lradiant/MiniPlayerGestures;->modifier(Landroidx/compose/ui/Modifier;Lyl0/l;Landroidx/compose/material3/SheetState;)Landroidx/compose/ui/Modifier; # attach swipe up listener ++ const/4 v10, __RL_MINI_PLAYER_SWIPE_UP_DRAG__ # Enable Drag option ++ ++ invoke-static {v0, v6, v8, v10}, Lradiant/MiniPlayerGestures;->modifier(Landroidx/compose/ui/Modifier;Lyl0/l;Landroidx/compose/material3/SheetState;Z)Landroidx/compose/ui/Modifier; # attach swipe up listener move-result-object v0 -@@ -2427,6 +2406,12 @@ - move-object/from16 v16, v9 - - .line 99 -+ move-object/from16 v9, v25 # same SheetState used by the modal sheet -+ -+ invoke-static {v5, v6, v9}, Lradiant/MiniPlayerGestures;->rootModifier(Landroidx/compose/ui/Modifier;Lyl0/l;Landroidx/compose/material3/SheetState;)Landroidx/compose/ui/Modifier; # continue drag after player recomposition -+ -+ move-result-object v5 -+ - invoke-static {v15, v5}, Landroidx/compose/ui/ComposedModifierKt;->materializeModifier(Landroidx/compose/runtime/Composer;Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier; - - move-result-object v9 --- a/com/tidal/android/feature/appscaffold/ui/composable/MiniPlayerKt.smali +++ b/com/tidal/android/feature/appscaffold/ui/composable/MiniPlayerKt.smali