Compare commits

...
23 Commits
Author SHA1 Message Date
meoware.exe 4911e7703d Merge pull request #66 from meowarex/dev
Nav Bar Color Hotfix <3
2026-07-06 14:25:27 +10:00
meoware.exe f9a174eafa Nav Bar Color Hotfix <3 2026-07-06 14:24:51 +10:00
meoware.exe 49fe4c0d91 Merge pull request #65 from meowarex/dev
APK Bump + Offline Support + Playing From
2026-07-05 23:03:16 +10:00
meoware.exe 189e3d28a2 Offline Repatch + Force Incompatible (Dev Option) 2026-07-05 23:00:14 +10:00
meoware.exe aae2f54fab Update APK Version & Add Playing From 2026-07-05 20:58:22 +10:00
meoware.exe 191dcca239 Merge pull request #64 from meowarex/dev
Waze Integration + Integrations UI <3
2026-07-03 20:20:14 +10:00
meoware.exe 08aee155c9 Integrations UI + Package Name Warnings/Gate <3 2026-07-03 20:19:16 +10:00
meoware.exe 47c9c37236 Merge pull request #63 from Se7en-dev/feat/waze-support-patch
[PATCH] Waze Integration
2026-07-03 15:46:39 +10:00
Se7en-dev 50b99b6193 feat(waze patch): customizable themeColor 2026-07-02 22:56:09 +02:00
Se7en-dev 03271bf26d feat(waze patch): Tidal cyan accent color for waze 2026-07-02 20:44:24 +02:00
Se7en-dev 75f8187526 feat(waze patch): waze media menu browse source options 2026-07-02 20:26:12 +02:00
Se7en-dev 523f0a342b feat(patch): waze integration patch 2026-07-02 15:49:18 +02:00
meoware.exe fb4c776c61 Merge pull request #60 from meowarex/dev
Fold Cover Everywhere -> Player Backdrop
2026-06-26 23:02:05 +10:00
meoware.exe cbf04d9fa7 Fold Cover Everywhere -> Player Backdrop 2026-06-26 23:01:26 +10:00
meoware.exe 266cd184dd Merge pull request #59 from meowarex/dev
Improve Swipe Gstures <3
2026-06-26 22:38:36 +10:00
meoware.exe 04ea66acdb Improve Swipe Gstures <3 2026-06-26 22:38:04 +10:00
meoware.exe 22526f4e0b Merge pull request #58 from Se7en-dev/fix/mini-player-gestures-swipe-up-android-gestures-nav-fix
Fix : Mini Player Gestures - Android gesture navigation swipe up gesture fix + enable drag option + visual swipe up feedback
2026-06-26 19:02:36 +10:00
Se7en-dev 5a3ad2df7a fix(MP gestures): axis locking + swipe up feedback reset fixes 2026-06-26 10:59:11 +02:00
Se7en-dev fa99d10134 lint(MP gestures enable drag option): remove now useless text 2026-06-26 00:00:12 +02:00
Se7en-dev 4e8af5960c fix(mini player gestures): scope swipe up gesture to track area 2026-06-25 23:57:46 +02:00
Se7en-dev 09f6e8d34f feat(mini player gestures): enable drag option 2026-06-25 21:58:27 +02:00
meoware.exe 160be11ac4 Merge pull request #55 from meowarex/dev
Improve Patch Option Style <3
2026-06-25 01:28:34 +10:00
meoware.exe 4486e52117 Improve Patch Option Style <3 2026-06-25 01:27:32 +10:00
81 changed files with 3662 additions and 1117 deletions
+10
View File
@@ -228,3 +228,13 @@ fun ProviderFactory.execIgnoreCode(vararg command: String): String = try {
} catch (_: Exception) { } catch (_: Exception) {
"" ""
} }
// Sync Local Cached Assets with Repo Releases to keep them up to date
val syncBundledManifest by tasks.registering(Copy::class) {
val src = rootProject.rootDir.resolve("../patches/manifest.json")
onlyIf { src.exists() }
from(src)
into(layout.projectDirectory.dir("src/main/assets"))
rename { "patches-manifest.json" }
}
tasks.named("preBuild") { dependsOn(syncBundledManifest) }
@@ -0,0 +1,357 @@
{
"version": 1,
"patches": [
{
"id": "EnableLegacyUi",
"order": 10,
"fileNames": [
"enable-legacy-ui.patch"
],
"title": "Enable Legacy UI",
"description": "[This patch will stop working soon] - Replaces the New Compose based UI with the Legacy UI (disables player-market-ui feature flag)",
"default": false,
"requires": [
"DebugMenuUnlock"
],
"disables": [
"LyricsDisableCover",
"LyricsReplaceLyricsButton",
"LyricsReplaceShareButton",
"LyricsRlApi",
"LyricsKeepControlsVisible",
"PlayerBackdrop",
"QualityBadgeColors",
"LyricsProgressPill",
"MiniPlayerRedesign"
]
},
{
"id": "LyricsRlApi",
"order": 20,
"fileNames": [
"lyrics-rl-api.patch",
"lyrics-rl-api-observer.patch"
],
"title": "Radiant Lyrics API - WIP",
"description": "Use Radiant Lyrics API to fetch Lyrics (Higher quality & More providers)",
"default": false
},
{
"id": "PlayerBackdrop",
"order": 30,
"fileNames": [
"player-backdrop.patch"
],
"title": "Player Backdrop",
"description": "Restores the legacy translucent backdrop blur behind the player",
"default": true,
"advancedOptions": [
{
"type": "slider",
"key": "blur_strength",
"title": "Blur Strength",
"description": "How strongly the album art behind the player is blurred",
"default": 50,
"min": 0,
"max": 100,
"steps": 19,
"displayAsPercent": true,
"token": "RL_BLUR_BITS",
"encode": {
"kind": "floatBits",
"scale": 1.8
}
},
{
"type": "slider",
"key": "dimming",
"title": "Backdrop Dimming",
"description": "Darkens the backdrop so the foreground controls stay legible",
"default": 50,
"min": 0,
"max": 100,
"steps": 19,
"displayAsPercent": true,
"token": "RL_SCRIM_ARGB",
"encode": {
"kind": "argbAlpha"
}
},
{
"type": "toggle",
"key": "cover_everywhere",
"title": "Cover Everywhere - WIP",
"description": "Applies the blurred backdrop to every Compose based page (Home & Collection)",
"default": false,
"inline": true,
"fileNames": [
"home-backdrop.patch",
"collection-backdrop.patch",
"cover-capture.patch"
]
}
]
},
{
"id": "QualityBadgeColors",
"order": 36,
"fileNames": [
"player-quality-badge-colors.patch"
],
"title": "Quality Badge Colors",
"description": "Brings color back to the player quality badge.",
"default": true
},
{
"id": "PlayerMovePlayingFrom",
"order": 37,
"fileNames": [
"player-move-playing-from.patch"
],
"extensionFiles": [
"radiant/PlayingFrom.smali"
],
"title": "Playing From",
"description": "Shows the source name (playlist/album/mix) above the track title",
"default": true
},
{
"id": "PlayerOneHanded",
"order": 38,
"fileNames": [
"player-one-handed.patch"
],
"title": "One-Handed Mode",
"description": "Mirrors the bottom player buttons left-to-right for easier one-handed reach.",
"default": false
},
{
"id": "LyricsProgressPill",
"order": 40,
"fileNames": [
"lyrics-progress-pill.patch",
"lyrics-fade-region.patch"
],
"title": "Lyrics Progress Pill",
"description": "Restores the old Track Progress Pill in the top of the Lyrics screen!",
"default": true,
"requires": [
"LyricsDisableCover",
"LyricsReplaceLyricsButton",
"LyricsReplaceShareButton"
]
},
{
"id": "LyricsDisableCover",
"order": 41,
"fileNames": [
"lyrics-disable-cover.patch"
],
"title": "Disable Lyrics Cover",
"description": "Removes the mini track cover from the lyrics screen.",
"default": true
},
{
"id": "LyricsReplaceLyricsButton",
"order": 42,
"fileNames": [
"lyrics-replace-lyrics-button.patch",
"lyrics-sparkle-conditional-visibility.patch"
],
"title": "Replace Lyrics Button",
"description": "Replaces the Lyrics button with the RL Sparkle!",
"default": true
},
{
"id": "LyricsReplaceShareButton",
"order": 43,
"fileNames": [
"lyrics-replace-share-button.patch"
],
"title": "Replace Share Button",
"description": "Replaces the share button with the Tidal Connect button from the top of the screen. (it's in the menu already)",
"default": true
},
{
"id": "MiniPlayerRedesign",
"order": 50,
"fileNames": [],
"title": "Redesigned Mini-Player",
"description": "Integrates the Seekbar into the control panel at the bottom of the screen.",
"default": false,
"defaultVariantIndex": 2,
"variants": [
{
"title": "Floating",
"fileNames": []
},
{
"title": "Grey",
"fileNames": [
"mini-player-grey.patch"
]
},
{
"title": "Black",
"fileNames": [
"mini-player-black.patch"
]
}
],
"advancedOptions": [
{
"type": "toggle",
"key": "dynamic_bg",
"title": "Mini-Player Dynamic Background",
"description": "Colorizes the Mini-Player depending on the currently playing track.",
"default": false,
"inline": true,
"fileNames": [
"mini-player-dynamic-bg.patch"
],
"extensionFiles": [
"radiant/MiniPlayerBackground.smali"
],
"hidesVariants": [
2
],
"relabelVariants": {
"1": "Legacy"
}
},
{
"type": "toggle",
"key": "border",
"title": "Progress Border",
"description": "Draws an animated progress ring around the floating mini-player. Requires the Floating style.",
"default": false,
"requiresVariant": 0,
"fileNames": [
"mini-player-floating-border.patch"
],
"extensionFiles": [
"radiant/MiniSeekerFloating.smali"
]
},
{
"type": "toggle",
"key": "gestures",
"title": "Mini-Player Gestures",
"description": "Adds swipe up gesture to the mini-player to reopen the player",
"default": true,
"fileNames": [
"mini-player-gestures.patch"
],
"extensionFiles": [
"radiant/MiniPlayerGestures.smali",
"radiant/MiniPlayerGestures$Gesture.smali",
"radiant/MiniPlayerGestures$FeedbackLayer.smali",
"radiant/MiniPlayerGestures$FeedbackResetAnimator.smali",
"radiant/MiniPlayerGestures$RootGesture.smali",
"radiant/MiniPlayerGestures$ApplyPending.smali"
]
},
{
"type": "choice",
"key": "swipe_up_drag",
"title": "Swipe Up Style",
"entries": [
"Static",
"Drag"
],
"values": [
"0x0",
"0x1"
],
"defaultIndex": 1,
"requiresOption": "gestures",
"token": "RL_MINI_PLAYER_SWIPE_UP_DRAG"
},
{
"type": "toggle",
"key": "next_prev",
"title": "Next/Previous Gestures",
"description": "Swipe left or right on the mini-player to skip tracks.",
"default": false,
"requiresOption": "gestures",
"fileNames": [
"mini-player-gestures-left-right.patch"
],
"extensionFiles": [
"radiant/MiniPlayerTrackGestures.smali",
"radiant/MiniPlayerTrackGestures$Gesture.smali",
"radiant/MiniPlayerTrackGestures$OffsetLayer.smali",
"radiant/MiniPlayerTrackGestures$ResetAnimator.smali",
"radiant/MiniPlayerTrackGestures$TextDraw.smali",
"com/tidal/android/feature/appscaffold/ui/s$c.smali"
]
}
]
},
{
"id": "LyricsKeepControlsVisible",
"order": 60,
"fileNames": [
"lyrics-keep-controls-visible.patch"
],
"extensionFiles": [
"radiant/LyricsReinitGuard.smali"
],
"title": "Keep Controls Visible",
"description": "Inverts the auto-hide behavior on the lyrics screen, playback controls stay visible by default and only hide when you tap them off. Also stops the open lyrics view from randomly closing when the player re-fetches the same track.",
"default": true
},
{
"id": "WazeIntegration",
"order": 90,
"category": "integration",
"pathLocked": true,
"fileNames": [
"integration-waze-playback.patch"
],
"extensionFiles": [
"radiant/WazeInitReceiver.smali",
"radiant/WazeServiceConnection.smali"
],
"title": "Waze Integration",
"description": "Control TIDAL playback from the Waze app",
"default": true,
"advancedOptions": [
{
"type": "choice",
"key": "browse_root",
"title": "Media Menu",
"entries": [
"Auto Menu",
"Home",
"Recents"
],
"values": [
"ROOT_AUTO",
"HOME_V2::home_page_v2_id",
"RECENTLY_PLAYED::home/pages/CONTINUE_LISTEN_TO/view-all"
],
"defaultIndex": 0,
"token": "RL_WAZE_ROOT_ID"
},
{
"type": "color",
"key": "accent_color",
"title": "Accent Color",
"default": -16747037,
"token": "RL_WAZE_THEME_COLOR"
}
]
},
{
"id": "DebugMenuUnlock",
"order": 100,
"fileNames": [
"debug-menu-unlock.patch"
],
"title": "Unlock Debug Menu",
"description": "Reveals TIDAL's hidden Debug Menu in Settings. (Unlocks Feature Flags & the legacy Debug Options)",
"default": false
}
]
}
@@ -22,7 +22,8 @@ class PathManager(
val patchingDownloadDir = patchingDir.resolve("downloads") val patchingDownloadDir = patchingDir.resolve("downloads")
val cacheDownloadDir = context.cacheDir.resolve("downloads") // Persistent Stash of assets for Offline Repatching
val cacheDownloadDir = patchingDir.resolve("downloads-cache")
val customComponentsDir = patchingDir.resolve("custom") val customComponentsDir = patchingDir.resolve("custom")
@@ -34,11 +35,15 @@ class PathManager(
val patchedApk = patchingWorkingDir.resolve("patched.apk") val patchedApk = patchingWorkingDir.resolve("patched.apk")
// Persistent snapshot of the last successful release fetch (build info + patches asset URL)
val cachedReleaseInfo = patchingDir.resolve("release-info.json")
fun clearCache() { fun clearCache() {
val targets = arrayOf( val targets = arrayOf(
patchingDownloadDir, patchingDownloadDir,
patchingWorkingDir, patchingWorkingDir,
cacheDownloadDir, cacheDownloadDir,
cachedReleaseInfo,
context.cacheDir, context.cacheDir,
) )
for (dir in targets) { for (dir in targets) {
@@ -54,6 +59,16 @@ class PathManager(
.resolve("patches") .resolve("patches")
.resolve("$version.zip") .resolve("$version.zip")
fun hasCachedTidalApk(version: Int, split: String = "base"): Boolean {
val rel = "tidal/$version/$split.apk"
return patchingDownloadDir.resolve(rel).exists() || cacheDownloadDir.resolve(rel).exists()
}
fun hasCachedSmaliPatches(version: SemVer): Boolean {
val rel = "patches/$version.zip"
return patchingDownloadDir.resolve(rel).exists() || cacheDownloadDir.resolve(rel).exists()
}
fun customTidalApks() = customTidalApksDir.listFiles()?.asList() ?: emptyList() fun customTidalApks() = customTidalApksDir.listFiles()?.asList() ?: emptyList()
fun customSmaliPatches() = customPatchesDir.listFiles()?.asList() ?: emptyList() fun customSmaliPatches() = customPatchesDir.listFiles()?.asList() ?: emptyList()
@@ -12,6 +12,8 @@ class PreferencesManager(preferences: SharedPreferences) : BasePreferenceManager
var devMode by booleanPreference("dev_mode", false) var devMode by booleanPreference("dev_mode", false)
var installer by enumPreference<InstallerSetting>("installer", InstallerSetting.PackageInstaller) var installer by enumPreference<InstallerSetting>("installer", InstallerSetting.PackageInstaller)
var keepPatchedApks by booleanPreference("keep_patched_apks", false) var keepPatchedApks by booleanPreference("keep_patched_apks", false)
// Dev: force-apply path-gated ("incompatible") patches even under a non-stock package name
var bypassIncompatible by booleanPreference("bypass_incompatible", false)
var showPlayProtectWarning by booleanPreference("show_play_protect_warning", true) var showPlayProtectWarning by booleanPreference("show_play_protect_warning", true)
var autoUpdateCheck by booleanPreference("auto_update_check", true) var autoUpdateCheck by booleanPreference("auto_update_check", true)
@@ -0,0 +1,32 @@
package com.meowarex.rlmobile.manager
import android.util.Log
import com.meowarex.rlmobile.BuildConfig
import com.meowarex.rlmobile.network.models.RLBuildInfo
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
// Snapshot of the last successful release fetch (build info + patches asset URL)
@Serializable
data class CachedReleaseInfo(
val data: RLBuildInfo,
val patchesAssetUrl: String,
)
object ReleaseInfoCache {
fun load(paths: PathManager, json: Json): CachedReleaseInfo? = try {
paths.cachedReleaseInfo
.takeIf { it.exists() }
?.let { json.decodeFromString<CachedReleaseInfo>(it.readText()) }
} catch (t: Throwable) {
Log.w(BuildConfig.TAG, "Failed to read cached release info", t)
null
}
fun save(paths: PathManager, json: Json, info: CachedReleaseInfo) = try {
paths.cachedReleaseInfo.parentFile?.mkdirs()
paths.cachedReleaseInfo.writeText(json.encodeToString(info))
} catch (t: Throwable) {
Log.w(BuildConfig.TAG, "Failed to cache release info", t)
}
}
@@ -26,11 +26,16 @@ class PatchManifestStep(private val options: PatchOptions) : Step() {
?: throw IllegalArgumentException("No manifest found in APK") ?: throw IllegalArgumentException("No manifest found in APK")
container.log("Patching manifest") container.log("Patching manifest")
val wazeDefault = container.getStep<SmaliPatchStep>().specs
.firstOrNull { it.id == "WazeIntegration" }?.defaultEnabled ?: false
val enableWazeIntegration = options.patchStates["WazeIntegration"] ?: wazeDefault
val patchedManifest = ManifestPatcher.patchManifest( val patchedManifest = ManifestPatcher.patchManifest(
manifestBytes = manifest, manifestBytes = manifest,
packageName = options.packageName, packageName = options.packageName,
appName = options.appName, appName = options.appName,
debuggable = options.debuggable, debuggable = options.debuggable,
enableWazeIntegration = enableWazeIntegration,
) )
container.log("Repacking apk with patched manifest") container.log("Repacking apk with patched manifest")
@@ -1,5 +1,6 @@
package com.meowarex.rlmobile.patcher.steps.patch package com.meowarex.rlmobile.patcher.steps.patch
import android.content.Context
import com.meowarex.rlmobile.R import com.meowarex.rlmobile.R
import com.meowarex.rlmobile.manager.PathManager import com.meowarex.rlmobile.manager.PathManager
import com.meowarex.rlmobile.patcher.StepRunner import com.meowarex.rlmobile.patcher.StepRunner
@@ -10,6 +11,7 @@ import com.meowarex.rlmobile.patcher.steps.download.CopyDependenciesStep
import com.meowarex.rlmobile.patcher.steps.download.DownloadPatchesStep import com.meowarex.rlmobile.patcher.steps.download.DownloadPatchesStep
import com.meowarex.rlmobile.ui.screens.patchopts.PatchManifest import com.meowarex.rlmobile.ui.screens.patchopts.PatchManifest
import com.meowarex.rlmobile.ui.screens.patchopts.PatchOptions import com.meowarex.rlmobile.ui.screens.patchopts.PatchOptions
import com.meowarex.rlmobile.ui.screens.patchopts.PatchSpec
import com.meowarex.rlmobile.ui.screens.patchopts.builtinPatchSpecs import com.meowarex.rlmobile.ui.screens.patchopts.builtinPatchSpecs
import com.android.tools.smali.baksmali.Baksmali import com.android.tools.smali.baksmali.Baksmali
import com.android.tools.smali.baksmali.BaksmaliOptions import com.android.tools.smali.baksmali.BaksmaliOptions
@@ -31,6 +33,10 @@ class SmaliPatchStep(
) : Step(), IDexProvider, KoinComponent { ) : Step(), IDexProvider, KoinComponent {
private val paths: PathManager by inject() private val paths: PathManager by inject()
private val json: Json by inject() private val json: Json by inject()
private val context: Context by inject()
var specs: List<PatchSpec> = emptyList()
private set
override val group = StepGroup.Patch override val group = StepGroup.Patch
override val localizedName = R.string.patch_step_patch_smali override val localizedName = R.string.patch_step_patch_smali
@@ -55,7 +61,7 @@ class SmaliPatchStep(
container.log("Failed to parse manifest.json (${t.message}); using built-in patch specs") container.log("Failed to parse manifest.json (${t.message}); using built-in patch specs")
null null
} }
val specs = manifestSpecs ?: builtinPatchSpecs { "" } specs = manifestSpecs ?: builtinPatchSpecs(context, json)
container.log( container.log(
"Loaded ${specs.size} patch specs from " + "Loaded ${specs.size} patch specs from " +
if (manifestSpecs != null) "manifest.json" else "built-in list" if (manifestSpecs != null) "manifest.json" else "built-in list"
@@ -95,7 +101,19 @@ class SmaliPatchStep(
val entry = zip.openEntry(patchFile) val entry = zip.openEntry(patchFile)
?: throw FileNotFoundException("Missing zip entry: $patchFile") ?: throw FileNotFoundException("Missing zip entry: $patchFile")
out.canonicalFile.parentFile?.mkdirs() out.canonicalFile.parentFile?.mkdirs()
out.writeBytes(entry.read()) var smaliText = entry.read()
.decodeToString()
.replace("\r\n", "\n")
for ((token, value) in substitutions) {
if (smaliText.contains(token)) {
smaliText = smaliText.replace(token, value)
container.log("Applied substitution $token -> $value in $patchFile")
}
}
UNRESOLVED_TOKEN.find(smaliText)?.let { match ->
throw Error("Unresolved option placeholder ${match.value} in $patchFile")
}
out.writeText(smaliText)
container.log("Extracted extension smali: $relative") container.log("Extracted extension smali: $relative")
continue continue
} }
@@ -1,19 +1,30 @@
package com.meowarex.rlmobile.patcher.steps.prepare package com.meowarex.rlmobile.patcher.steps.prepare
import android.app.Application
import android.util.Log
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
import com.meowarex.rlmobile.R import com.meowarex.rlmobile.R
import com.meowarex.rlmobile.manager.CachedReleaseInfo
import com.meowarex.rlmobile.manager.PathManager
import com.meowarex.rlmobile.manager.ReleaseInfoCache
import com.meowarex.rlmobile.network.models.RLBuildInfo import com.meowarex.rlmobile.network.models.RLBuildInfo
import com.meowarex.rlmobile.network.services.RadiantLyricsGithubService import com.meowarex.rlmobile.network.services.RadiantLyricsGithubService
import com.meowarex.rlmobile.network.utils.getOrThrow import com.meowarex.rlmobile.network.utils.getOrThrow
import com.meowarex.rlmobile.patcher.StepRunner import com.meowarex.rlmobile.patcher.StepRunner
import com.meowarex.rlmobile.patcher.steps.StepGroup import com.meowarex.rlmobile.patcher.steps.StepGroup
import com.meowarex.rlmobile.patcher.steps.base.Step import com.meowarex.rlmobile.patcher.steps.base.Step
import com.meowarex.rlmobile.util.isOnline
import kotlinx.serialization.json.Json
import org.koin.core.component.KoinComponent import org.koin.core.component.KoinComponent
import org.koin.core.component.inject import org.koin.core.component.inject
import kotlin.coroutines.cancellation.CancellationException
@Stable @Stable
class FetchInfoStep : Step(), KoinComponent { class FetchInfoStep : Step(), KoinComponent {
private val github: RadiantLyricsGithubService by inject() private val github: RadiantLyricsGithubService by inject()
private val context: Application by inject()
private val paths: PathManager by inject()
private val json: Json by inject()
override val group = StepGroup.Prepare override val group = StepGroup.Prepare
override val localizedName = R.string.patch_step_fetch_info override val localizedName = R.string.patch_step_fetch_info
@@ -25,6 +36,33 @@ class FetchInfoStep : Step(), KoinComponent {
private set private set
override suspend fun execute(container: StepRunner) { override suspend fun execute(container: StepRunner) {
// Fetch the latest release and refresh the cache (when online)
if (context.isOnline()) {
try {
fetchFromRemote(container)
return
} catch (e: CancellationException) {
throw e
} catch (t: Throwable) {
container.log("Failed to fetch latest release: ${Log.getStackTraceString(t)}")
container.log("Falling back to cached release info for a local re-patch")
}
} else {
container.log("No network connection — using cached release info for a local re-patch")
}
val cached = ReleaseInfoCache.load(paths, json)
?: throw IllegalStateException(
"Could not fetch the latest release and no cached release info is available. " +
"Connect to the internet and try again."
)
data = cached.data
patchesAssetUrl = cached.patchesAssetUrl
container.log("Using cached build info: $data")
container.log("Cached patches asset URL: $patchesAssetUrl")
}
private suspend fun fetchFromRemote(container: StepRunner) {
container.log("Fetching latest release from ${RadiantLyricsGithubService.REPO_OWNER}/${RadiantLyricsGithubService.REPO_NAME}") container.log("Fetching latest release from ${RadiantLyricsGithubService.REPO_OWNER}/${RadiantLyricsGithubService.REPO_NAME}")
val release = github.getLatestRelease(force = true).getOrThrow() val release = github.getLatestRelease(force = true).getOrThrow()
@@ -33,14 +71,19 @@ class FetchInfoStep : Step(), KoinComponent {
?.browserDownloadUrl ?.browserDownloadUrl
?: throw IllegalStateException("No ${RadiantLyricsGithubService.DATA_JSON_ASSET_NAME} asset found in latest release ${release.tagName}") ?: throw IllegalStateException("No ${RadiantLyricsGithubService.DATA_JSON_ASSET_NAME} asset found in latest release ${release.tagName}")
patchesAssetUrl = release.assets val patchesUrl = release.assets
.find { it.name == RadiantLyricsGithubService.PATCHES_ASSET_NAME } .find { it.name == RadiantLyricsGithubService.PATCHES_ASSET_NAME }
?.browserDownloadUrl ?.browserDownloadUrl
?: throw IllegalStateException("No ${RadiantLyricsGithubService.PATCHES_ASSET_NAME} asset found in latest release ${release.tagName}") ?: throw IllegalStateException("No ${RadiantLyricsGithubService.PATCHES_ASSET_NAME} asset found in latest release ${release.tagName}")
container.log("Fetching build info from $dataJsonUrl") container.log("Fetching build info from $dataJsonUrl")
data = github.getBuildInfo(dataJsonUrl, force = true).getOrThrow() val buildInfo = github.getBuildInfo(dataJsonUrl, force = true).getOrThrow()
data = buildInfo
patchesAssetUrl = patchesUrl
container.log("Fetched build info: $data") container.log("Fetched build info: $data")
container.log("Patches asset URL: $patchesAssetUrl") container.log("Patches asset URL: $patchesAssetUrl")
ReleaseInfoCache.save(paths, json, CachedReleaseInfo(buildInfo, patchesUrl))
} }
} }
@@ -18,12 +18,16 @@ object ManifestPatcher {
private const val IS_SPLIT_REQUIRED = "isSplitRequired" private const val IS_SPLIT_REQUIRED = "isSplitRequired"
private const val REQUIRED_SPLIT_TYPES = "requiredSplitTypes" private const val REQUIRED_SPLIT_TYPES = "requiredSplitTypes"
private const val SPLIT_TYPES = "splitTypes" private const val SPLIT_TYPES = "splitTypes"
private const val WAZE_PACKAGE = "com.waze"
private const val WAZE_INIT_RECEIVER = "radiant.WazeInitReceiver"
private const val WAZE_ACTION_INIT = "com.waze.sdk.audio.ACTION_INIT"
fun patchManifest( fun patchManifest(
manifestBytes: ByteArray, manifestBytes: ByteArray,
packageName: String, packageName: String,
appName: String, appName: String,
debuggable: Boolean, debuggable: Boolean,
enableWazeIntegration: Boolean,
): ByteArray { ): ByteArray {
// Extract original package name to rewrite every reference to it // Extract original package name to rewrite every reference to it
// (permissions, provider authorities) to the new packageName. // (permissions, provider authorities) to the new packageName.
@@ -84,6 +88,49 @@ object ManifestPatcher {
} }
return when (name) { return when (name) {
"queries" -> object : NodeVisitor(nv) {
private var hasWazePackage = false
override fun child(ns: String?, name: String): NodeVisitor {
val visitor = super.child(ns, name)
return if (enableWazeIntegration && name == "package") {
object : NodeVisitor(visitor) {
override fun attr(
ns: String?,
name: String?,
resourceId: Int,
type: Int,
value: Any?,
) {
if (name == "name" && value == WAZE_PACKAGE) {
hasWazePackage = true
}
super.attr(ns, name, resourceId, type, value)
}
}
} else {
visitor
}
}
override fun end() {
if (enableWazeIntegration && !hasWazePackage) {
super.child(null, "package").apply {
attr(
ANDROID_NAMESPACE,
"name",
android.R.attr.name,
TYPE_STRING,
WAZE_PACKAGE,
)
end()
}
}
super.end()
}
}
"uses-permission" -> object : NodeVisitor(nv) { "uses-permission" -> object : NodeVisitor(nv) {
override fun attr(ns: String?, name: String?, resourceId: Int, type: Int, value: Any?) { override fun attr(ns: String?, name: String?, resourceId: Int, type: Int, value: Any?) {
if (name != "maxSdkVersion") { if (name != "maxSdkVersion") {
@@ -132,6 +179,7 @@ object ManifestPatcher {
private var addUseEmbeddedDex = true private var addUseEmbeddedDex = true
private var addExtractNativeLibs = true private var addExtractNativeLibs = true
private var addMetadata = true private var addMetadata = true
private var hasWazeInitReceiver = false
override fun attr(ns: String?, name: String, resourceId: Int, type: Int, value: Any?) { override fun attr(ns: String?, name: String, resourceId: Int, type: Int, value: Any?) {
if (name == REQUEST_LEGACY_EXTERNAL_STORAGE) addLegacyStorage = false if (name == REQUEST_LEGACY_EXTERNAL_STORAGE) addLegacyStorage = false
@@ -161,6 +209,22 @@ object ManifestPatcher {
return when (name) { return when (name) {
"activity" -> ReplaceAttrsVisitor(visitor, mapOf("label" to appName)) "activity" -> ReplaceAttrsVisitor(visitor, mapOf("label" to appName))
"receiver" -> object : NodeVisitor(visitor) {
override fun attr(
ns: String?,
name: String,
resourceId: Int,
type: Int,
value: Any?
) {
if (name == "name" && value == WAZE_INIT_RECEIVER) {
hasWazeInitReceiver = true
}
super.attr(ns, name, resourceId, type, value)
}
}
"provider" -> object : NodeVisitor(visitor) { "provider" -> object : NodeVisitor(visitor) {
override fun attr( override fun attr(
ns: String?, ns: String?,
@@ -219,6 +283,39 @@ object ManifestPatcher {
0 0
) )
if (enableWazeIntegration && !hasWazeInitReceiver) {
super.child(null, "receiver").apply {
attr(
ANDROID_NAMESPACE,
"name",
android.R.attr.name,
TYPE_STRING,
WAZE_INIT_RECEIVER,
)
attr(
ANDROID_NAMESPACE,
"exported",
android.R.attr.exported,
TYPE_INT_BOOLEAN,
1,
)
child(null, "intent-filter").apply {
child(null, "action").apply {
attr(
ANDROID_NAMESPACE,
"name",
android.R.attr.name,
TYPE_STRING,
WAZE_ACTION_INIT,
)
end()
}
end()
}
end()
}
}
super.end() super.end()
} }
} }
@@ -9,6 +9,7 @@ import com.meowarex.rlmobile.network.utils.SemVer
import com.meowarex.rlmobile.ui.screens.componentopts.PatchComponent import com.meowarex.rlmobile.ui.screens.componentopts.PatchComponent
import com.meowarex.rlmobile.ui.screens.patchopts.* import com.meowarex.rlmobile.ui.screens.patchopts.*
import com.meowarex.rlmobile.ui.theme.ManagerTheme import com.meowarex.rlmobile.ui.theme.ManagerTheme
import kotlinx.serialization.json.Json
import kotlin.time.Clock import kotlin.time.Clock
// This preview has scrollable/interactable content that cannot be tested from an IDE preview // This preview has scrollable/interactable content that cannot be tested from an IDE preview
@@ -21,7 +22,7 @@ private fun PatchOptionsScreenPreview(
parameters: PatchOptionsParameters, parameters: PatchOptionsParameters,
) { ) {
val context = LocalContext.current val context = LocalContext.current
val specs = remember { builtinPatchSpecs { context.getString(it) } } val specs = remember { builtinPatchSpecs(context, Json { ignoreUnknownKeys = true }) }
ManagerTheme { ManagerTheme {
PatchOptionsScreenContent( PatchOptionsScreenContent(
@@ -29,18 +30,22 @@ private fun PatchOptionsScreenPreview(
isDevMode = parameters.isDevMode, isDevMode = parameters.isDevMode,
debuggable = parameters.debuggable, debuggable = parameters.debuggable,
setDebuggable = {}, setDebuggable = {},
bypassIncompatible = false,
setBypassIncompatible = {},
appName = parameters.appName, appName = parameters.appName,
appNameIsError = parameters.appNameIsError, appNameIsError = parameters.appNameIsError,
setAppName = {}, setAppName = {},
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 },
@@ -19,7 +19,9 @@ import cafe.adriel.voyager.core.model.screenModelScope
import com.github.diamondminer88.zip.ZipReader import com.github.diamondminer88.zip.ZipReader
import com.meowarex.rlmobile.BuildConfig import com.meowarex.rlmobile.BuildConfig
import com.meowarex.rlmobile.R import com.meowarex.rlmobile.R
import com.meowarex.rlmobile.manager.PathManager
import com.meowarex.rlmobile.manager.PreferencesManager import com.meowarex.rlmobile.manager.PreferencesManager
import com.meowarex.rlmobile.manager.ReleaseInfoCache
import com.meowarex.rlmobile.network.models.GithubCommit import com.meowarex.rlmobile.network.models.GithubCommit
import com.meowarex.rlmobile.network.models.RLBuildInfo import com.meowarex.rlmobile.network.models.RLBuildInfo
import com.meowarex.rlmobile.network.services.RadiantLyricsGithubService import com.meowarex.rlmobile.network.services.RadiantLyricsGithubService
@@ -42,6 +44,7 @@ class HomeModel(
private val github: RadiantLyricsGithubService, private val github: RadiantLyricsGithubService,
private val json: Json, private val json: Json,
private val prefs: PreferencesManager, private val prefs: PreferencesManager,
private val paths: PathManager,
) : ScreenModel { ) : ScreenModel {
var state by mutableStateOf<HomeState>(HomeState.Loading) var state by mutableStateOf<HomeState>(HomeState.Loading)
@@ -170,16 +173,23 @@ class HomeModel(
refreshingLock.withLock { refreshingLock.withLock {
val pkg = fetchInstalled() val pkg = fetchInstalled()
val remote = async(Dispatchers.IO) { if (remoteDataJson == null) fetchRemoteData() } // Skip the remote fetch entirely when offline
remote.await() val online = application.isOnline()
if (online) {
val remote = async(Dispatchers.IO) { if (remoteDataJson == null) fetchRemoteData() }
remote.await()
}
val install = pkg?.toInstallData() val install = pkg?.toInstallData()
val latest = remoteDataJson?.tidalVersionCode val latest = remoteDataJson?.tidalVersionCode
val offlineRepatchReady = hasOfflineRepatchAssets()
mainThread { mainThread {
state = HomeState.Loaded( state = HomeState.Loaded(
install = install, install = install,
latestTidalVersionCode = latest, latestTidalVersionCode = latest,
offline = !online,
offlineRepatchReady = offlineRepatchReady,
) )
maybeCheckManagerUpdate(pkg) maybeCheckManagerUpdate(pkg)
} }
@@ -257,6 +267,13 @@ class HomeModel(
) )
} }
// check if an offline "Local Repatch" is possible
private fun hasOfflineRepatchAssets(): Boolean {
val info = ReleaseInfoCache.load(paths, json) ?: return false
return paths.hasCachedTidalApk(info.data.tidalVersionCode) &&
paths.hasCachedSmaliPatches(info.data.patchesVersion)
}
private suspend fun fetchRemoteData() { private suspend fun fetchRemoteData() {
val release = try { val release = try {
github.getLatestRelease().fold( github.getLatestRelease().fold(
@@ -210,14 +210,19 @@ private fun ColumnScope.HomeContent(
} }
val blockedByManagerUpdate = managerUpdateAvailable && (patchesBehind || tidalBehind) val blockedByManagerUpdate = managerUpdateAvailable && (patchesBehind || tidalBehind)
val canLocalRepatch = install != null && state.offlineRepatchReady
val onlineEnabled = state.latestTidalVersionCode != null || install != null
val buttonEnabled = !blockedByManagerUpdate && (if (state.offline) canLocalRepatch else onlineEnabled)
Button( Button(
onClick = if (install == null) onInstall else onRepatch, onClick = if (install == null) onInstall else onRepatch,
enabled = state.latestTidalVersionCode != null && !blockedByManagerUpdate, enabled = buttonEnabled,
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
) { ) {
val label = when { val label = when {
blockedByManagerUpdate -> "Manager Update Required" blockedByManagerUpdate -> "Manager Update Required"
state.latestTidalVersionCode == null -> "Loading…" state.offline && install != null -> "Local Repatch"
state.offline -> "No Network"
install == null && state.latestTidalVersionCode == null -> "Loading…"
install == null -> "Install" install == null -> "Install"
patchesBehind && tidalBehind -> "Update Patches & TIDAL" patchesBehind && tidalBehind -> "Update Patches & TIDAL"
patchesBehind -> "Update Patches" patchesBehind -> "Update Patches"
@@ -234,6 +239,18 @@ private fun ColumnScope.HomeContent(
) )
} }
if (state.offline && install != null) {
Text(
text = "No Network Connection",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
textAlign = TextAlign.Center,
modifier = Modifier
.fillMaxWidth()
.padding(top = 6.dp),
)
}
AnimatedVisibility(visible = install != null) { AnimatedVisibility(visible = install != null) {
Row( Row(
horizontalArrangement = Arrangement.spacedBy(2.dp), horizontalArrangement = Arrangement.spacedBy(2.dp),
@@ -8,5 +8,7 @@ sealed interface HomeState {
data class Loaded( data class Loaded(
val install: InstallData?, val install: InstallData?,
val latestTidalVersionCode: Int?, val latestTidalVersionCode: Int?,
val offline: Boolean = false,
val offlineRepatchReady: Boolean = false,
) : HomeState ) : HomeState
} }
@@ -1,245 +0,0 @@
package com.meowarex.rlmobile.ui.screens.patchopts
import androidx.annotation.StringRes
import com.meowarex.rlmobile.R
import com.meowarex.rlmobile.ui.screens.patchopts.PatchDefault.Disabled
import com.meowarex.rlmobile.ui.screens.patchopts.PatchDefault.Enabled
data class PatchVariant(
@StringRes val titleRes: Int,
val fileNames: List<String>,
val extensionFiles: List<String> = emptyList(),
)
enum class KnownPatch(
val order: Int, // Patch order in the UI List (lower = higher up) [Main Patches: multiples of 10 | Sub Patches: multiples of 1]
val fileNames: List<String>,
val extensionFiles: List<String> = emptyList(),
@StringRes val titleRes: Int,
@StringRes val descRes: Int,
val default: PatchDefault, // Default state of the patch in the UI List (enabled/disabled)
val requires: List<KnownPatch> = emptyList(),
val disables: List<KnownPatch> = emptyList(),
val variants: List<PatchVariant> = emptyList(),
val defaultVariantIndex: Int = 0,
val advancedOptions: List<PatchOption> = emptyList(),
) {
LyricsDisableCover(
order = 41,
fileNames = listOf("lyrics-disable-cover.patch"),
titleRes = R.string.patch_lyrics_disable_cover_title,
descRes = R.string.patch_lyrics_disable_cover_desc,
default = Enabled,
),
LyricsReplaceLyricsButton(
order = 42,
fileNames = listOf(
"lyrics-replace-lyrics-button.patch",
"lyrics-sparkle-conditional-visibility.patch",
),
titleRes = R.string.patch_lyrics_replace_button_title,
descRes = R.string.patch_lyrics_replace_button_desc,
default = Enabled,
),
LyricsReplaceShareButton(
order = 43,
fileNames = listOf("lyrics-replace-share-button.patch"),
titleRes = R.string.patch_lyrics_replace_share_button_title,
descRes = R.string.patch_lyrics_replace_share_button_desc,
default = Enabled,
),
LyricsRlApi(
order = 20,
fileNames = listOf(
"lyrics-rl-api.patch",
"lyrics-rl-api-observer.patch",
),
titleRes = R.string.patch_lyrics_rl_api_title,
descRes = R.string.patch_lyrics_rl_api_desc,
default = Disabled,
),
LyricsKeepControlsVisible(
order = 60,
fileNames = listOf("lyrics-keep-controls-visible.patch"),
titleRes = R.string.patch_lyrics_keep_controls_title,
descRes = R.string.patch_lyrics_keep_controls_desc,
default = Enabled,
),
PlayerBackdrop(
order = 30,
fileNames = listOf("player-backdrop.patch"),
titleRes = R.string.patch_player_backdrop_title,
descRes = R.string.patch_player_backdrop_desc,
default = Enabled,
advancedOptions = listOf(
PatchOption.Slider(
key = "blur_strength",
titleRes = R.string.patch_opt_backdrop_blur_title,
descRes = R.string.patch_opt_backdrop_blur_desc,
default = 50f,
valueRange = 0f..100f,
steps = 19, // dots every 5% (0,5,…,100); snap only when locked
displayAsPercent = true,
token = "RL_BLUR_BITS",
encode = SmaliEncode(EncodeKind.FloatBits, scale = 1.8f),
),
PatchOption.Slider(
key = "dimming",
titleRes = R.string.patch_opt_backdrop_dimming_title,
descRes = R.string.patch_opt_backdrop_dimming_desc,
default = 50f, // 50% == the original -0x80000000
valueRange = 0f..100f,
steps = 19, // dots every 5%
displayAsPercent = true,
token = "RL_SCRIM_ARGB",
encode = SmaliEncode(EncodeKind.ArgbAlpha),
),
),
),
QualityBadgeColors(
order = 36,
fileNames = listOf("player-quality-badge-colors.patch"),
titleRes = R.string.patch_quality_badge_colors_title,
descRes = R.string.patch_quality_badge_colors_desc,
default = Enabled,
),
PlayerOneHanded(
order = 37,
fileNames = listOf("player-one-handed.patch"),
titleRes = R.string.patch_player_one_handed_title,
descRes = R.string.patch_player_one_handed_desc,
default = Disabled,
),
CoverEverywhere(
order = 35,
fileNames = listOf(
"home-backdrop.patch",
"collection-backdrop.patch",
"cover-capture.patch",
),
titleRes = R.string.patch_cover_everywhere_title,
descRes = R.string.patch_cover_everywhere_desc,
default = Disabled,
),
DebugMenuUnlock(
order = 100,
fileNames = listOf("debug-menu-unlock.patch"),
titleRes = R.string.patch_debug_menu_unlock_title,
descRes = R.string.patch_debug_menu_unlock_desc,
default = Disabled,
),
LyricsProgressPill(
order = 40,
fileNames = listOf(
"lyrics-progress-pill.patch",
"lyrics-fade-region.patch",
),
titleRes = R.string.patch_lyrics_progress_pill_title,
descRes = R.string.patch_lyrics_progress_pill_desc,
default = Enabled,
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,
default = Disabled,
defaultVariantIndex = 2,
variants = listOf(
PatchVariant( // 0: Floating — stock rounded pill (no patch; the progress border is an option)
titleRes = R.string.patch_mini_player_variant_floating_title,
fileNames = emptyList(),
),
PatchVariant( // 1: Grey — square, theme background (shown as "Legacy" when Dynamic BG is on)
titleRes = R.string.patch_mini_player_variant_square_grey_title,
fileNames = listOf("mini-player-grey.patch"),
),
PatchVariant( // 2: Black — square, forced black background (hidden when Dynamic BG is on)
titleRes = R.string.patch_mini_player_variant_square_black_title,
fileNames = listOf("mini-player-black.patch"),
),
),
advancedOptions = listOf(
PatchOption.Toggle(
key = "dynamic_bg",
titleRes = R.string.patch_mini_player_dynamic_bg_title,
descRes = R.string.patch_mini_player_dynamic_bg_desc,
default = false,
inline = true,
fileNames = listOf("mini-player-dynamic-bg.patch"),
extensionFiles = listOf("radiant/MiniPlayerBackground.smali"),
hidesVariants = listOf(2),
relabelVariants = mapOf(1 to R.string.patch_mini_player_variant_legacy_title),
),
// Animated progress border around the floating pill
PatchOption.Toggle(
key = "border",
titleRes = R.string.patch_mini_player_border_title,
descRes = R.string.patch_mini_player_border_desc,
default = false,
requiresVariant = 0,
fileNames = listOf("mini-player-floating-border.patch"),
extensionFiles = listOf("radiant/MiniSeekerFloating.smali"),
),
// Swipe up to open the full player
PatchOption.Toggle(
key = "gestures",
titleRes = R.string.patch_mini_player_gestures_title,
descRes = R.string.patch_mini_player_gestures_desc,
default = true,
fileNames = listOf("mini-player-gestures.patch"),
extensionFiles = listOf(
"radiant/MiniPlayerGestures.smali",
"radiant/MiniPlayerGestures\$Gesture.smali",
"radiant/MiniPlayerGestures\$RootGesture.smali",
"radiant/MiniPlayerGestures\$ApplyPending.smali",
),
),
// Swipe left/right to skip
PatchOption.Toggle(
key = "next_prev",
titleRes = R.string.patch_mini_player_left_right_gestures_title,
descRes = R.string.patch_mini_player_left_right_gestures_desc,
default = false,
requiresOption = "gestures",
fileNames = listOf("mini-player-gestures-left-right.patch"),
extensionFiles = listOf(
"radiant/MiniPlayerTrackGestures.smali",
"radiant/MiniPlayerTrackGestures\$Gesture.smali",
"radiant/MiniPlayerTrackGestures\$OffsetLayer.smali",
"radiant/MiniPlayerTrackGestures\$ResetAnimator.smali",
"radiant/MiniPlayerTrackGestures\$TextDraw.smali",
"com/tidal/android/feature/appscaffold/ui/q\$c.smali",
),
),
),
),
EnableLegacyUi(
order = 10,
fileNames = listOf("enable-legacy-ui.patch"),
titleRes = R.string.patch_enable_legacy_ui_title,
descRes = R.string.patch_enable_legacy_ui_desc,
default = Disabled,
requires = listOf(DebugMenuUnlock),
disables = listOf(
LyricsDisableCover,
LyricsReplaceLyricsButton,
LyricsReplaceShareButton,
LyricsRlApi,
LyricsKeepControlsVisible,
PlayerBackdrop,
QualityBadgeColors,
LyricsProgressPill,
CoverEverywhere,
MiniPlayerRedesign,
),
);
companion object {
val All: List<KnownPatch> = entries.sortedWith(
compareBy({ it.order }, { it.fileNames.firstOrNull() ?: it.name })
)
}
}
@@ -1,6 +0,0 @@
package com.meowarex.rlmobile.ui.screens.patchopts
enum class PatchDefault(val isEnabled: Boolean) {
Enabled(true),
Disabled(false),
}
@@ -1,68 +0,0 @@
package com.meowarex.rlmobile.ui.screens.patchopts
import androidx.annotation.StringRes
sealed interface PatchOption {
/** Stable identifier, unique within a single patch. */
val key: String
@get:StringRes
val titleRes: Int
@get:StringRes
val descRes: Int
/** A simple on/off switch. */
data class Toggle(
override val key: String,
@StringRes override val titleRes: Int,
@StringRes override val descRes: Int,
val default: Boolean,
/** Patch files applied only while this toggle is on (and its patch is enabled). */
val fileNames: List<String> = emptyList(),
/** Helper smali extracted only while this toggle is on. */
val extensionFiles: List<String> = emptyList(),
/** Render inline beneath the variant selector instead of inside the advanced sheet. */
val inline: Boolean = false,
/** Greyed out (with the lock dialog) unless this variant index is the selected one. */
val requiresVariant: Int? = null,
/** Greyed out unless the sibling option with this key is currently on. */
val requiresOption: String? = null,
/** Variant indices hidden from the picker while this toggle is on. */
val hidesVariants: List<Int> = emptyList(),
/** Variant title overrides (index -> @StringRes) applied while this toggle is on. */
val relabelVariants: Map<Int, Int> = emptyMap(),
) : PatchOption
/** A continuous (or stepped) numeric value within [valueRange]. */
data class Slider(
override val key: String,
@StringRes override val titleRes: Int,
@StringRes override val descRes: Int,
val default: Float,
val valueRange: ClosedFloatingPointRange<Float>,
/** Number of discrete steps between the range ends (0 = continuous). */
val steps: Int = 0,
/** Render the value as a rounded percentage (e.g. "50%"). */
val displayAsPercent: Boolean = false,
/** Optional unit suffix shown after the value (e.g. "dp"). */
@StringRes val unitRes: Int? = null,
/** Placeholder name (without the surrounding `__`) baked into the `.patch` files. */
val token: String? = null,
/** How the chosen value becomes the smali literal that replaces the [token]. */
val encode: SmaliEncode? = null,
) : PatchOption
/** A single choice out of a small list, rendered as a segmented control. */
data class Choice(
override val key: String,
@StringRes override val titleRes: Int,
@StringRes override val descRes: Int,
val entries: List<ChoiceEntry>,
val defaultIndex: Int = 0,
) : PatchOption
}
data class ChoiceEntry(
@StringRes val labelRes: Int,
)
@@ -52,6 +52,13 @@ data class PatchOptions(
fun sliderValue(spec: PatchSpec, option: OptionSpec.Slider): Float = fun sliderValue(spec: PatchSpec, option: OptionSpec.Slider): Float =
(optionFloats["${spec.id}/${option.key}"] ?: option.default).coerceIn(option.min, option.max) (optionFloats["${spec.id}/${option.key}"] ?: option.default).coerceIn(option.min, option.max)
fun choiceIndex(spec: PatchSpec, option: OptionSpec.Choice): Int =
(optionInts["${spec.id}/${option.key}"] ?: option.defaultIndex)
.coerceIn(0, option.entries.lastIndex.coerceAtLeast(0))
fun colorValue(spec: PatchSpec, option: OptionSpec.Color): Int =
optionInts["${spec.id}/${option.key}"] ?: option.default
fun isToggleOn(spec: PatchSpec, option: OptionSpec.Toggle): Boolean = fun isToggleOn(spec: PatchSpec, option: OptionSpec.Toggle): Boolean =
optionBools["${spec.id}/${option.key}"] ?: option.default optionBools["${spec.id}/${option.key}"] ?: option.default
@@ -111,10 +118,31 @@ data class PatchOptions(
for (spec in specs) { for (spec in specs) {
if (!isEnabled(spec)) continue if (!isEnabled(spec)) continue
for (option in spec.advancedOptions) { for (option in spec.advancedOptions) {
if (option !is OptionSpec.Slider) continue when (option) {
val token = option.token ?: continue is OptionSpec.Toggle -> {
val encode = option.encode ?: continue val token = option.token ?: continue
put("__${token}__", encode.encode(sliderValue(spec, option))) 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 -> {
val token = option.token ?: continue
val gatedOff = option.requiresOption?.let { key ->
spec.advancedOptions.filterIsInstance<OptionSpec.Toggle>()
.firstOrNull { it.key == key }
?.let { !isToggleOn(spec, it) }
} ?: false
val index = if (gatedOff) 0 else choiceIndex(spec, option)
put("__${token}__", option.values.getOrNull(index) ?: continue)
}
is OptionSpec.Color -> {
val token = option.token ?: continue
put("__${token}__", colorValue(spec, option).toString())
}
}
} }
} }
} }
@@ -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 && !bypassIncompatible
/** 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
@@ -61,10 +79,20 @@ class PatchOptionsModel(
debuggable = value debuggable = value
} }
/** Dev override: force-allow path-gated ("incompatible") patches under a non-stock package name. */
var bypassIncompatible by mutableStateOf(prefs.bypassIncompatible)
private set
fun changeBypassIncompatible(value: Boolean) {
bypassIncompatible = value
prefs.bypassIncompatible = value
validatePatchSelection()
}
// The accordion renders from [specs]. It defaults to the compiled-in (localized) list and is // The accordion renders from [specs]. It defaults to the compiled-in (localized) list and is
// rebuilt from a custom zip's manifest.json whenever a custom patch set is selected. (Rminder for others about the new custom patch selection flow) // rebuilt from a custom zip's manifest.json whenever a custom patch set is selected. (Rminder for others about the new custom patch selection flow)
private val builtinSpecs: List<PatchSpec> = builtinPatchSpecs { context.getString(it) } private val builtinSpecs: List<PatchSpec> = builtinPatchSpecs(context, json)
var specs by mutableStateOf(builtinSpecs) var specs by mutableStateOf(builtinSpecs)
private set private set
@@ -83,7 +111,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 }
@@ -153,11 +181,19 @@ class PatchOptionsModel(
optionInts = optionInts + (keyOf(spec, option) to index) optionInts = optionInts + (keyOf(spec, option) to index)
} }
fun colorValue(spec: PatchSpec, option: OptionSpec.Color): Int =
optionInts[keyOf(spec, option)] ?: option.default
fun setColorValue(spec: PatchSpec, option: OptionSpec.Color, value: Int) {
optionInts = optionInts + (keyOf(spec, option) to value)
}
fun isAdvancedModified(spec: PatchSpec): Boolean = spec.advancedOptions.any { option -> fun isAdvancedModified(spec: PatchSpec): Boolean = spec.advancedOptions.any { option ->
when (option) { when (option) {
is OptionSpec.Toggle -> toggleValue(spec, option) != option.default is OptionSpec.Toggle -> toggleValue(spec, option) != option.default
is OptionSpec.Slider -> sliderValue(spec, option) != option.default is OptionSpec.Slider -> sliderValue(spec, option) != option.default
is OptionSpec.Choice -> choiceValue(spec, option) != option.defaultIndex is OptionSpec.Choice -> choiceValue(spec, option) != option.defaultIndex
is OptionSpec.Color -> colorValue(spec, option) != option.default
} }
} }
@@ -175,11 +211,14 @@ class PatchOptionsModel(
setSlider = ::setSliderValue, setSlider = ::setSliderValue,
choice = ::choiceValue, choice = ::choiceValue,
setChoice = ::setChoiceValue, setChoice = ::setChoiceValue,
color = ::colorValue,
setColor = ::setColorValue,
isModified = ::isAdvancedModified, isModified = ::isAdvancedModified,
reset = ::resetAdvanced, reset = ::resetAdvanced,
) )
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 }
@@ -206,9 +245,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)
@@ -255,6 +291,7 @@ class PatchOptionsModel(
val bytes = ZipReader(file).use { it.openEntry(MANIFEST_NAME)?.read() } ?: return null val bytes = ZipReader(file).use { it.openEntry(MANIFEST_NAME)?.read() } ?: return null
json.decodeFromString(PatchManifest.serializer(), bytes.decodeToString()) json.decodeFromString(PatchManifest.serializer(), bytes.decodeToString())
.patches .patches
.sortedBy { it.order } // manifest is authoritative for UI order (not KnownPatch)
.takeIf { it.isNotEmpty() } .takeIf { it.isNotEmpty() }
} catch (t: Throwable) { } catch (t: Throwable) {
Log.w(BuildConfig.TAG, "Failed to parse $MANIFEST_NAME; using built-in list", t) Log.w(BuildConfig.TAG, "Failed to parse $MANIFEST_NAME; using built-in list", t)
@@ -294,10 +331,19 @@ class PatchOptionsModel(
null null
} }
/** Default (non-custom) source: the latest release manifest, falling back to the built-in list. */ private fun loadCachedReleaseManifestSpecs(): List<PatchSpec>? =
paths.cacheDownloadDir
.listFiles { f -> f.name.startsWith("manifest-") && f.name.endsWith(".zip") }
?.maxByOrNull { it.lastModified() }
?.let { loadManifestSpecs(it) }
?.also { Log.i(BuildConfig.TAG, "Loaded ${it.size} patches from cached release manifest (offline)") }
/** Default (non-custom) source: latest release manifest → last cached manifest → built-in list. */
private fun loadDefaultSpecs() = screenModelScope.launchIO { private fun loadDefaultSpecs() = screenModelScope.launchIO {
mainThread { specsLoading = true } mainThread { specsLoading = true }
val loaded = loadLatestReleaseSpecs() ?: builtinSpecs // Only hit the network when actually online
val loaded = (if (context.isOnline()) loadLatestReleaseSpecs() else null)
?: loadCachedReleaseManifestSpecs() ?: builtinSpecs
mainThread { mainThread {
specs = loaded specs = loaded
validatePatchSelection() validatePatchSelection()
@@ -323,7 +369,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,
@@ -385,4 +434,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.*
@@ -46,6 +48,8 @@ class PatchOptionsScreen(
debuggable = model.debuggable, debuggable = model.debuggable,
setDebuggable = model::changeDebuggable, setDebuggable = model::changeDebuggable,
bypassIncompatible = model.bypassIncompatible,
setBypassIncompatible = model::changeBypassIncompatible,
appName = model.appName, appName = model.appName,
appNameIsError = model.appNameIsError, appNameIsError = model.appNameIsError,
@@ -55,13 +59,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,
@@ -84,6 +91,8 @@ fun PatchOptionsScreenContent(
debuggable: Boolean, debuggable: Boolean,
setDebuggable: (Boolean) -> Unit, setDebuggable: (Boolean) -> Unit,
bypassIncompatible: Boolean,
setBypassIncompatible: (Boolean) -> Unit,
appName: String, appName: String,
appNameIsError: Boolean, appNameIsError: Boolean,
@@ -93,13 +102,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 +122,19 @@ fun PatchOptionsScreenContent(
isConfigValid: Boolean, isConfigValid: Boolean,
onInstall: () -> Unit, onInstall: () -> Unit,
) { ) {
var showPkgUnlockDialog by rememberSaveable { mutableStateOf(false) }
if (showPkgUnlockDialog) {
PackageNameUnlockDialog(
// With "Bypass Incompatible" on, path-gated patches are force-applied, not disabled.
blockedTitles = if (bypassIncompatible) emptyList() else 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 +184,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 +196,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) {
@@ -221,6 +273,14 @@ fun PatchOptionsScreenContent(
) )
} }
} }
SwitchPatchOption(
icon = painterResource(R.drawable.ic_lock_open),
name = stringResource(R.string.patchopts_bypass_incompatible_title),
description = stringResource(R.string.patchopts_bypass_incompatible_desc),
value = bypassIncompatible,
onValueChange = setBypassIncompatible,
)
} }
Spacer(Modifier.weight(1f)) Spacer(Modifier.weight(1f))
@@ -1,9 +1,11 @@
package com.meowarex.rlmobile.ui.screens.patchopts package com.meowarex.rlmobile.ui.screens.patchopts
import android.content.Context
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlin.math.roundToInt import kotlin.math.roundToInt
@Serializable @Serializable
@@ -29,7 +31,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
@@ -68,6 +79,8 @@ sealed interface OptionSpec {
val hidesVariants: List<Int> = emptyList(), val hidesVariants: List<Int> = emptyList(),
/** Variant title overrides (index -> title) applied while this toggle is on. */ /** Variant title overrides (index -> title) applied while this toggle is on. */
val relabelVariants: Map<Int, String> = emptyMap(), val relabelVariants: Map<Int, String> = emptyMap(),
/** Placeholder name (without the surrounding `__`) baked into the `.patch` files. */
val token: String? = null,
) : OptionSpec ) : OptionSpec
@Immutable @Immutable
@@ -96,10 +109,25 @@ sealed interface OptionSpec {
@SerialName("choice") @SerialName("choice")
data class Choice( data class Choice(
override val key: String, override val key: String,
override val title: String, override val title: String = "",
override val description: String = "", override val description: String = "",
val entries: List<String> = emptyList(), val entries: List<String> = emptyList(),
val defaultIndex: Int = 0, val defaultIndex: Int = 0,
val values: List<String> = emptyList(),
val requiresOption: String? = null,
val token: String? = null,
) : OptionSpec
@Immutable
@Serializable
@SerialName("color")
data class Color(
override val key: String,
override val title: String = "",
override val description: String = "",
val default: Int = 0,
/** Placeholder name (without the surrounding `__`) baked into the `.patch`/extension files. */
val token: String? = null,
) : OptionSpec ) : OptionSpec
} }
@@ -131,60 +159,17 @@ data class SmaliEncode(
} }
} }
fun builtinPatchSpecs(resolve: (Int) -> String): List<PatchSpec> = /** Asset filename of the bundled fallback manifest snapshot (a copy of the release manifest.json). */
KnownPatch.All.map { patch -> const val BUNDLED_MANIFEST_ASSET = "patches-manifest.json"
PatchSpec(
id = patch.name,
order = patch.order,
fileNames = patch.fileNames,
extensionFiles = patch.extensionFiles,
title = resolve(patch.titleRes),
description = resolve(patch.descRes),
defaultEnabled = patch.default.isEnabled,
requires = patch.requires.map { it.name },
disables = patch.disables.map { it.name },
variants = patch.variants.map { VariantSpec(resolve(it.titleRes), it.fileNames, it.extensionFiles) },
defaultVariantIndex = patch.defaultVariantIndex,
advancedOptions = patch.advancedOptions.map { it.toSpec(resolve) },
)
}
private fun PatchOption.toSpec(resolve: (Int) -> String): OptionSpec = when (this) { // Fallback patch list (snapshot of the release manifest bundled in the app's assets)
is PatchOption.Toggle -> OptionSpec.Toggle( fun builtinPatchSpecs(context: Context, json: Json): List<PatchSpec> = try {
key = key, context.assets.open(BUNDLED_MANIFEST_ASSET).use { it.readBytes() }
title = resolve(titleRes), .let { json.decodeFromString(PatchManifest.serializer(), it.decodeToString()) }
description = resolve(descRes), .patches
default = default, .sortedBy { it.order }
fileNames = fileNames, } catch (t: Throwable) {
extensionFiles = extensionFiles, emptyList()
inline = inline,
requiresVariant = requiresVariant,
requiresOption = requiresOption,
hidesVariants = hidesVariants,
relabelVariants = relabelVariants.mapValues { resolve(it.value) },
)
is PatchOption.Slider -> OptionSpec.Slider(
key = key,
title = resolve(titleRes),
description = resolve(descRes),
default = default,
min = valueRange.start,
max = valueRange.endInclusive,
steps = steps,
displayAsPercent = displayAsPercent,
unit = unitRes?.let(resolve),
token = token,
encode = encode,
)
is PatchOption.Choice -> OptionSpec.Choice(
key = key,
title = resolve(titleRes),
description = resolve(descRes),
entries = entries.map { resolve(it.labelRes) },
defaultIndex = defaultIndex,
)
} }
@Immutable @Immutable
@@ -249,6 +234,8 @@ class PatchOptionState(
val setSlider: (PatchSpec, OptionSpec.Slider, Float) -> Unit, val setSlider: (PatchSpec, OptionSpec.Slider, Float) -> Unit,
val choice: (PatchSpec, OptionSpec.Choice) -> Int, val choice: (PatchSpec, OptionSpec.Choice) -> Int,
val setChoice: (PatchSpec, OptionSpec.Choice, Int) -> Unit, val setChoice: (PatchSpec, OptionSpec.Choice, Int) -> Unit,
val color: (PatchSpec, OptionSpec.Color) -> Int,
val setColor: (PatchSpec, OptionSpec.Color, Int) -> Unit,
val isModified: (PatchSpec) -> Boolean, val isModified: (PatchSpec) -> Boolean,
val reset: (PatchSpec) -> Unit, val reset: (PatchSpec) -> Unit,
) { ) {
@@ -261,6 +248,8 @@ class PatchOptionState(
setSlider = { _, _, _ -> }, setSlider = { _, _, _ -> },
choice = { _, option -> option.defaultIndex }, choice = { _, option -> option.defaultIndex },
setChoice = { _, _, _ -> }, setChoice = { _, _, _ -> },
color = { _, option -> option.default },
setColor = { _, _, _ -> },
isModified = { false }, isModified = { false },
reset = {}, reset = {},
) )
@@ -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,9 +1,14 @@
package com.meowarex.rlmobile.ui.screens.patchopts.components package com.meowarex.rlmobile.ui.screens.patchopts.components
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.* import androidx.compose.runtime.*
@@ -11,11 +16,16 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.fromHtml import androidx.compose.ui.text.fromHtml
import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@@ -87,18 +97,91 @@ fun PatchAdvancedOptionsSheet(
HorizontalDivider() HorizontalDivider()
val sheetOptions = patch.advancedOptions.filter { it !is OptionSpec.Toggle || !it.inline } val parentKeys = patch.advancedOptions
.filterIsInstance<OptionSpec.Toggle>()
.filter { !it.inline }
.map { it.key }
.toSet()
val sheetOptions = patch.advancedOptions.filter { option ->
when {
option is OptionSpec.Toggle && option.inline -> false
option is OptionSpec.Toggle && option.requiresOption in parentKeys -> false
else -> true
}
}
for (option in sheetOptions) key(option.key) { for (option in sheetOptions) key(option.key) {
val lock = patch.optionLock(option, selectedVariant) { state.toggle(patch, it) } val lock = patch.optionLock(option, selectedVariant) { state.toggle(patch, it) }
when (option) { when (option) {
is OptionSpec.Toggle -> ToggleOptionRow( is OptionSpec.Toggle -> {
title = option.title, val toggleOn = state.toggle(patch, option)
description = option.description, val gatedChoices = patch.advancedOptions.filterIsInstance<OptionSpec.Choice>()
checked = state.toggle(patch, option), .filter { it.requiresOption == option.key }
onCheckedChange = { state.setToggle(patch, option, it) }, val gatedToggles = patch.advancedOptions.filterIsInstance<OptionSpec.Toggle>()
locked = lock != OptionLock.Free, .filter { it.requiresOption == option.key && !it.inline }
onLockedTap = { lockDialog = lock }, val hasSubOptions = gatedChoices.isNotEmpty() || gatedToggles.isNotEmpty()
) val carded = hasSubOptions && toggleOn
Column(
modifier = if (carded) {
Modifier
.fillMaxWidth()
.clip(MaterialTheme.shapes.medium)
.background(MaterialTheme.colorScheme.primary.copy(alpha = 0.07f))
.border(
width = 1.5.dp,
color = MaterialTheme.colorScheme.primary.copy(alpha = 0.55f),
shape = MaterialTheme.shapes.medium,
)
.padding(horizontal = 12.dp, vertical = 4.dp)
} else {
Modifier.fillMaxWidth()
},
) {
ToggleOptionRow(
title = option.title,
description = option.description,
checked = toggleOn,
onCheckedChange = { state.setToggle(patch, option, it) },
locked = lock != OptionLock.Free,
onLockedTap = { lockDialog = lock },
modifier = if (hasSubOptions) Modifier.padding(vertical = 6.dp) else Modifier,
)
if (hasSubOptions) {
AnimatedVisibility(visible = toggleOn) {
Column(
verticalArrangement = Arrangement.spacedBy(10.dp),
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 8.dp),
) {
gatedChoices.forEach { choice ->
key(choice.key) {
ChoiceOptionRow(
title = choice.title,
entries = choice.entries,
selectedIndex = state.choice(patch, choice),
onSelect = { state.setChoice(patch, choice, it) },
)
}
}
gatedToggles.forEach { sub ->
key(sub.key) {
val subLock = patch.optionLock(sub, selectedVariant) { state.toggle(patch, it) }
ToggleOptionRow(
title = sub.title,
description = sub.description,
checked = state.toggle(patch, sub),
onCheckedChange = { state.setToggle(patch, sub, it) },
locked = subLock != OptionLock.Free,
onLockedTap = { lockDialog = subLock },
)
}
}
}
}
}
}
}
is OptionSpec.Slider -> SliderOptionRow( is OptionSpec.Slider -> SliderOptionRow(
title = option.title, title = option.title,
@@ -110,12 +193,20 @@ fun PatchAdvancedOptionsSheet(
onValueChange = { state.setSlider(patch, option, it) }, onValueChange = { state.setSlider(patch, option, it) },
) )
is OptionSpec.Choice -> ChoiceOptionRow( is OptionSpec.Choice ->
if (option.requiresOption == null) {
ChoiceOptionRow(
title = option.title,
entries = option.entries,
selectedIndex = state.choice(patch, option),
onSelect = { state.setChoice(patch, option, it) },
)
}
is OptionSpec.Color -> ColorOptionRow(
title = option.title, title = option.title,
description = option.description, color = state.color(patch, option),
entries = option.entries, onColorChange = { state.setColor(patch, option, it) },
selectedIndex = state.choice(patch, option),
onSelect = { state.setChoice(patch, option, it) },
) )
} }
} }
@@ -147,13 +238,14 @@ private fun ToggleOptionRow(
onCheckedChange: (Boolean) -> Unit, onCheckedChange: (Boolean) -> Unit,
locked: Boolean = false, locked: Boolean = false,
onLockedTap: () -> Unit = {}, onLockedTap: () -> Unit = {},
modifier: Modifier = Modifier,
) { ) {
val interactionSource = remember(::MutableInteractionSource) val interactionSource = remember(::MutableInteractionSource)
Row( Row(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(12.dp), horizontalArrangement = Arrangement.spacedBy(12.dp),
modifier = Modifier modifier = modifier
.fillMaxWidth() .fillMaxWidth()
.clickable( .clickable(
interactionSource = interactionSource, interactionSource = interactionSource,
@@ -279,18 +371,58 @@ private fun snapToNearestStep(
@Composable @Composable
private fun ChoiceOptionRow( private fun ChoiceOptionRow(
title: String,
description: String,
entries: List<String>, entries: List<String>,
selectedIndex: Int, selectedIndex: Int,
onSelect: (Int) -> Unit, onSelect: (Int) -> Unit,
title: String = "",
modifier: Modifier = Modifier,
) { ) {
Column( Column(
modifier = Modifier.fillMaxWidth(), modifier = modifier.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(6.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) { ) {
OptionText(title = title, description = description) if (title.isNotEmpty()) {
Text(
text = title,
style = MaterialTheme.typography.labelMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
textAlign = TextAlign.Center,
)
}
if (entries.size > 3) {
var expanded by rememberSaveable { mutableStateOf(false) }
val selectedLabel = entries.getOrNull(selectedIndex).orEmpty()
Box(modifier = Modifier.fillMaxWidth()) {
OutlinedButton(
onClick = { expanded = true },
modifier = Modifier.fillMaxWidth(),
) {
Text(
text = selectedLabel,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false },
modifier = Modifier.fillMaxWidth(),
) {
entries.forEachIndexed { index, entry ->
DropdownMenuItem(
text = { Text(entry) },
onClick = {
onSelect(index)
expanded = false
},
)
}
}
}
return@Column
}
SingleChoiceSegmentedButtonRow(modifier = Modifier.fillMaxWidth()) { SingleChoiceSegmentedButtonRow(modifier = Modifier.fillMaxWidth()) {
entries.forEachIndexed { index, entry -> entries.forEachIndexed { index, entry ->
SegmentedButton( SegmentedButton(
@@ -313,6 +445,150 @@ private fun ChoiceOptionRow(
} }
} }
@Composable
private fun ColorOptionRow(
title: String,
color: Int,
onColorChange: (Int) -> Unit,
) {
var showPicker by rememberSaveable { mutableStateOf(false) }
val selectedColor = color.withOpaqueAlpha()
val materialYouColor = MaterialTheme.colorScheme.primary.toArgb().withOpaqueAlpha()
val presets = listOf(
stringResource(R.string.patch_waze_color_waze_default),
stringResource(R.string.patch_waze_color_tidal_cyan),
stringResource(R.string.patch_waze_color_material_you),
)
val presetColors = listOf(WAZE_DEFAULT, TIDAL_CYAN, materialYouColor)
val selectedPreset = presetColors.indexOf(selectedColor)
Column(
modifier = Modifier.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
Text(
text = title,
style = MaterialTheme.typography.labelMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.align(Alignment.CenterHorizontally),
)
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(10.dp),
modifier = Modifier
.fillMaxWidth()
.clip(MaterialTheme.shapes.medium)
.clickable { showPicker = true }
.padding(vertical = 4.dp),
) {
ColorSwatch(color = selectedColor)
Text(
text = selectedColor.toRgbHex(),
style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.primary,
)
}
SingleChoiceSegmentedButtonRow(modifier = Modifier.fillMaxWidth()) {
presets.forEachIndexed { index, label ->
SegmentedButton(
selected = index == selectedPreset,
onClick = { onColorChange(presetColors[index]) },
shape = SegmentedButtonDefaults.itemShape(index = index, count = presets.size),
icon = {},
label = {
Text(
text = label,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
textAlign = TextAlign.Center,
style = MaterialTheme.typography.labelMedium,
)
},
)
}
}
}
if (showPicker) {
ColorPickerDialog(
initialColor = selectedColor,
onDismiss = { showPicker = false },
onColorSelected = {
onColorChange(it)
showPicker = false
},
)
}
}
@Composable
private fun ColorSwatch(color: Int, modifier: Modifier = Modifier) {
Box(
modifier = modifier
.size(32.dp)
.clip(CircleShape)
.background(Color(color))
.border(1.dp, MaterialTheme.colorScheme.outlineVariant, CircleShape),
)
}
@Composable
private fun ColorPickerDialog(
initialColor: Int,
onDismiss: () -> Unit,
onColorSelected: (Int) -> Unit,
) {
var color by rememberSaveable(initialColor) { mutableIntStateOf(initialColor.withOpaqueAlpha()) }
var hex by rememberSaveable(initialColor) { mutableStateOf(color.toRgbHex()) }
val parsedHex = parseRgbHex(hex)
AlertDialog(
onDismissRequest = onDismiss,
title = { Text(stringResource(R.string.patch_color_picker_title)) },
text = {
Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
ColorSwatch(color = parsedHex ?: color, modifier = Modifier.size(40.dp))
OutlinedTextField(
value = hex,
onValueChange = { value ->
hex = value
parseRgbHex(value)?.let { color = it }
},
label = { Text(stringResource(R.string.patch_color_picker_hex)) },
singleLine = true,
isError = parsedHex == null,
keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.Characters,
keyboardType = KeyboardType.Ascii,
),
supportingText = if (parsedHex == null) {
{ Text(stringResource(R.string.patch_color_picker_hex_error)) }
} else null,
modifier = Modifier.weight(1f),
)
}
}
},
confirmButton = {
TextButton(
enabled = parsedHex != null,
onClick = { parsedHex?.let(onColorSelected) },
) {
Text(stringResource(R.string.action_done))
}
},
dismissButton = {
TextButton(onClick = onDismiss) {
Text(stringResource(R.string.action_cancel))
}
},
)
}
@Composable @Composable
private fun OptionText( private fun OptionText(
title: String, title: String,
@@ -345,6 +621,26 @@ private fun formatSliderValue(option: OptionSpec.Slider, value: Float): String {
} }
} }
private const val OPAQUE_ALPHA = -0x1000000
private const val WAZE_DEFAULT = -16747037 // #ff0075e3
private const val TIDAL_CYAN = -14549268 // #ff21feec
private fun Int.withOpaqueAlpha(): Int = (this and 0x00FFFFFF) or OPAQUE_ALPHA
private fun Int.toRgbHex(): String = "#" +
(this and 0x00FFFFFF).toString(16).uppercase().padStart(6, '0')
private fun parseRgbHex(value: String): Int? {
val clean = value.trim()
.removePrefix("#")
.removePrefix("0x")
.removePrefix("0X")
if (clean.length != 6 && clean.length != 8) return null
val parsed = clean.toLongOrNull(16) ?: return null
val rgb = if (clean.length == 8) parsed and 0x00FFFFFFL else parsed
return (0xFF000000L or rgb).toInt()
}
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
private fun OptionLockDialog(lock: OptionLock, onDismiss: () -> Unit) { private fun OptionLockDialog(lock: OptionLock, onDismiss: () -> Unit) {
@@ -1,9 +1,12 @@
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
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
@@ -26,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
@@ -34,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,
@@ -68,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(
@@ -105,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)
@@ -115,75 +127,85 @@ fun PatchSelectionAccordion(
for (patch in specs) key(patch.id) { for (patch in specs) key(patch.id) {
val checked = isEnabled(patch) val checked = isEnabled(patch)
val lock = lockState(patch) val lock = lockState(patch)
PatchSwitchRow(
title = patch.title,
description = patch.description,
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),
) {
val effective = patch.effectiveVariants { optionState.toggle(patch, it) }
val resolved = patch.resolveVariantIndex(variantIndex(patch)) {
optionState.toggle(patch, it)
}
PatchVariantSelector(
variants = effective,
selectedIndex = effective
.indexOfFirst { it.originalIndex == resolved }
.coerceAtLeast(0),
onSelect = { pos ->
effective.getOrNull(pos)?.let { onSelectVariant(patch, it.originalIndex) }
},
)
}
}
}
val inlineToggles = patch.advancedOptions val inlineToggles = patch.advancedOptions
.filterIsInstance<OptionSpec.Toggle>() .filterIsInstance<OptionSpec.Toggle>()
.filter { it.inline } .filter { it.inline }
if (inlineToggles.isNotEmpty()) {
AnimatedVisibility(visible = checked) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 4.dp),
verticalArrangement = Arrangement.spacedBy(2.dp),
) {
for (option in inlineToggles) key(option.key) {
InlineToggleRow(
title = option.title,
description = option.description,
checked = optionState.toggle(patch, option),
onCheckedChange = { optionState.setToggle(patch, option, it) },
)
}
}
}
}
val hasSheetOptions = patch.advancedOptions.any { it !is OptionSpec.Toggle || !it.inline } val hasSheetOptions = patch.advancedOptions.any { it !is OptionSpec.Toggle || !it.inline }
if (hasSheetOptions) { val hasSettings = patch.variants.isNotEmpty() || inlineToggles.isNotEmpty() || hasSheetOptions
AnimatedVisibility(visible = checked) {
Box( // When a patch is enabled and has settings show a carded view of the settings
modifier = Modifier val carded = checked && hasSettings
.fillMaxWidth() Column(
.padding(vertical = 4.dp), modifier = if (carded) {
contentAlignment = Alignment.Center, Modifier
) { .fillMaxWidth()
AdvancedOptionsButton( .clip(MaterialTheme.shapes.medium)
modified = optionState.isModified(patch), .background(MaterialTheme.colorScheme.primary.copy(alpha = 0.07f))
onClick = { advancedFor = patch }, .border(
width = 1.5.dp,
color = MaterialTheme.colorScheme.primary.copy(alpha = 0.55f),
shape = MaterialTheme.shapes.medium,
) )
.padding(horizontal = 12.dp, vertical = 4.dp)
} else {
Modifier.fillMaxWidth()
},
) {
PatchSwitchRow(
title = patch.title,
description = patch.description,
checked = checked,
lock = lock,
onCheckedChange = { onToggle(patch, it) },
onLockedTap = { lockInfo = LockInfo(patch, lock) },
)
if (hasSettings) {
AnimatedVisibility(visible = checked) {
Column(
verticalArrangement = Arrangement.spacedBy(10.dp),
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 8.dp),
) {
if (patch.variants.isNotEmpty()) {
val effective = patch.effectiveVariants { optionState.toggle(patch, it) }
val resolved = patch.resolveVariantIndex(variantIndex(patch)) {
optionState.toggle(patch, it)
}
PatchVariantSelector(
variants = effective,
selectedIndex = effective
.indexOfFirst { it.originalIndex == resolved }
.coerceAtLeast(0),
onSelect = { pos ->
effective.getOrNull(pos)?.let { onSelectVariant(patch, it.originalIndex) }
},
)
}
for (option in inlineToggles) key(option.key) {
InlineToggleRow(
title = option.title,
description = option.description,
checked = optionState.toggle(patch, option),
onCheckedChange = { optionState.setToggle(patch, option, it) },
)
}
if (hasSheetOptions) {
Box(
modifier = Modifier.fillMaxWidth(),
contentAlignment = Alignment.Center,
) {
AdvancedOptionsButton(
modified = optionState.isModified(patch),
onClick = { advancedFor = patch },
)
}
}
}
} }
} }
} }
@@ -361,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
} }
@@ -380,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()
@@ -5,6 +5,8 @@ import android.app.Activity
import android.content.* import android.content.*
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.content.res.Resources import android.content.res.Resources
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.net.Uri import android.net.Uri
import android.os.* import android.os.*
import android.provider.Settings import android.provider.Settings
@@ -63,6 +65,15 @@ fun Context.getPackageVersion(pkg: String): Pair<String?, Int> {
.let { it.versionName to it.versionCode } .let { it.versionName to it.versionCode }
} }
// Whether the device currently has a validated internet connection
fun Context.isOnline(): Boolean {
val cm = getSystemService<ConnectivityManager>() ?: return true
val network = cm.activeNetwork ?: return false
val caps = cm.getNetworkCapabilities(network) ?: return false
return caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
}
fun Context.isPackageInstalled(packageName: String): Boolean { fun Context.isPackageInstalled(packageName: String): Boolean {
return try { return try {
packageManager.getPackageInfo(packageName, 0) packageManager.getPackageInfo(packageName, 0)
@@ -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>
+29 -1
View File
@@ -180,7 +180,7 @@
<string name="install_error_timeout">Installer timed out</string> <string name="install_error_timeout">Installer timed out</string>
<string name="install_group_prepare">Prepare</string> <string name="install_group_prepare">Prepare</string>
<string name="install_group_download">Download dependencies</string> <string name="install_group_download">Download Batteries</string>
<string name="install_group_patch">Patch APK</string> <string name="install_group_patch">Patch APK</string>
<string name="install_group_install">Install APK</string> <string name="install_group_install">Install APK</string>
@@ -247,14 +247,23 @@
<string name="patchopts_custom_tidal_apk_desc">Provide your own Stock TIDAL APK to patch instead of the version from Github.</string> <string name="patchopts_custom_tidal_apk_desc">Provide your own Stock TIDAL APK to patch instead of the version from Github.</string>
<string name="patchopts_custom_patches_title">Custom Patches</string> <string name="patchopts_custom_patches_title">Custom Patches</string>
<string name="patchopts_custom_patches_desc">Provide your own Patches Zip to use instead of the ones from Github.</string> <string name="patchopts_custom_patches_desc">Provide your own Patches Zip to use instead of the ones from Github.</string>
<string name="patchopts_bypass_incompatible_title">Bypass Incompatible</string>
<string name="patchopts_bypass_incompatible_desc">Force-allow path-gated patches. This can be VERY DANGEROUS!</string>
<string name="patchopts_divider_basic">Basic</string> <string name="patchopts_divider_basic">Basic</string>
<string name="patchopts_divider_advanced">Advanced</string> <string name="patchopts_divider_advanced">Advanced</string>
<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>
@@ -286,6 +295,19 @@
<string <string
name="patch_debug_menu_unlock_desc" name="patch_debug_menu_unlock_desc"
>Reveals TIDAL\'s hidden Debug Menu in Settings. (Unlocks Feature Flags &amp; the legacy Debug Options)</string> >Reveals TIDAL\'s hidden Debug Menu in Settings. (Unlocks Feature Flags &amp; the legacy Debug Options)</string>
<string name="patch_waze_integration_title">Waze Integration</string>
<string name="patch_waze_integration_desc">Control TIDAL playback from the Waze app</string>
<string name="patch_waze_browse_root_title">Media Menu</string>
<string name="patch_waze_accent_color_title">Accent Color</string>
<string name="patch_waze_color_waze_default">Waze Default</string>
<string name="patch_waze_color_tidal_cyan">TIDAL Cyan</string>
<string name="patch_waze_color_material_you">Material You</string>
<string name="patch_waze_root_auto">Auto Menu</string>
<string name="patch_waze_root_home">Home</string>
<string name="patch_waze_root_recents">Recents</string>
<string name="patch_color_picker_title">Custom color</string>
<string name="patch_color_picker_hex">Hex color</string>
<string name="patch_color_picker_hex_error">Use #RRGGBB or #AARRGGBB.</string>
<string name="patch_enable_legacy_ui_title">Enable Legacy UI</string> <string name="patch_enable_legacy_ui_title">Enable Legacy UI</string>
<string <string
name="patch_enable_legacy_ui_desc" name="patch_enable_legacy_ui_desc"
@@ -295,6 +317,10 @@
<string name="patch_mini_player_redesign_desc">Integrates the Seekbar into the control panel at the bottom of the screen.</string> <string name="patch_mini_player_redesign_desc">Integrates the Seekbar into the control panel at the bottom of the screen.</string>
<string name="patch_mini_player_gestures_title">Mini-Player Gestures</string> <string name="patch_mini_player_gestures_title">Mini-Player Gestures</string>
<string name="patch_mini_player_gestures_desc">Swipe up on the mini-player to open the full player.</string> <string name="patch_mini_player_gestures_desc">Swipe up on the mini-player to open the full player.</string>
<string name="patch_mini_player_drag_title">Swipe Up Style</string>
<string name="patch_mini_player_drag_desc">Whether the player follows your finger when swiping up to open it.</string>
<string name="patch_mini_player_drag_static">Static</string>
<string name="patch_mini_player_drag_drag">Drag</string>
<string name="patch_mini_player_left_right_gestures_title">Next/Previous Gestures</string> <string name="patch_mini_player_left_right_gestures_title">Next/Previous Gestures</string>
<string name="patch_mini_player_left_right_gestures_desc">Swipe left or right on the mini-player to skip tracks.</string> <string name="patch_mini_player_left_right_gestures_desc">Swipe left or right on the mini-player to skip tracks.</string>
<string name="patch_mini_player_dynamic_bg_title">Mini-Player Dynamic Background</string> <string name="patch_mini_player_dynamic_bg_title">Mini-Player Dynamic Background</string>
@@ -316,6 +342,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>
+9 -9
View File
@@ -1,11 +1,11 @@
--- a/com/tidal/android/feature/appscaffold/ui/p.smali --- a/com/tidal/android/feature/appscaffold/ui/r.smali
+++ b/com/tidal/android/feature/appscaffold/ui/p.smali +++ b/com/tidal/android/feature/appscaffold/ui/r.smali
@@ -51,6 +51,8 @@ @@ -48,6 +48,8 @@
.line 10 .line 5
iput-object p4, p0, Lcom/tidal/android/feature/appscaffold/ui/p;->d:Ljava/lang/String; iput-object p4, p0, Lcom/tidal/android/feature/appscaffold/ui/r;->d:Ljava/lang/String;
+ invoke-static {p3, p4}, Lradiant/HomeBackdrop;->fromMiniPlayer(ILjava/lang/String;)V # capture cover state + invoke-static {p3, p4}, Lradiant/HomeBackdrop;->fromMiniPlayer(ILjava/lang/String;)V # capture cover state
+ +
.line 11 .line 6
.line 12 iput-boolean p5, p0, Lcom/tidal/android/feature/appscaffold/ui/r;->e:Z
iput-boolean p5, p0, Lcom/tidal/android/feature/appscaffold/ui/p;->e:Z
+2 -2
View File
@@ -1,5 +1,5 @@
{ {
"tidalVersionCode": 9090, "tidalVersionCode": 10002,
"tidalApkUrl": "https://github.com/meowarex/rl-mobile/releases/download/latest/tidal-stock.apk", "tidalApkUrl": "https://github.com/meowarex/rl-mobile/releases/download/latest/tidal-stock.apk",
"patchesVersion": "0.9.12" "patchesVersion": "0.10.1"
} }
+10 -9
View File
@@ -3,17 +3,17 @@
@@ -54,6 +54,9 @@ @@ -54,6 +54,9 @@
.method public final a()Z .method public final a()Z
.locals 2 .locals 2
+ const/4 v0, 0x1 # force true + const/4 v0, 0x1 # force true
+ return v0 # bypass debug flag + return v0 # bypass debug flag
+ +
.line 1 .line 1
iget-object v0, p0, Lcom/tidal/android/core/debug/DebugFeatureInteractorDefault;->a:Lcom/tidal/android/featureflags/l; iget-object v0, p0, Lcom/tidal/android/core/debug/DebugFeatureInteractorDefault;->a:Lcom/tidal/android/featureflags/l;
@@ -98,6 +101,14 @@ @@ -99,6 +102,14 @@
} }
.end annotation .end annotation
+ sget-object v0, Ljava/lang/Boolean;->TRUE:Ljava/lang/Boolean; # always-true value + sget-object v0, Ljava/lang/Boolean;->TRUE:Ljava/lang/Boolean; # always-true value
+ +
+ invoke-static {v0}, Lkotlinx/coroutines/flow/StateFlowKt;->MutableStateFlow(Ljava/lang/Object;)Lkotlinx/coroutines/flow/MutableStateFlow; # wrap in flow + invoke-static {v0}, Lkotlinx/coroutines/flow/StateFlowKt;->MutableStateFlow(Ljava/lang/Object;)Lkotlinx/coroutines/flow/MutableStateFlow; # wrap in flow
@@ -23,14 +23,15 @@
+ return-object v0 # short-circuit b() + return-object v0 # short-circuit b()
+ +
.line 1 .line 1
sget-object v0, Lj50/a;->a:Ljava/lang/String; sget-object v0, Lp50/a;->a:Ljava/lang/String;
@@ -261,5 +272,8 @@ @@ -261,6 +272,9 @@
.method public final c()Z .method public final c()Z
.locals 3 .locals 3
+ const/4 v0, 0x1 # force true + const/4 v0, 0x1 # force true
+ return v0 # bypass debug flag + return v0 # bypass debug flag
+ +
.line 1 .line 1
sget-object v0, Lj50/a;->a:Ljava/lang/String; sget-object v0, Lp50/a;->a:Ljava/lang/String;
+5 -6
View File
@@ -1,12 +1,11 @@
--- a/kg/e.smali --- a/jg/d.smali
+++ b/kg/e.smali +++ b/jg/d.smali
@@ -26,8 +26,8 @@ @@ -27,7 +27,7 @@
new-instance v0, Lkg/e;
.line 2 .line 2
.line 3 .line 3
- const-string v1, "player-market-ui" - const-string v1, "player-market-ui"
+ const-string v1, "player-market-ui-rl-forced-off" # break flag key lookup + const-string v1, "player-market-ui-rl-forced-off" # break flag key lookup
.line 4 .line 4
.line 5 .line 5
@@ -1,13 +1,12 @@
.class public final Lcom/tidal/android/feature/appscaffold/ui/q$c; .class public final Lcom/tidal/android/feature/appscaffold/ui/s$c;
.super Lcom/tidal/android/feature/appscaffold/ui/q; .super Lcom/tidal/android/feature/appscaffold/ui/s;
.source "SourceFile" .source "SourceFile"
# Synthetic mini-player event used by right swipe (previous/rewind). # Synthetic mini-player event used by right swipe (previous/rewind).
# TIDAL already exposes q$a for next in this path
# annotations # annotations
.annotation system Ldalvik/annotation/EnclosingClass; .annotation system Ldalvik/annotation/EnclosingClass;
value = Lcom/tidal/android/feature/appscaffold/ui/q; value = Lcom/tidal/android/feature/appscaffold/ui/s;
.end annotation .end annotation
.annotation system Ldalvik/annotation/InnerClass; .annotation system Ldalvik/annotation/InnerClass;
@@ -17,18 +16,18 @@
# static fields # static fields
.field public static final a:Lcom/tidal/android/feature/appscaffold/ui/q$c; .field public static final a:Lcom/tidal/android/feature/appscaffold/ui/s$c;
# direct methods # direct methods
.method static constructor <clinit>()V .method static constructor <clinit>()V
.locals 1 .locals 1
new-instance v0, Lcom/tidal/android/feature/appscaffold/ui/q$c; new-instance v0, Lcom/tidal/android/feature/appscaffold/ui/s$c;
invoke-direct {v0}, Lcom/tidal/android/feature/appscaffold/ui/q;-><init>()V invoke-direct {v0}, Lcom/tidal/android/feature/appscaffold/ui/s;-><init>()V
sput-object v0, Lcom/tidal/android/feature/appscaffold/ui/q$c;->a:Lcom/tidal/android/feature/appscaffold/ui/q$c; sput-object v0, Lcom/tidal/android/feature/appscaffold/ui/s$c;->a:Lcom/tidal/android/feature/appscaffold/ui/s$c;
return-void return-void
.end method .end method
@@ -45,7 +44,7 @@
return v0 return v0
:cond_0 :cond_0
instance-of p1, p1, Lcom/tidal/android/feature/appscaffold/ui/q$c; instance-of p1, p1, Lcom/tidal/android/feature/appscaffold/ui/s$c;
if-nez p1, :cond_1 if-nez p1, :cond_1
+3 -3
View File
@@ -273,9 +273,9 @@
sget v2, Lradiant/HomeBackdrop;->currentAlbumId:I sget v2, Lradiant/HomeBackdrop;->currentAlbumId:I
new-instance v3, Lcom/tidal/android/feature/playerscreen/ui/composables/n0; new-instance v3, Lcom/tidal/android/feature/playerscreen/ui/composables/o0;
invoke-direct {v3, v2, v1}, Lcom/tidal/android/feature/playerscreen/ui/composables/n0;-><init>(ILjava/lang/String;)V invoke-direct {v3, v2, v1}, Lcom/tidal/android/feature/playerscreen/ui/composables/o0;-><init>(ILjava/lang/String;)V
sget-object v4, Landroidx/compose/ui/Modifier;->Companion:Landroidx/compose/ui/Modifier$Companion; sget-object v4, Landroidx/compose/ui/Modifier;->Companion:Landroidx/compose/ui/Modifier$Companion;
@@ -331,7 +331,7 @@
const/16 v15, 0x48 const/16 v15, 0x48
invoke-static/range {v6 .. v15}, Lxd0/f;->a(Lyl0/l;Ljava/lang/String;Landroidx/compose/ui/Modifier;Landroidx/compose/ui/graphics/ColorFilter;Landroidx/compose/ui/layout/ContentScale;Ljava/lang/Object;Lyl0/a;Landroidx/compose/runtime/Composer;II)V invoke-static/range {v6 .. v15}, Lee0/e;->a(Lem0/l;Ljava/lang/String;Landroidx/compose/ui/Modifier;Landroidx/compose/ui/graphics/ColorFilter;Landroidx/compose/ui/layout/ContentScale;Ljava/lang/Object;Lem0/a;Landroidx/compose/runtime/Composer;II)V
sget-object v3, Landroidx/compose/ui/Modifier;->Companion:Landroidx/compose/ui/Modifier$Companion; sget-object v3, Landroidx/compose/ui/Modifier;->Companion:Landroidx/compose/ui/Modifier$Companion;
@@ -0,0 +1,21 @@
.class public final Lradiant/LyricsReinitGuard;
.super Ljava/lang/Object;
.source "LyricsReinitGuard.smali"
# static fields
# stuff that makes lyrics view stays open.. i forgot what it actually does other than short circuit a call or some shit <3
.field public static lastMediaId:I
# direct methods
.method static constructor <clinit>()V
.locals 1
const/4 v0, -0x1
sput v0, Lradiant/LyricsReinitGuard;->lastMediaId:I
return-void
.end method
@@ -83,7 +83,7 @@
const/16 v7, 0x8 const/16 v7, 0x8
invoke-static/range {v0 .. v7}, Landroidx/compose/animation/SingleValueAnimationKt;->animateColorAsState-euL9pac(JLandroidx/compose/animation/core/AnimationSpec;Ljava/lang/String;Lyl0/l;Landroidx/compose/runtime/Composer;II)Landroidx/compose/runtime/State; invoke-static/range {v0 .. v7}, Landroidx/compose/animation/SingleValueAnimationKt;->animateColorAsState-euL9pac(JLandroidx/compose/animation/core/AnimationSpec;Ljava/lang/String;Lem0/l;Landroidx/compose/runtime/Composer;II)Landroidx/compose/runtime/State;
move-result-object v0 move-result-object v0
@@ -0,0 +1,70 @@
.class public final Lradiant/MiniPlayerGestures$FeedbackLayer;
.super Ljava/lang/Object;
.implements Lem0/l;
# annotations
.annotation system Ldalvik/annotation/EnclosingClass;
value = Lradiant/MiniPlayerGestures;
.end annotation
.annotation system Ldalvik/annotation/InnerClass;
accessFlags = 0x19
name = "FeedbackLayer"
.end annotation
# static fields
.field public static final INSTANCE:Lradiant/MiniPlayerGestures$FeedbackLayer;
# direct methods
.method static constructor <clinit>()V
.locals 1
new-instance v0, Lradiant/MiniPlayerGestures$FeedbackLayer;
invoke-direct {v0}, Lradiant/MiniPlayerGestures$FeedbackLayer;-><init>()V
sput-object v0, Lradiant/MiniPlayerGestures$FeedbackLayer;->INSTANCE:Lradiant/MiniPlayerGestures$FeedbackLayer;
return-void
.end method
.method private constructor <init>()V
.locals 0
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void
.end method
# virtual methods
.method public final invoke(Landroidx/compose/ui/graphics/GraphicsLayerScope;)Lkotlin/v;
.locals 1
sget-object v0, Lradiant/MiniPlayerGestures;->v:Landroidx/compose/runtime/MutableFloatState;
invoke-interface {v0}, Landroidx/compose/runtime/MutableFloatState;->getFloatValue()F
move-result v0
invoke-interface {p1, v0}, Landroidx/compose/ui/graphics/GraphicsLayerScope;->setTranslationY(F)V
sget-object p1, Lkotlin/v;->a:Lkotlin/v;
return-object p1
.end method
.method public bridge synthetic invoke(Ljava/lang/Object;)Ljava/lang/Object;
.locals 0
check-cast p1, Landroidx/compose/ui/graphics/GraphicsLayerScope;
invoke-virtual {p0, p1}, Lradiant/MiniPlayerGestures$FeedbackLayer;->invoke(Landroidx/compose/ui/graphics/GraphicsLayerScope;)Lkotlin/v;
move-result-object p1
return-object p1
.end method
@@ -0,0 +1,60 @@
.class public final Lradiant/MiniPlayerGestures$FeedbackResetAnimator;
.super Ljava/lang/Object;
.implements Landroid/animation/ValueAnimator$AnimatorUpdateListener;
# annotations
.annotation system Ldalvik/annotation/EnclosingClass;
value = Lradiant/MiniPlayerGestures;
.end annotation
.annotation system Ldalvik/annotation/InnerClass;
accessFlags = 0x19
name = "FeedbackResetAnimator"
.end annotation
# direct methods
.method public constructor <init>()V
.locals 0
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void
.end method
# virtual methods
.method public final onAnimationUpdate(Landroid/animation/ValueAnimator;)V
.locals 3
move-object v0, p1
invoke-virtual {p1}, Landroid/animation/ValueAnimator;->getAnimatedValue()Ljava/lang/Object;
move-result-object v1
check-cast v1, Ljava/lang/Float;
invoke-virtual {v1}, Ljava/lang/Float;->floatValue()F
move-result v1
invoke-static {v1}, Lradiant/MiniPlayerGestures;->setSwipeFeedbackDirect(F)V
invoke-virtual {v0}, Landroid/animation/ValueAnimator;->getAnimatedFraction()F
move-result v1
const/high16 v2, 0x3f800000 # 1.0f
cmpg-float v1, v1, v2
if-gez v1, :done
invoke-static {v0}, Lradiant/MiniPlayerGestures;->clearSwipeFeedbackAnimator(Landroid/animation/ValueAnimator;)V
:done
return-void
.end method
@@ -1,6 +1,6 @@
.class public final Lradiant/MiniPlayerGestures$Gesture; .class public final Lradiant/MiniPlayerGestures$Gesture;
.super Ljava/lang/Object; .super Ljava/lang/Object;
.implements Lyl0/l; .implements Lem0/l;
# annotations # annotations
.annotation system Ldalvik/annotation/EnclosingClass; .annotation system Ldalvik/annotation/EnclosingClass;
@@ -14,7 +14,7 @@
# instance fields # instance fields
.field public final a:Lyl0/l; .field public final a:Lem0/l;
# Y at ACTION_DOWN # Y at ACTION_DOWN
.field public b:F .field public b:F
@@ -38,17 +38,22 @@
# True once horizontal movement wins (prevents later vertical start) # True once horizontal movement wins (prevents later vertical start)
.field public j:Z .field public j:Z
# Drag option enabled
.field public final k:Z
# direct methods # direct methods
.method public constructor <init>(Lyl0/l;Landroidx/compose/material3/SheetState;)V .method public constructor <init>(Lem0/l;Landroidx/compose/material3/SheetState;Z)V
.locals 0 .locals 0
invoke-direct {p0}, Ljava/lang/Object;-><init>()V invoke-direct {p0}, Ljava/lang/Object;-><init>()V
iput-object p1, p0, Lradiant/MiniPlayerGestures$Gesture;->a:Lyl0/l; iput-object p1, p0, Lradiant/MiniPlayerGestures$Gesture;->a:Lem0/l;
iput-object p2, p0, Lradiant/MiniPlayerGestures$Gesture;->f:Landroidx/compose/material3/SheetState; iput-object p2, p0, Lradiant/MiniPlayerGestures$Gesture;->f:Landroidx/compose/material3/SheetState;
iput-boolean p3, p0, Lradiant/MiniPlayerGestures$Gesture;->k:Z
return-void return-void
.end method .end method
@@ -85,9 +90,9 @@
iget-object v0, p0, Lradiant/MiniPlayerGestures$Gesture;->f:Landroidx/compose/material3/SheetState; iget-object v0, p0, Lradiant/MiniPlayerGestures$Gesture;->f:Landroidx/compose/material3/SheetState;
iget-object v1, p0, Lradiant/MiniPlayerGestures$Gesture;->a:Lyl0/l; iget-object v1, p0, Lradiant/MiniPlayerGestures$Gesture;->a:Lem0/l;
invoke-static {v0, v1, p1}, Lradiant/MiniPlayerGestures;->finishDrag(Landroidx/compose/material3/SheetState;Lyl0/l;F)V invoke-static {v0, v1, p1}, Lradiant/MiniPlayerGestures;->finishDrag(Landroidx/compose/material3/SheetState;Lem0/l;F)V
return-void return-void
.end method .end method
@@ -95,11 +100,11 @@
.method private openPlayer()V .method private openPlayer()V
.locals 2 .locals 2
iget-object v0, p0, Lradiant/MiniPlayerGestures$Gesture;->a:Lyl0/l; iget-object v0, p0, Lradiant/MiniPlayerGestures$Gesture;->a:Lem0/l;
sget-object v1, Lcom/tidal/android/feature/appscaffold/ui/b$b;->a:Lcom/tidal/android/feature/appscaffold/ui/b$b; sget-object v1, Lcom/tidal/android/feature/appscaffold/ui/b$b;->a:Lcom/tidal/android/feature/appscaffold/ui/b$b;
invoke-interface {v0, v1}, Lyl0/l;->invoke(Ljava/lang/Object;)Ljava/lang/Object; invoke-interface {v0, v1}, Lem0/l;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
return-void return-void
.end method .end method
@@ -150,6 +155,10 @@
iput-boolean v0, p0, Lradiant/MiniPlayerGestures$Gesture;->e:Z 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-object v1, p0, Lradiant/MiniPlayerGestures$Gesture;->f:Landroidx/compose/material3/SheetState;
iget v0, p0, Lradiant/MiniPlayerGestures$Gesture;->b:F iget v0, p0, Lradiant/MiniPlayerGestures$Gesture;->b:F
@@ -158,13 +167,14 @@
invoke-direct {p0}, Lradiant/MiniPlayerGestures$Gesture;->openPlayer()V invoke-direct {p0}, Lradiant/MiniPlayerGestures$Gesture;->openPlayer()V
:done
return-void return-void
.end method .end method
# virtual methods # virtual methods
# Listens for MotionEvents # Listens for MotionEvents
.method public final invoke(Landroid/view/MotionEvent;)Lkotlin/u; .method public final invoke(Landroid/view/MotionEvent;)Lkotlin/v;
.locals 11 .locals 11
invoke-virtual {p1}, Landroid/view/MotionEvent;->getActionMasked()I invoke-virtual {p1}, Landroid/view/MotionEvent;->getActionMasked()I
@@ -189,6 +199,8 @@
# ACTION_DOWN # ACTION_DOWN
:down :down
invoke-static {}, Lradiant/MiniPlayerGestures;->resetGestureLock()V
invoke-static {p1}, Lradiant/MiniPlayerGestures;->beginMotion(Landroid/view/MotionEvent;)V invoke-static {p1}, Lradiant/MiniPlayerGestures;->beginMotion(Landroid/view/MotionEvent;)V
invoke-virtual {p1}, Landroid/view/MotionEvent;->getRawY()F invoke-virtual {p1}, Landroid/view/MotionEvent;->getRawY()F
@@ -221,6 +233,12 @@
iput-boolean v0, p0, Lradiant/MiniPlayerGestures$Gesture;->j:Z iput-boolean v0, p0, Lradiant/MiniPlayerGestures$Gesture;->j:Z
iget v0, p0, Lradiant/MiniPlayerGestures$Gesture;->b:F
invoke-static {v0}, Lradiant/MiniPlayerGestures;->beginSwipeGesture(F)V
:skip_feedback_down
goto :done goto :done
# ACTION_MOVE # ACTION_MOVE
@@ -253,8 +271,17 @@
if-eqz v3, :maybe_start if-eqz v3, :maybe_start
invoke-static {}, Lradiant/MiniPlayerGestures;->suppressHorizontalGestures()V
iget-boolean v3, p0, Lradiant/MiniPlayerGestures$Gesture;->k:Z
if-eqz v3, :feedback_active
invoke-direct {p0, v2, v5, v6}, Lradiant/MiniPlayerGestures$Gesture;->dragSheet(FJ)V invoke-direct {p0, v2, v5, v6}, Lradiant/MiniPlayerGestures$Gesture;->dragSheet(FJ)V
:feedback_active
invoke-static {v2}, Lradiant/MiniPlayerGestures;->setSwipeFeedbackFromDrag(F)V
goto :store_last goto :store_last
:maybe_start :maybe_start
@@ -281,28 +308,60 @@
move-result v8 move-result v8
const/high16 v9, 0x41800000 # 16.0f const/high16 v9, 0x40c00000 # 6.0f axis deadzone
invoke-static {v9}, Lradiant/MiniPlayerGestures$Gesture;->dp(F)F invoke-static {v9}, Lradiant/MiniPlayerGestures$Gesture;->dp(F)F
move-result v9 move-result v9
invoke-static {}, Lradiant/MiniPlayerGestures;->isHorizontalGestureLocked()Z
move-result v10
if-eqz v10, :horizontal_check
const/4 v10, 0x0
invoke-static {v10}, Lradiant/MiniPlayerGestures;->setSwipeFeedbackDirect(F)V
goto :store_last
:horizontal_check
cmpg-float v10, v7, v9 cmpg-float v10, v7, v9
if-gez v10, :vertical_check if-gez v10, :horizontal_dominance
const/high16 v10, 0x3fc00000 # 1.5f goto :vertical_check
:horizontal_dominance
const v10, 0x3f8ccccd # 1.1f
mul-float/2addr v10, v8 mul-float/2addr v10, v8
cmpl-float v10, v7, v10 cmpg-float v10, v7, v10
if-lez v10, :vertical_check if-gez v10, :horizontal_wins
goto :vertical_check
:horizontal_wins
invoke-static {}, Lradiant/MiniPlayerGestures;->lockHorizontalGesture()Z
move-result v10
if-eqz v10, :store_last
const/4 v10, 0x1 const/4 v10, 0x1
iput-boolean v10, p0, Lradiant/MiniPlayerGestures$Gesture;->j:Z iput-boolean v10, p0, Lradiant/MiniPlayerGestures$Gesture;->j:Z
const/4 v10, 0x0
invoke-static {v10}, Lradiant/MiniPlayerGestures;->setSwipeFeedbackDirect(F)V
goto :store_last goto :store_last
# At least 16dp up to open the player # At least 16dp up to open the player
@@ -313,10 +372,12 @@
if-lez v10, :vertical_dominance if-lez v10, :vertical_dominance
invoke-static {v2}, Lradiant/MiniPlayerGestures;->setSwipeFeedbackFromDrag(F)V
goto :store_last goto :store_last
:vertical_dominance :vertical_dominance
const/high16 v10, 0x3fc00000 # 1.5f -> has to dominate horizontal mov. by 1.5x const v10, 0x3f8ccccd # 1.1f -> early vertical axis lock
mul-float/2addr v7, v10 mul-float/2addr v7, v10
@@ -327,10 +388,29 @@
goto :store_last goto :store_last
:begin :begin
invoke-static {}, Lradiant/MiniPlayerGestures;->lockVerticalGesture()Z
move-result v10
if-eqz v10, :store_last
invoke-direct {p0, v2, v5, v6}, Lradiant/MiniPlayerGestures$Gesture;->startSheet(FJ)V invoke-direct {p0, v2, v5, v6}, Lradiant/MiniPlayerGestures$Gesture;->startSheet(FJ)V
iget-boolean v10, p0, Lradiant/MiniPlayerGestures$Gesture;->e:Z
if-eqz v10, :store_last
invoke-static {}, Lradiant/MiniPlayerGestures;->suppressHorizontalGestures()V
iget-boolean v10, p0, Lradiant/MiniPlayerGestures$Gesture;->k:Z
if-eqz v10, :feedback_begin
invoke-direct {p0, v2, v5, v6}, Lradiant/MiniPlayerGestures$Gesture;->dragSheet(FJ)V invoke-direct {p0, v2, v5, v6}, Lradiant/MiniPlayerGestures$Gesture;->dragSheet(FJ)V
:feedback_begin
invoke-static {v2}, Lradiant/MiniPlayerGestures;->setSwipeFeedbackFromDrag(F)V
:store_last :store_last
iput v0, p0, Lradiant/MiniPlayerGestures$Gesture;->c:F iput v0, p0, Lradiant/MiniPlayerGestures$Gesture;->c:F
@@ -345,7 +425,11 @@
iget-boolean v0, p0, Lradiant/MiniPlayerGestures$Gesture;->e:Z iget-boolean v0, p0, Lradiant/MiniPlayerGestures$Gesture;->e:Z
if-eqz v0, :finish if-eqz v0, :up_no_drag
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-static {p1}, Lradiant/MiniPlayerGestures;->trackMotion(Landroid/view/MotionEvent;)V
@@ -367,6 +451,28 @@
invoke-direct {p0, v0}, Lradiant/MiniPlayerGestures$Gesture;->finishSheet(F)V invoke-direct {p0, v0}, Lradiant/MiniPlayerGestures$Gesture;->finishSheet(F)V
invoke-static {}, Lradiant/MiniPlayerGestures;->animateSwipeFeedbackReset()V
goto :finish
:up_no_drag
invoke-static {}, Lradiant/MiniPlayerGestures;->animateSwipeFeedbackReset()V
goto :finish
:open_simple
invoke-static {}, Lradiant/MiniPlayerGestures;->suppressHorizontalGestures()V
invoke-virtual {p1}, Landroid/view/MotionEvent;->getRawY()F
move-result v0
iget-object v1, p0, Lradiant/MiniPlayerGestures$Gesture;->a:Lem0/l;
invoke-static {v1, v0}, Lradiant/MiniPlayerGestures;->completeSimpleSwipe(Lem0/l;F)Z
invoke-static {}, Lradiant/MiniPlayerGestures;->animateSwipeFeedbackReset()V
:finish :finish
invoke-direct {p0}, Lradiant/MiniPlayerGestures$Gesture;->reset()V invoke-direct {p0}, Lradiant/MiniPlayerGestures$Gesture;->reset()V
@@ -377,20 +483,27 @@
:cancel :cancel
iget-boolean v0, p0, Lradiant/MiniPlayerGestures$Gesture;->e:Z iget-boolean v0, p0, Lradiant/MiniPlayerGestures$Gesture;->e:Z
if-eqz v0, :cancel_reset if-eqz v0, :cancel_no_active
invoke-static {}, Lradiant/MiniPlayerGestures;->animateSwipeFeedbackReset()V
iget-object v0, p0, Lradiant/MiniPlayerGestures$Gesture;->f:Landroidx/compose/material3/SheetState; iget-object v0, p0, Lradiant/MiniPlayerGestures$Gesture;->f:Landroidx/compose/material3/SheetState;
iget-object v1, p0, Lradiant/MiniPlayerGestures$Gesture;->a:Lyl0/l; iget-object v1, p0, Lradiant/MiniPlayerGestures$Gesture;->a:Lem0/l;
invoke-static {v0, v1}, Lradiant/MiniPlayerGestures;->cancelDrag(Landroidx/compose/material3/SheetState;Lyl0/l;)V invoke-static {v0, v1}, Lradiant/MiniPlayerGestures;->cancelDrag(Landroidx/compose/material3/SheetState;Lem0/l;)V
goto :cancel_reset
:cancel_no_active
invoke-static {}, Lradiant/MiniPlayerGestures;->animateSwipeFeedbackReset()V
:cancel_reset :cancel_reset
invoke-direct {p0}, Lradiant/MiniPlayerGestures$Gesture;->reset()V invoke-direct {p0}, Lradiant/MiniPlayerGestures$Gesture;->reset()V
:done :done
sget-object p1, Lkotlin/u;->a:Lkotlin/u; sget-object p1, Lkotlin/v;->a:Lkotlin/v;
return-object p1 return-object p1
.end method .end method
@@ -400,7 +513,7 @@
check-cast p1, Landroid/view/MotionEvent; check-cast p1, Landroid/view/MotionEvent;
invoke-virtual {p0, p1}, Lradiant/MiniPlayerGestures$Gesture;->invoke(Landroid/view/MotionEvent;)Lkotlin/u; invoke-virtual {p0, p1}, Lradiant/MiniPlayerGestures$Gesture;->invoke(Landroid/view/MotionEvent;)Lkotlin/v;
move-result-object p1 move-result-object p1
@@ -1,6 +1,6 @@
.class public final Lradiant/MiniPlayerGestures$RootGesture; .class public final Lradiant/MiniPlayerGestures$RootGesture;
.super Ljava/lang/Object; .super Ljava/lang/Object;
.implements Lyl0/l; .implements Lem0/l;
# annotations # annotations
@@ -15,18 +15,18 @@
# instance fields # instance fields
.field public final a:Lyl0/l; .field public final a:Lem0/l;
.field public final b:Landroidx/compose/material3/SheetState; .field public final b:Landroidx/compose/material3/SheetState;
# direct methods # direct methods
.method public constructor <init>(Lyl0/l;Landroidx/compose/material3/SheetState;)V .method public constructor <init>(Lem0/l;Landroidx/compose/material3/SheetState;)V
.locals 0 .locals 0
invoke-direct {p0}, Ljava/lang/Object;-><init>()V invoke-direct {p0}, Ljava/lang/Object;-><init>()V
iput-object p1, p0, Lradiant/MiniPlayerGestures$RootGesture;->a:Lyl0/l; iput-object p1, p0, Lradiant/MiniPlayerGestures$RootGesture;->a:Lem0/l;
iput-object p2, p0, Lradiant/MiniPlayerGestures$RootGesture;->b:Landroidx/compose/material3/SheetState; iput-object p2, p0, Lradiant/MiniPlayerGestures$RootGesture;->b:Landroidx/compose/material3/SheetState;
@@ -35,21 +35,21 @@
# virtual methods # virtual methods
.method public final invoke(Landroid/view/MotionEvent;)Lkotlin/u; .method public final invoke(Landroid/view/MotionEvent;)Lkotlin/v;
.locals 6 .locals 6
iget-object v0, p0, Lradiant/MiniPlayerGestures$RootGesture;->b:Landroidx/compose/material3/SheetState; iget-object v0, p0, Lradiant/MiniPlayerGestures$RootGesture;->b:Landroidx/compose/material3/SheetState;
invoke-static {v0}, Lradiant/MiniPlayerGestures;->isDragging(Landroidx/compose/material3/SheetState;)Z
move-result v1
if-eqz v1, :done
invoke-virtual {p1}, Landroid/view/MotionEvent;->getActionMasked()I invoke-virtual {p1}, Landroid/view/MotionEvent;->getActionMasked()I
move-result v1 move-result v1
invoke-static {v0}, Lradiant/MiniPlayerGestures;->isDragging(Landroidx/compose/material3/SheetState;)Z
move-result v2
if-eqz v2, :maybe_reset_only
const/4 v2, 0x1 const/4 v2, 0x1
if-eq v1, v2, :up if-eq v1, v2, :up
@@ -64,6 +64,51 @@
goto :done goto :done
:maybe_reset_only
const/4 v2, 0x1
if-eq v1, v2, :simple_up
const/4 v2, 0x3
if-eq v1, v2, :reset_only
const/4 v2, 0x2
if-eq v1, v2, :simple_move
goto :done
:reset_only
invoke-static {}, Lradiant/MiniPlayerGestures;->resetGestureLock()V
invoke-static {}, Lradiant/MiniPlayerGestures;->animateSwipeFeedbackReset()V
goto :done
:simple_move
invoke-virtual {p1}, Landroid/view/MotionEvent;->getRawY()F
move-result v1
invoke-static {v1}, Lradiant/MiniPlayerGestures;->updateSimpleSwipe(F)Z
goto :done
:simple_up
invoke-virtual {p1}, Landroid/view/MotionEvent;->getRawY()F
move-result v1
iget-object v2, p0, Lradiant/MiniPlayerGestures$RootGesture;->a:Lem0/l;
invoke-static {v2, v1}, Lradiant/MiniPlayerGestures;->completeSimpleSwipe(Lem0/l;F)Z
invoke-static {}, Lradiant/MiniPlayerGestures;->animateSwipeFeedbackReset()V
goto :done
# ACTION_MOVE # ACTION_MOVE
:move :move
invoke-static {p1}, Lradiant/MiniPlayerGestures;->trackMotion(Landroid/view/MotionEvent;)V invoke-static {p1}, Lradiant/MiniPlayerGestures;->trackMotion(Landroid/view/MotionEvent;)V
@@ -98,20 +143,24 @@
move-result v1 move-result v1
iget-object v2, p0, Lradiant/MiniPlayerGestures$RootGesture;->a:Lyl0/l; iget-object v2, p0, Lradiant/MiniPlayerGestures$RootGesture;->a:Lem0/l;
invoke-static {v0, v2, v1}, Lradiant/MiniPlayerGestures;->finishDrag(Landroidx/compose/material3/SheetState;Lyl0/l;F)V invoke-static {v0, v2, v1}, Lradiant/MiniPlayerGestures;->finishDrag(Landroidx/compose/material3/SheetState;Lem0/l;F)V
invoke-static {}, Lradiant/MiniPlayerGestures;->animateSwipeFeedbackReset()V
goto :done goto :done
# ACTION_CANCEL # ACTION_CANCEL
:cancel :cancel
iget-object v2, p0, Lradiant/MiniPlayerGestures$RootGesture;->a:Lyl0/l; iget-object v2, p0, Lradiant/MiniPlayerGestures$RootGesture;->a:Lem0/l;
invoke-static {v0, v2}, Lradiant/MiniPlayerGestures;->cancelDrag(Landroidx/compose/material3/SheetState;Lyl0/l;)V invoke-static {v0, v2}, Lradiant/MiniPlayerGestures;->cancelDrag(Landroidx/compose/material3/SheetState;Lem0/l;)V
invoke-static {}, Lradiant/MiniPlayerGestures;->animateSwipeFeedbackReset()V
:done :done
sget-object p1, Lkotlin/u;->a:Lkotlin/u; sget-object p1, Lkotlin/v;->a:Lkotlin/v;
return-object p1 return-object p1
.end method .end method
@@ -121,7 +170,7 @@
check-cast p1, Landroid/view/MotionEvent; check-cast p1, Landroid/view/MotionEvent;
invoke-virtual {p0, p1}, Lradiant/MiniPlayerGestures$RootGesture;->invoke(Landroid/view/MotionEvent;)Lkotlin/u; invoke-virtual {p0, p1}, Lradiant/MiniPlayerGestures$RootGesture;->invoke(Landroid/view/MotionEvent;)Lkotlin/v;
move-result-object p1 move-result-object p1
@@ -23,7 +23,7 @@
.field private static g:Landroidx/compose/material3/SheetState; .field private static g:Landroidx/compose/material3/SheetState;
# Material3 settle lambda # Material3 settle lambda
.field private static h:Lyl0/l; .field private static h:Lem0/l;
# Latest MotionEvent eventTime for drag updates # Latest MotionEvent eventTime for drag updates
.field private static i:J .field private static i:J
@@ -50,8 +50,43 @@
# Mini player media state # Mini player media state
.field private static r:Z .field private static r:Z
# AppScaffold context
.field private static s:Lem0/l;
.field private static t:Landroidx/compose/material3/SheetState;
.field private static u:Z
# Feedback offset
.field public static v:Landroidx/compose/runtime/MutableFloatState;
.field private static w:Landroid/animation/ValueAnimator;
# Gesture axis lock: 0 = none, 1 = vertical, 2 = horizontal
.field private static x:I
# Swipe gesture start Y
.field private static y:F
# Relative to Y drag offset
.field private static z:F
# direct methods # direct methods
.method static constructor <clinit>()V
.locals 1
const/4 v0, 0x0
invoke-static {v0}, Landroidx/compose/runtime/PrimitiveSnapshotStateKt;->mutableFloatStateOf(F)Landroidx/compose/runtime/MutableFloatState;
move-result-object v0
sput-object v0, Lradiant/MiniPlayerGestures;->v:Landroidx/compose/runtime/MutableFloatState;
return-void
.end method
.method private constructor <init>()V .method private constructor <init>()V
.locals 0 .locals 0
@@ -60,6 +95,119 @@
return-void return-void
.end method .end method
.method public static animateSwipeFeedbackReset()V
.locals 7
sget-object v0, Lradiant/MiniPlayerGestures;->w:Landroid/animation/ValueAnimator;
if-eqz v0, :read_offset
invoke-virtual {v0}, Landroid/animation/ValueAnimator;->cancel()V
const/4 v0, 0x0
sput-object v0, Lradiant/MiniPlayerGestures;->w:Landroid/animation/ValueAnimator;
:read_offset
sget-object v0, Lradiant/MiniPlayerGestures;->v:Landroidx/compose/runtime/MutableFloatState;
invoke-interface {v0}, Landroidx/compose/runtime/MutableFloatState;->getFloatValue()F
move-result v0
invoke-static {v0}, Ljava/lang/Math;->abs(F)F
move-result v1
const/4 v3, 0x0
const/high16 v2, 0x3f000000 # 0.5f
cmpg-float v1, v1, v2
if-lez v1, :snap_zero
const/4 v1, 0x2
new-array v1, v1, [F
const/4 v2, 0x0
aput v0, v1, v2
const/4 v0, 0x1
aput v3, v1, v0
invoke-static {v1}, Landroid/animation/ValueAnimator;->ofFloat([F)Landroid/animation/ValueAnimator;
move-result-object v1
const-wide/16 v4, 0xb4 # 180ms
invoke-virtual {v1, v4, v5}, Landroid/animation/ValueAnimator;->setDuration(J)Landroid/animation/ValueAnimator;
new-instance v0, Landroid/view/animation/DecelerateInterpolator;
const/high16 v4, 0x3fc00000 # 1.5f
invoke-direct {v0, v4}, Landroid/view/animation/DecelerateInterpolator;-><init>(F)V
invoke-virtual {v1, v0}, Landroid/animation/ValueAnimator;->setInterpolator(Landroid/animation/TimeInterpolator;)V
new-instance v0, Lradiant/MiniPlayerGestures$FeedbackResetAnimator;
invoke-direct {v0}, Lradiant/MiniPlayerGestures$FeedbackResetAnimator;-><init>()V
invoke-virtual {v1, v0}, Landroid/animation/ValueAnimator;->addUpdateListener(Landroid/animation/ValueAnimator$AnimatorUpdateListener;)V
sput-object v1, Lradiant/MiniPlayerGestures;->w:Landroid/animation/ValueAnimator;
invoke-virtual {v1}, Landroid/animation/ValueAnimator;->start()V
return-void
:snap_zero
invoke-static {v3}, Lradiant/MiniPlayerGestures;->setSwipeFeedbackDirect(F)V
return-void
.end method
.method public static beginSwipeFeedback()V
.locals 1
sget-object v0, Lradiant/MiniPlayerGestures;->w:Landroid/animation/ValueAnimator;
if-eqz v0, :zero
invoke-virtual {v0}, Landroid/animation/ValueAnimator;->cancel()V
const/4 v0, 0x0
sput-object v0, Lradiant/MiniPlayerGestures;->w:Landroid/animation/ValueAnimator;
:zero
const/4 v0, 0x0
invoke-static {v0}, Lradiant/MiniPlayerGestures;->setSwipeFeedbackDirect(F)V
return-void
.end method
.method public static beginSwipeGesture(F)V
.locals 1
sput p0, Lradiant/MiniPlayerGestures;->y:F
const/4 v0, 0x0
sput v0, Lradiant/MiniPlayerGestures;->z:F
invoke-static {}, Lradiant/MiniPlayerGestures;->beginSwipeFeedback()V
return-void
.end method
.method public static applyPendingDrag(Landroidx/compose/material3/SheetState;)V .method public static applyPendingDrag(Landroidx/compose/material3/SheetState;)V
.locals 5 .locals 5
@@ -173,7 +321,7 @@
sput-object v0, Lradiant/MiniPlayerGestures;->g:Landroidx/compose/material3/SheetState; sput-object v0, Lradiant/MiniPlayerGestures;->g:Landroidx/compose/material3/SheetState;
sput-object v0, Lradiant/MiniPlayerGestures;->h:Lyl0/l; sput-object v0, Lradiant/MiniPlayerGestures;->h:Lem0/l;
sput v0, Lradiant/MiniPlayerGestures;->d:F sput v0, Lradiant/MiniPlayerGestures;->d:F
@@ -289,7 +437,7 @@
return-void return-void
.end method .end method
.method public static cancelDrag(Landroidx/compose/material3/SheetState;Lyl0/l;)V .method public static cancelDrag(Landroidx/compose/material3/SheetState;Lem0/l;)V
.locals 1 .locals 1
invoke-static {p0}, Lradiant/MiniPlayerGestures;->isDragging(Landroidx/compose/material3/SheetState;)Z invoke-static {p0}, Lradiant/MiniPlayerGestures;->isDragging(Landroidx/compose/material3/SheetState;)Z
@@ -302,13 +450,13 @@
sget-object p0, Lcom/tidal/android/feature/appscaffold/ui/b$a;->a:Lcom/tidal/android/feature/appscaffold/ui/b$a; sget-object p0, Lcom/tidal/android/feature/appscaffold/ui/b$a;->a:Lcom/tidal/android/feature/appscaffold/ui/b$a;
invoke-interface {p1, p0}, Lyl0/l;->invoke(Ljava/lang/Object;)Ljava/lang/Object; invoke-interface {p1, p0}, Lem0/l;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
:done :done
return-void return-void
.end method .end method
.method public static finishDrag(Landroidx/compose/material3/SheetState;Lyl0/l;F)V .method public static finishDrag(Landroidx/compose/material3/SheetState;Lem0/l;F)V
.locals 6 .locals 6
invoke-static {p0}, Lradiant/MiniPlayerGestures;->isDragging(Landroidx/compose/material3/SheetState;)Z invoke-static {p0}, Lradiant/MiniPlayerGestures;->isDragging(Landroidx/compose/material3/SheetState;)Z
@@ -321,7 +469,7 @@
if-ne v0, p0, :fallback_snap if-ne v0, p0, :fallback_snap
sget-object v0, Lradiant/MiniPlayerGestures;->h:Lyl0/l; sget-object v0, Lradiant/MiniPlayerGestures;->h:Lem0/l;
if-eqz v0, :fallback_snap if-eqz v0, :fallback_snap
@@ -337,7 +485,7 @@
move-result-object p0 move-result-object p0
invoke-interface {v0, p0}, Lyl0/l;->invoke(Ljava/lang/Object;)Ljava/lang/Object; invoke-interface {v0, p0}, Lem0/l;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
goto/16 :done goto/16 :done
@@ -441,7 +589,7 @@
sget-object p0, Lcom/tidal/android/feature/appscaffold/ui/b$a;->a:Lcom/tidal/android/feature/appscaffold/ui/b$a; sget-object p0, Lcom/tidal/android/feature/appscaffold/ui/b$a;->a:Lcom/tidal/android/feature/appscaffold/ui/b$a;
invoke-interface {p1, p0}, Lyl0/l;->invoke(Ljava/lang/Object;)Ljava/lang/Object; invoke-interface {p1, p0}, Lem0/l;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
:done :done
return-void return-void
@@ -473,6 +621,114 @@
sget-boolean v0, Lradiant/MiniPlayerGestures;->b:Z sget-boolean v0, Lradiant/MiniPlayerGestures;->b:Z
if-nez v0, :yes
invoke-static {}, Lradiant/MiniPlayerGestures;->isHorizontalGestureSuppressed()Z
move-result v0
return v0
:yes
const/4 v0, 0x1
return v0
.end method
.method public static isHorizontalGestureSuppressed()Z
.locals 2
sget v0, Lradiant/MiniPlayerGestures;->x:I
const/4 v1, 0x1
if-ne v0, v1, :no
const/4 v0, 0x1
return v0
:no
const/4 v0, 0x0
return v0
.end method
.method public static isHorizontalGestureLocked()Z
.locals 2
sget v0, Lradiant/MiniPlayerGestures;->x:I
const/4 v1, 0x2
if-ne v0, v1, :no
const/4 v0, 0x1
return v0
:no
const/4 v0, 0x0
return v0
.end method
.method public static lockHorizontalGesture()Z
.locals 2
sget v0, Lradiant/MiniPlayerGestures;->x:I
const/4 v1, 0x1
if-ne v0, v1, :lock
const/4 v0, 0x0
return v0
:lock
const/4 v0, 0x2
sput v0, Lradiant/MiniPlayerGestures;->x:I
const/4 v0, 0x1
return v0
.end method
.method public static resetGestureLock()V
.locals 1
const/4 v0, 0x0
sput v0, Lradiant/MiniPlayerGestures;->x:I
sput v0, Lradiant/MiniPlayerGestures;->y:F
sput v0, Lradiant/MiniPlayerGestures;->z:F
return-void
.end method
.method public static lockVerticalGesture()Z
.locals 2
sget v0, Lradiant/MiniPlayerGestures;->x:I
const/4 v1, 0x2
if-ne v0, v1, :lock
const/4 v0, 0x0
return v0
:lock
const/4 v0, 0x1
sput v0, Lradiant/MiniPlayerGestures;->x:I
return v0 return v0
.end method .end method
@@ -492,6 +748,63 @@
return-void return-void
.end method .end method
.method public static configure(Lem0/l;Landroidx/compose/material3/SheetState;Z)V
.locals 0
sput-object p0, Lradiant/MiniPlayerGestures;->s:Lem0/l;
sput-object p1, Lradiant/MiniPlayerGestures;->t:Landroidx/compose/material3/SheetState;
sput-boolean p2, Lradiant/MiniPlayerGestures;->u:Z
return-void
.end method
.method public static clearSwipeFeedbackAnimator(Landroid/animation/ValueAnimator;)V
.locals 1
sget-object v0, Lradiant/MiniPlayerGestures;->w:Landroid/animation/ValueAnimator;
if-ne v0, p0, :done
const/4 v0, 0x0
sput-object v0, Lradiant/MiniPlayerGestures;->w:Landroid/animation/ValueAnimator;
:done
return-void
.end method
.method private static dp(F)F
.locals 1
invoke-static {}, Landroid/content/res/Resources;->getSystem()Landroid/content/res/Resources;
move-result-object v0
invoke-virtual {v0}, Landroid/content/res/Resources;->getDisplayMetrics()Landroid/util/DisplayMetrics;
move-result-object v0
iget v0, v0, Landroid/util/DisplayMetrics;->density:F
mul-float/2addr p0, v0
return p0
.end method
.method public static feedbackModifier(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier;
.locals 1
sget-object v0, Lradiant/MiniPlayerGestures$FeedbackLayer;->INSTANCE:Lradiant/MiniPlayerGestures$FeedbackLayer;
invoke-static {p0, v0}, Landroidx/compose/ui/graphics/GraphicsLayerModifierKt;->graphicsLayer(Landroidx/compose/ui/Modifier;Lem0/l;)Landroidx/compose/ui/Modifier;
move-result-object p0
return-object p0
.end method
.method private static clampReleaseVelocity(F)F .method private static clampReleaseVelocity(F)F
.locals 4 .locals 4
@@ -535,20 +848,263 @@
return p0 return p0
.end method .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;Lem0/l;Landroidx/compose/material3/SheetState;Z)Landroidx/compose/ui/Modifier;
.locals 1 .locals 1
new-instance v0, Lradiant/MiniPlayerGestures$Gesture; new-instance v0, Lradiant/MiniPlayerGestures$Gesture;
invoke-direct {v0, p1, p2}, Lradiant/MiniPlayerGestures$Gesture;-><init>(Lyl0/l;Landroidx/compose/material3/SheetState;)V invoke-direct {v0, p1, p2, p3}, Lradiant/MiniPlayerGestures$Gesture;-><init>(Lem0/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; invoke-static {p0, v0}, Landroidx/compose/ui/input/pointer/PointerInteropFilter_androidKt;->motionEventSpy(Landroidx/compose/ui/Modifier;Lem0/l;)Landroidx/compose/ui/Modifier;
move-result-object p0 move-result-object p0
return-object p0 return-object p0
.end method .end method
.method public static trackAreaModifier(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier;
.locals 3
sget-object v0, Lradiant/MiniPlayerGestures;->s:Lem0/l;
if-eqz v0, :done
sget-object v1, Lradiant/MiniPlayerGestures;->t:Landroidx/compose/material3/SheetState;
if-eqz v1, :done
sget-boolean v2, Lradiant/MiniPlayerGestures;->u:Z
invoke-static {p0, v0, v1, v2}, Lradiant/MiniPlayerGestures;->modifier(Landroidx/compose/ui/Modifier;Lem0/l;Landroidx/compose/material3/SheetState;Z)Landroidx/compose/ui/Modifier;
move-result-object p0
:done
return-object p0
.end method
.method public static setSwipeFeedback(F)V
.locals 5
const/4 v4, 0x0
cmpl-float v0, p0, v4
if-gtz v0, :snap_zero
sget-object v0, Lradiant/MiniPlayerGestures;->w:Landroid/animation/ValueAnimator;
if-eqz v0, :rubber_band
invoke-virtual {v0}, Landroid/animation/ValueAnimator;->cancel()V
const/4 v0, 0x0
sput-object v0, Lradiant/MiniPlayerGestures;->w:Landroid/animation/ValueAnimator;
:rubber_band
invoke-static {p0}, Ljava/lang/Math;->abs(F)F
move-result v0
const/high16 v1, 0x41800000 # 16.0f dp travel
invoke-static {v1}, Lradiant/MiniPlayerGestures;->dp(F)F
move-result v1
cmpg-float v2, v0, v1
if-lez v2, :publish
sub-float/2addr v0, v1
const v2, 0x3e19999a # 0.15f resistance after 16dp
mul-float/2addr v0, v2
const/high16 v2, 0x3d800000 # 0.0625f max up travel
mul-float/2addr v2, v1
invoke-static {v0, v2}, Ljava/lang/Math;->min(FF)F
move-result v0
add-float/2addr v0, v1
neg-float p0, v0
:publish
invoke-static {p0}, Lradiant/MiniPlayerGestures;->setSwipeFeedbackDirect(F)V
return-void
:snap_zero
invoke-static {v4}, Lradiant/MiniPlayerGestures;->setSwipeFeedbackDirect(F)V
return-void
.end method
.method public static setSwipeFeedbackFromDrag(F)V
.locals 3
sput p0, Lradiant/MiniPlayerGestures;->z:F
const/4 v0, 0x0
cmpl-float v1, p0, v0
if-ltz v1, :maybe_up
invoke-static {v0}, Lradiant/MiniPlayerGestures;->setSwipeFeedbackDirect(F)V
return-void
:maybe_up
const/high16 v0, 0x40c00000 # 6.0f feedback deadzone
invoke-static {v0}, Lradiant/MiniPlayerGestures;->dp(F)F
move-result v0
neg-float v1, v0
cmpg-float v2, p0, v1
if-gtz v2, :snap_zero
add-float/2addr p0, v0
invoke-static {p0}, Lradiant/MiniPlayerGestures;->setSwipeFeedback(F)V
return-void
:snap_zero
const/4 v0, 0x0
invoke-static {v0}, Lradiant/MiniPlayerGestures;->setSwipeFeedbackDirect(F)V
return-void
.end method
.method public static completeSimpleSwipe(Lem0/l;F)Z
.locals 4
sget-boolean v0, Lradiant/MiniPlayerGestures;->u:Z
if-nez v0, :no
sget v0, Lradiant/MiniPlayerGestures;->x:I
const/4 v1, 0x1
if-ne v0, v1, :no
sget-boolean v0, Lradiant/MiniPlayerGestures;->r:Z
if-eqz v0, :consume_no
sget v0, Lradiant/MiniPlayerGestures;->y:F
sub-float/2addr p1, v0
sput p1, Lradiant/MiniPlayerGestures;->z:F
const/high16 v0, 0x42400000 # 48.0f release threshold
invoke-static {v0}, Lradiant/MiniPlayerGestures;->dp(F)F
move-result v0
neg-float v0, v0
cmpg-float v2, p1, v0
if-lez v2, :open
:consume_no
invoke-static {}, Lradiant/MiniPlayerGestures;->resetGestureLock()V
const/4 v0, 0x0
return v0
:open
invoke-static {}, Lradiant/MiniPlayerGestures;->resetGestureLock()V
sget-object v0, Lcom/tidal/android/feature/appscaffold/ui/b$b;->a:Lcom/tidal/android/feature/appscaffold/ui/b$b;
invoke-interface {p0, v0}, Lem0/l;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
const/4 v0, 0x1
return v0
:no
const/4 v0, 0x0
return v0
.end method
.method public static updateSimpleSwipe(F)Z
.locals 3
sget-boolean v0, Lradiant/MiniPlayerGestures;->u:Z
if-nez v0, :no
sget v0, Lradiant/MiniPlayerGestures;->x:I
const/4 v1, 0x1
if-ne v0, v1, :no
sget v0, Lradiant/MiniPlayerGestures;->y:F
sub-float/2addr p0, v0
invoke-static {p0}, Lradiant/MiniPlayerGestures;->setSwipeFeedbackFromDrag(F)V
const/4 v0, 0x1
return v0
:no
const/4 v0, 0x0
return v0
.end method
.method public static setSwipeFeedbackDirect(F)V
.locals 1
sget-object v0, Lradiant/MiniPlayerGestures;->v:Landroidx/compose/runtime/MutableFloatState;
invoke-interface {v0, p0}, Landroidx/compose/runtime/MutableFloatState;->setFloatValue(F)V
return-void
.end method
.method public static suppressHorizontalGestures()V
.locals 2
sget v0, Lradiant/MiniPlayerGestures;->x:I
const/4 v1, 0x2
if-ne v0, v1, :lock
return-void
:lock
const/4 v0, 0x1
sput v0, Lradiant/MiniPlayerGestures;->x:I
return-void
.end method
.method private static minFlingVelocity()F .method private static minFlingVelocity()F
.locals 2 .locals 2
@@ -751,26 +1307,26 @@
return p0 return p0
.end method .end method
.method public static rootModifier(Landroidx/compose/ui/Modifier;Lyl0/l;Landroidx/compose/material3/SheetState;)Landroidx/compose/ui/Modifier; .method public static rootModifier(Landroidx/compose/ui/Modifier;Lem0/l;Landroidx/compose/material3/SheetState;)Landroidx/compose/ui/Modifier;
.locals 1 .locals 1
new-instance v0, Lradiant/MiniPlayerGestures$RootGesture; new-instance v0, Lradiant/MiniPlayerGestures$RootGesture;
invoke-direct {v0, p1, p2}, Lradiant/MiniPlayerGestures$RootGesture;-><init>(Lyl0/l;Landroidx/compose/material3/SheetState;)V invoke-direct {v0, p1, p2}, Lradiant/MiniPlayerGestures$RootGesture;-><init>(Lem0/l;Landroidx/compose/material3/SheetState;)V
invoke-static {p0, v0}, Landroidx/compose/ui/input/pointer/PointerInteropFilter_androidKt;->motionEventSpy(Landroidx/compose/ui/Modifier;Lyl0/l;)Landroidx/compose/ui/Modifier; invoke-static {p0, v0}, Landroidx/compose/ui/input/pointer/PointerInteropFilter_androidKt;->motionEventSpy(Landroidx/compose/ui/Modifier;Lem0/l;)Landroidx/compose/ui/Modifier;
move-result-object p0 move-result-object p0
return-object p0 return-object p0
.end method .end method
.method public static setSettleCallback(Landroidx/compose/material3/SheetState;Lyl0/l;)V .method public static setSettleCallback(Landroidx/compose/material3/SheetState;Lem0/l;)V
.locals 0 .locals 0
sput-object p0, Lradiant/MiniPlayerGestures;->g:Landroidx/compose/material3/SheetState; sput-object p0, Lradiant/MiniPlayerGestures;->g:Landroidx/compose/material3/SheetState;
sput-object p1, Lradiant/MiniPlayerGestures;->h:Lyl0/l; sput-object p1, Lradiant/MiniPlayerGestures;->h:Lem0/l;
return-void return-void
.end method .end method
@@ -1007,6 +1563,8 @@
:apply :apply
invoke-static {p1}, Lradiant/MiniPlayerGestures;->setSwipeFeedbackFromDrag(F)V
invoke-static {p0}, Lradiant/MiniPlayerGestures;->applyPendingDrag(Landroidx/compose/material3/SheetState;)V invoke-static {p0}, Lradiant/MiniPlayerGestures;->applyPendingDrag(Landroidx/compose/material3/SheetState;)V
const/4 v0, 0x3 const/4 v0, 0x3
@@ -1,6 +1,6 @@
.class public final Lradiant/MiniPlayerTrackGestures$Gesture; .class public final Lradiant/MiniPlayerTrackGestures$Gesture;
.super Ljava/lang/Object; .super Ljava/lang/Object;
.implements Lyl0/l; .implements Lem0/l;
# annotations # annotations
@@ -15,16 +15,16 @@
# instance fields # instance fields
.field public final a:Lyl0/l; .field public final a:Lem0/l;
# direct methods # direct methods
.method public constructor <init>(Lyl0/l;)V .method public constructor <init>(Lem0/l;)V
.locals 0 .locals 0
invoke-direct {p0}, Ljava/lang/Object;-><init>()V invoke-direct {p0}, Ljava/lang/Object;-><init>()V
iput-object p1, p0, Lradiant/MiniPlayerTrackGestures$Gesture;->a:Lyl0/l; iput-object p1, p0, Lradiant/MiniPlayerTrackGestures$Gesture;->a:Lem0/l;
return-void return-void
.end method .end method
@@ -32,11 +32,11 @@
.method private nextTrack()V .method private nextTrack()V
.locals 2 .locals 2
iget-object v0, p0, Lradiant/MiniPlayerTrackGestures$Gesture;->a:Lyl0/l; iget-object v0, p0, Lradiant/MiniPlayerTrackGestures$Gesture;->a:Lem0/l;
sget-object v1, Lcom/tidal/android/feature/appscaffold/ui/q$a;->a:Lcom/tidal/android/feature/appscaffold/ui/q$a; # Tidal's built-in next track mini-player event sget-object v1, Lcom/tidal/android/feature/appscaffold/ui/s$a;->a:Lcom/tidal/android/feature/appscaffold/ui/s$a; # Tidal's built-in next track mini-player event
invoke-interface {v0, v1}, Lyl0/l;->invoke(Ljava/lang/Object;)Ljava/lang/Object; invoke-interface {v0, v1}, Lem0/l;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
return-void return-void
.end method .end method
@@ -44,18 +44,18 @@
.method private previousTrack()V .method private previousTrack()V
.locals 2 .locals 2
iget-object v0, p0, Lradiant/MiniPlayerTrackGestures$Gesture;->a:Lyl0/l; iget-object v0, p0, Lradiant/MiniPlayerTrackGestures$Gesture;->a:Lem0/l;
sget-object v1, Lcom/tidal/android/feature/appscaffold/ui/q$c;->a:Lcom/tidal/android/feature/appscaffold/ui/q$c; # Our synthetic previous track event sget-object v1, Lcom/tidal/android/feature/appscaffold/ui/s$c;->a:Lcom/tidal/android/feature/appscaffold/ui/s$c; # Our synthetic previous track event
invoke-interface {v0, v1}, Lyl0/l;->invoke(Ljava/lang/Object;)Ljava/lang/Object; invoke-interface {v0, v1}, Lem0/l;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
return-void return-void
.end method .end method
# virtual methods # virtual methods
.method public final invoke(Landroid/view/MotionEvent;)Lkotlin/u; .method public final invoke(Landroid/view/MotionEvent;)Lkotlin/v;
.locals 3 .locals 3
invoke-virtual {p1}, Landroid/view/MotionEvent;->getActionMasked()I invoke-virtual {p1}, Landroid/view/MotionEvent;->getActionMasked()I
@@ -132,7 +132,7 @@
invoke-static {}, Lradiant/MiniPlayerTrackGestures;->cancelDrag()V invoke-static {}, Lradiant/MiniPlayerTrackGestures;->cancelDrag()V
:done :done
sget-object p1, Lkotlin/u;->a:Lkotlin/u; sget-object p1, Lkotlin/v;->a:Lkotlin/v;
return-object p1 return-object p1
.end method .end method
@@ -142,7 +142,7 @@
check-cast p1, Landroid/view/MotionEvent; check-cast p1, Landroid/view/MotionEvent;
invoke-virtual {p0, p1}, Lradiant/MiniPlayerTrackGestures$Gesture;->invoke(Landroid/view/MotionEvent;)Lkotlin/u; invoke-virtual {p0, p1}, Lradiant/MiniPlayerTrackGestures$Gesture;->invoke(Landroid/view/MotionEvent;)Lkotlin/v;
move-result-object p1 move-result-object p1
@@ -1,6 +1,6 @@
.class public final Lradiant/MiniPlayerTrackGestures$OffsetLayer; .class public final Lradiant/MiniPlayerTrackGestures$OffsetLayer;
.super Ljava/lang/Object; .super Ljava/lang/Object;
.implements Lyl0/l; .implements Lem0/l;
# annotations # annotations
@@ -41,7 +41,7 @@
# virtual methods # virtual methods
.method public final invoke(Landroidx/compose/ui/graphics/GraphicsLayerScope;)Lkotlin/u; .method public final invoke(Landroidx/compose/ui/graphics/GraphicsLayerScope;)Lkotlin/v;
.locals 1 .locals 1
sget-object v0, Lradiant/MiniPlayerTrackGestures;->b:Landroidx/compose/runtime/MutableFloatState; sget-object v0, Lradiant/MiniPlayerTrackGestures;->b:Landroidx/compose/runtime/MutableFloatState;
@@ -52,7 +52,7 @@
invoke-interface {p1, v0}, Landroidx/compose/ui/graphics/GraphicsLayerScope;->setTranslationX(F)V invoke-interface {p1, v0}, Landroidx/compose/ui/graphics/GraphicsLayerScope;->setTranslationX(F)V
sget-object p1, Lkotlin/u;->a:Lkotlin/u; sget-object p1, Lkotlin/v;->a:Lkotlin/v;
return-object p1 return-object p1
.end method .end method
@@ -62,7 +62,7 @@
check-cast p1, Landroidx/compose/ui/graphics/GraphicsLayerScope; check-cast p1, Landroidx/compose/ui/graphics/GraphicsLayerScope;
invoke-virtual {p0, p1}, Lradiant/MiniPlayerTrackGestures$OffsetLayer;->invoke(Landroidx/compose/ui/graphics/GraphicsLayerScope;)Lkotlin/u; invoke-virtual {p0, p1}, Lradiant/MiniPlayerTrackGestures$OffsetLayer;->invoke(Landroidx/compose/ui/graphics/GraphicsLayerScope;)Lkotlin/v;
move-result-object p1 move-result-object p1
@@ -1,6 +1,6 @@
.class public final Lradiant/MiniPlayerTrackGestures$TextDraw; .class public final Lradiant/MiniPlayerTrackGestures$TextDraw;
.super Ljava/lang/Object; .super Ljava/lang/Object;
.implements Lyl0/l; .implements Lem0/l;
# annotations # annotations
@@ -41,7 +41,7 @@
# virtual methods # virtual methods
.method public final invoke(Landroidx/compose/ui/graphics/drawscope/ContentDrawScope;)Lkotlin/u; .method public final invoke(Landroidx/compose/ui/graphics/drawscope/ContentDrawScope;)Lkotlin/v;
.locals 12 .locals 12
sget-object v0, Lradiant/MiniPlayerTrackGestures;->b:Landroidx/compose/runtime/MutableFloatState; sget-object v0, Lradiant/MiniPlayerTrackGestures;->b:Landroidx/compose/runtime/MutableFloatState;
@@ -101,16 +101,28 @@
:try_end_0 :try_end_0
.catchall {:try_start_0 .. :try_end_0} :catchall_0 .catchall {:try_start_0 .. :try_end_0} :catchall_0
invoke-static {v7, v8, v9}, Landroidx/compose/animation/i;->b(Landroidx/compose/ui/graphics/drawscope/DrawContext;J)V invoke-interface {v7}, Landroidx/compose/ui/graphics/drawscope/DrawContext;->getCanvas()Landroidx/compose/ui/graphics/Canvas;
sget-object p1, Lkotlin/u;->a:Lkotlin/u; move-result-object v0
invoke-interface {v0}, Landroidx/compose/ui/graphics/Canvas;->restore()V
invoke-interface {v7, v8, v9}, Landroidx/compose/ui/graphics/drawscope/DrawContext;->setSize-uvyYCjk(J)V
sget-object p1, Lkotlin/v;->a:Lkotlin/v;
return-object p1 return-object p1
:catchall_0 :catchall_0
move-exception v0 move-exception v0
invoke-static {v7, v8, v9}, Landroidx/compose/animation/i;->b(Landroidx/compose/ui/graphics/drawscope/DrawContext;J)V invoke-interface {v7}, Landroidx/compose/ui/graphics/drawscope/DrawContext;->getCanvas()Landroidx/compose/ui/graphics/Canvas;
move-result-object v1
invoke-interface {v1}, Landroidx/compose/ui/graphics/Canvas;->restore()V
invoke-interface {v7, v8, v9}, Landroidx/compose/ui/graphics/drawscope/DrawContext;->setSize-uvyYCjk(J)V
throw v0 throw v0
.end method .end method
@@ -120,7 +132,7 @@
check-cast p1, Landroidx/compose/ui/graphics/drawscope/ContentDrawScope; check-cast p1, Landroidx/compose/ui/graphics/drawscope/ContentDrawScope;
invoke-virtual {p0, p1}, Lradiant/MiniPlayerTrackGestures$TextDraw;->invoke(Landroidx/compose/ui/graphics/drawscope/ContentDrawScope;)Lkotlin/u; invoke-virtual {p0, p1}, Lradiant/MiniPlayerTrackGestures$TextDraw;->invoke(Landroidx/compose/ui/graphics/drawscope/ContentDrawScope;)Lkotlin/v;
move-result-object p1 move-result-object p1
@@ -126,6 +126,8 @@
.method public static beginDrag(FF)V .method public static beginDrag(FF)V
.locals 2 .locals 2
invoke-static {}, Lradiant/MiniPlayerGestures;->resetGestureLock()V
sput p0, Lradiant/MiniPlayerTrackGestures;->e:F sput p0, Lradiant/MiniPlayerTrackGestures;->e:F
sput p1, Lradiant/MiniPlayerTrackGestures;->f:F sput p1, Lradiant/MiniPlayerTrackGestures;->f:F
@@ -188,6 +190,24 @@
.method public static finishDrag(FF)I .method public static finishDrag(FF)I
.locals 5 .locals 5
invoke-static {}, Lradiant/MiniPlayerGestures;->isAnyDragging()Z
move-result v0
if-eqz v0, :check_active
const/4 v0, 0x0
sput-boolean v0, Lradiant/MiniPlayerTrackGestures;->g:Z
sput-boolean v0, Lradiant/MiniPlayerTrackGestures;->h:Z
invoke-static {}, Lradiant/MiniPlayerTrackGestures;->animateReset()V
return v0
:check_active
sget-boolean v0, Lradiant/MiniPlayerTrackGestures;->g:Z sget-boolean v0, Lradiant/MiniPlayerTrackGestures;->g:Z
if-nez v0, :active if-nez v0, :active
@@ -336,17 +356,38 @@
goto :done goto :done
:accept :accept
invoke-static {}, Lradiant/MiniPlayerGestures;->lockHorizontalGesture()Z
move-result v2
if-eqz v2, :cancel_locked
const/4 v2, 0x1 const/4 v2, 0x1
sput-boolean v2, Lradiant/MiniPlayerTrackGestures;->h:Z sput-boolean v2, Lradiant/MiniPlayerTrackGestures;->h:Z
:publish :publish
const/4 v2, 0x0
invoke-static {v2}, Lradiant/MiniPlayerGestures;->setSwipeFeedbackDirect(F)V
invoke-static {}, Lradiant/MiniPlayerTrackGestures;->suppressTapOpen()V invoke-static {}, Lradiant/MiniPlayerTrackGestures;->suppressTapOpen()V
invoke-static {p0}, Lradiant/MiniPlayerTrackGestures;->setDragOffset(F)V invoke-static {p0}, Lradiant/MiniPlayerTrackGestures;->setDragOffset(F)V
:done :done
return-void return-void
:cancel_locked
const/4 v0, 0x0
sput-boolean v0, Lradiant/MiniPlayerTrackGestures;->g:Z
sput-boolean v0, Lradiant/MiniPlayerTrackGestures;->h:Z
invoke-static {}, Lradiant/MiniPlayerTrackGestures;->animateReset()V
goto :done
.end method .end method
.method private static dp(F)F .method private static dp(F)F
@@ -378,7 +419,7 @@
sget-object v0, Lradiant/MiniPlayerTrackGestures$OffsetLayer;->INSTANCE:Lradiant/MiniPlayerTrackGestures$OffsetLayer; sget-object v0, Lradiant/MiniPlayerTrackGestures$OffsetLayer;->INSTANCE:Lradiant/MiniPlayerTrackGestures$OffsetLayer;
invoke-static {p0, v0}, Landroidx/compose/ui/graphics/GraphicsLayerModifierKt;->graphicsLayer(Landroidx/compose/ui/Modifier;Lyl0/l;)Landroidx/compose/ui/Modifier; invoke-static {p0, v0}, Landroidx/compose/ui/graphics/GraphicsLayerModifierKt;->graphicsLayer(Landroidx/compose/ui/Modifier;Lem0/l;)Landroidx/compose/ui/Modifier;
move-result-object p0 move-result-object p0
@@ -390,7 +431,7 @@
sget-object v0, Lradiant/MiniPlayerTrackGestures$TextDraw;->INSTANCE:Lradiant/MiniPlayerTrackGestures$TextDraw; # text clip on right only sget-object v0, Lradiant/MiniPlayerTrackGestures$TextDraw;->INSTANCE:Lradiant/MiniPlayerTrackGestures$TextDraw; # text clip on right only
invoke-static {p0, v0}, Landroidx/compose/ui/draw/DrawModifierKt;->drawWithContent(Landroidx/compose/ui/Modifier;Lyl0/l;)Landroidx/compose/ui/Modifier; invoke-static {p0, v0}, Landroidx/compose/ui/draw/DrawModifierKt;->drawWithContent(Landroidx/compose/ui/Modifier;Lem0/l;)Landroidx/compose/ui/Modifier;
move-result-object p0 move-result-object p0
@@ -549,14 +590,14 @@
return-void return-void
.end method .end method
.method public static trackModifier(Landroidx/compose/ui/Modifier;Lyl0/l;)Landroidx/compose/ui/Modifier; .method public static trackModifier(Landroidx/compose/ui/Modifier;Lem0/l;)Landroidx/compose/ui/Modifier;
.locals 1 .locals 1
new-instance v0, Lradiant/MiniPlayerTrackGestures$Gesture; new-instance v0, Lradiant/MiniPlayerTrackGestures$Gesture;
invoke-direct {v0, p1}, Lradiant/MiniPlayerTrackGestures$Gesture;-><init>(Lyl0/l;)V invoke-direct {v0, p1}, Lradiant/MiniPlayerTrackGestures$Gesture;-><init>(Lem0/l;)V
invoke-static {p0, v0}, Landroidx/compose/ui/input/pointer/PointerInteropFilter_androidKt;->motionEventSpy(Landroidx/compose/ui/Modifier;Lyl0/l;)Landroidx/compose/ui/Modifier; invoke-static {p0, v0}, Landroidx/compose/ui/input/pointer/PointerInteropFilter_androidKt;->motionEventSpy(Landroidx/compose/ui/Modifier;Lem0/l;)Landroidx/compose/ui/Modifier;
move-result-object p0 move-result-object p0
@@ -1,7 +1,7 @@
.class public final Lradiant/MiniSeekerFloating; .class public final Lradiant/MiniSeekerFloating;
.super Ljava/lang/Object; .super Ljava/lang/Object;
.implements Lyl0/l; .implements Lem0/l;
# static fields # static fields
@@ -46,7 +46,7 @@
.catch Ljava/lang/Throwable; {:try_start .. :try_end} :swallow .catch Ljava/lang/Throwable; {:try_start .. :try_end} :swallow
:swallow :swallow
sget-object v0, Lkotlin/u;->a:Lkotlin/u; # Unit sget-object v0, Lkotlin/v;->a:Lkotlin/v; # Unit
return-object v0 return-object v0
.end method .end method
+13 -13
View File
@@ -5,7 +5,7 @@
# static fields # static fields
.field public static progressState:Landroidx/compose/runtime/MutableFloatState; .field public static progressState:Landroidx/compose/runtime/MutableFloatState;
.field public static volatile vm:Ljh/h; .field public static volatile vm:Lih/g;
.field public static volatile sub:Lio/reactivex/disposables/Disposable; .field public static volatile sub:Lio/reactivex/disposables/Disposable;
@@ -57,7 +57,7 @@
:start_block :start_block
:try_start :try_start
sget-object v0, Lradiant/MiniSeekerLine;->vm:Ljh/h; # cached vm sget-object v0, Lradiant/MiniSeekerLine;->vm:Lih/g; # cached vm
if-nez v0, :got_vm # reuse if present if-nez v0, :got_vm # reuse if present
@@ -65,32 +65,32 @@
move-result-object v0 # app move-result-object v0 # app
invoke-virtual {v0}, Lcom/aspiro/wamp/App;->e()Lf5/c; # dagger component invoke-virtual {v0}, Lcom/aspiro/wamp/App;->e()Le5/c; # dagger component
move-result-object v0 # component move-result-object v0 # component
check-cast v0, Lf5/d0$n2; # narrow type check-cast v0, Le5/u$n2; # narrow type
iget-object v0, v0, Lf5/d0$n2;->z0:Ldagger/internal/j; # playqueue provider iget-object v0, v0, Le5/u$n2;->z0:Ldagger/internal/j; # playqueue provider
invoke-interface {v0}, Lol0/a;->get()Ljava/lang/Object; # resolve invoke-interface {v0}, Lul0/a;->get()Ljava/lang/Object; # resolve
move-result-object v0 # playqueue move-result-object v0 # playqueue
check-cast v0, Lcom/aspiro/wamp/playqueue/z0; # narrow type check-cast v0, Lcom/aspiro/wamp/playqueue/y0; # narrow type
new-instance v1, Ljh/h; # build vm new-instance v1, Lih/g; # build vm
invoke-direct {v1, v0}, Ljh/h;-><init>(Lcom/aspiro/wamp/playqueue/z0;)V # ctor invoke-direct {v1, v0}, Lih/g;-><init>(Lcom/aspiro/wamp/playqueue/y0;)V # ctor
sput-object v1, Lradiant/MiniSeekerLine;->vm:Ljh/h; # cache sput-object v1, Lradiant/MiniSeekerLine;->vm:Lih/g; # cache
:got_vm :got_vm
sget-object v0, Lradiant/MiniSeekerLine;->vm:Ljh/h; # vm ref sget-object v0, Lradiant/MiniSeekerLine;->vm:Lih/g; # vm ref
invoke-virtual {v0}, Ljh/h;->a()V # activate emission invoke-virtual {v0}, Lih/g;->a()V # activate emission
iget-object v0, v0, Ljh/h;->d:Lio/reactivex/subjects/BehaviorSubject; # position subject iget-object v0, v0, Lih/g;->d:Lio/reactivex/subjects/BehaviorSubject; # position subject
invoke-static {}, Lio/reactivex/android/schedulers/AndroidSchedulers;->mainThread()Lio/reactivex/Scheduler; # main scheduler invoke-static {}, Lio/reactivex/android/schedulers/AndroidSchedulers;->mainThread()Lio/reactivex/Scheduler; # main scheduler
+2 -2
View File
@@ -1,6 +1,6 @@
.class public final Lradiant/NoOp; .class public final Lradiant/NoOp;
.super Ljava/lang/Object; .super Ljava/lang/Object;
.implements Lyl0/a; .implements Lem0/a;
# static fields # static fields
@@ -33,7 +33,7 @@
.method public final invoke()Ljava/lang/Object; .method public final invoke()Ljava/lang/Object;
.locals 1 .locals 1
sget-object v0, Lkotlin/u;->a:Lkotlin/u; sget-object v0, Lkotlin/v;->a:Lkotlin/v;
return-object v0 return-object v0
.end method .end method
@@ -0,0 +1,9 @@
.class public final Lradiant/PlayingFrom;
.super Ljava/lang/Object;
.source "PlayingFrom.smali"
# static fields
# puts the "Playing from" source above track title
.field public static a:Ljava/lang/String;
+6 -6
View File
@@ -85,15 +85,15 @@
return-object p0 return-object p0
.end method .end method
.method public static style(ILn20/e2;)Ln20/e2; .method public static style(ILr20/c2;)Lr20/c2;
.registers 16 .registers 16
invoke-static {p0}, Lradiant/QualityBadge;->textArgb(I)I invoke-static {p0}, Lradiant/QualityBadge;->textArgb(I)I
move-result v0 move-result v0
new-instance v1, Lc20/a; new-instance v1, Lg20/a;
invoke-direct {v1, v0}, Lc20/a;-><init>(I)V invoke-direct {v1, v0}, Lg20/a;-><init>(I)V
new-instance v0, Lc20/d; new-instance v0, Lg20/d;
const/4 v2, 0x0 const/4 v2, 0x0
const/4 v3, 0x0 const/4 v3, 0x0
const/4 v4, 0x0 const/4 v4, 0x0
@@ -107,7 +107,7 @@
const/4 v12, 0x0 const/4 v12, 0x0
const/16 v13, 0xffe const/16 v13, 0xffe
const/4 v14, 0x0 const/4 v14, 0x0
invoke-direct/range {v0 .. v14}, Lc20/d;-><init>(Lc20/a;Lc20/a;Lc20/a;Lc20/a;Lc20/a;Lc20/a;Lc20/a;Lc20/a;Lc20/a;Lc20/a;Lc20/a;Lc20/a;ILkotlin/jvm/internal/DefaultConstructorMarker;)V invoke-direct/range {v0 .. v14}, Lg20/d;-><init>(Lg20/a;Lg20/a;Lg20/a;Lg20/a;Lg20/a;Lg20/a;Lg20/a;Lg20/a;Lg20/a;Lg20/a;Lg20/a;Lg20/a;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
move-object v9, v0 move-object v9, v0
move-object/from16 v0, p1 move-object/from16 v0, p1
@@ -118,7 +118,7 @@
const/4 v5, 0x0 const/4 v5, 0x0
const/16 v6, 0x1d const/16 v6, 0x1d
const/4 v7, 0x0 const/4 v7, 0x0
invoke-static/range {v0 .. v7}, Ln20/e2;->g(Ln20/e2;Ln20/u4;Lc20/d;Lcom/squareup/ui/market/core/text/MarketTextAlignment;Lcom/squareup/ui/market/core/text/MarketTextTransform;Ln20/t4;ILjava/lang/Object;)Ln20/e2; invoke-static/range {v0 .. v7}, Lr20/c2;->g(Lr20/c2;Lr20/s4;Lg20/d;Lcom/squareup/ui/market/core/text/MarketTextAlignment;Lcom/squareup/ui/market/core/text/MarketTextTransform;Lr20/r4;ILjava/lang/Object;)Lr20/c2;
move-result-object p0 move-result-object p0
return-object p0 return-object p0
.end method .end method
@@ -65,10 +65,6 @@
invoke-static {p1}, Lradiant/HomeBackdrop;->onTrack(Lcom/aspiro/wamp/model/Track;)V invoke-static {p1}, Lradiant/HomeBackdrop;->onTrack(Lcom/aspiro/wamp/model/Track;)V
const/4 v3, 0x0
sput-boolean v3, Lradiant/RLAPILyricsHook;->isRlState:Z
const-string v3, "onWampTrack: hook entered" const-string v3, "onWampTrack: hook entered"
invoke-static {v3}, Lradiant/RLAPILyricsHook;->dlog(Ljava/lang/String;)V invoke-static {v3}, Lradiant/RLAPILyricsHook;->dlog(Ljava/lang/String;)V
@@ -157,6 +153,25 @@
move-result-object v4 move-result-object v4
sget-object v5, Lradiant/RLAPILyricsHook;->currentKey:Ljava/lang/String;
invoke-virtual {v4, v5}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
move-result v5
if-eqz v5, :rl_new_track
const-string v5, "onWampTrack: same track re-fired, skipping duplicate fetch"
invoke-static {v5}, Lradiant/RLAPILyricsHook;->dlog(Ljava/lang/String;)V
return-void
:rl_new_track
const/4 v5, 0x0
sput-boolean v5, Lradiant/RLAPILyricsHook;->isRlState:Z
sput-object v4, Lradiant/RLAPILyricsHook;->currentKey:Ljava/lang/String; sput-object v4, Lradiant/RLAPILyricsHook;->currentKey:Ljava/lang/String;
new-instance v5, Ljava/lang/StringBuilder; new-instance v5, Ljava/lang/StringBuilder;
@@ -396,13 +396,23 @@
invoke-static {v4}, Lradiant/RLAPILyricsHook;->dlog(Ljava/lang/String;)V invoke-static {v4}, Lradiant/RLAPILyricsHook;->dlog(Ljava/lang/String;)V
iget-object v4, p0, Lradiant/RLAPILyricsWorker;->key:Ljava/lang/String;
sget-object v5, Lradiant/RLAPILyricsHook;->currentKey:Ljava/lang/String;
invoke-virtual {v4, v5}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
move-result v4
if-eqz v4, :no_close # Smthn needed to keep lyrics open
sget-boolean v4, Lradiant/StickyLyrics;->enabled:Z sget-boolean v4, Lradiant/StickyLyrics;->enabled:Z
if-nez v4, :no_close if-nez v4, :no_close
iget-object v4, p0, Lradiant/RLAPILyricsWorker;->vm:Lcom/tidal/android/feature/playerscreen/ui/PlayerViewModel; iget-object v4, p0, Lradiant/RLAPILyricsWorker;->vm:Lcom/tidal/android/feature/playerscreen/ui/PlayerViewModel;
iget-object v5, v4, Lcom/tidal/android/feature/playerscreen/ui/PlayerViewModel;->N:Lkotlinx/coroutines/flow/MutableStateFlow; iget-object v5, v4, Lcom/tidal/android/feature/playerscreen/ui/PlayerViewModel;->O:Lkotlinx/coroutines/flow/MutableStateFlow;
sget-object v6, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean; sget-object v6, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean;
@@ -475,9 +485,9 @@
:key_ok :key_ok
iget-object v4, p0, Lradiant/RLAPILyricsWorker;->vm:Lcom/tidal/android/feature/playerscreen/ui/PlayerViewModel; iget-object v4, p0, Lradiant/RLAPILyricsWorker;->vm:Lcom/tidal/android/feature/playerscreen/ui/PlayerViewModel;
iget-object v5, v4, Lcom/tidal/android/feature/playerscreen/ui/PlayerViewModel;->M:Lkotlinx/coroutines/flow/MutableStateFlow; iget-object v5, v4, Lcom/tidal/android/feature/playerscreen/ui/PlayerViewModel;->N:Lkotlinx/coroutines/flow/MutableStateFlow;
invoke-static {v3}, Ltn0/a;->c(Ljava/lang/Iterable;)Ltn0/b; invoke-static {v3}, Lzn0/a;->c(Ljava/lang/Iterable;)Lzn0/b;
move-result-object v6 move-result-object v6
@@ -494,9 +504,9 @@
const/4 v10, 0x0 const/4 v10, 0x0
invoke-direct {v8, v7, v6, v9, v10}, Lcom/tidal/android/feature/playerscreen/ui/g$c;-><init>(Ljava/lang/String;Ltn0/b;IZ)V invoke-direct {v8, v7, v6, v9, v10}, Lcom/tidal/android/feature/playerscreen/ui/g$c;-><init>(Ljava/lang/String;Lzn0/b;IZ)V
const-string v6, "publishing g$c -> J=true N=true M=g$c" const-string v6, "publishing g$c -> K=true (O=true if sticky) N=g$c"
invoke-static {v6}, Lradiant/RLAPILyricsHook;->dlog(Ljava/lang/String;)V invoke-static {v6}, Lradiant/RLAPILyricsHook;->dlog(Ljava/lang/String;)V
@@ -504,7 +514,7 @@
sput-boolean v6, Lradiant/RLAPILyricsHook;->isRlState:Z sput-boolean v6, Lradiant/RLAPILyricsHook;->isRlState:Z
iget-object v6, v4, Lcom/tidal/android/feature/playerscreen/ui/PlayerViewModel;->J:Lkotlinx/coroutines/flow/MutableStateFlow; iget-object v6, v4, Lcom/tidal/android/feature/playerscreen/ui/PlayerViewModel;->K:Lkotlinx/coroutines/flow/MutableStateFlow;
sget-object v7, Ljava/lang/Boolean;->TRUE:Ljava/lang/Boolean; sget-object v7, Ljava/lang/Boolean;->TRUE:Ljava/lang/Boolean;
@@ -514,7 +524,7 @@
if-eqz v9, :skip_n if-eqz v9, :skip_n
iget-object v6, v4, Lcom/tidal/android/feature/playerscreen/ui/PlayerViewModel;->N:Lkotlinx/coroutines/flow/MutableStateFlow; iget-object v6, v4, Lcom/tidal/android/feature/playerscreen/ui/PlayerViewModel;->O:Lkotlinx/coroutines/flow/MutableStateFlow;
invoke-interface {v6, v7}, Lkotlinx/coroutines/flow/MutableStateFlow;->setValue(Ljava/lang/Object;)V invoke-interface {v6, v7}, Lkotlinx/coroutines/flow/MutableStateFlow;->setValue(Ljava/lang/Object;)V
@@ -20,13 +20,13 @@
if-eqz p1, :ret # null guard if-eqz p1, :ret # null guard
instance-of v0, p1, Ljh/b; # type guard instance-of v0, p1, Lih/b; # type guard
if-eqz v0, :ret # skip if wrong type if-eqz v0, :ret # skip if wrong type
check-cast p1, Ljh/b; # narrow type check-cast p1, Lih/b; # narrow type
iget v0, p1, Ljh/b;->b:F # raw progress iget v0, p1, Lih/b;->b:F # raw progress
invoke-static {v0}, Ljava/lang/Float;->isNaN(F)Z # nan check invoke-static {v0}, Ljava/lang/Float;->isNaN(F)Z # nan check
@@ -4,7 +4,7 @@
# direct methods # direct methods
.method public static final a(ILandroidx/compose/runtime/Composer;Landroidx/compose/ui/Modifier;Lyl0/a;)V .method public static final a(ILandroidx/compose/runtime/Composer;Landroidx/compose/ui/Modifier;Lem0/a;)V
.locals 21 .locals 21
.annotation build Landroidx/compose/runtime/Composable; .annotation build Landroidx/compose/runtime/Composable;
.end annotation .end annotation
@@ -98,7 +98,7 @@
const/4 v4, 0x6 const/4 v4, 0x6
invoke-static {v2, v11, v4}, Lcom/squareup/ui/market/core/theme/x;->t(Lcom/squareup/ui/market/core/theme/k$a;Landroidx/compose/runtime/Composer;I)Lcom/squareup/ui/market/core/theme/MarketStylesheet; invoke-static {v2, v11, v4}, Lcom/squareup/ui/market/core/theme/y;->t(Lcom/squareup/ui/market/core/theme/k$a;Landroidx/compose/runtime/Composer;I)Lcom/squareup/ui/market/core/theme/MarketStylesheet;
move-result-object v15 move-result-object v15
@@ -131,7 +131,7 @@
const/16 v18, 0x0 const/16 v18, 0x0
invoke-static/range {v15 .. v20}, Lcom/squareup/ui/market/components/MarketIconButtonKt;->P(Lcom/squareup/ui/market/core/theme/MarketStylesheet;Lcom/squareup/ui/market/core/components/properties/IconButton$Size;Lcom/squareup/ui/market/core/components/properties/IconButton$Rank;Lcom/squareup/ui/market/core/components/properties/IconButton$Variant;ILjava/lang/Object;)Ln20/w1; invoke-static/range {v15 .. v20}, Lcom/squareup/ui/market/components/MarketIconButtonKt;->P(Lcom/squareup/ui/market/core/theme/MarketStylesheet;Lcom/squareup/ui/market/core/components/properties/IconButton$Size;Lcom/squareup/ui/market/core/components/properties/IconButton$Rank;Lcom/squareup/ui/market/core/components/properties/IconButton$Variant;ILjava/lang/Object;)Lr20/u1;
move-result-object v4 move-result-object v4
@@ -140,7 +140,7 @@
:cond_5 :cond_5
move-object v9, v4 move-object v9, v4
check-cast v9, Ln20/w1; check-cast v9, Lr20/u1;
sget v2, Lcom/tidal/android/feature/playerscreen/ui/R$string;->lyrics:I sget v2, Lcom/tidal/android/feature/playerscreen/ui/R$string;->lyrics:I
@@ -172,7 +172,7 @@
const/4 v8, 0x0 const/4 v8, 0x0
invoke-static/range {v1 .. v13}, Lcom/squareup/ui/market/components/MarketIconButtonKt;->c(Lyl0/a;Ljava/lang/String;Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/interaction/MutableInteractionSource;ZLcom/squareup/ui/market/components/n;Lyl0/a;Ljava/lang/String;Ln20/w1;Lyl0/p;Landroidx/compose/runtime/Composer;II)V invoke-static/range {v1 .. v13}, Lcom/squareup/ui/market/components/MarketIconButtonKt;->c(Lem0/a;Ljava/lang/String;Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/interaction/MutableInteractionSource;ZLcom/squareup/ui/market/components/n;Lem0/a;Ljava/lang/String;Lr20/u1;Lem0/p;Landroidx/compose/runtime/Composer;II)V
invoke-static {}, Landroidx/compose/runtime/ComposerKt;->isTraceInProgress()Z invoke-static {}, Landroidx/compose/runtime/ComposerKt;->isTraceInProgress()Z
@@ -3,7 +3,7 @@
.source "SourceFile" .source "SourceFile"
# interfaces # interfaces
.implements Lyl0/p; .implements Lem0/p;
# virtual methods # virtual methods
@@ -35,7 +35,7 @@
invoke-static {v0, p2, v1, v2}, Landroidx/compose/runtime/ComposerKt;->traceEventStart(IIILjava/lang/String;)V invoke-static {v0, p2, v1, v2}, Landroidx/compose/runtime/ComposerKt;->traceEventStart(IIILjava/lang/String;)V
:cond_0 :cond_0
const p2, 0x7f08051d const p2, 0x7f080521
const/4 v0, 0x0 const/4 v0, 0x0
+1 -1
View File
@@ -1,6 +1,6 @@
.class public final Lradiant/SpvFactory; .class public final Lradiant/SpvFactory;
.super Ljava/lang/Object; .super Ljava/lang/Object;
.implements Lyl0/l; .implements Lem0/l;
# static fields # static fields
@@ -0,0 +1,87 @@
.class public final Lradiant/WazeInitReceiver;
.super Landroid/content/BroadcastReceiver;
.source "WazeInitReceiver.smali"
# direct methods
.method public constructor <init>()V
.locals 0
invoke-direct {p0}, Landroid/content/BroadcastReceiver;-><init>()V
return-void
.end method
# virtual methods
.method public onReceive(Landroid/content/Context;Landroid/content/Intent;)V
.locals 5
if-eqz p1, :return
if-eqz p2, :return
const-string v0, "com.waze.sdk.audio.ACTION_INIT"
invoke-virtual {p2}, Landroid/content/Intent;->getAction()Ljava/lang/String;
move-result-object v1
invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
move-result v0
if-eqz v0, :return
const-string v0, "token"
invoke-virtual {p2, v0}, Landroid/content/Intent;->getStringExtra(Ljava/lang/String;)Ljava/lang/String;
move-result-object v0
if-eqz v0, :return
invoke-virtual {v0}, Ljava/lang/String;->length()I
move-result v1
if-lez v1, :return
invoke-virtual {p1}, Landroid/content/Context;->getApplicationContext()Landroid/content/Context;
move-result-object v1
if-eqz v1, :context_ready
move-object p1, v1
:context_ready
new-instance v1, Landroid/content/Intent;
invoke-direct {v1}, Landroid/content/Intent;-><init>()V
const-string v2, "com.waze"
const-string v3, "com.waze.sdk.SdkService"
invoke-virtual {v1, v2, v3}, Landroid/content/Intent;->setClassName(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;
new-instance v2, Lradiant/WazeServiceConnection;
invoke-direct {v2, p1, v0}, Lradiant/WazeServiceConnection;-><init>(Landroid/content/Context;Ljava/lang/String;)V
:try_start_0
const/4 v3, 0x1
invoke-virtual {p1, v1, v2, v3}, Landroid/content/Context;->bindService(Landroid/content/Intent;Landroid/content/ServiceConnection;I)Z
:try_end_0
.catch Ljava/lang/Throwable; {:try_start_0 .. :try_end_0} :catch_0
goto :return
:catch_0
move-exception v4
:return
return-void
.end method
@@ -0,0 +1,228 @@
.class public final Lradiant/WazeServiceConnection;
.super Ljava/lang/Object;
.source "WazeServiceConnection.smali"
# interfaces
.implements Landroid/content/ServiceConnection;
# instance fields
.field private final context:Landroid/content/Context;
.field private final token:Ljava/lang/String;
# direct methods
.method public constructor <init>(Landroid/content/Context;Ljava/lang/String;)V
.locals 0
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
iput-object p1, p0, Lradiant/WazeServiceConnection;->context:Landroid/content/Context;
iput-object p2, p0, Lradiant/WazeServiceConnection;->token:Ljava/lang/String;
return-void
.end method
.method private addOpenMeIntent(Landroid/os/Bundle;)V
.locals 4
iget-object v0, p0, Lradiant/WazeServiceConnection;->context:Landroid/content/Context;
invoke-virtual {v0}, Landroid/content/Context;->getPackageManager()Landroid/content/pm/PackageManager;
move-result-object v1
invoke-virtual {v0}, Landroid/content/Context;->getPackageName()Ljava/lang/String;
move-result-object v2
invoke-virtual {v1, v2}, Landroid/content/pm/PackageManager;->getLaunchIntentForPackage(Ljava/lang/String;)Landroid/content/Intent;
move-result-object v1
if-eqz v1, :return
const/high16 v2, 0x10000000
invoke-virtual {v1, v2}, Landroid/content/Intent;->addFlags(I)Landroid/content/Intent;
const v2, 0xc000000
const/4 v3, 0x0
invoke-static {v0, v3, v1, v2}, Landroid/app/PendingIntent;->getActivity(Landroid/content/Context;ILandroid/content/Intent;I)Landroid/app/PendingIntent;
move-result-object v1
const-string v2, "openMeIntent"
invoke-virtual {p1, v2, v1}, Landroid/os/Bundle;->putParcelable(Ljava/lang/String;Landroid/os/Parcelable;)V
:return
return-void
.end method
.method private createClientMessenger()Landroid/os/Messenger;
.locals 3
new-instance v0, Landroid/os/Handler;
invoke-static {}, Landroid/os/Looper;->getMainLooper()Landroid/os/Looper;
move-result-object v1
invoke-direct {v0, v1}, Landroid/os/Handler;-><init>(Landroid/os/Looper;)V
new-instance v2, Landroid/os/Messenger;
invoke-direct {v2, v0}, Landroid/os/Messenger;-><init>(Landroid/os/Handler;)V
return-object v2
.end method
.method private createConfigBundle()Landroid/os/Bundle;
.locals 3
new-instance v0, Landroid/os/Bundle;
invoke-direct {v0}, Landroid/os/Bundle;-><init>()V
const-string v1, "versionCode"
const/16 v2, 0xa
invoke-virtual {v0, v1, v2}, Landroid/os/Bundle;->putInt(Ljava/lang/String;I)V
const-string v1, "themeColor"
const v2, __RL_WAZE_THEME_COLOR__ # Waze SDK themeColor
invoke-virtual {v0, v1, v2}, Landroid/os/Bundle;->putInt(Ljava/lang/String;I)V
invoke-direct {p0, v0}, Lradiant/WazeServiceConnection;->addOpenMeIntent(Landroid/os/Bundle;)V
return-object v0
.end method
.method private register(Landroid/os/IBinder;)V
.locals 5
if-eqz p1, :return
invoke-static {}, Landroid/os/Parcel;->obtain()Landroid/os/Parcel;
move-result-object v0
invoke-static {}, Landroid/os/Parcel;->obtain()Landroid/os/Parcel;
move-result-object v1
const-string v2, "com.waze.sdk.ISdkService"
invoke-virtual {v0, v2}, Landroid/os/Parcel;->writeInterfaceToken(Ljava/lang/String;)V
iget-object v2, p0, Lradiant/WazeServiceConnection;->token:Ljava/lang/String;
invoke-virtual {v0, v2}, Landroid/os/Parcel;->writeString(Ljava/lang/String;)V
invoke-direct {p0}, Lradiant/WazeServiceConnection;->createConfigBundle()Landroid/os/Bundle;
move-result-object v2
invoke-static {v0, v2}, Lradiant/WazeServiceConnection;->writeParcelable(Landroid/os/Parcel;Landroid/os/Parcelable;)V
invoke-direct {p0}, Lradiant/WazeServiceConnection;->createClientMessenger()Landroid/os/Messenger;
move-result-object v2
invoke-static {v0, v2}, Lradiant/WazeServiceConnection;->writeParcelable(Landroid/os/Parcel;Landroid/os/Parcelable;)V
const/4 v2, 0x1
const/4 v3, 0x0
invoke-interface {p1, v2, v0, v1, v3}, Landroid/os/IBinder;->transact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z
move-result v4
if-eqz v4, :cleanup
invoke-virtual {v1}, Landroid/os/Parcel;->readException()V
:cleanup
invoke-virtual {v1}, Landroid/os/Parcel;->recycle()V
invoke-virtual {v0}, Landroid/os/Parcel;->recycle()V
:return
return-void
.end method
.method private safeUnbind()V
.locals 1
:try_start_0
iget-object v0, p0, Lradiant/WazeServiceConnection;->context:Landroid/content/Context;
invoke-virtual {v0, p0}, Landroid/content/Context;->unbindService(Landroid/content/ServiceConnection;)V
:try_end_0
.catch Ljava/lang/Throwable; {:try_start_0 .. :try_end_0} :catch_0
goto :return
:catch_0
move-exception v0
:return
return-void
.end method
.method private static writeParcelable(Landroid/os/Parcel;Landroid/os/Parcelable;)V
.locals 2
const/4 v0, 0x0
if-eqz p1, :null_value
const/4 v1, 0x1
invoke-virtual {p0, v1}, Landroid/os/Parcel;->writeInt(I)V
invoke-interface {p1, p0, v0}, Landroid/os/Parcelable;->writeToParcel(Landroid/os/Parcel;I)V
return-void
:null_value
invoke-virtual {p0, v0}, Landroid/os/Parcel;->writeInt(I)V
return-void
.end method
# virtual methods
.method public onServiceConnected(Landroid/content/ComponentName;Landroid/os/IBinder;)V
.locals 1
:try_start_0
invoke-direct {p0, p2}, Lradiant/WazeServiceConnection;->register(Landroid/os/IBinder;)V
:try_end_0
.catch Ljava/lang/Throwable; {:try_start_0 .. :try_end_0} :catch_0
goto :unbind
:catch_0
move-exception v0
:unbind
invoke-direct {p0}, Lradiant/WazeServiceConnection;->safeUnbind()V
return-void
.end method
.method public onServiceDisconnected(Landroid/content/ComponentName;)V
.locals 0
return-void
.end method
+15 -14
View File
@@ -1,16 +1,16 @@
--- a/com/tidal/android/feature/home/ui/k.smali --- a/com/tidal/android/feature/home/ui/k.smali
+++ b/com/tidal/android/feature/home/ui/k.smali +++ b/com/tidal/android/feature/home/ui/k.smali
@@ -424,7 +424,7 @@ @@ -427,7 +427,7 @@
const/4 v6, 0x0 const/4 v6, 0x0
.line 181
- move-wide v7, v8
+ const-wide/16 v7, 0x0 # transparent containerColor
.line 182 .line 182
- move-wide v7, v9
+ const-wide/16 v7, 0x0 # transparent containerColor
.line 183
const-wide/16 v9, 0x0 const-wide/16 v9, 0x0
--- a/com/tidal/android/feature/home/ui/p.smali --- a/com/tidal/android/feature/home/ui/n.smali
+++ b/com/tidal/android/feature/home/ui/p.smali +++ b/com/tidal/android/feature/home/ui/n.smali
@@ -187,6 +187,10 @@ @@ -187,6 +187,10 @@
.line 61 .line 61
.line 62 .line 62
@@ -20,24 +20,25 @@
+ invoke-static {v4, v0}, Lradiant/HomeBackdrop;->render(Landroidx/compose/runtime/Composer;I)V # render album-art backdrop + invoke-static {v4, v0}, Lradiant/HomeBackdrop;->render(Landroidx/compose/runtime/Composer;I)V # render album-art backdrop
+ +
invoke-interface {p1}, Landroidx/compose/foundation/layout/PaddingValues;->calculateTopPadding-D9Ej5fM()F invoke-interface {p1}, Landroidx/compose/foundation/layout/PaddingValues;->calculateTopPadding-D9Ej5fM()F
.line 63 .line 63
--- a/com/tidal/android/feature/home/ui/composables/e.smali --- a/com/tidal/android/feature/home/ui/composables/f.smali
+++ b/com/tidal/android/feature/home/ui/composables/e.smali +++ b/com/tidal/android/feature/home/ui/composables/f.smali
@@ -790,6 +790,8 @@ @@ -790,6 +790,8 @@
.line 104 .line 104
move-result-wide v14 move-result-wide v14
+ const-wide/16 v14, 0x0 # transparent topBar background + const-wide/16 v14, 0x0 # transparent topBar background
+ +
.line 105 .line 105
const/16 v17, 0x2 const/16 v17, 0x2
@@ -850,6 +852,8 @@ @@ -850,6 +852,8 @@
.line 134 .line 134
move-result-wide v14 move-result-wide v14
+ const-wide/16 v14, 0x0 # transparent TopAppBar containerColor + const-wide/16 v14, 0x0 # transparent TopAppBar containerColor
+ +
.line 135 .line 135
sget-object v3, Landroidx/compose/ui/graphics/Color;->Companion:Landroidx/compose/ui/graphics/Color$Companion; sget-object v3, Landroidx/compose/ui/graphics/Color;->Companion:Landroidx/compose/ui/graphics/Color$Companion;
+55
View File
@@ -0,0 +1,55 @@
--- a/ob/e.smali
+++ b/ob/e.smali
@@ -613,6 +613,25 @@
.line 236
:goto_8
+ const-string/jumbo v5, "com.waze"
+
+ invoke-static {v3, v5}, Lkotlin/jvm/internal/n;->b(Ljava/lang/Object;Ljava/lang/Object;)Z # package match
+
+ move-result v5
+
+ if-eqz v5, :rl_waze_done
+
+ const-string/jumbo v5, "03:63:7f:6c:5d:8f:60:4e:6f:db:79:a6:ff:bf:a5:78:de:4e:31:8f:8d:a2:2f:c6:10:66:65:24:7f:88:07:d7" # Waze cert
+
+ invoke-static {v2, v5}, Lkotlin/jvm/internal/n;->b(Ljava/lang/Object;Ljava/lang/Object;)Z # cert match
+
+ move-result v5
+
+ if-eqz v5, :rl_waze_done
+
+ goto :goto_9 # trust Waze
+
+ :rl_waze_done
invoke-static {}, Landroid/os/Process;->myUid()I
.line 237
@@ -769,6 +788,26 @@
:goto_b
if-eqz v2, :cond_14
+ const-string/jumbo v1, "com.waze"
+
+ invoke-static {v3, v1}, Lkotlin/jvm/internal/n;->b(Ljava/lang/Object;Ljava/lang/Object;)Z # package match
+
+ move-result v1
+
+ if-eqz v1, :rl_waze_recent_root_done_2
+
+ new-instance v1, Landroidx/media/MediaBrowserServiceCompat$BrowserRoot;
+
+ const-string/jumbo v4, "__RL_WAZE_ROOT_ID__"
+
+ const/4 v5, 0x0
+
+ invoke-direct {v1, v4, v5}, Landroidx/media/MediaBrowserServiceCompat$BrowserRoot;-><init>(Ljava/lang/String;Landroid/os/Bundle;)V
+
+ return-object v1
+
+ :rl_waze_recent_root_done_2
+
.line 306
.line 307
iget-object v1, v0, Lob/e;->c:Ljava/util/Map;
+7 -7
View File
@@ -1,23 +1,23 @@
--- a/com/tidal/android/feature/playerscreen/ui/h0.smali --- a/com/tidal/android/feature/playerscreen/ui/v0.smali
+++ b/com/tidal/android/feature/playerscreen/ui/h0.smali +++ b/com/tidal/android/feature/playerscreen/ui/v0.smali
@@ -669,8 +669,23 @@ @@ -669,8 +669,23 @@
move-object v5, v1 move-object v5, v1
.line 289 .line 289
+ const v1, 0x52414443 # group key + const v1, 0x52414443 # group key
+ +
+ invoke-interface {v7, v1}, Landroidx/compose/runtime/Composer;->startReplaceGroup(I)V # open group around the cover + invoke-interface {v7, v1}, Landroidx/compose/runtime/Composer;->startReplaceGroup(I)V # open group around the cover
+ +
+ iget-object v1, v0, Lcom/tidal/android/feature/playerscreen/ui/h0;->b:Lcom/tidal/android/feature/playerscreen/ui/r$a; # player state + iget-object v1, v0, Lcom/tidal/android/feature/playerscreen/ui/v0;->b:Lcom/tidal/android/feature/playerscreen/ui/s$a; # player state
+ +
+ iget-object v1, v1, Lcom/tidal/android/feature/playerscreen/ui/r$a;->j:Lcom/tidal/android/feature/playerscreen/ui/g; # current view mode + iget-object v1, v1, Lcom/tidal/android/feature/playerscreen/ui/s$a;->j:Lcom/tidal/android/feature/playerscreen/ui/g; # current view mode
+ +
+ instance-of v1, v1, Lcom/tidal/android/feature/playerscreen/ui/g$a; # cover mode only + instance-of v1, v1, Lcom/tidal/android/feature/playerscreen/ui/g$a; # cover mode only
+ +
+ if-eqz v1, :radiant_after_cover # lyrics/credits mode -> skip cover + if-eqz v1, :radiant_after_cover # lyrics/credits mode -> skip cover
+ +
invoke-static/range {v2 .. v9}, Lcom/tidal/android/feature/playerscreen/ui/composables/CoverPagerKt;->c(Lcom/tidal/android/feature/playerscreen/ui/d;Lyl0/l;FLandroidx/compose/ui/Modifier;ZLandroidx/compose/runtime/Composer;II)V invoke-static/range {v2 .. v9}, Lcom/tidal/android/feature/playerscreen/ui/composables/CoverPagerKt;->c(Lcom/tidal/android/feature/playerscreen/ui/d;Lem0/l;FLandroidx/compose/ui/Modifier;ZLandroidx/compose/runtime/Composer;II)V
+ :radiant_after_cover # skip target + :radiant_after_cover # skip target
+ invoke-interface {v7}, Landroidx/compose/runtime/Composer;->endReplaceGroup()V # close group + invoke-interface {v7}, Landroidx/compose/runtime/Composer;->endReplaceGroup()V # close group
+ +
+11 -12
View File
@@ -1,16 +1,15 @@
--- a/com/tidal/android/feature/playerscreen/ui/composables/o1.smali --- a/com/tidal/android/feature/playerscreen/ui/composables/l1.smali
+++ b/com/tidal/android/feature/playerscreen/ui/composables/o1.smali +++ b/com/tidal/android/feature/playerscreen/ui/composables/l1.smali
@@ -64,26 +64,29 @@ @@ -64,7 +64,7 @@
.line 16 .line 16
.line 17 .line 17
- iget v2, p0, Lcom/tidal/android/feature/playerscreen/ui/composables/o1;->a:F - iget v2, p0, Lcom/tidal/android/feature/playerscreen/ui/composables/l1;->a:F
+ const/high16 v2, 0x43200000 # 160f start dp + const/high16 v2, 0x43200000 # 160f start dp
.line 18 .line 18
.line 19 .line 19
invoke-interface {p1, v2}, Landroidx/compose/ui/unit/Density;->toPx-0680j_4(F)F @@ -73,7 +73,13 @@
.line 20 .line 20
.line 21 .line 21
.line 22 .line 22
@@ -22,16 +21,16 @@
+ invoke-interface {p1, v3}, Landroidx/compose/ui/unit/Density;->toPx-0680j_4(F)F # dp to px + invoke-interface {p1, v3}, Landroidx/compose/ui/unit/Density;->toPx-0680j_4(F)F # dp to px
+ +
+ move-result v3 # endY in px + move-result v3 # endY in px
.line 23 .line 23
const/16 v5, 0x8 const/16 v5, 0x8
@@ -82,9 +88,6 @@
.line 24
.line 25 .line 25
const/4 v6, 0x0 const/4 v6, 0x0
- .line 26 - .line 26
- const/4 v2, 0x0 - const/4 v2, 0x0
- -
.line 27 .line 27
const/4 v4, 0x0 const/4 v4, 0x0
@@ -13,3 +13,20 @@
.line 27 .line 27
.line 28 .line 28
iput v2, p0, Lcom/tidal/android/feature/playerscreen/ui/PlayerScreenKt$PlayerScreenPortrait$2$1;->label:I iput v2, p0, Lcom/tidal/android/feature/playerscreen/ui/PlayerScreenKt$PlayerScreenPortrait$2$1;->label:I
--- a/com/tidal/android/feature/playerscreen/ui/PlayerViewModel.smali
+++ b/com/tidal/android/feature/playerscreen/ui/PlayerViewModel.smali
@@ -1299,6 +1299,14 @@
.line 109
.line 110
move-result v1
+ sget v4, Lradiant/LyricsReinitGuard;->lastMediaId:I
+ if-eq v1, v4, :rl_skip_reinit # same track re-emitted -> skip the redundant re-init (avoids the loading-state flash)
+ sput v1, Lradiant/LyricsReinitGuard;->lastMediaId:I
+ goto :rl_reinit_ok
+ :rl_skip_reinit
+ sget-object v4, Lkotlin/v;->a:Lkotlin/v;
+ return-object v4
+ :rl_reinit_ok
.line 111
invoke-static {v1}, Ljava/lang/String;->valueOf(I)Ljava/lang/String;
+10 -10
View File
@@ -1,18 +1,18 @@
--- a/com/tidal/android/feature/playerscreen/ui/c0.smali --- a/com/tidal/android/feature/playerscreen/ui/s0.smali
+++ b/com/tidal/android/feature/playerscreen/ui/c0.smali +++ b/com/tidal/android/feature/playerscreen/ui/s0.smali
@@ -47,7 +47,7 @@ @@ -45,7 +45,7 @@
# virtual methods # virtual methods
.method public final invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; .method public final invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
- .locals 17 - .locals 17
+ .locals 26 # extra regs for AndroidView + .locals 26 # extra regs for AndroidView
.line 1 .line 1
move-object/from16 v0, p0 move-object/from16 v0, p0
@@ -461,6 +461,64 @@ @@ -460,6 +460,64 @@
.line 200 .line 200
invoke-static/range {v2 .. v9}, Lcom/tidal/android/feature/playerscreen/ui/composables/LyricsKt;->a(Lcom/tidal/android/feature/playerscreen/ui/g;Lyl0/l;Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/layout/PaddingValues;Lyl0/l;Landroidx/compose/runtime/Composer;II)V invoke-static/range {v2 .. v9}, Lcom/tidal/android/feature/playerscreen/ui/composables/LyricsKt;->a(Lcom/tidal/android/feature/playerscreen/ui/g;Lem0/l;Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/layout/PaddingValues;Lem0/l;Landroidx/compose/runtime/Composer;II)V
+ sget-object v17, Lradiant/SpvFactory;->a:Lradiant/SpvFactory; # progress view factory + sget-object v17, Lradiant/SpvFactory;->a:Lradiant/SpvFactory; # progress view factory
+ +
+ sget-object v18, Landroidx/compose/ui/Modifier;->Companion:Landroidx/compose/ui/Modifier$Companion; # base modifier + sget-object v18, Landroidx/compose/ui/Modifier;->Companion:Landroidx/compose/ui/Modifier$Companion; # base modifier
@@ -29,7 +29,7 @@
+ +
+ const/16 v24, 0x0 # synthetic null + const/16 v24, 0x0 # synthetic null
+ +
+ invoke-static/range {v18 .. v24}, Landroidx/compose/foundation/ClickableKt;->clickable-XHw0xAI$default(Landroidx/compose/ui/Modifier;ZLjava/lang/String;Landroidx/compose/ui/semantics/Role;Lyl0/a;ILjava/lang/Object;)Landroidx/compose/ui/Modifier; # apply clickable + invoke-static/range {v18 .. v24}, Landroidx/compose/foundation/ClickableKt;->clickable-XHw0xAI$default(Landroidx/compose/ui/Modifier;ZLjava/lang/String;Landroidx/compose/ui/semantics/Role;Lem0/a;ILjava/lang/Object;)Landroidx/compose/ui/Modifier; # apply clickable
+ +
+ move-result-object v23 # clickable modifier + move-result-object v23 # clickable modifier
+ +
@@ -69,7 +69,7 @@
+ +
+ const/16 v22, 0x4 # default mask + const/16 v22, 0x4 # default mask
+ +
+ invoke-static/range {v17 .. v22}, Landroidx/compose/ui/viewinterop/AndroidView_androidKt;->AndroidView(Lyl0/l;Landroidx/compose/ui/Modifier;Lyl0/l;Landroidx/compose/runtime/Composer;II)V # mount progress pill + invoke-static/range {v17 .. v22}, Landroidx/compose/ui/viewinterop/AndroidView_androidKt;->AndroidView(Lem0/l;Landroidx/compose/ui/Modifier;Lem0/l;Landroidx/compose/runtime/Composer;II)V # mount progress pill
+ +
.line 201 .line 201
.line 202 .line 202
+22 -22
View File
@@ -1,34 +1,30 @@
# rl-locals: com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali e( 79 # rl-locals: com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali e( 79
--- a/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali --- a/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali
+++ b/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali +++ b/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali
@@ -4945,7 +4945,11 @@ @@ -5002,7 +5002,11 @@
const/4 v7, 0x0 const/4 v13, 0x0
.line 226 .line 230
- invoke-static {v7, v9, v4, v2, v10}, Lcom/tidal/android/feature/playerscreen/ui/composables/k1;->a(Landroidx/compose/ui/Modifier;Lyl0/a;ZLandroidx/compose/runtime/Composer;I)V - invoke-static {v13, v6, v4, v14, v11}, Lcom/tidal/android/feature/playerscreen/ui/composables/h1;->a(Landroidx/compose/ui/Modifier;Lem0/a;ZLandroidx/compose/runtime/Composer;I)V
+ const v10, 0x52414448 # empty group key + const v13, 0x52414448 # empty group key
+ +
+ invoke-interface {v2, v10}, Landroidx/compose/runtime/Composer;->startReplaceGroup(I)V # open empty + invoke-interface {v14, v13}, Landroidx/compose/runtime/Composer;->startReplaceGroup(I)V # open empty
+ +
+ invoke-interface {v2}, Landroidx/compose/runtime/Composer;->endReplaceGroup()V # close empty + invoke-interface {v14}, Landroidx/compose/runtime/Composer;->endReplaceGroup()V # close empty
.line 227 .line 231
invoke-interface {v2}, Landroidx/compose/runtime/Composer;->endReplaceGroup()V invoke-interface {v14}, Landroidx/compose/runtime/Composer;->endReplaceGroup()V
@@ -5720,6 +5724,22 @@ @@ -5791,6 +5795,22 @@
:cond_51
check-cast v4, Lyl0/a; invoke-static {v15, v7, v8, v3}, Lcom/tidal/android/feature/playerscreen/ui/composables/i3;->a(ILandroidx/compose/runtime/Composer;Landroidx/compose/ui/Modifier;Lem0/a;)V
const/4 v2, 0x0 + new-instance v74, Lcom/tidal/android/feature/playerscreen/ui/u0; # lyrics toggle lambda
invoke-static {v13, v7, v2, v4}, Lcom/tidal/android/feature/playerscreen/ui/composables/l3;->a(ILandroidx/compose/runtime/Composer;Landroidx/compose/ui/Modifier;Lyl0/a;)V
+
+ new-instance v74, Lcom/tidal/android/feature/playerscreen/ui/g0; # lyrics toggle lambda
+ +
+ move-object/from16 v75, p5 # action dispatcher + move-object/from16 v75, p5 # action dispatcher
+ +
+ const/16 v76, 0x0 # lyrics action disc + const/16 v76, 0x0 # lyrics action disc
+ +
+ invoke-direct/range {v74 .. v76}, Lcom/tidal/android/feature/playerscreen/ui/g0;-><init>(Ljava/lang/Object;I)V # build lambda + invoke-direct/range {v74 .. v76}, Lcom/tidal/android/feature/playerscreen/ui/u0;-><init>(Ljava/lang/Object;I)V # build lambda
+ +
+ const/16 v71, 0x0 # changed flags + const/16 v71, 0x0 # changed flags
+ +
@@ -36,4 +32,8 @@
+ +
+ const/16 v73, 0x0 # null modifier + const/16 v73, 0x0 # null modifier
+ +
+ invoke-static/range {v71 .. v74}, Lradiant/SparkleButton;->a(ILandroidx/compose/runtime/Composer;Landroidx/compose/ui/Modifier;Lyl0/a;)V # render sparkle button + invoke-static/range {v71 .. v74}, Lradiant/SparkleButton;->a(ILandroidx/compose/runtime/Composer;Landroidx/compose/ui/Modifier;Lem0/a;)V # render sparkle button
+
.line 336
iget-object v3, v10, Lcom/tidal/android/feature/playerscreen/ui/s$a;->l:Lcom/tidal/android/feature/playerscreen/ui/p;
+39 -43
View File
@@ -1,50 +1,46 @@
--- a/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali --- a/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali
+++ b/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali +++ b/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali
@@ -5094,7 +5094,11 @@ @@ -5155,7 +5155,11 @@
const/4 v13, 0x0 const/4 v13, 0x0
.line 247 .line 251
- invoke-static {v9, v0, v10, v2, v13}, Lcom/tidal/android/feature/playerscreen/ui/composables/BroadcastButtonKt;->b(Lcom/tidal/android/feature/playerscreen/ui/b;Lyl0/a;Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)V - invoke-static {v6, v10, v13, v14, v7}, Lcom/tidal/android/feature/playerscreen/ui/composables/BroadcastButtonKt;->b(Lcom/tidal/android/feature/playerscreen/ui/b;Lem0/a;Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)V
+ const v9, 0x52414244 # empty group key + const v13, 0x52414244 # empty group key
+ +
+ invoke-interface {v2, v9}, Landroidx/compose/runtime/Composer;->startReplaceGroup(I)V # open empty + invoke-interface {v14, v13}, Landroidx/compose/runtime/Composer;->startReplaceGroup(I)V # open empty
+ +
+ invoke-interface {v2}, Landroidx/compose/runtime/Composer;->endReplaceGroup()V # close empty + invoke-interface {v14}, Landroidx/compose/runtime/Composer;->endReplaceGroup()V # close empty
.line 248 .line 252
invoke-interface {v2}, Landroidx/compose/runtime/Composer;->endNode()V invoke-interface {v14}, Landroidx/compose/runtime/Composer;->endNode()V
@@ -5770,16 +5774,20 @@ @@ -5978,11 +5982,11 @@
.line 335 .line 356
:cond_53 :cond_59
- new-instance v4, Lcom/aspiro/wamp/tidalconnect/playback/i; :goto_29
- - new-instance v0, Lcom/tidal/android/feature/playerscreen/ui/i0;
- invoke-direct {v4, v11, v1}, Lcom/aspiro/wamp/tidalconnect/playback/i;-><init>(Ljava/lang/Object;I)V + new-instance v0, Lcom/squareup/ui/market/modal/o; # connect click lambda (was share i0)
-
- .line 336 - const/4 v15, 0x0
- invoke-interface {v7, v4}, Landroidx/compose/runtime/Composer;->updateRememberedValue(Ljava/lang/Object;)V + const/4 v15, 0x1 # connect-clicked disc
-
- .line 337 - invoke-direct {v0, v11, v15}, Lcom/tidal/android/feature/playerscreen/ui/i0;-><init>(Ljava/lang/Object;I)V
- :cond_54 + invoke-direct {v0, v11, v15}, Lcom/squareup/ui/market/modal/o;-><init>(Ljava/lang/Object;I)V # build connect lambda
- check-cast v4, Lyl0/a;
- .line 357
- const/4 v2, 0x0 invoke-interface {v7, v0}, Landroidx/compose/runtime/Composer;->updateRememberedValue(Ljava/lang/Object;)V
- @@ -5991,9 +5995,13 @@
- invoke-static {v13, v7, v2, v4}, Lcom/tidal/android/feature/playerscreen/ui/composables/x4;->a(ILandroidx/compose/runtime/Composer;Landroidx/compose/ui/Modifier;Lyl0/a;)V :goto_2a
+ new-instance v4, Landroidx/navigation/fragment/k; # connect click lambda factory check-cast v0, Lem0/a;
- const/4 v8, 0x0
+ iget-object v8, v10, Lcom/tidal/android/feature/playerscreen/ui/s$a;->d:Lcom/tidal/android/feature/playerscreen/ui/b; # broadcast state
+ +
+ move-object/from16 v6, p5 # action dispatcher + const/4 v13, 0x0 # null modifier
+ +
+ const/4 v8, 0x1 # connect-clicked disc + const/4 v15, 0x0 # changed flags
+
+ invoke-direct {v4, v6, v8}, Landroidx/navigation/fragment/k;-><init>(Ljava/lang/Object;I)V # build lambda - invoke-static {v15, v7, v8, v0}, Lcom/tidal/android/feature/playerscreen/ui/composables/t4;->a(ILandroidx/compose/runtime/Composer;Landroidx/compose/ui/Modifier;Lem0/a;)V
+ + invoke-static {v8, v0, v13, v7, v15}, Lcom/tidal/android/feature/playerscreen/ui/composables/BroadcastButtonKt;->b(Lcom/tidal/android/feature/playerscreen/ui/b;Lem0/a;Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)V # render connect button
+ invoke-interface {v7, v4}, Landroidx/compose/runtime/Composer;->updateRememberedValue(Ljava/lang/Object;)V # cache lambda
+ if-ne v1, v2, :cond_5a
+ :cond_54 # cache join
+ check-cast v4, Lyl0/a; # cast to Function0
+
+ iget-object v8, v10, Lcom/tidal/android/feature/playerscreen/ui/r$a;->d:Lcom/tidal/android/feature/playerscreen/ui/b; # broadcast state
+
+ const/4 v2, 0x0 # changed flags
+
+ invoke-static {v8, v4, v13, v7, v2}, Lcom/tidal/android/feature/playerscreen/ui/composables/BroadcastButtonKt;->b(Lcom/tidal/android/feature/playerscreen/ui/b;Lyl0/a;Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)V # render connect button
+51 -6
View File
@@ -1,21 +1,66 @@
--- a/com/tidal/android/feature/playerscreen/ui/PlayerViewModel.smali --- a/com/tidal/android/feature/playerscreen/ui/PlayerViewModel.smali
+++ b/com/tidal/android/feature/playerscreen/ui/PlayerViewModel.smali +++ b/com/tidal/android/feature/playerscreen/ui/PlayerViewModel.smali
@@ -1277,7 +1277,9 @@ @@ -1291,6 +1291,8 @@
.line 104
.line 105 .line 105
check-cast v1, Lcom/aspiro/wamp/model/Track; check-cast v1, Lcom/aspiro/wamp/model/Track;
+ invoke-static {v0, v1}, Lradiant/RLAPILyricsHook;->onWampTrack(Lcom/tidal/android/feature/playerscreen/ui/PlayerViewModel;Lcom/aspiro/wamp/model/Track;)V # RL API lyrics hook + invoke-static {v0, v1}, Lradiant/RLAPILyricsHook;->onWampTrack(Lcom/tidal/android/feature/playerscreen/ui/PlayerViewModel;Lcom/aspiro/wamp/model/Track;)V # RL API lyrics hook
+ +
.line 106 .line 106
.line 107 .line 107
invoke-virtual {v1}, Lcom/aspiro/wamp/model/MediaItem;->getId()I invoke-virtual {v1}, Lcom/aspiro/wamp/model/MediaItem;->getId()I
@@ -1551,7 +1553,7 @@ @@ -1564,7 +1566,7 @@
.line 235 .line 235
.line 236 .line 236
.line 237 .line 237
- if-nez v9, :cond_a - if-nez v9, :cond_a
+ goto :cond_a # skip TIDAL N=false setter + goto :cond_a # RL: skip TIDAL O=false in the has-lyrics path
.line 238 .line 238
.line 239 .line 239
@@ -2256,7 +2258,10 @@
.line 568
:goto_c
+ sget-boolean v5, Lradiant/RLAPILyricsHook;->isRlState:Z
+ if-nez v5, :rl_keep_n2 # RL active -> keep worker content
invoke-interface {v9, v1}, Lkotlinx/coroutines/flow/MutableStateFlow;->setValue(Ljava/lang/Object;)V
+ :rl_keep_n2
.line 569
.line 570
@@ -2305,7 +2310,10 @@
.line 591
.line 592
+ sget-boolean v7, Lradiant/RLAPILyricsHook;->isRlState:Z
+ if-nez v7, :rl_keep_o # RL active -> keep view-open flag
invoke-interface {v1, v5}, Lkotlinx/coroutines/flow/MutableStateFlow;->setValue(Ljava/lang/Object;)V
+ :rl_keep_o
.line 593
.line 594
@@ -2334,7 +2342,10 @@
.line 606
.line 607
+ sget-boolean v7, Lradiant/RLAPILyricsHook;->isRlState:Z
+ if-nez v7, :rl_keep_n # RL active -> keep worker content
invoke-interface {v1, v6}, Lkotlinx/coroutines/flow/MutableStateFlow;->setValue(Ljava/lang/Object;)V
+ :rl_keep_n
.line 608
.line 609
--- a/com/tidal/android/feature/playerscreen/ui/PlayerViewModel$special$$inlined$mapNotNull$1$2.smali
+++ b/com/tidal/android/feature/playerscreen/ui/PlayerViewModel$special$$inlined$mapNotNull$1$2.smali
@@ -2202,6 +2202,10 @@
.line 1011
.line 1012
move-result v31
+ sget-boolean v5, Lradiant/RLAPILyricsHook;->isRlState:Z
+ if-eqz v5, :rl_hl_done # not RL -> use TIDAL's hasLyrics
+ const/16 v31, 0x1 # RL lyrics active -> force hasLyrics so the sparkle stays
+ :rl_hl_done
.line 1013
iget-object v5, v1, Lcom/tidal/android/feature/playerscreen/ui/PlayerViewModel;->O:Lkotlinx/coroutines/flow/MutableStateFlow;
@@ -1,32 +1,24 @@
--- a/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali --- a/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali
+++ b/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali +++ b/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali
@@ -5725,17 +5725,38 @@ @@ -5795,6 +5795,14 @@
invoke-static {v13, v7, v2, v4}, Lcom/tidal/android/feature/playerscreen/ui/composables/l3;->a(ILandroidx/compose/runtime/Composer;Landroidx/compose/ui/Modifier;Lyl0/a;)V
+ invoke-static {v15, v7, v8, v3}, Lcom/tidal/android/feature/playerscreen/ui/composables/i3;->a(ILandroidx/compose/runtime/Composer;Landroidx/compose/ui/Modifier;Lem0/a;)V
+ iget-boolean v2, v10, Lcom/tidal/android/feature/playerscreen/ui/r$a;->i:Z # hasLyrics flag
+ iget-boolean v2, v10, Lcom/tidal/android/feature/playerscreen/ui/s$a;->i:Z # hasLyrics flag
+ +
+ if-eqz v2, :cond_sparkle_no_lyrics # branch when no lyrics + if-eqz v2, :cond_sparkle_no_lyrics # branch when no lyrics
+ +
+ const v2, 0x30551b59 # group key (lyrics) + const v2, 0x30551b59 # group key (lyrics)
+ +
+ invoke-interface {v7, v2}, Landroidx/compose/runtime/Composer;->startReplaceGroup(I)V # open lyrics branch + invoke-interface {v7, v2}, Landroidx/compose/runtime/Composer;->startReplaceGroup(I)V # open lyrics branch
new-instance v74, Lcom/tidal/android/feature/playerscreen/ui/g0; # lyrics toggle lambda
move-object/from16 v75, p5 # action dispatcher
const/16 v76, 0x0 # lyrics action disc
invoke-direct/range {v74 .. v76}, Lcom/tidal/android/feature/playerscreen/ui/g0;-><init>(Ljava/lang/Object;I)V # build lambda
const/16 v71, 0x0 # changed flags
move-object/from16 v72, v7 # composer
const/16 v73, 0x0 # null modifier
invoke-static/range {v71 .. v74}, Lradiant/SparkleButton;->a(ILandroidx/compose/runtime/Composer;Landroidx/compose/ui/Modifier;Lyl0/a;)V # render sparkle button
+ +
new-instance v74, Lcom/tidal/android/feature/playerscreen/ui/u0; # lyrics toggle lambda
move-object/from16 v75, p5 # action dispatcher
@@ -5811,6 +5819,19 @@
invoke-static/range {v71 .. v74}, Lradiant/SparkleButton;->a(ILandroidx/compose/runtime/Composer;Landroidx/compose/ui/Modifier;Lem0/a;)V # render sparkle button
+ invoke-interface {v7}, Landroidx/compose/runtime/Composer;->endReplaceGroup()V # close lyrics branch + invoke-interface {v7}, Landroidx/compose/runtime/Composer;->endReplaceGroup()V # close lyrics branch
+ +
+ goto :goto_sparkle_done # skip empty branch + goto :goto_sparkle_done # skip empty branch
@@ -39,3 +31,7 @@
+ invoke-interface {v7}, Landroidx/compose/runtime/Composer;->endReplaceGroup()V # close empty + invoke-interface {v7}, Landroidx/compose/runtime/Composer;->endReplaceGroup()V # close empty
+ +
+ :goto_sparkle_done # join target + :goto_sparkle_done # join target
+
.line 336
iget-object v3, v10, Lcom/tidal/android/feature/playerscreen/ui/s$a;->l:Lcom/tidal/android/feature/playerscreen/ui/p;
+187 -42
View File
@@ -4,11 +4,15 @@
{ {
"id": "EnableLegacyUi", "id": "EnableLegacyUi",
"order": 10, "order": 10,
"fileNames": ["enable-legacy-ui.patch"], "fileNames": [
"enable-legacy-ui.patch"
],
"title": "Enable Legacy UI", "title": "Enable Legacy UI",
"description": "[This patch will stop working soon] - Replaces the New Compose based UI with the Legacy UI (disables player-market-ui feature flag)", "description": "[This patch will stop working soon] - Replaces the New Compose based UI with the Legacy UI (disables player-market-ui feature flag)",
"default": false, "default": false,
"requires": ["DebugMenuUnlock"], "requires": [
"DebugMenuUnlock"
],
"disables": [ "disables": [
"LyricsDisableCover", "LyricsDisableCover",
"LyricsReplaceLyricsButton", "LyricsReplaceLyricsButton",
@@ -18,14 +22,16 @@
"PlayerBackdrop", "PlayerBackdrop",
"QualityBadgeColors", "QualityBadgeColors",
"LyricsProgressPill", "LyricsProgressPill",
"CoverEverywhere",
"MiniPlayerRedesign" "MiniPlayerRedesign"
] ]
}, },
{ {
"id": "LyricsRlApi", "id": "LyricsRlApi",
"order": 20, "order": 20,
"fileNames": ["lyrics-rl-api.patch", "lyrics-rl-api-observer.patch"], "fileNames": [
"lyrics-rl-api.patch",
"lyrics-rl-api-observer.patch"
],
"title": "Radiant Lyrics API - WIP", "title": "Radiant Lyrics API - WIP",
"description": "Use Radiant Lyrics API to fetch Lyrics (Higher quality & More providers)", "description": "Use Radiant Lyrics API to fetch Lyrics (Higher quality & More providers)",
"default": false "default": false
@@ -33,59 +39,88 @@
{ {
"id": "PlayerBackdrop", "id": "PlayerBackdrop",
"order": 30, "order": 30,
"fileNames": ["player-backdrop.patch"], "fileNames": [
"player-backdrop.patch"
],
"title": "Player Backdrop", "title": "Player Backdrop",
"description": "Restores the legacy translucent backdrop blur behind the player.", "description": "Restores the legacy translucent backdrop blur behind the player",
"default": true, "default": true,
"advancedOptions": [ "advancedOptions": [
{ {
"type": "slider", "type": "slider",
"key": "blur_strength", "key": "blur_strength",
"title": "Blur Strength", "title": "Blur Strength",
"description": "How strongly the album art behind the player is blurred. 0% is sharp, 50% matches the original look.", "description": "How strongly the album art behind the player is blurred",
"default": 50, "default": 50,
"min": 0, "min": 0,
"max": 100, "max": 100,
"steps": 19, "steps": 19,
"displayAsPercent": true, "displayAsPercent": true,
"token": "RL_BLUR_BITS", "token": "RL_BLUR_BITS",
"encode": { "kind": "floatBits", "scale": 1.8 } "encode": {
"kind": "floatBits",
"scale": 1.8
}
}, },
{ {
"type": "slider", "type": "slider",
"key": "dimming", "key": "dimming",
"title": "Backdrop Dimming", "title": "Backdrop Dimming",
"description": "Darkens the backdrop so the foreground controls stay legible.", "description": "Darkens the backdrop so the foreground controls stay legible",
"default": 50, "default": 50,
"min": 0, "min": 0,
"max": 100, "max": 100,
"steps": 19, "steps": 19,
"displayAsPercent": true, "displayAsPercent": true,
"token": "RL_SCRIM_ARGB", "token": "RL_SCRIM_ARGB",
"encode": { "kind": "argbAlpha" } "encode": {
"kind": "argbAlpha"
}
},
{
"type": "toggle",
"key": "cover_everywhere",
"title": "Cover Everywhere - WIP",
"description": "Applies the blurred backdrop to every Compose based page (Home & Collection)",
"default": false,
"inline": true,
"fileNames": [
"home-backdrop.patch",
"collection-backdrop.patch",
"cover-capture.patch"
]
} }
] ]
}, },
{
"id": "CoverEverywhere",
"order": 35,
"fileNames": ["home-backdrop.patch", "collection-backdrop.patch", "cover-capture.patch"],
"title": "Cover Everywhere - WIP",
"description": "Applies the blurred backdrop to every Compose based page (Home & Collection)",
"default": false
},
{ {
"id": "QualityBadgeColors", "id": "QualityBadgeColors",
"order": 36, "order": 36,
"fileNames": ["player-quality-badge-colors.patch"], "fileNames": [
"player-quality-badge-colors.patch"
],
"title": "Quality Badge Colors", "title": "Quality Badge Colors",
"description": "Brings color back to the player quality badge.", "description": "Brings color back to the player quality badge.",
"default": true "default": true
}, },
{ {
"id": "PlayerOneHanded", "id": "PlayerMovePlayingFrom",
"order": 37, "order": 37,
"fileNames": ["player-one-handed.patch"], "fileNames": [
"player-move-playing-from.patch"
],
"extensionFiles": [
"radiant/PlayingFrom.smali"
],
"title": "Playing From",
"description": "Shows the source name (playlist/album/mix) above the track title",
"default": true
},
{
"id": "PlayerOneHanded",
"order": 38,
"fileNames": [
"player-one-handed.patch"
],
"title": "One-Handed Mode", "title": "One-Handed Mode",
"description": "Mirrors the bottom player buttons left-to-right for easier one-handed reach.", "description": "Mirrors the bottom player buttons left-to-right for easier one-handed reach.",
"default": false "default": false
@@ -93,16 +128,25 @@
{ {
"id": "LyricsProgressPill", "id": "LyricsProgressPill",
"order": 40, "order": 40,
"fileNames": ["lyrics-progress-pill.patch", "lyrics-fade-region.patch"], "fileNames": [
"lyrics-progress-pill.patch",
"lyrics-fade-region.patch"
],
"title": "Lyrics Progress Pill", "title": "Lyrics Progress Pill",
"description": "Restores the old Track Progress Pill in the top of the Lyrics screen!", "description": "Restores the old Track Progress Pill in the top of the Lyrics screen!",
"default": true, "default": true,
"requires": ["LyricsDisableCover", "LyricsReplaceLyricsButton", "LyricsReplaceShareButton"] "requires": [
"LyricsDisableCover",
"LyricsReplaceLyricsButton",
"LyricsReplaceShareButton"
]
}, },
{ {
"id": "LyricsDisableCover", "id": "LyricsDisableCover",
"order": 41, "order": 41,
"fileNames": ["lyrics-disable-cover.patch"], "fileNames": [
"lyrics-disable-cover.patch"
],
"title": "Disable Lyrics Cover", "title": "Disable Lyrics Cover",
"description": "Removes the mini track cover from the lyrics screen.", "description": "Removes the mini track cover from the lyrics screen.",
"default": true "default": true
@@ -110,7 +154,10 @@
{ {
"id": "LyricsReplaceLyricsButton", "id": "LyricsReplaceLyricsButton",
"order": 42, "order": 42,
"fileNames": ["lyrics-replace-lyrics-button.patch", "lyrics-sparkle-conditional-visibility.patch"], "fileNames": [
"lyrics-replace-lyrics-button.patch",
"lyrics-sparkle-conditional-visibility.patch"
],
"title": "Replace Lyrics Button", "title": "Replace Lyrics Button",
"description": "Replaces the Lyrics button with the RL Sparkle!", "description": "Replaces the Lyrics button with the RL Sparkle!",
"default": true "default": true
@@ -118,7 +165,9 @@
{ {
"id": "LyricsReplaceShareButton", "id": "LyricsReplaceShareButton",
"order": 43, "order": 43,
"fileNames": ["lyrics-replace-share-button.patch"], "fileNames": [
"lyrics-replace-share-button.patch"
],
"title": "Replace Share Button", "title": "Replace Share Button",
"description": "Replaces the share button with the Tidal Connect button from the top of the screen. (it's in the menu already)", "description": "Replaces the share button with the Tidal Connect button from the top of the screen. (it's in the menu already)",
"default": true "default": true
@@ -132,9 +181,22 @@
"default": false, "default": false,
"defaultVariantIndex": 2, "defaultVariantIndex": 2,
"variants": [ "variants": [
{ "title": "Floating", "fileNames": [] }, {
{ "title": "Grey", "fileNames": ["mini-player-grey.patch"] }, "title": "Floating",
{ "title": "Black", "fileNames": ["mini-player-black.patch"] } "fileNames": []
},
{
"title": "Grey",
"fileNames": [
"mini-player-grey.patch"
]
},
{
"title": "Black",
"fileNames": [
"mini-player-black.patch"
]
}
], ],
"advancedOptions": [ "advancedOptions": [
{ {
@@ -144,10 +206,18 @@
"description": "Colorizes the Mini-Player depending on the currently playing track.", "description": "Colorizes the Mini-Player depending on the currently playing track.",
"default": false, "default": false,
"inline": true, "inline": true,
"fileNames": ["mini-player-dynamic-bg.patch"], "fileNames": [
"extensionFiles": ["radiant/MiniPlayerBackground.smali"], "mini-player-dynamic-bg.patch"
"hidesVariants": [2], ],
"relabelVariants": { "1": "Legacy" } "extensionFiles": [
"radiant/MiniPlayerBackground.smali"
],
"hidesVariants": [
2
],
"relabelVariants": {
"1": "Legacy"
}
}, },
{ {
"type": "toggle", "type": "toggle",
@@ -156,23 +226,47 @@
"description": "Draws an animated progress ring around the floating mini-player. Requires the Floating style.", "description": "Draws an animated progress ring around the floating mini-player. Requires the Floating style.",
"default": false, "default": false,
"requiresVariant": 0, "requiresVariant": 0,
"fileNames": ["mini-player-floating-border.patch"], "fileNames": [
"extensionFiles": ["radiant/MiniSeekerFloating.smali"] "mini-player-floating-border.patch"
],
"extensionFiles": [
"radiant/MiniSeekerFloating.smali"
]
}, },
{ {
"type": "toggle", "type": "toggle",
"key": "gestures", "key": "gestures",
"title": "Mini-Player Gestures", "title": "Mini-Player Gestures",
"description": "Swipe up on the mini-player to open the full player.", "description": "Adds swipe up gesture to the mini-player to reopen the player",
"default": true, "default": true,
"fileNames": ["mini-player-gestures.patch"], "fileNames": [
"mini-player-gestures.patch"
],
"extensionFiles": [ "extensionFiles": [
"radiant/MiniPlayerGestures.smali", "radiant/MiniPlayerGestures.smali",
"radiant/MiniPlayerGestures$Gesture.smali", "radiant/MiniPlayerGestures$Gesture.smali",
"radiant/MiniPlayerGestures$FeedbackLayer.smali",
"radiant/MiniPlayerGestures$FeedbackResetAnimator.smali",
"radiant/MiniPlayerGestures$RootGesture.smali", "radiant/MiniPlayerGestures$RootGesture.smali",
"radiant/MiniPlayerGestures$ApplyPending.smali" "radiant/MiniPlayerGestures$ApplyPending.smali"
] ]
}, },
{
"type": "choice",
"key": "swipe_up_drag",
"title": "Swipe Up Style",
"entries": [
"Static",
"Drag"
],
"values": [
"0x0",
"0x1"
],
"defaultIndex": 1,
"requiresOption": "gestures",
"token": "RL_MINI_PLAYER_SWIPE_UP_DRAG"
},
{ {
"type": "toggle", "type": "toggle",
"key": "next_prev", "key": "next_prev",
@@ -180,14 +274,16 @@
"description": "Swipe left or right on the mini-player to skip tracks.", "description": "Swipe left or right on the mini-player to skip tracks.",
"default": false, "default": false,
"requiresOption": "gestures", "requiresOption": "gestures",
"fileNames": ["mini-player-gestures-left-right.patch"], "fileNames": [
"mini-player-gestures-left-right.patch"
],
"extensionFiles": [ "extensionFiles": [
"radiant/MiniPlayerTrackGestures.smali", "radiant/MiniPlayerTrackGestures.smali",
"radiant/MiniPlayerTrackGestures$Gesture.smali", "radiant/MiniPlayerTrackGestures$Gesture.smali",
"radiant/MiniPlayerTrackGestures$OffsetLayer.smali", "radiant/MiniPlayerTrackGestures$OffsetLayer.smali",
"radiant/MiniPlayerTrackGestures$ResetAnimator.smali", "radiant/MiniPlayerTrackGestures$ResetAnimator.smali",
"radiant/MiniPlayerTrackGestures$TextDraw.smali", "radiant/MiniPlayerTrackGestures$TextDraw.smali",
"com/tidal/android/feature/appscaffold/ui/q$c.smali" "com/tidal/android/feature/appscaffold/ui/s$c.smali"
] ]
} }
] ]
@@ -195,15 +291,64 @@
{ {
"id": "LyricsKeepControlsVisible", "id": "LyricsKeepControlsVisible",
"order": 60, "order": 60,
"fileNames": ["lyrics-keep-controls-visible.patch"], "fileNames": [
"lyrics-keep-controls-visible.patch"
],
"extensionFiles": [
"radiant/LyricsReinitGuard.smali"
],
"title": "Keep Controls Visible", "title": "Keep Controls Visible",
"description": "Inverts the auto-hide behavior on the lyrics screen, playback controls stay visible by default and only hide when you tap them off.", "description": "Inverts the auto-hide behavior on the lyrics screen, playback controls stay visible by default and only hide when you tap them off. Also stops the open lyrics view from randomly closing when the player re-fetches the same track.",
"default": true "default": true
}, },
{
"id": "WazeIntegration",
"order": 90,
"category": "integration",
"pathLocked": true,
"fileNames": [
"integration-waze-playback.patch"
],
"extensionFiles": [
"radiant/WazeInitReceiver.smali",
"radiant/WazeServiceConnection.smali"
],
"title": "Waze Integration",
"description": "Control TIDAL playback from the Waze app",
"default": true,
"advancedOptions": [
{
"type": "choice",
"key": "browse_root",
"title": "Media Menu",
"entries": [
"Auto Menu",
"Home",
"Recents"
],
"values": [
"ROOT_AUTO",
"HOME_V2::home_page_v2_id",
"RECENTLY_PLAYED::home/pages/CONTINUE_LISTEN_TO/view-all"
],
"defaultIndex": 0,
"token": "RL_WAZE_ROOT_ID"
},
{
"type": "color",
"key": "accent_color",
"title": "Accent Color",
"default": -16747037,
"token": "RL_WAZE_THEME_COLOR"
}
]
},
{ {
"id": "DebugMenuUnlock", "id": "DebugMenuUnlock",
"order": 100, "order": 100,
"fileNames": ["debug-menu-unlock.patch"], "fileNames": [
"debug-menu-unlock.patch"
],
"title": "Unlock Debug Menu", "title": "Unlock Debug Menu",
"description": "Reveals TIDAL's hidden Debug Menu in Settings. (Unlocks Feature Flags & the legacy Debug Options)", "description": "Reveals TIDAL's hidden Debug Menu in Settings. (Unlocks Feature Flags & the legacy Debug Options)",
"default": false "default": false
+31 -32
View File
@@ -20,61 +20,60 @@
.line 71 .line 71
--- a/com/tidal/android/feature/appscaffold/ui/composable/i.smali --- a/com/tidal/android/feature/appscaffold/ui/composable/i.smali
+++ b/com/tidal/android/feature/appscaffold/ui/composable/i.smali +++ b/com/tidal/android/feature/appscaffold/ui/composable/i.smali
@@ -2756,12 +2756,7 @@ @@ -2275,11 +2275,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 move-result-object v2
- .line 143
- invoke-static {v2}, Landroidx/compose/foundation/layout/WindowInsetsPadding_androidKt;->navigationBarsPadding(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier;
- -
- .line 140 - move-result-object v2
- 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 + # flush bottom; skip nav inset
.line 141 .line 144
invoke-interface/range {v17 .. v17}, Landroidx/compose/runtime/State;->getValue()Ljava/lang/Object; invoke-interface/range {v21 .. v21}, Landroidx/compose/runtime/State;->getValue()Ljava/lang/Object;
@@ -2773,6 +2768,8 @@ @@ -2291,6 +2287,8 @@
move-result v10 move-result v4
+ const/4 v10, 0x0 # zero horizontal padding + const/4 v4, 0x0 # zero horizontal padding
+ +
const/4 v11, 0x2 const/4 v6, 0x2
.line 142 .line 145
@@ -2816,6 +2813,12 @@ @@ -2334,6 +2332,12 @@
move-result-wide v10 move-result-wide v3
+ const v8, -0x1000000 # 0xFF000000 opaque black + const v5, -0x1000000 # 0xFF000000 opaque black
+ +
+ invoke-static {v8}, Landroidx/compose/ui/graphics/ColorKt;->Color(I)J # pack to color long + invoke-static {v5}, Landroidx/compose/ui/graphics/ColorKt;->Color(I)J # pack to color long
+ +
+ move-result-wide v10 # override theme color + move-result-wide v3 # override theme color
+ +
.line 147 .line 150
sget-object v8, Lcom/tidal/android/feature/appscaffold/ui/composable/a;->c:Landroidx/compose/foundation/shape/RoundedCornerShape; sget-object v5, Lcom/tidal/android/feature/appscaffold/ui/composable/a;->c:Landroidx/compose/foundation/shape/RoundedCornerShape;
@@ -2857,6 +2860,10 @@ @@ -2375,6 +2379,10 @@
move-result-object v0 move-result-object v2
+ invoke-static {v0}, Landroidx/compose/foundation/layout/WindowInsetsPadding_androidKt;->navigationBarsPadding(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier; # inset bar content above nav bar (Prevents Bleeding behind Nav Buttons) + invoke-static {v2}, Landroidx/compose/foundation/layout/WindowInsetsPadding_androidKt;->navigationBarsPadding(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier; # inset bar content above nav bar (Prevents Bleeding behind Nav Buttons)
+ +
+ move-result-object v0 + move-result-object v2
+ +
.line 155 .line 158
sget-object v8, Landroidx/compose/foundation/layout/Arrangement;->INSTANCE:Landroidx/compose/foundation/layout/Arrangement; sget-object v3, Landroidx/compose/foundation/layout/Arrangement;->INSTANCE:Landroidx/compose/foundation/layout/Arrangement;
@@ -2969,6 +2976,10 @@ @@ -2487,6 +2495,10 @@
invoke-static {v12, v0, v8}, Landroidx/compose/runtime/Updater;->set-impl(Landroidx/compose/runtime/Composer;Ljava/lang/Object;Lyl0/p;)V invoke-static {v6, v2, v3}, Landroidx/compose/runtime/Updater;->set-impl(Landroidx/compose/runtime/Composer;Ljava/lang/Object;Lem0/p;)V
+ const/4 v8, 0x0 # composer $changed flags + const/4 v8, 0x0 # composer $changed flags
+ +
+ invoke-static {v15, v8}, Lradiant/MiniSeekerLine;->render(Landroidx/compose/runtime/Composer;I)V # draw top-edge seeker + invoke-static {v7, v8}, Lradiant/MiniSeekerLine;->render(Landroidx/compose/runtime/Composer;I)V # draw top-edge seeker
+ +
.line 172 .line 175
sget-object v0, Landroidx/compose/foundation/layout/ColumnScopeInstance;->INSTANCE:Landroidx/compose/foundation/layout/ColumnScopeInstance; sget-object v2, Landroidx/compose/foundation/layout/ColumnScopeInstance;->INSTANCE:Landroidx/compose/foundation/layout/ColumnScopeInstance;
+16 -17
View File
@@ -1,33 +1,32 @@
--- a/com/tidal/android/feature/appscaffold/ui/composable/i.smali --- a/com/tidal/android/feature/appscaffold/ui/composable/i.smali
+++ b/com/tidal/android/feature/appscaffold/ui/composable/i.smali +++ b/com/tidal/android/feature/appscaffold/ui/composable/i.smali
@@ -2819,4 +2819,10 @@ @@ -2334,6 +2334,12 @@
.line 147
+ const/4 v8, 0x0 move-result-wide v3
+ const/4 v5, 0x0
+ +
+ invoke-static {v10, v11, v15, v8}, Lradiant/MiniPlayerBackground;->color(JLandroidx/compose/runtime/Composer;I)J # dynamic bg or fallback + invoke-static {v3, v4, v7, v5}, Lradiant/MiniPlayerBackground;->color(JLandroidx/compose/runtime/Composer;I)J # dynamic bg or fallback
+ +
+ move-result-wide v10 + move-result-wide v3
+ +
sget-object v8, Lcom/tidal/android/feature/appscaffold/ui/composable/a;->c:Landroidx/compose/foundation/shape/RoundedCornerShape; .line 150
sget-object v5, Lcom/tidal/android/feature/appscaffold/ui/composable/a;->c:Landroidx/compose/foundation/shape/RoundedCornerShape;
.line 148
--- a/com/tidal/android/feature/playerscreen/ui/PlayerViewModel.smali --- a/com/tidal/android/feature/playerscreen/ui/PlayerViewModel.smali
+++ b/com/tidal/android/feature/playerscreen/ui/PlayerViewModel.smali +++ b/com/tidal/android/feature/playerscreen/ui/PlayerViewModel.smali
@@ -1047,9 +1047,13 @@ @@ -1063,6 +1063,10 @@
invoke-static {v2, v1, v4, v3}, Lkotlinx/coroutines/flow/FlowKt;->stateIn(Lkotlinx/coroutines/flow/Flow;Lkotlinx/coroutines/CoroutineScope;Lkotlinx/coroutines/flow/SharingStarted;Ljava/lang/Object;)Lkotlinx/coroutines/flow/StateFlow;
move-result-object v1 iput-object v1, v0, Lcom/tidal/android/feature/playerscreen/ui/PlayerViewModel;->V:Lkotlinx/coroutines/flow/StateFlow;
iput-object v1, v0, Lcom/tidal/android/feature/playerscreen/ui/PlayerViewModel;->U:Lkotlinx/coroutines/flow/StateFlow; + iget-object v1, v0, Lcom/tidal/android/feature/playerscreen/ui/PlayerViewModel;->P:Lkotlin/i;
+ iget-object v1, v0, Lcom/tidal/android/feature/playerscreen/ui/PlayerViewModel;->O:Lkotlin/h;
+ +
+ invoke-interface {v1}, Lkotlin/h;->getValue()Ljava/lang/Object; # init player bg color + invoke-interface {v1}, Lkotlin/i;->getValue()Ljava/lang/Object; # init player bg color
+ +
return-void return-void
.end method .end method
@@ -1607,6 +1611,8 @@ @@ -1620,6 +1624,8 @@
:goto_6 :goto_6
invoke-interface {v9, v10}, Lkotlinx/coroutines/flow/MutableStateFlow;->setValue(Ljava/lang/Object;)V invoke-interface {v9, v10}, Lkotlinx/coroutines/flow/MutableStateFlow;->setValue(Ljava/lang/Object;)V
@@ -36,7 +35,7 @@
.line 263 .line 263
.line 264 .line 264
.line 265 .line 265
@@ -2306,6 +2312,8 @@ @@ -2319,6 +2325,8 @@
.line 598 .line 598
invoke-interface {v1, v5}, Lkotlinx/coroutines/flow/MutableStateFlow;->setValue(Ljava/lang/Object;)V invoke-interface {v1, v5}, Lkotlinx/coroutines/flow/MutableStateFlow;->setValue(Ljava/lang/Object;)V
@@ -45,7 +44,7 @@
.line 599 .line 599
.line 600 .line 600
.line 601 .line 601
@@ -2523,6 +2531,8 @@ @@ -2536,6 +2544,8 @@
.line 704 .line 704
invoke-interface {v1, v5}, Lkotlinx/coroutines/flow/MutableStateFlow;->setValue(Ljava/lang/Object;)V invoke-interface {v1, v5}, Lkotlinx/coroutines/flow/MutableStateFlow;->setValue(Ljava/lang/Object;)V
+7 -7
View File
@@ -1,15 +1,15 @@
--- a/com/tidal/android/feature/appscaffold/ui/composable/i.smali --- a/com/tidal/android/feature/appscaffold/ui/composable/i.smali
+++ b/com/tidal/android/feature/appscaffold/ui/composable/i.smali +++ b/com/tidal/android/feature/appscaffold/ui/composable/i.smali
@@ -2829,6 +2829,12 @@ @@ -2347,6 +2347,12 @@
move-result-object v0 move-result-object v2
+ sget-object v8, Lradiant/MiniSeekerFloating;->INSTANCE:Lradiant/MiniSeekerFloating; # draw lambda + sget-object v5, 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 + invoke-static {v2, v5}, Landroidx/compose/ui/draw/DrawModifierKt;->drawWithContent(Landroidx/compose/ui/Modifier;Lem0/l;)Landroidx/compose/ui/Modifier; # overlay perimeter stroke
+ +
+ move-result-object v0 # updated modifier + move-result-object v2 # updated modifier
+ +
.line 150 .line 153
sget-object v8, Lkotlin/u;->a:Lkotlin/u; sget-object v3, Lkotlin/v;->a:Lkotlin/v;
+43 -41
View File
@@ -1,42 +1,50 @@
--- a/com/tidal/android/feature/appscaffold/ui/composable/MiniPlayerKt.smali --- a/com/tidal/android/feature/appscaffold/ui/composable/MiniPlayerKt.smali
+++ b/com/tidal/android/feature/appscaffold/ui/composable/MiniPlayerKt.smali +++ b/com/tidal/android/feature/appscaffold/ui/composable/MiniPlayerKt.smali
@@ -1746,6 +1746,10 @@ @@ -1215,6 +1215,10 @@
invoke-static {v9, v10, v15, v6, v8}, Landroidx/compose/foundation/layout/PaddingKt;->padding-qDBjuR0(Landroidx/compose/ui/Modifier;FFFF)Landroidx/compose/ui/Modifier;
move-result-object v6 move-result-object v6
+
+ invoke-static {v6, v1}, Lradiant/MiniPlayerTrackGestures;->trackModifier(Landroidx/compose/ui/Modifier;Lyl0/l;)Landroidx/compose/ui/Modifier; # attach horizontal swipe listener + invoke-static {v6, v1}, Lradiant/MiniPlayerTrackGestures;->trackModifier(Landroidx/compose/ui/Modifier;Lem0/l;)Landroidx/compose/ui/Modifier; # attach horizontal swipe listener
+ +
+ move-result-object v6 + move-result-object v6
+
.line 38 .line 38
sget-object v21, Landroidx/compose/ui/Alignment;->Companion:Landroidx/compose/ui/Alignment$Companion; sget-object v21, Landroidx/compose/ui/Alignment;->Companion:Landroidx/compose/ui/Alignment$Companion;
@@ -1884,5 +1888,5 @@
@@ -1352,6 +1356,8 @@
.line 56 .line 56
iget-object v6, v0, Lcom/tidal/android/feature/appscaffold/ui/s;->b:Lcom/tidal/android/feature/appscaffold/ui/p; iget-object v6, v0, Lcom/tidal/android/feature/appscaffold/ui/u;->b:Lcom/tidal/android/feature/appscaffold/ui/r;
-
+ invoke-static {v6}, Lradiant/MiniPlayerTrackGestures;->onRenderedItem(Ljava/lang/Object;)V # reset stale drag offset if track metadata changes mid-gesture + invoke-static {v6}, Lradiant/MiniPlayerTrackGestures;->onRenderedItem(Ljava/lang/Object;)V # reset stale drag offset if track metadata changes mid-gesture
+
.line 57 .line 57
invoke-virtual/range {v16 .. v16}, Lcom/squareup/ui/market/core/theme/MarketStylesheet;->getBorderRadii()Lcom/squareup/ui/market/core/theme/MarketStylesheet$b; invoke-virtual/range {v16 .. v16}, Lcom/squareup/ui/market/core/theme/MarketStylesheet;->getBorderRadii()Lcom/squareup/ui/market/core/theme/MarketStylesheet$b;
@@ -1919,5 +1923,6 @@
invoke-static {v5, v4}, Landroidx/compose/foundation/layout/SizeKt;->size-3ABfNKs(Landroidx/compose/ui/Modifier;F)Landroidx/compose/ui/Modifier; @@ -1388,6 +1394,10 @@
-
move-result-object v4 move-result-object v4
-
+ invoke-static {v4}, Lradiant/MiniPlayerTrackGestures;->feedbackModifier(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier; # move the whole cover container with horizontal swipe + invoke-static {v4}, Lradiant/MiniPlayerTrackGestures;->feedbackModifier(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier; # move the whole cover container with horizontal swipe
+
+ move-result-object v4 + move-result-object v4
+ +
.line 63 .line 63
@@ -2032,3 +2038,5 @@ invoke-virtual/range {v22 .. v22}, Lcom/squareup/ui/market/core/theme/MarketStylesheet$c;->p0()Lg20/a;
@@ -1499,6 +1509,10 @@
move-result-object v4 move-result-object v4
-
+ invoke-static {v4}, Lradiant/MiniPlayerTrackGestures;->textFeedbackModifier(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier; # move title/artist + invoke-static {v4}, Lradiant/MiniPlayerTrackGestures;->textFeedbackModifier(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier; # move title/artist
+
+ move-result-object v4 + move-result-object v4
+ +
.line 72 .line 72
invoke-virtual/range {v31 .. v31}, Landroidx/compose/foundation/layout/Arrangement;->getTop()Landroidx/compose/foundation/layout/Arrangement$Vertical;
--- a/com/tidal/android/feature/appscaffold/ui/MiniPlayerViewModel.smali --- a/com/tidal/android/feature/appscaffold/ui/MiniPlayerViewModel.smali
+++ b/com/tidal/android/feature/appscaffold/ui/MiniPlayerViewModel.smali +++ b/com/tidal/android/feature/appscaffold/ui/MiniPlayerViewModel.smali
@@ -816,10 +816,10 @@ @@ -595,10 +595,10 @@
.line 111 .line 111
.line 112 .line 112
.line 113 .line 113
@@ -49,21 +57,19 @@
.line 115 .line 115
.line 116 .line 116
@@ -997,11 +997,32 @@ @@ -778,6 +778,28 @@
:cond_e
return-void
- .line 195 .line 195
:cond_f :cond_f
+ sget-object v0, Lcom/tidal/android/feature/appscaffold/ui/q$c;->a:Lcom/tidal/android/feature/appscaffold/ui/q$c; + sget-object v0, Lcom/tidal/android/feature/appscaffold/ui/s$c;->a:Lcom/tidal/android/feature/appscaffold/ui/s$c; # our synthetic previous-track event
+ +
+ invoke-virtual {p1, v0}, Ljava/lang/Object;->equals(Ljava/lang/Object;)Z + invoke-virtual {p1, v0}, Ljava/lang/Object;->equals(Ljava/lang/Object;)Z # is this the swipe-previous event?
+ +
+ move-result p1 + move-result p1
+ +
+ if-eqz p1, :unknown_event + if-eqz p1, :unknown_event
+ +
+ invoke-interface {v3}, Lei/e;->canSkipToPreviousOrRewind()Z + invoke-interface {v3}, Ldi/e;->canSkipToPreviousOrRewind()Z
+ +
+ move-result p1 + move-result p1
+ +
@@ -71,36 +77,32 @@
+ +
+ const/4 p1, 0x0 + const/4 p1, 0x0
+ +
+ invoke-interface {v3, p1}, Lei/e;->h(Z)V # false = previous/rewind + invoke-interface {v3, p1}, Ldi/e;->h(Z)V # false = previous/rewind
+ +
+ :previous_done + :previous_done
+ return-void + return-void
+ +
+ :unknown_event + :unknown_event
invoke-static {}, Landroidx/compose/ui/graphics/y;->b()V invoke-static {}, Lcoil/util/i;->a()V
.line 196 .line 196
.line 197 --- a/com/aspiro/wamp/util/m.smali
.line 198 +++ b/com/aspiro/wamp/util/m.smali
return-void @@ -61,6 +61,17 @@
--- a/com/tidal/android/feature/appscaffold/ui/composable/e.smali
+++ b/com/tidal/android/feature/appscaffold/ui/composable/e.smali .line 15
@@ -75,6 +75,18 @@
.line 22
:pswitch_0 :pswitch_0
+ invoke-static {}, Lradiant/MiniPlayerTrackGestures;->consumeTapOpenSuppression()Z # prevent tap open after horizontal swipe + invoke-static {}, Lradiant/MiniPlayerTrackGestures;->consumeTapOpenSuppression()Z # skip open-player if a horizontal skip-swipe just happened
+ +
+ move-result v0 + move-result v0
+ +
+ if-eqz v0, :continue_open + if-eqz v0, :rl_continue_open
+ +
+ sget-object v0, Lkotlin/u;->a:Lkotlin/u; + sget-object v0, Lkotlin/v;->a:Lkotlin/v;
+ +
+ return-object v0 + return-object v0
+ +
+ :continue_open + :rl_continue_open
+ iget-object v0, p0, Lcom/aspiro/wamp/util/m;->b:Ljava/lang/Object;
iget-object v0, p0, Lcom/tidal/android/feature/appscaffold/ui/composable/e;->b:Ljava/lang/Object;
.line 23 .line 16
.line 24
+74 -63
View File
@@ -1,62 +1,32 @@
# rl-locals: com/tidal/android/feature/appscaffold/ui/composable/i.smali b( 52
--- a/com/tidal/android/feature/appscaffold/ui/composable/i.smali --- a/com/tidal/android/feature/appscaffold/ui/composable/i.smali
+++ b/com/tidal/android/feature/appscaffold/ui/composable/i.smali +++ b/com/tidal/android/feature/appscaffold/ui/composable/i.smali
@@ -2832,27 +2832,5 @@ @@ -1691,6 +1691,14 @@
- .line 150
- sget-object v8, Lkotlin/u;->a:Lkotlin/u;
-
- .line 151
- invoke-interface {v15}, Landroidx/compose/runtime/Composer;->rememberedValue()Ljava/lang/Object;
-
- move-result-object v10
-
- .line 152
- invoke-virtual/range {v22 .. v22}, Landroidx/compose/runtime/Composer$Companion;->getEmpty()Ljava/lang/Object;
-
- move-result-object v11
-
- if-ne v10, v11, :cond_48
-
- .line 153
- sget-object v10, Lcom/tidal/android/feature/appscaffold/ui/composable/AppScaffoldKt$AppScaffold$3$2$1$1;->a:Lcom/tidal/android/feature/appscaffold/ui/composable/AppScaffoldKt$AppScaffold$3$2$1$1;
-
- invoke-interface {v15, v10}, Landroidx/compose/runtime/Composer;->updateRememberedValue(Ljava/lang/Object;)V
-
- .line 154
- :cond_48
- check-cast v10, Landroidx/compose/ui/input/pointer/PointerInputEventHandler;
-
- 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
move-result-object v0 move-result-object v24
@@ -2427,6 +2406,12 @@
move-object/from16 v16, v9 + move-object/from16 v49, p5 # gesture expand lambda (AppScaffold Function1 param)
.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-object/from16 v50, v24 # SheetState
+ +
+ move-result-object v5 + const/16 v51, __RL_MINI_PLAYER_SWIPE_UP_DRAG__ # Enable Drag option
+ +
invoke-static {v15, v5}, Landroidx/compose/ui/ComposedModifierKt;->materializeModifier(Landroidx/compose/runtime/Composer;Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier; + invoke-static/range {v49 .. v51}, Lradiant/MiniPlayerGestures;->configure(Lem0/l;Landroidx/compose/material3/SheetState;Z)V # wire swipe-up to expand the sheet
+
move-result-object v9 .line 69
invoke-static {}, Landroidx/compose/ui/platform/CompositionLocalsKt;->getLocalDensity()Landroidx/compose/runtime/ProvidableCompositionLocal;
--- a/com/tidal/android/feature/appscaffold/ui/composable/MiniPlayerKt.smali --- a/com/tidal/android/feature/appscaffold/ui/composable/MiniPlayerKt.smali
+++ b/com/tidal/android/feature/appscaffold/ui/composable/MiniPlayerKt.smali +++ b/com/tidal/android/feature/appscaffold/ui/composable/MiniPlayerKt.smali
@@ -1243,5 +1243,21 @@ @@ -712,6 +712,22 @@
invoke-virtual {v0}, Ljava/lang/Object;->getClass()Ljava/lang/Class;
iget-object v3, v0, Lcom/tidal/android/feature/appscaffold/ui/s;->c:Lcom/tidal/android/feature/appscaffold/ui/MiniPlayerContract$PlayState; iget-object v3, v0, Lcom/tidal/android/feature/appscaffold/ui/u;->c:Lcom/tidal/android/feature/appscaffold/ui/MiniPlayerContract$PlayState;
+ iget-object v5, v0, Lcom/tidal/android/feature/appscaffold/ui/u;->a:Lcom/tidal/android/feature/appscaffold/ui/MiniPlayerContract$ItemType; # currently rendered mini player media type
+ +
+ iget-object v5, v0, Lcom/tidal/android/feature/appscaffold/ui/s;->a:Lcom/tidal/android/feature/appscaffold/ui/MiniPlayerContract$ItemType; # currently rendered mini player media type + sget-object v6, Lcom/tidal/android/feature/appscaffold/ui/MiniPlayerContract$ItemType;->Unknown:Lcom/tidal/android/feature/appscaffold/ui/MiniPlayerContract$ItemType; # Unknown = no media playing
+ +
+ sget-object v6, Lcom/tidal/android/feature/appscaffold/ui/MiniPlayerContract$ItemType;->Unknown:Lcom/tidal/android/feature/appscaffold/ui/MiniPlayerContract$ItemType; # Unknown = no media playing. other media types : Track, Video. + if-ne v5, v6, :rl_has_media # prevent swipe up when nothing playing
+
+ if-ne v5, v6, :rl_has_media # used to prevent swipe up when nothing is playing
+ +
+ const/4 v5, 0x0 + const/4 v5, 0x0
+ +
@@ -67,48 +37,89 @@
+ +
+ :rl_set_media + :rl_set_media
+ invoke-static {v5}, Lradiant/MiniPlayerGestures;->setHasMiniPlayerMedia(Z)V + invoke-static {v5}, Lradiant/MiniPlayerGestures;->setHasMiniPlayerMedia(Z)V
+
invoke-virtual {v1}, Ljava/lang/Object;->getClass()Ljava/lang/Class; invoke-virtual {v1}, Ljava/lang/Object;->getClass()Ljava/lang/Class;
const v4, -0x571456a1
@@ -1215,6 +1231,10 @@
move-result-object v6
+ invoke-static {v6}, Lradiant/MiniPlayerGestures;->trackAreaModifier(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier; # attach swipe up listener
+
+ move-result-object v6
+
.line 38
sget-object v21, Landroidx/compose/ui/Alignment;->Companion:Landroidx/compose/ui/Alignment$Companion;
@@ -1388,6 +1408,10 @@
move-result-object v4
+ invoke-static {v4}, Lradiant/MiniPlayerGestures;->feedbackModifier(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier; # move cover (swipe up feedback)
+
+ move-result-object v4
+
.line 63
invoke-virtual/range {v22 .. v22}, Lcom/squareup/ui/market/core/theme/MarketStylesheet$c;->p0()Lg20/a;
@@ -1499,6 +1523,10 @@
move-result-object v4
+ invoke-static {v4}, Lradiant/MiniPlayerGestures;->feedbackModifier(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier; # move title/artist (swipe up feedback)
+
+ move-result-object v4
+
.line 72
invoke-virtual/range {v31 .. v31}, Landroidx/compose/foundation/layout/Arrangement;->getTop()Landroidx/compose/foundation/layout/Arrangement$Vertical;
--- a/androidx/compose/material3/ModalBottomSheetKt$ModalBottomSheet$4$1.smali --- a/androidx/compose/material3/ModalBottomSheetKt$ModalBottomSheet$4$1.smali
+++ b/androidx/compose/material3/ModalBottomSheetKt$ModalBottomSheet$4$1.smali +++ b/androidx/compose/material3/ModalBottomSheetKt$ModalBottomSheet$4$1.smali
@@ -210,8 +210,10 @@ @@ -212,6 +212,12 @@
.line 22
.line 23
.line 24 .line 24
iget-object p1, p0, Landroidx/compose/material3/ModalBottomSheetKt$ModalBottomSheet$4$1;->$sheetState:Landroidx/compose/material3/SheetState; iget-object p1, p0, Landroidx/compose/material3/ModalBottomSheetKt$ModalBottomSheet$4$1;->$sheetState:Landroidx/compose/material3/SheetState;
-
+ invoke-static {p1}, Lradiant/MiniPlayerGestures;->suppressAutoShow(Landroidx/compose/material3/SheetState;)Z # avoid Material3 show() taking over manual drag + invoke-static {p1}, Lradiant/MiniPlayerGestures;->suppressAutoShow(Landroidx/compose/material3/SheetState;)Z # avoid Material3 show() taking over manual drag
+
+ move-result v1 + move-result v1
+
+ if-nez v1, :skip_show + if-nez v1, :skip_show
+
.line 25 .line 25
.line 26 .line 26
iput v2, p0, Landroidx/compose/material3/ModalBottomSheetKt$ModalBottomSheet$4$1;->label:I iput v2, p0, Landroidx/compose/material3/ModalBottomSheetKt$ModalBottomSheet$4$1;->label:I
@@ -231,7 +233,7 @@ @@ -232,6 +238,7 @@
.line 33
.line 34 .line 34
return-object v0 return-object v0
-
+ :skip_show + :skip_show
.line 35 .line 35
:cond_2 :cond_2
:goto_0 :goto_0
--- a/androidx/compose/material3/ModalBottomSheetKt.smali --- a/androidx/compose/material3/ModalBottomSheetKt.smali
+++ b/androidx/compose/material3/ModalBottomSheetKt.smali +++ b/androidx/compose/material3/ModalBottomSheetKt.smali
@@ -1370,3 +1370,6 @@ @@ -1291,6 +1291,12 @@
.line 34 .line 34
:cond_47 :cond_47
+ move-object v14, v12 + move-object v14, v12 # settle callback
+ check-cast v14, Lyl0/l; +
+ invoke-static {v13, v14}, Lradiant/MiniPlayerGestures;->setSettleCallback(Landroidx/compose/material3/SheetState;Lyl0/l;)V # reuse native settle animation on release + check-cast v14, Lem0/l; # to Function1
+
+ invoke-static {v13, v14}, Lradiant/MiniPlayerGestures;->setSettleCallback(Landroidx/compose/material3/SheetState;Lem0/l;)V # reuse native settle animation on release
+
move-object/from16 v32, v12 move-object/from16 v32, v12
check-cast v32, Lem0/l;
--- a/androidx/compose/material3/SheetDefaultsKt.smali --- a/androidx/compose/material3/SheetDefaultsKt.smali
+++ b/androidx/compose/material3/SheetDefaultsKt.smali +++ b/androidx/compose/material3/SheetDefaultsKt.smali
@@ -100,6 +100,5 @@ @@ -98,7 +98,7 @@
const/4 v2, 0x0
.line 16 .line 16
- const/16 v3, 0x12c - const/16 v3, 0x12c
-
+ const/16 v3, 0x64 # 100ms + const/16 v3, 0x64 # 100ms
.line 17 .line 17
.line 18 .line 18
const/4 v4, 0x0
+24 -25
View File
@@ -20,48 +20,47 @@
.line 71 .line 71
--- a/com/tidal/android/feature/appscaffold/ui/composable/i.smali --- a/com/tidal/android/feature/appscaffold/ui/composable/i.smali
+++ b/com/tidal/android/feature/appscaffold/ui/composable/i.smali +++ b/com/tidal/android/feature/appscaffold/ui/composable/i.smali
@@ -2756,12 +2756,7 @@ @@ -2275,11 +2275,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 move-result-object v2
- .line 143
- invoke-static {v2}, Landroidx/compose/foundation/layout/WindowInsetsPadding_androidKt;->navigationBarsPadding(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier;
- -
- .line 140 - move-result-object v2
- 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 + # flush bottom; skip nav inset
.line 141 .line 144
invoke-interface/range {v17 .. v17}, Landroidx/compose/runtime/State;->getValue()Ljava/lang/Object; invoke-interface/range {v21 .. v21}, Landroidx/compose/runtime/State;->getValue()Ljava/lang/Object;
@@ -2773,6 +2768,8 @@ @@ -2291,6 +2287,8 @@
move-result v10 move-result v4
+ const/4 v10, 0x0 # zero horizontal padding + const/4 v4, 0x0 # zero horizontal padding
+ +
const/4 v11, 0x2 const/4 v6, 0x2
.line 142 .line 145
@@ -2857,6 +2854,10 @@ @@ -2375,6 +2373,10 @@
move-result-object v0 move-result-object v2
+ invoke-static {v0}, Landroidx/compose/foundation/layout/WindowInsetsPadding_androidKt;->navigationBarsPadding(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier; # inset bar content above nav bar (Prevents Bleeding behind Nav Buttons) + invoke-static {v2}, Landroidx/compose/foundation/layout/WindowInsetsPadding_androidKt;->navigationBarsPadding(Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier; # inset bar content above nav bar (Prevents Bleeding behind Nav Buttons)
+ +
+ move-result-object v0 + move-result-object v2
+ +
.line 155 .line 158
sget-object v8, Landroidx/compose/foundation/layout/Arrangement;->INSTANCE:Landroidx/compose/foundation/layout/Arrangement; sget-object v3, Landroidx/compose/foundation/layout/Arrangement;->INSTANCE:Landroidx/compose/foundation/layout/Arrangement;
@@ -2969,6 +2970,10 @@ @@ -2487,6 +2489,10 @@
invoke-static {v12, v0, v8}, Landroidx/compose/runtime/Updater;->set-impl(Landroidx/compose/runtime/Composer;Ljava/lang/Object;Lyl0/p;)V invoke-static {v6, v2, v3}, Landroidx/compose/runtime/Updater;->set-impl(Landroidx/compose/runtime/Composer;Ljava/lang/Object;Lem0/p;)V
+ const/4 v8, 0x0 # composer $changed flags + const/4 v8, 0x0 # composer $changed flags
+ +
+ invoke-static {v15, v8}, Lradiant/MiniSeekerLine;->render(Landroidx/compose/runtime/Composer;I)V # draw top-edge seeker + invoke-static {v7, v8}, Lradiant/MiniSeekerLine;->render(Landroidx/compose/runtime/Composer;I)V # draw top-edge seeker
+ +
.line 172 .line 175
sget-object v0, Landroidx/compose/foundation/layout/ColumnScopeInstance;->INSTANCE:Landroidx/compose/foundation/layout/ColumnScopeInstance; sget-object v2, Landroidx/compose/foundation/layout/ColumnScopeInstance;->INSTANCE:Landroidx/compose/foundation/layout/ColumnScopeInstance;
+40 -17
View File
@@ -1,19 +1,21 @@
# rl-locals: com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali e( 71 # rl-locals: com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali e( 71
--- a/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali --- a/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali
+++ b/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali +++ b/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali
@@ -4172,6 +4172,148 @@ @@ -4221,6 +4221,153 @@
invoke-static {v5, v3, v4}, Landroidx/compose/runtime/Updater;->set-impl(Landroidx/compose/runtime/Composer;Ljava/lang/Object;Lyl0/p;)V invoke-static {v6, v3, v4}, Landroidx/compose/runtime/Updater;->set-impl(Landroidx/compose/runtime/Composer;Ljava/lang/Object;Lem0/p;)V
+ const v3, 0x52414449 # slot table key + move-object/from16 v57, v6 # capture live composer into free reg
+ +
+ invoke-interface {v10, v3}, Landroidx/compose/runtime/Composer;->startReplaceGroup(I)V # open group + const v58, 0x52414449 # slot table key
+
+ invoke-interface/range {v57 .. v58}, Landroidx/compose/runtime/Composer;->startReplaceGroup(I)V # open group
+ +
+ move-object/from16 v3, p3 # player state + move-object/from16 v3, p3 # player state
+ +
+ iget-object v3, v3, Lcom/tidal/android/feature/playerscreen/ui/r$a;->c:Lcom/tidal/android/feature/playerscreen/ui/d; # cover pager + iget-object v3, v3, Lcom/tidal/android/feature/playerscreen/ui/s$a;->c:Lcom/tidal/android/feature/playerscreen/ui/d; # cover pager
+ +
+ iget-object v4, v3, Lcom/tidal/android/feature/playerscreen/ui/d;->a:Ltn0/b; # item list + iget-object v4, v3, Lcom/tidal/android/feature/playerscreen/ui/d;->a:Lzn0/b; # item list
+ +
+ iget v5, v3, Lcom/tidal/android/feature/playerscreen/ui/d;->b:I # current index + iget v5, v3, Lcom/tidal/android/feature/playerscreen/ui/d;->b:I # current index
+ +
@@ -53,10 +55,9 @@
+ iget-object v4, v4, Lcom/tidal/android/feature/playerscreen/ui/c$b;->c:Ljava/lang/String; # still cover uuid (blur this) + iget-object v4, v4, Lcom/tidal/android/feature/playerscreen/ui/c$b;->c:Ljava/lang/String; # still cover uuid (blur this)
+ +
+ :radiant_have_cover # v5 = album id, v4 = cover uuid + :radiant_have_cover # v5 = album id, v4 = cover uuid
+ new-instance v6, Lcom/tidal/android/feature/playerscreen/ui/composables/o0; # cover request lambda
+ +
+ new-instance v6, Lcom/tidal/android/feature/playerscreen/ui/composables/n0; # cover request lambda + invoke-direct {v6, v5, v4}, Lcom/tidal/android/feature/playerscreen/ui/composables/o0;-><init>(ILjava/lang/String;)V # build request
+
+ invoke-direct {v6, v5, v4}, Lcom/tidal/android/feature/playerscreen/ui/composables/n0;-><init>(ILjava/lang/String;)V # build request
+ +
+ sget-object v5, Landroidx/compose/ui/Modifier;->Companion:Landroidx/compose/ui/Modifier$Companion; # base modifier + sget-object v5, Landroidx/compose/ui/Modifier;->Companion:Landroidx/compose/ui/Modifier$Companion; # base modifier
+ +
@@ -106,13 +107,13 @@
+ +
+ const/16 v67, 0x0 # null onError + const/16 v67, 0x0 # null onError
+ +
+ move-object/from16 v68, v10 # composer + move-object/from16 v68, v57 # composer
+ +
+ const/16 v69, 0x0 # changed flags + const/16 v69, 0x0 # changed flags
+ +
+ const/16 v70, 0x48 # default mask + const/16 v70, 0x48 # default mask
+ +
+ invoke-static/range {v61 .. v70}, Lxd0/f;->a(Lyl0/l;Ljava/lang/String;Landroidx/compose/ui/Modifier;Landroidx/compose/ui/graphics/ColorFilter;Landroidx/compose/ui/layout/ContentScale;Ljava/lang/Object;Lyl0/a;Landroidx/compose/runtime/Composer;II)V # render blurred cover + invoke-static/range {v61 .. v70}, Lee0/e;->a(Lem0/l;Ljava/lang/String;Landroidx/compose/ui/Modifier;Landroidx/compose/ui/graphics/ColorFilter;Landroidx/compose/ui/layout/ContentScale;Ljava/lang/Object;Lem0/a;Landroidx/compose/runtime/Composer;II)V # render blurred cover
+ +
+ sget-object v3, Landroidx/compose/ui/Modifier;->Companion:Landroidx/compose/ui/Modifier$Companion; # scrim chain start + sget-object v3, Landroidx/compose/ui/Modifier;->Companion:Landroidx/compose/ui/Modifier$Companion; # scrim chain start
+ +
@@ -140,13 +141,35 @@
+ +
+ move-result-object v3 # tinted modifier + move-result-object v3 # tinted modifier
+ +
+ const/4 v4, 0x0 # changed flags + move-object/from16 v58, v3 # scrim modifier
+ +
+ invoke-static {v3, v10, v4}, Landroidx/compose/foundation/layout/SpacerKt;->Spacer(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)V # draw scrim + move-object/from16 v59, v57 # composer
+
+ const/16 v60, 0x0 # changed flags
+
+ invoke-static/range {v58 .. v60}, Landroidx/compose/foundation/layout/SpacerKt;->Spacer(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)V # draw scrim
+ +
+ :radiant_skip # skip target + :radiant_skip # skip target
+ invoke-interface {v10}, Landroidx/compose/runtime/Composer;->endReplaceGroup()V # close group + invoke-interface/range {v57 .. v57}, Landroidx/compose/runtime/Composer;->endReplaceGroup()V # close group
+ +
.line 138 .line 142
sget-object v3, Landroidx/compose/foundation/layout/BoxScopeInstance;->INSTANCE:Landroidx/compose/foundation/layout/BoxScopeInstance; sget-object v3, Landroidx/compose/foundation/layout/BoxScopeInstance;->INSTANCE:Landroidx/compose/foundation/layout/BoxScopeInstance;
--- a/com/tidal/android/core/ui/composable/z.smali
+++ b/com/tidal/android/core/ui/composable/z.smali
@@ -13,13 +13,15 @@
.line 2
.line 3
.line 4
move-result p0
.line 5
- invoke-virtual {p2, p0}, Landroid/view/Window;->setNavigationBarColor(I)V
+ const/4 v3, 0x0
+
+ invoke-virtual {p2, v3}, Landroid/view/Window;->setNavigationBarColor(I)V # RL: force transparent nav bar so the player backdrop shows through (was p0 = TIDAL's extracted single-color BG). Luminance below still uses p0 so the light/dark icon choice adapts to the backdrop behind the now-transparent bar.
.line 6
.line 7
.line 8
sget p1, Landroid/os/Build$VERSION;->SDK_INT:I
+20 -20
View File
@@ -1,24 +1,24 @@
--- a/com/tidal/android/feature/playerscreen/ui/composables/c1.smali --- a/com/tidal/android/feature/playerscreen/ui/composables/z0.smali
+++ b/com/tidal/android/feature/playerscreen/ui/composables/c1.smali +++ b/com/tidal/android/feature/playerscreen/ui/composables/z0.smali
@@ -259,7 +259,7 @@ @@ -91,7 +91,7 @@
.line 109 .line 32
.line 110 .line 33
- sget p2, Lcom/tidal/android/feature/playerscreen/ui/R$drawable;->ic_circle_checked:I - sget p2, Lcom/tidal/android/feature/playerscreen/ui/R$drawable;->ic_circle_checked:I
+ sget p2, Lcom/tidal/android/feature/playerscreen/ui/R$drawable;->ic_shapes_heart_filled_medium:I # favorited: filled heart (was circle-check) + sget p2, Lcom/tidal/android/feature/playerscreen/ui/R$drawable;->ic_shapes_heart_filled_medium:I # favorited: filled heart (was circle-check)
.line 111 .line 34
.line 112 .line 35
@@ -267,11 +267,7 @@ @@ -99,11 +99,7 @@
.line 113 .line 36
:cond_5 :cond_1
- sget-object p2, Lx20/b;->O:Lx20/a; - sget-object p2, Lb30/b;->O:Lb30/a;
- -
- .line 114 - .line 37
- .line 115 - .line 38
- iget p2, p2, Lx20/a;->a:I - iget p2, p2, Lb30/a;->a:I
+ sget p2, Lcom/tidal/android/feature/playerscreen/ui/R$drawable;->ic_shapes_heart_medium:I # not favorited: outline heart (was market plus) + sget p2, Lcom/tidal/android/feature/playerscreen/ui/R$drawable;->ic_shapes_heart_medium:I # not favorited: outline heart (was market plus)
.line 116 .line 39
.line 117 .line 40
+11
View File
@@ -0,0 +1,11 @@
--- a/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali
+++ b/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali
@@ -5794,6 +5794,8 @@
.line 336
iget-object v3, v10, Lcom/tidal/android/feature/playerscreen/ui/s$a;->l:Lcom/tidal/android/feature/playerscreen/ui/p;
+ const/4 v3, 0x0 # Never show the "Playing from" source at the bottom (relocated above the title, or hidden when off)
+
if-nez v3, :cond_52
const v3, 0x26ba353b
+66
View File
@@ -0,0 +1,66 @@
# rl-locals: com/tidal/android/feature/playerscreen/ui/composables/k2.smali a( 42
--- a/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali
+++ b/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali
@@ -5023,6 +5023,20 @@
.line 233
:goto_1d
+ iget-object v0, v3, Lcom/tidal/android/feature/playerscreen/ui/s$a;->l:Lcom/tidal/android/feature/playerscreen/ui/p; # RL move-playing-from: SourceLabel — published in BOTH cover & lyrics view (may be null)
+
+ if-eqz v0, :rl_pf_null # no source -> clear
+
+ iget-object v0, v0, Lcom/tidal/android/feature/playerscreen/ui/p;->a:Ljava/lang/String; # sourceName
+
+ goto :rl_pf_set
+
+ :rl_pf_null
+ const/4 v0, 0x0
+
+ :rl_pf_set
+ sput-object v0, Lradiant/PlayingFrom;->a:Ljava/lang/String; # publish for k2 (rendered above the title)
+
iget-object v0, v3, Lcom/tidal/android/feature/playerscreen/ui/s$a;->c:Lcom/tidal/android/feature/playerscreen/ui/d;
.line 234
--- a/com/tidal/android/feature/playerscreen/ui/composables/k2.smali
+++ b/com/tidal/android/feature/playerscreen/ui/composables/k2.smali
@@ -632,6 +632,39 @@
.line 42
:cond_1c
check-cast v5, Lr20/c2;
+ sget-object v30, Lradiant/PlayingFrom;->a:Ljava/lang/String; # RL: published "Playing from" source name
+
+ const v13, 0x52414450 # RL group key (v13 is dead here; the title setup below resets it)
+
+ invoke-interface {v1, v13}, Landroidx/compose/runtime/Composer;->startReplaceGroup(I)V
+
+ if-eqz v30, :rl_pf_skip # no source -> render nothing above the title
+
+ sget-object v31, Landroidx/compose/ui/Modifier;->Companion:Landroidx/compose/ui/Modifier$Companion;
+
+ const/16 v32, 0x1 # maxLines = 1
+
+ const/16 v33, 0x0
+
+ const/16 v34, 0x0
+
+ const/16 v35, 0x0
+
+ const/16 v36, 0x0
+
+ move-object/from16 v37, v5 # reuse the artist PARAGRAPH_30 style (same colour + size as the artist names)
+
+ move-object/from16 v38, v1 # composer
+
+ const/16 v39, 0x0
+
+ const/16 v40, 0x78 # default-arg mask (matches the artist MarketLabel.e call)
+
+ invoke-static/range {v30 .. v40}, Lcom/squareup/ui/market/components/MarketLabelKt;->e(Ljava/lang/String;Landroidx/compose/ui/Modifier;IILcom/squareup/ui/market/text/a;Landroidx/compose/foundation/interaction/MutableInteractionSource;Lem0/l;Lr20/c2;Landroidx/compose/runtime/Composer;II)V
+
+ :rl_pf_skip
+ invoke-interface {v1}, Landroidx/compose/runtime/Composer;->endReplaceGroup()V
+
.line 43
sget-object v13, Landroidx/compose/ui/Modifier;->Companion:Landroidx/compose/ui/Modifier$Companion;
+7 -19
View File
@@ -1,10 +1,7 @@
# rl-locals: com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali e( 80 # rl-locals: com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali e( 80
--- a/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali --- a/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali
+++ b/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali +++ b/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali
@@ -5650,12 +5650,26 @@ @@ -5579,6 +5579,20 @@
invoke-static {v2, v15, v7, v9}, Lcom/aspiro/wamp/dynamicpages/ui/compose/f;->a(FLandroidx/compose/ui/Modifier$Companion;Landroidx/compose/runtime/Composer;I)V
const/4 v2, 0x0
const/4 v9, 0x0 const/4 v9, 0x0
@@ -22,24 +19,15 @@
+ +
+ invoke-interface/range {v76 .. v77}, Landroidx/compose/runtime/Composer;->startProvider(Landroidx/compose/runtime/ProvidedValue;)V # open Rtl scope (mirror row) + invoke-interface/range {v76 .. v77}, Landroidx/compose/runtime/Composer;->startProvider(Landroidx/compose/runtime/ProvidedValue;)V # open Rtl scope (mirror row)
+ +
.line 302 .line 306
invoke-static {v15, v9, v1, v2}, Landroidx/compose/foundation/layout/SizeKt;->fillMaxWidth$default(Landroidx/compose/ui/Modifier;FILjava/lang/Object;)Landroidx/compose/ui/Modifier; invoke-static {v0, v9, v14, v8}, Landroidx/compose/foundation/layout/SizeKt;->fillMaxWidth$default(Landroidx/compose/ui/Modifier;FILjava/lang/Object;)Landroidx/compose/ui/Modifier;
move-result-object v4 @@ -6049,6 +6063,8 @@
.line 364
move/from16 v5, v58
@@ -6001,12 +6015,14 @@
invoke-static {v13, v7, v2, v4}, Lcom/tidal/android/feature/playerscreen/ui/composables/m0;->a(ILandroidx/compose/runtime/Composer;Landroidx/compose/ui/Modifier;Lyl0/a;)V
.line 343
invoke-interface {v7}, Landroidx/compose/runtime/Composer;->endNode()V invoke-interface {v7}, Landroidx/compose/runtime/Composer;->endNode()V
+ invoke-interface {v7}, Landroidx/compose/runtime/Composer;->endProvider()V # close Rtl scope (end mirror) + invoke-interface {v7}, Landroidx/compose/runtime/Composer;->endProvider()V # close Rtl scope (end mirror)
+ +
.line 344 .line 365
invoke-static/range {v40 .. v40}, Landroidx/compose/ui/unit/Dp;->constructor-impl(F)F invoke-static/range {v27 .. v27}, Landroidx/compose/ui/unit/Dp;->constructor-impl(F)F
move-result v20
const/16 v21, 0x7
+41 -40
View File
@@ -2,8 +2,8 @@
+++ b/com/tidal/android/feature/playerscreen/ui/composables/SeekbarAndTimeKt.smali +++ b/com/tidal/android/feature/playerscreen/ui/composables/SeekbarAndTimeKt.smali
@@ -372,6 +372,10 @@ @@ -372,6 +372,10 @@
.line 158 .line 158
sget v4, Lcom/tidal/android/feature/playerscreen/ui/composables/o4;->g:F sget v4, Lcom/tidal/android/feature/playerscreen/ui/composables/m4;->g:F
+ const/high16 v11, 0x40000000 # 2.0f + const/high16 v11, 0x40000000 # 2.0f
+ +
+ mul-float/2addr v4, v11 # scale atmos icon 2x as it is too small in stock app + mul-float/2addr v4, v11 # scale atmos icon 2x as it is too small in stock app
@@ -14,7 +14,7 @@
@@ -461,6 +465,8 @@ @@ -461,6 +465,8 @@
.line 200 .line 200
check-cast v3, Lcom/tidal/android/feature/playerscreen/ui/i$a; check-cast v3, Lcom/tidal/android/feature/playerscreen/ui/i$a;
+ iget v13, v3, Lcom/tidal/android/feature/playerscreen/ui/i$a;->b:I + iget v13, v3, Lcom/tidal/android/feature/playerscreen/ui/i$a;->b:I
+ +
.line 201 .line 201
@@ -23,29 +23,29 @@
@@ -481,6 +487,16 @@ @@ -481,6 +487,16 @@
.line 210 .line 210
move-object v1, v3 move-object v1, v3
+ invoke-static {v2, v13}, Lradiant/QualityBadge;->modifier(Landroidx/compose/ui/Modifier;I)Landroidx/compose/ui/Modifier; + invoke-static {v2, v13}, Lradiant/QualityBadge;->modifier(Landroidx/compose/ui/Modifier;I)Landroidx/compose/ui/Modifier;
+ +
+ move-result-object v2 + move-result-object v2
+ +
+ move-object/from16 v3, p1 + move-object/from16 v3, p1
+ +
+ invoke-static {v13, v3}, Lradiant/QualityBadge;->style(ILn20/e2;)Ln20/e2; + invoke-static {v13, v3}, Lradiant/QualityBadge;->style(ILr20/c2;)Lr20/c2;
+ +
+ move-result-object v8 + move-result-object v8
+ +
.line 211 .line 211
const/4 v3, 0x0 const/4 v3, 0x0
--- a/com/tidal/android/feature/playerscreen/ui/i$a.smali --- a/com/tidal/android/feature/playerscreen/ui/i$a.smali
+++ b/com/tidal/android/feature/playerscreen/ui/i$a.smali +++ b/com/tidal/android/feature/playerscreen/ui/i$a.smali
@@ -21,9 +21,21 @@ @@ -21,9 +21,21 @@
# instance fields # instance fields
.field public final a:Ljava/lang/String; .field public final a:Ljava/lang/String;
+.field public final b:I +.field public final b:I
+ +
# direct methods # direct methods
.method public constructor <init>(Ljava/lang/String;)V .method public constructor <init>(Ljava/lang/String;)V
+ .locals 1 + .locals 1
@@ -59,12 +59,12 @@
+ +
+.method public constructor <init>(Ljava/lang/String;I)V +.method public constructor <init>(Ljava/lang/String;I)V
.locals 0 .locals 0
.line 1 .line 1
@@ -34,6 +46,8 @@ @@ -34,6 +46,8 @@
.line 4 .line 4
iput-object p1, p0, Lcom/tidal/android/feature/playerscreen/ui/i$a;->a:Ljava/lang/String; iput-object p1, p0, Lcom/tidal/android/feature/playerscreen/ui/i$a;->a:Ljava/lang/String;
+ iput p2, p0, Lcom/tidal/android/feature/playerscreen/ui/i$a;->b:I + iput p2, p0, Lcom/tidal/android/feature/playerscreen/ui/i$a;->b:I
+ +
.line 5 .line 5
@@ -72,45 +72,46 @@
return-void return-void
--- a/com/tidal/android/feature/playerscreen/ui/PlayerViewModel$special$$inlined$mapNotNull$1$2.smali --- a/com/tidal/android/feature/playerscreen/ui/PlayerViewModel$special$$inlined$mapNotNull$1$2.smali
+++ b/com/tidal/android/feature/playerscreen/ui/PlayerViewModel$special$$inlined$mapNotNull$1$2.smali +++ b/com/tidal/android/feature/playerscreen/ui/PlayerViewModel$special$$inlined$mapNotNull$1$2.smali
@@ -1356,6 +1356,14 @@ @@ -1399,7 +1399,15 @@
.line 617 .line 634
- move-result v10 .line 635
+ move-result v10 # isCurrentStreamHiResLosslessQuality() result .line 636
- move-result v9
+ move-result v9 # isCurrentStreamHiResLosslessQuality() result
+
+ const/16 v31, 0x0 # LOW / HIGH quality + const/16 v31, 0x0 # LOW / HIGH quality
+ +
+ if-eqz v10, :radiant_qbc_not_hires + if-eqz v9, :radiant_qbc_not_hires
+ +
+ const/16 v31, 0x2 # HI_RES_LOSSLESS quality + const/16 v31, 0x2 # HI_RES_LOSSLESS quality
+ +
+ :radiant_qbc_not_hires + :radiant_qbc_not_hires
.line 637
if-nez v9, :cond_1e
@@ -1411,7 +1419,13 @@
.line 640
.line 641
.line 642
- move-result v9
+ move-result v9 # isCurrentStreamLossless() result
+ +
.line 618 + if-eqz v9, :radiant_qbc_not_lossless
if-nez v10, :cond_19
@@ -1368,6 +1376,12 @@
.line 623
- move-result v10
+ move-result v10 # isCurrentStreamLossless() result
+ if-eqz v10, :radiant_qbc_not_lossless
+ +
+ const/16 v31, 0x1 # LOSSLESS quality + const/16 v31, 0x1 # LOSSLESS quality
+ +
+ :radiant_qbc_not_lossless + :radiant_qbc_not_lossless
+
.line 624
if-eqz v10, :cond_18
@@ -1695,7 +1709,10 @@
.line 771
.line 772
- invoke-direct {v8, v5}, Lcom/tidal/android/feature/playerscreen/ui/i$a;-><init>(Ljava/lang/String;)V
+ move/from16 v10, v31 # quality
+
+ invoke-direct {v8, v5, v10}, Lcom/tidal/android/feature/playerscreen/ui/i$a;-><init>(Ljava/lang/String;I)V
+
.line 773 .line 643
.line 774 if-eqz v9, :cond_1d
@@ -1740,7 +1754,9 @@
.line 790
.line 791
- invoke-direct {v7, v5}, Lcom/tidal/android/feature/playerscreen/ui/i$a;-><init>(Ljava/lang/String;)V
+ move/from16 v9, v31 # quality
+
+ invoke-direct {v7, v5, v9}, Lcom/tidal/android/feature/playerscreen/ui/i$a;-><init>(Ljava/lang/String;I)V
.line 792
.line 793