Release 1.2.3 (#67)

* Fix Android XR metadata placement

* Update README

* Fix broken max aspect metadata

* fix: wrong placement of uses-library

* refactor: bitmap caching and coroutine scopes

* chore: update ARSCLib to 1.4.0

* chore: bump version to 1.2.3
This commit is contained in:
Mathew Tkachuk authored and GitHub committed 2026-07-25 18:40:18 +03:00
1 parent 474f7bf12a
commit c790854772
10 files changed
+74 -71

No files matched your search

@@ -15,7 +15,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import moe.crx.overport.app.decodeBitmap
import moe.crx.overport.app.util.ModifierUtil.rounded
@@ -25,43 +24,53 @@ import overportapp.composeapp.generated.resources.Res
import overportapp.composeapp.generated.resources.unknown_package
import java.util.*
val iconCache = mutableMapOf<String, ImageBitmap?>()
val coverCache = mutableMapOf<String, ImageBitmap?>()
@Composable
fun ApplicationInfo(
applicationName: String? = "Application",
applicationPackage: String? = "com.company.application",
applicationVersion: String? = "1.0.0",
applicationName: String,
applicationPackage: String,
applicationVersion: String,
applicationIcon: ImageBitmap? = null,
forceLocalInfo: Boolean = false,
useCover: Boolean = false,
) {
var iconIsLoading by rememberSaveable(applicationPackage) { mutableStateOf(true) }
var onlineIcon by rememberSaveable(applicationPackage) { mutableStateOf<ImageBitmap?>(null) }
var onlineCover by rememberSaveable(applicationPackage) { mutableStateOf<ImageBitmap?>(null) }
var iconIsLoading by remember(applicationPackage) { mutableStateOf(true) }
var onlineIcon by remember(applicationPackage) { mutableStateOf(iconCache[applicationPackage]) }
var onlineCover by remember(applicationPackage) { mutableStateOf(coverCache[applicationPackage]) }
var onlineLabel by rememberSaveable(applicationPackage) { mutableStateOf<String?>(null) }
val scope = rememberCoroutineScope()
LaunchedEffect(applicationPackage) {
scope.launch {
withContext(Dispatchers.IO) {
runCatching {
val info = applicationPackage?.let { getApplicationInfo(it) }
onlineLabel = info?.displayName
val icon = info?.run {
val associated = images.associateBy { it.imageType }
associated["APP_IMG_ICON"] ?: associated["APP_IMG_COVER_SQUARE"]
}
val cover = info?.run {
val associated = images.associateBy { it.imageType }
associated["APP_IMG_COVER_SQUARE"] ?: associated["APP_IMG_ICON"]
}
onlineIcon = icon?.uri?.let { Base64.getDecoder().decode(it) }?.decodeBitmap()
onlineCover = cover?.uri?.let { Base64.getDecoder().decode(it) }?.decodeBitmap()
}
iconIsLoading = false
withContext(Dispatchers.IO) {
if (iconCache.containsKey(applicationPackage)) {
return@withContext
}
val info = getApplicationInfo(applicationPackage)
onlineLabel = info?.displayName
val icon = info?.run {
val associated = images.associateBy { it.imageType }
associated["APP_IMG_ICON"] ?: associated["APP_IMG_COVER_SQUARE"]
}
val cover = info?.run {
val associated = images.associateBy { it.imageType }
associated["APP_IMG_COVER_SQUARE"] ?: associated["APP_IMG_ICON"]
}
val iconBitmap = icon?.uri?.let { Base64.getDecoder().decode(it) }?.decodeBitmap()
val coverBitmap = cover?.uri?.let { Base64.getDecoder().decode(it) }?.decodeBitmap()
iconCache[applicationPackage] = iconBitmap
coverCache[applicationPackage] = coverBitmap
onlineIcon = iconBitmap
onlineCover = coverBitmap
iconIsLoading = false
}
}
@@ -21,9 +21,9 @@ import overportapp.composeapp.generated.resources.*
@Composable
@Preview
fun ApplicationInfoContent(
applicationName: String? = "Application",
applicationPackage: String? = "",
applicationVersion: String? = "1.0.0",
applicationName: String,
applicationPackage: String,
applicationVersion: String,
applicationIcon: ImageBitmap? = null,
onCancel: () -> Unit = {},
onConfirm: (Map<String, List<String>>) -> Unit = {}
@@ -35,30 +35,26 @@ fun PatcherScreen(
val isPatcherVisible = !viewModel.working && viewModel.isApkLoaded()
LaunchedEffect(openFlow) {
scope.launch {
openFlow.collect {
inputFile = it
}
openFlow.collect {
inputFile = it
}
}
LaunchedEffect(saveFlow) {
scope.launch {
saveFlow.collect { stream ->
val outputStream = stream ?: return@collect
try {
viewModel.process(patches)
viewModel.export(outputStream)
scope.launch {
snackbarHostState.showSnackbar(getString(Res.string.apk_file_exported))
}
} catch (ex: Throwable) {
ex.printStackTrace()
errorMessage = getString(Res.string.unknown_error) to ex.stackTraceToString()
} finally {
viewModel.cancel()
outputStream.close()
saveFlow.collect { stream ->
val outputStream = stream ?: return@collect
try {
viewModel.process(patches)
viewModel.export(outputStream)
scope.launch {
snackbarHostState.showSnackbar(getString(Res.string.apk_file_exported))
}
} catch (ex: Throwable) {
ex.printStackTrace()
errorMessage = getString(Res.string.unknown_error) to ex.stackTraceToString()
} finally {
viewModel.cancel()
//outputStream.close()
}
}
}
@@ -71,9 +67,9 @@ fun PatcherScreen(
FadeVisibility(isPatcherVisible) {
ApplicationInfoContent(
viewModel.currentAppName(),
viewModel.currentAppPackage(),
viewModel.currentAppVersion(),
viewModel.currentAppName() ?: "",
viewModel.currentAppPackage() ?: "",
viewModel.currentAppVersion() ?: "",
viewModel.currentAppIcon(),
onCancel = {
scope.launch {
@@ -27,10 +27,8 @@ fun VersionManagerSheet(viewModel: MainViewModel, onSelected: (String) -> Unit,
var available by remember { mutableStateOf<List<OverportRelease>?>(null) }
LaunchedEffect(Unit) {
scope.launch {
withContext(Dispatchers.IO) {
available = viewModel.versionManager.available()
}
withContext(Dispatchers.IO) {
available = viewModel.versionManager.available()
}
}