mirror of
https://github.com/meowarex/rl-mobile.git
synced 2026-06-18 05:23:12 +10:00
Code Review for UI Rewrite
This commit is contained in:
@@ -26,6 +26,7 @@ import com.meowarex.rlmobile.ui.screens.settings.SettingsModel
|
||||
import com.meowarex.rlmobile.ui.widgets.updater.UpdaterViewModel
|
||||
import com.meowarex.rlmobile.updatechecker.UpdateCheckWorker
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import org.koin.android.ext.android.get
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.core.context.startKoin
|
||||
import org.koin.core.module.dsl.*
|
||||
@@ -101,7 +102,12 @@ class ManagerApplication : Application() {
|
||||
.build()
|
||||
}
|
||||
|
||||
// Schedule periodic update check
|
||||
UpdateCheckWorker.schedule(this)
|
||||
// Schedule periodic update check only when the user has opted in,
|
||||
// so the disabled state survives app restarts instead of being re-enqueued.
|
||||
if (get<PreferencesManager>().autoUpdateCheck) {
|
||||
UpdateCheckWorker.schedule(this)
|
||||
} else {
|
||||
UpdateCheckWorker.cancel(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -10,7 +10,10 @@ class CommitsPagingSource(
|
||||
) : PagingSource<Int, GithubCommit>() {
|
||||
|
||||
override fun getRefreshKey(state: PagingState<Int, GithubCommit>): Int? =
|
||||
state.anchorPosition?.let { state.closestPageToPosition(it)?.prevKey }
|
||||
state.anchorPosition?.let {
|
||||
val page = state.closestPageToPosition(it) ?: return null
|
||||
page.prevKey?.plus(1) ?: page.nextKey?.minus(1)
|
||||
}
|
||||
|
||||
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, GithubCommit> {
|
||||
val page = params.key ?: 0
|
||||
|
||||
+10
-2
@@ -51,8 +51,16 @@ class SmaliPatchStep : Step(), IDexProvider, KoinComponent {
|
||||
if (patchFile.endsWith(".smali") && patchFile.startsWith("extension/")) {
|
||||
val relative = patchFile.removePrefix("extension/")
|
||||
val out = smaliDir.resolve(relative)
|
||||
out.parentFile?.mkdirs()
|
||||
out.writeBytes(zip.openEntry(patchFile)!!.read())
|
||||
// Guard against zip-slip: a crafted entry could otherwise escape smaliDir.
|
||||
val baseCanonical = smaliDir.canonicalPath + File.separator
|
||||
val outCanonical = out.canonicalPath
|
||||
if (!outCanonical.startsWith(baseCanonical)) {
|
||||
throw SecurityException("Zip entry escapes target directory: $patchFile")
|
||||
}
|
||||
val entry = zip.openEntry(patchFile)
|
||||
?: throw FileNotFoundException("Missing zip entry: $patchFile")
|
||||
out.canonicalFile.parentFile?.mkdirs()
|
||||
out.writeBytes(entry.read())
|
||||
container.log("Extracted extension smali: $relative")
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -35,7 +35,8 @@ object ManifestPatcher {
|
||||
}
|
||||
}
|
||||
})
|
||||
val origPkg = originalPackage ?: "com.aspiro.tidal"
|
||||
val origPkg = originalPackage
|
||||
?: throw IllegalStateException("Manifest has no package attribute; refusing to rewrite authorities/permissions without a known originalPackage")
|
||||
|
||||
val reader = AxmlReader(manifestBytes)
|
||||
val writer = AxmlWriter()
|
||||
@@ -104,7 +105,7 @@ object ManifestPatcher {
|
||||
super.attr(
|
||||
ns, name, resourceId, type,
|
||||
when (name) {
|
||||
"name" -> (value as String).replace(origPkg, packageName)
|
||||
"name" -> (value as? String)?.replace(origPkg, packageName) ?: value
|
||||
else -> value
|
||||
}
|
||||
)
|
||||
@@ -155,7 +156,7 @@ object ManifestPatcher {
|
||||
super.attr(
|
||||
ns, name, resourceId, type,
|
||||
if (name == "authorities") {
|
||||
(value as String).replace(origPkg, packageName)
|
||||
(value as? String)?.replace(origPkg, packageName) ?: value
|
||||
} else {
|
||||
value
|
||||
}
|
||||
|
||||
@@ -97,6 +97,7 @@ class HomeModel(
|
||||
fun openApp(packageName: String) {
|
||||
val launchIntent = application.packageManager.getLaunchIntentForPackage(packageName)
|
||||
if (launchIntent != null) {
|
||||
launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
application.startActivity(launchIntent)
|
||||
} else {
|
||||
application.showToast(R.string.launch_app_fail)
|
||||
|
||||
@@ -12,10 +12,15 @@ import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.graphics.painter.BitmapPainter
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import androidx.lifecycle.compose.LifecycleResumeEffect
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import cafe.adriel.voyager.core.screen.Screen
|
||||
@@ -55,16 +60,28 @@ class HomeScreen : Screen, Parcelable {
|
||||
title = { Text(stringResource(R.string.navigation_home)) },
|
||||
actions = {
|
||||
IconButton(onClick = { model.refresh() }) {
|
||||
Icon(painterResource(R.drawable.ic_refresh), contentDescription = null)
|
||||
Icon(
|
||||
painterResource(R.drawable.ic_refresh),
|
||||
contentDescription = stringResource(R.string.navigation_refresh),
|
||||
)
|
||||
}
|
||||
IconButton(onClick = { navigator.push(AboutScreen()) }) {
|
||||
Icon(painterResource(R.drawable.ic_info), contentDescription = null)
|
||||
Icon(
|
||||
painterResource(R.drawable.ic_info),
|
||||
contentDescription = stringResource(R.string.navigation_about),
|
||||
)
|
||||
}
|
||||
IconButton(onClick = { navigator.push(LogsListScreen()) }) {
|
||||
Icon(painterResource(R.drawable.ic_receipt), contentDescription = null)
|
||||
Icon(
|
||||
painterResource(R.drawable.ic_receipt),
|
||||
contentDescription = stringResource(R.string.navigation_logs),
|
||||
)
|
||||
}
|
||||
IconButton(onClick = { navigator.push(SettingsScreen()) }) {
|
||||
Icon(painterResource(R.drawable.ic_settings), contentDescription = null)
|
||||
Icon(
|
||||
painterResource(R.drawable.ic_settings),
|
||||
contentDescription = stringResource(R.string.navigation_settings),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
@@ -117,17 +134,19 @@ private fun ColumnScope.HomeContent(
|
||||
val currentVersionName = install?.version?.let { "v${it.toString()}" }
|
||||
val latestVersionName = state.latestTidalVersionCode?.let { "build $it" }
|
||||
|
||||
if (install?.icon != null) {
|
||||
val fallbackPainter = if (install?.icon == null) {
|
||||
// R.mipmap.ic_launcher is an adaptive-icon XML on API 26+, which painterResource cannot decode.
|
||||
val context = LocalContext.current
|
||||
remember {
|
||||
val drawable = ContextCompat.getDrawable(context, R.mipmap.ic_launcher)
|
||||
drawable?.toBitmap()?.asImageBitmap()?.let(::BitmapPainter)
|
||||
}
|
||||
} else null
|
||||
|
||||
val iconPainter = install?.icon ?: fallbackPainter
|
||||
if (iconPainter != null) {
|
||||
Image(
|
||||
painter = install.icon,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.size(60.dp)
|
||||
.clip(CircleShape),
|
||||
)
|
||||
} else {
|
||||
Image(
|
||||
painter = painterResource(R.mipmap.ic_launcher),
|
||||
painter = iconPainter,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.size(60.dp)
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ data class PatchOptions(
|
||||
companion object {
|
||||
val Default = PatchOptions(
|
||||
appName = "TIDAL",
|
||||
packageName = "com.tidal.music",
|
||||
packageName = "com.aspiro.tidal",
|
||||
debuggable = false,
|
||||
customInjector = null,
|
||||
customPatches = null,
|
||||
|
||||
+2
-2
@@ -7,6 +7,7 @@ import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import androidx.core.app.ActivityCompat
|
||||
@@ -14,7 +15,6 @@ import androidx.core.app.NotificationCompat
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.work.*
|
||||
import com.meowarex.rlmobile.BuildConfig
|
||||
import com.meowarex.rlmobile.MainActivity
|
||||
import com.meowarex.rlmobile.R
|
||||
import com.meowarex.rlmobile.manager.PreferencesManager
|
||||
import com.meowarex.rlmobile.network.services.RadiantLyricsGithubService
|
||||
@@ -81,7 +81,7 @@ class UpdateCheckWorker(
|
||||
val pendingIntent = PendingIntent.getActivity(
|
||||
applicationContext,
|
||||
0,
|
||||
Intent(applicationContext, MainActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) },
|
||||
Intent(Intent.ACTION_VIEW, Uri.parse(releaseUrl)).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) },
|
||||
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT,
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user