Merge pull request #87 from meowarex/dev

Refactor Backdrop <3
This commit is contained in:
meowarex
2026-08-14 16:55:38 +00:00
12 changed files with 97 additions and 126 deletions
+12
View File
@@ -6,6 +6,8 @@ on:
- main
paths-ignore:
- "**/*.md"
# Lets a release be re-run by hand from the Actions tab if a push event is ever missed.
workflow_dispatch:
jobs:
Version:
@@ -23,6 +25,16 @@ jobs:
BASE=$(cat .version | tr -d '[:space:]')
echo "version=$BASE" >> $GITHUB_OUTPUT
# Releasing onto an existing tag silently overwrites that release's assets, so a
# forgotten .version bump replaces history instead of publishing. Fail loudly instead.
# ls-remote, not rev-parse: actions/checkout does not fetch tags by default,
# so a local lookup would always miss and the guard would never fire.
if git ls-remote --exit-code --tags origin "refs/tags/v$BASE" >/dev/null 2>&1; then
echo "::error::Tag v$BASE already exists - bump .version before releasing." \
"Re-running this workflow as-is would overwrite the v$BASE release assets."
exit 1
fi
Build:
needs: Version
uses: ./.github/workflows/build.yml
+1 -1
View File
@@ -1 +1 @@
1.1.1
1.1.4
+2 -2
View File
@@ -31,8 +31,8 @@ android {
defaultConfig {
minSdk = 24
targetSdk = 36
versionCode = 63
versionName = "1.1.1"
versionCode = 66
versionName = "1.1.4"
vectorDrawables {
useSupportLibrary = true
+1 -1
View File
@@ -1,5 +1,5 @@
{
"tidalVersionCode": 10004,
"tidalApkUrl": "https://github.com/meowarex/rl-mobile/releases/download/latest/tidal-stock.apk",
"patchesVersion": "1.2.1"
"patchesVersion": "1.2.4"
}
+35 -17
View File
@@ -34,12 +34,12 @@
.field private volatile coverToken:I
.field private volatile darkenBrightness:F
.field private volatile dithering:F
.field private lastFrameUptime:J
.field private volatile nextDarken:F
.field private volatile nextShader:Landroid/graphics/BitmapShader;
.field private final paint:Landroid/graphics/Paint;
@@ -50,6 +50,8 @@
.field private volatile playing:Z
.field private volatile prevDarken:F
.field private volatile prevShader:Landroid/graphics/BitmapShader;
.field private volatile saturation:F
@@ -155,7 +157,9 @@
iput-object v1, p0, Ldev/kawarp/KawarpEngine;->paint:Landroid/graphics/Paint;
iput v0, p0, Ldev/kawarp/KawarpEngine;->darkenBrightness:F
iput v0, p0, Ldev/kawarp/KawarpEngine;->prevDarken:F
iput v0, p0, Ldev/kawarp/KawarpEngine;->nextDarken:F
iput v0, p0, Ldev/kawarp/KawarpEngine;->speedFactor:F
@@ -163,7 +167,7 @@
move-result v0
if-eqz v0, :cond_55
if-eqz v0, :cond_57
new-instance v0, Landroid/graphics/RuntimeShader;
@@ -175,7 +179,7 @@
return-void
:cond_55
:cond_57
new-instance v0, Ljava/lang/IllegalStateException;
const-string v1, "KawarpEngine needs API 33+ (AGSL)"
@@ -738,11 +742,15 @@
iput-object v1, v0, Ldev/kawarp/KawarpEngine;->nextShader:Landroid/graphics/BitmapShader;
iget v1, v0, Ldev/kawarp/KawarpEngine;->nextDarken:F
iput v1, v0, Ldev/kawarp/KawarpEngine;->prevDarken:F
invoke-direct {v0, v12}, Ldev/kawarp/KawarpEngine;->brightnessFor(F)F
move-result v1
iput v1, v0, Ldev/kawarp/KawarpEngine;->darkenBrightness:F
iput v1, v0, Ldev/kawarp/KawarpEngine;->nextDarken:F
invoke-static {}, Landroid/os/SystemClock;->uptimeMillis()J
@@ -760,19 +768,19 @@
iget-object v0, p0, Ldev/kawarp/KawarpEngine;->nextShader:Landroid/graphics/BitmapShader;
if-eqz v0, :cond_ee
if-eqz v0, :cond_f5
const/4 v1, 0x0
cmpg-float v2, p2, v1
if-lez v2, :cond_ee
if-lez v2, :cond_f5
cmpg-float v2, p3, v1
if-gtz v2, :cond_f
goto/16 :goto_ee
goto/16 :goto_f5
:cond_f
invoke-static {}, Landroid/os/SystemClock;->uptimeMillis()J
@@ -976,17 +984,27 @@
invoke-virtual {v0, v1, v2}, Landroid/graphics/RuntimeShader;->setFloatUniform(Ljava/lang/String;F)V
iget-object v0, p0, Ldev/kawarp/KawarpEngine;->shader:Landroid/graphics/RuntimeShader;
iget v0, p0, Ldev/kawarp/KawarpEngine;->prevDarken:F
iget v1, p0, Ldev/kawarp/KawarpEngine;->brightness:F
iget v1, p0, Ldev/kawarp/KawarpEngine;->nextDarken:F
iget v2, p0, Ldev/kawarp/KawarpEngine;->darkenBrightness:F
iget v2, p0, Ldev/kawarp/KawarpEngine;->prevDarken:F
mul-float/2addr v1, v2
sub-float/2addr v1, v2
const-string v2, "uBright"
mul-float/2addr v1, v6
invoke-virtual {v0, v2, v1}, Landroid/graphics/RuntimeShader;->setFloatUniform(Ljava/lang/String;F)V
add-float/2addr v0, v1
iget-object v1, p0, Ldev/kawarp/KawarpEngine;->shader:Landroid/graphics/RuntimeShader;
iget v2, p0, Ldev/kawarp/KawarpEngine;->brightness:F
mul-float/2addr v2, v0
const-string v0, "uBright"
invoke-virtual {v1, v0, v2}, Landroid/graphics/RuntimeShader;->setFloatUniform(Ljava/lang/String;F)V
iget-object v0, p0, Ldev/kawarp/KawarpEngine;->shader:Landroid/graphics/RuntimeShader;
@@ -1020,8 +1038,8 @@
return p1
:cond_ee
:goto_ee
:cond_f5
:goto_f5
const/4 p1, 0x0
return p1
+1 -25
View File
@@ -5,9 +5,6 @@
# static fields
.field public static volatile currentAlbumId:I
# 2 = Stock (TIDAL's blurred cover, follows live play state), 3 = Kawarp (AGSL shader)
.field public static volatile mode:I
# Live play state from the mini-player (t.c PlayState = Playing)
.field public static isPlayingState:Landroidx/compose/runtime/MutableState;
.annotation system Ldalvik/annotation/Signature;
@@ -38,10 +35,6 @@
sput v0, Lradiant/HomeBackdrop;->currentAlbumId:I
const/4 v0, 0x2
sput v0, Lradiant/HomeBackdrop;->mode:I
sget-object v0, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean;
const/4 v1, 0x0
@@ -73,16 +66,6 @@
return-void
.end method
.method public static setModePlayback()V
.locals 1
const/4 v0, 0x2
sput v0, Lradiant/HomeBackdrop;->mode:I
return-void
.end method
# from the mini-player state ctor (t.<init>) whenever play state changes.
.method public static onPlayState(Lcom/tidal/android/feature/appscaffold/ui/MiniPlayerContract$PlayState;)V
.locals 2
@@ -358,13 +341,7 @@
move-object v9, v1 # v9 = cover uuid
# v10 = isPlaying, mirrored from the Player Backdrop variant
sget v10, Lradiant/HomeBackdrop;->mode:I
const/4 v11, 0x2
if-ne v10, v11, :rl_mode_done
# v10 = isPlaying, straight from the live mini-player state (both modes follow it)
sget-object v10, Lradiant/HomeBackdrop;->isPlayingState:Landroidx/compose/runtime/MutableState;
invoke-interface {v10}, Landroidx/compose/runtime/State;->getValue()Ljava/lang/Object;
@@ -377,7 +354,6 @@
move-result v10
:rl_mode_done
const/4 v11, 0x0 # v11 = isSeeking = false
const/4 v12, 0x0 # v12 = progress callback = null (unused while not seeking)
+13 -21
View File
@@ -22,7 +22,7 @@
.field private static frameScheduled:Z
.field private static final frameState:Landroidx/compose/runtime/MutableState;
.field private static final frameState:Landroidx/compose/runtime/MutableIntState;
.field private static frameTick:I
@@ -53,23 +53,19 @@
const/4 v0, 0x0
invoke-static {v0}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;
invoke-static {v0}, Landroidx/compose/runtime/SnapshotIntStateKt;->mutableIntStateOf(I)Landroidx/compose/runtime/MutableIntState;
move-result-object v1
const/4 v2, 0x0
const/4 v3, 0x2
invoke-static {v1, v2, v3, v2}, Landroidx/compose/runtime/SnapshotStateKt;->mutableStateOf$default(Ljava/lang/Object;Landroidx/compose/runtime/SnapshotMutationPolicy;ILjava/lang/Object;)Landroidx/compose/runtime/MutableState;
move-result-object v1
sput-object v1, Lradiant/Kawarp;->frameState:Landroidx/compose/runtime/MutableState;
sput-object v1, Lradiant/Kawarp;->frameState:Landroidx/compose/runtime/MutableIntState;
sget-object v1, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean;
invoke-static {v1, v2, v3, v2}, Landroidx/compose/runtime/SnapshotStateKt;->mutableStateOf$default(Ljava/lang/Object;Landroidx/compose/runtime/SnapshotMutationPolicy;ILjava/lang/Object;)Landroidx/compose/runtime/MutableState;
const/4 v2, 0x2
const/4 v3, 0x0
invoke-static {v1, v3, v2, v3}, Landroidx/compose/runtime/SnapshotStateKt;->mutableStateOf$default(Ljava/lang/Object;Landroidx/compose/runtime/SnapshotMutationPolicy;ILjava/lang/Object;)Landroidx/compose/runtime/MutableState;
move-result-object v1
@@ -77,7 +73,7 @@
new-instance v1, Lradiant/Kawarp;
invoke-direct {v1, v2, v0}, Lradiant/Kawarp;-><init>(Ljava/lang/String;I)V
invoke-direct {v1, v3, v0}, Lradiant/Kawarp;-><init>(Ljava/lang/String;I)V
sput-object v1, Lradiant/Kawarp;->DRAW:Lradiant/Kawarp;
@@ -107,9 +103,9 @@
.method private static draw(Landroidx/compose/ui/graphics/drawscope/DrawScope;)V
.registers 6
sget-object v0, Lradiant/Kawarp;->frameState:Landroidx/compose/runtime/MutableState;
sget-object v0, Lradiant/Kawarp;->frameState:Landroidx/compose/runtime/MutableIntState;
invoke-interface {v0}, Landroidx/compose/runtime/MutableState;->getValue()Ljava/lang/Object;
invoke-interface {v0}, Landroidx/compose/runtime/MutableIntState;->getIntValue()I
invoke-static {}, Landroid/os/SystemClock;->uptimeMillis()J
@@ -610,7 +606,7 @@
return-void
:cond_11
sget-object p1, Lradiant/Kawarp;->frameState:Landroidx/compose/runtime/MutableState;
sget-object p1, Lradiant/Kawarp;->frameState:Landroidx/compose/runtime/MutableIntState;
sget p2, Lradiant/Kawarp;->frameTick:I
@@ -618,11 +614,7 @@
sput p2, Lradiant/Kawarp;->frameTick:I
invoke-static {p2}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer;
move-result-object p2
invoke-interface {p1, p2}, Landroidx/compose/runtime/MutableState;->setValue(Ljava/lang/Object;)V
invoke-interface {p1, p2}, Landroidx/compose/runtime/MutableIntState;->setIntValue(I)V
invoke-static {}, Lradiant/Kawarp;->schedule()V
+12 -51
View File
@@ -1,11 +1,9 @@
--- a/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali
+++ b/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali
@@ -4613,8 +4613,10 @@
@@ -4613,8 +4613,8 @@
move-object/from16 v25, v10
+ invoke-static {}, Lradiant/HomeBackdrop;->setModeKawarp()V # RL: mirror the mode to Cover Everywhere
+
.line 171
- invoke-static/range {v16 .. v26}, Lcom/tidal/android/feature/playerscreen/ui/composables/p3;->b(Lcom/tidal/android/feature/playerscreen/ui/model/PlayerBackgroundStyle;JILjava/lang/String;ZZLam0/a;Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)V
+ invoke-static/range {v16 .. v26}, Lradiant/Kawarp;->b(Lcom/tidal/android/feature/playerscreen/ui/model/PlayerBackgroundStyle;JILjava/lang/String;ZZLam0/a;Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)V
@@ -27,53 +25,16 @@
.line 7
--- a/radiant/HomeBackdrop.smali
+++ b/radiant/HomeBackdrop.smali
@@ -83,6 +83,16 @@
return-void
.end method
+.method public static setModeKawarp()V
+ .locals 1
+
+ const/4 v0, 0x3
+
+ sput v0, Lradiant/HomeBackdrop;->mode:I
+
+ return-void
+.end method
+
# from the mini-player state ctor (t.<init>) whenever play state changes.
.method public static onPlayState(Lcom/tidal/android/feature/appscaffold/ui/MiniPlayerContract$PlayState;)V
.locals 2
@@ -363,8 +373,13 @@
const/4 v11, 0x2
+ if-eq v10, v11, :rl_live_play
+
+ const/4 v11, 0x3 # RL: Kawarp follows live play state as well
+
if-ne v10, v11, :rl_mode_done
+ :rl_live_play
sget-object v10, Lradiant/HomeBackdrop;->isPlayingState:Landroidx/compose/runtime/MutableState;
invoke-interface {v10}, Landroidx/compose/runtime/State;->getValue()Ljava/lang/Object;
@@ -378,6 +393,18 @@
move-result v10
:rl_mode_done
+ # RL: Kawarp renders its own AGSL backdrop rather than TIDAL's blurred cover
+ sget v11, Lradiant/HomeBackdrop;->mode:I
+
+ const/4 v12, 0x3
+
+ if-ne v11, v12, :rl_native_backdrop
+
+ invoke-static {v8, v9, v10, v13, v0}, Lradiant/Kawarp;->render(ILjava/lang/String;ZLandroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;)V
+
+ goto :skip
+
+ :rl_native_backdrop
const/4 v11, 0x0 # v11 = isSeeking = false
@@ -358,11 +358,7 @@
const/4 v12, 0x0 # v12 = progress callback = null (unused while not seeking)
- move-object v14, v0 # v14 = composer
-
- const/4 v15, 0x0 # v15 = changed flags
-
- invoke-static/range {v8 .. v15}, Lcom/tidal/android/feature/playerscreen/ui/composables/p3;->a(ILjava/lang/String;ZZLam0/a;Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)V
+ invoke-static {v8, v9, v10, v13, v0}, Lradiant/Kawarp;->render(ILjava/lang/String;ZLandroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;)V # RL: Radiant AGSL backdrop
:skip
invoke-interface {v0}, Landroidx/compose/runtime/Composer;->endReplaceGroup()V
+1 -3
View File
@@ -1,12 +1,10 @@
--- a/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali
+++ b/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali
@@ -4433,6 +4433,10 @@
@@ -4433,6 +4433,8 @@
move-object/from16 v25, v10
+ sget-object v16, Lcom/tidal/android/feature/playerscreen/ui/model/PlayerBackgroundStyle;->DARK_BLUR:Lcom/tidal/android/feature/playerscreen/ui/model/PlayerBackgroundStyle; # RL: force native Blur player background
+
+ invoke-static {}, Lradiant/HomeBackdrop;->setModePlayback()V # RL: mirror rotation to Cover Everywhere
+
.line 171
invoke-static/range {v16 .. v26}, Lcom/tidal/android/feature/playerscreen/ui/composables/p3;->b(Lcom/tidal/android/feature/playerscreen/ui/model/PlayerBackgroundStyle;JILjava/lang/String;ZZLam0/a;Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)V
+10 -5
View File
@@ -9,6 +9,8 @@ import android.view.Choreographer;
import androidx.compose.foundation.layout.SizeKt;
import androidx.compose.foundation.layout.SpacerKt;
import androidx.compose.runtime.Composer;
import androidx.compose.runtime.MutableIntState;
import androidx.compose.runtime.SnapshotIntStateKt;
import androidx.compose.runtime.MutableState;
import androidx.compose.runtime.SnapshotStateKt;
import androidx.compose.ui.Modifier;
@@ -56,9 +58,12 @@ public final class Kawarp implements am0.l, Runnable, Choreographer.FrameCallbac
private static final ExecutorService LOADER = Executors.newSingleThreadExecutor();
/** Bumped every frame so the draw lambda's snapshot read invalidates the draw phase. */
private static final MutableState frameState =
SnapshotStateKt.mutableStateOf$default(Integer.valueOf(0), null, 2, null);
/**
* Bumped every frame so the draw lambda's snapshot read invalidates the draw phase.
* An int state rather than MutableState<Integer>: this ticks at 60 Hz, and boxing here
* would allocate an Integer per frame for nothing.
*/
private static final MutableIntState frameState = SnapshotIntStateKt.mutableIntStateOf(0);
/** Flips true on any shader failure; read during composition so we recompose onto p3.a. */
private static final MutableState fallbackState =
SnapshotStateKt.mutableStateOf$default(Boolean.FALSE, null, 2, null);
@@ -186,7 +191,7 @@ public final class Kawarp implements am0.l, Runnable, Choreographer.FrameCallbac
frameScheduled = false;
// Nothing has drawn for a while: the backdrop is off-screen, so stop burning frames.
if (SystemClock.uptimeMillis() - lastDrawUptime > IDLE_STOP_MS) return;
frameState.setValue(Integer.valueOf(++frameTick));
frameState.setIntValue(++frameTick);
schedule();
}
@@ -203,7 +208,7 @@ public final class Kawarp implements am0.l, Runnable, Choreographer.FrameCallbac
private static void draw(DrawScope scope) {
// Snapshot read: this is what ties the draw phase to the frame clock.
frameState.getValue();
frameState.getIntValue();
lastDrawUptime = SystemClock.uptimeMillis();
schedule();
@@ -0,0 +1,5 @@
package androidx.compose.runtime;
public interface MutableIntState extends State {
int getIntValue();
void setIntValue(int value);
}
@@ -0,0 +1,4 @@
package androidx.compose.runtime;
public final class SnapshotIntStateKt {
public static MutableIntState mutableIntStateOf(int value) { return null; }
}