diff --git a/api/api/api.api b/api/api/api.api index eccdb145..272df323 100644 --- a/api/api/api.api +++ b/api/api/api.api @@ -24,14 +24,6 @@ public final class app/revanced/manager/plugin/downloader/DownloadUrl : android/ public final fun writeToParcel (Landroid/os/Parcel;I)V } -public final class app/revanced/manager/plugin/downloader/DownloadUrl$Creator : android/os/Parcelable$Creator { - public fun ()V - public final fun createFromParcel (Landroid/os/Parcel;)Lapp/revanced/manager/plugin/downloader/DownloadUrl; - public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object; - public final fun newArray (I)[Lapp/revanced/manager/plugin/downloader/DownloadUrl; - public synthetic fun newArray (I)[Ljava/lang/Object; -} - public final class app/revanced/manager/plugin/downloader/Downloader { public static final field $stable I } @@ -85,14 +77,6 @@ public final class app/revanced/manager/plugin/downloader/Package : android/os/P public final fun writeToParcel (Landroid/os/Parcel;I)V } -public final class app/revanced/manager/plugin/downloader/Package$Creator : android/os/Parcelable$Creator { - public fun ()V - public final fun createFromParcel (Landroid/os/Parcel;)Lapp/revanced/manager/plugin/downloader/Package; - public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object; - public final fun newArray (I)[Lapp/revanced/manager/plugin/downloader/Package; - public synthetic fun newArray (I)[Ljava/lang/Object; -} - public abstract interface annotation class app/revanced/manager/plugin/downloader/PluginHostApi : java/lang/annotation/Annotation { } @@ -159,14 +143,6 @@ public abstract class app/revanced/manager/plugin/downloader/webview/IWebViewEve public fun onTransact (ILandroid/os/Parcel;Landroid/os/Parcel;I)Z } -public final class app/revanced/manager/plugin/downloader/webview/WebViewActivity$Parameters$Creator : android/os/Parcelable$Creator { - public fun ()V - public final fun createFromParcel (Landroid/os/Parcel;)Lapp/revanced/manager/plugin/downloader/webview/WebViewActivity$Parameters; - public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object; - public final fun newArray (I)[Lapp/revanced/manager/plugin/downloader/webview/WebViewActivity$Parameters; - public synthetic fun newArray (I)[Ljava/lang/Object; -} - public abstract interface class app/revanced/manager/plugin/downloader/webview/WebViewCallbackScope : app/revanced/manager/plugin/downloader/Scope { public abstract fun finish (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public abstract fun load (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; diff --git a/api/build.gradle.kts b/api/build.gradle.kts index 4e4392af..dd20c5d0 100644 --- a/api/build.gradle.kts +++ b/api/build.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + plugins { alias(libs.plugins.android.library) alias(libs.plugins.kotlin.android) @@ -17,9 +19,16 @@ dependencies { implementation(libs.appcompat) } +kotlin { + jvmToolchain(17) + compilerOptions { + jvmTarget = JvmTarget.JVM_17 + } +} + android { namespace = "app.revanced.manager.plugin.downloader" - compileSdk = 35 + compileSdk = 36 defaultConfig { minSdk = 26 @@ -42,10 +51,6 @@ android { targetCompatibility = JavaVersion.VERSION_17 } - kotlinOptions { - jvmTarget = "17" - } - buildFeatures { aidl = true } diff --git a/app/build.gradle.kts b/app/build.gradle.kts index b805efb6..f9d728db 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,4 +1,7 @@ +import com.mikepenz.aboutlibraries.plugin.DuplicateMode +import com.mikepenz.aboutlibraries.plugin.DuplicateRule import io.github.z4kn4fein.semver.toVersion +import org.jetbrains.kotlin.gradle.dsl.JvmTarget import kotlin.random.Random plugins { @@ -9,6 +12,7 @@ plugins { alias(libs.plugins.compose.compiler) alias(libs.plugins.devtools) alias(libs.plugins.about.libraries) + alias(libs.plugins.about.libraries.android) signing } @@ -81,7 +85,8 @@ dependencies { implementation(libs.koin.workmanager) // Licenses - implementation(libs.about.libraries) + implementation(libs.about.libraries.core) + implementation(libs.about.libraries.m3) // Ktor implementation(libs.ktor.core) @@ -126,7 +131,7 @@ buildscript { android { namespace = "app.revanced.manager" - compileSdk = 35 + compileSdk = 36 buildToolsVersion = "35.0.1" defaultConfig { @@ -233,10 +238,6 @@ android { arg("room.schemaLocation", "$projectDir/schemas") } - kotlinOptions { - jvmTarget = "17" - } - buildFeatures { compose = true aidl = true @@ -257,6 +258,18 @@ android { kotlin { jvmToolchain(17) + compilerOptions { + jvmTarget = JvmTarget.JVM_17 + } +} + +aboutLibraries { + library { + // Enable the duplication mode, allows to merge, or link dependencies which relate + duplicationMode = DuplicateMode.MERGE + // Configure the duplication rule, to match "duplicates" with + duplicationRule = DuplicateRule.EXACT + } } tasks { diff --git a/app/src/main/java/app/revanced/manager/MainActivity.kt b/app/src/main/java/app/revanced/manager/MainActivity.kt index 8cd65806..dd841d8c 100644 --- a/app/src/main/java/app/revanced/manager/MainActivity.kt +++ b/app/src/main/java/app/revanced/manager/MainActivity.kt @@ -59,7 +59,6 @@ import app.revanced.manager.ui.viewmodel.SelectedAppInfoViewModel import app.revanced.manager.util.EventEffect import kotlinx.coroutines.launch import org.koin.androidx.compose.koinViewModel -import org.koin.androidx.compose.navigation.koinNavViewModel import org.koin.core.parameter.parametersOf import org.koin.androidx.viewmodel.ext.android.getViewModel as getActivityViewModel @@ -185,7 +184,7 @@ private fun ReVancedManager(vm: MainViewModel) { val data = parentBackStackEntry.getComplexArg() val viewModel = - koinNavViewModel(viewModelStoreOwner = parentBackStackEntry) { + koinViewModel(viewModelStoreOwner = parentBackStackEntry) { parametersOf(data) } @@ -226,7 +225,7 @@ private fun ReVancedManager(vm: MainViewModel) { composable { val data = it.getComplexArg() - val selectedAppInfoVm = koinNavViewModel( + val selectedAppInfoVm = koinViewModel( viewModelStoreOwner = navController.navGraphEntry(it) ) @@ -243,7 +242,7 @@ private fun ReVancedManager(vm: MainViewModel) { composable { val data = it.getComplexArg() - val selectedAppInfoVm = koinNavViewModel( + val selectedAppInfoVm = koinViewModel( viewModelStoreOwner = navController.navGraphEntry(it) ) diff --git a/app/src/main/java/app/revanced/manager/di/ViewModelModule.kt b/app/src/main/java/app/revanced/manager/di/ViewModelModule.kt index 6970e886..c1b45d78 100644 --- a/app/src/main/java/app/revanced/manager/di/ViewModelModule.kt +++ b/app/src/main/java/app/revanced/manager/di/ViewModelModule.kt @@ -1,7 +1,7 @@ package app.revanced.manager.di import app.revanced.manager.ui.viewmodel.* -import org.koin.androidx.viewmodel.dsl.viewModelOf +import org.koin.core.module.dsl.* import org.koin.dsl.module val viewModelModule = module { diff --git a/app/src/main/java/app/revanced/manager/network/service/HttpService.kt b/app/src/main/java/app/revanced/manager/network/service/HttpService.kt index ea4cfb18..bc6ee4a9 100644 --- a/app/src/main/java/app/revanced/manager/network/service/HttpService.kt +++ b/app/src/main/java/app/revanced/manager/network/service/HttpService.kt @@ -16,8 +16,11 @@ import io.ktor.http.isSuccess import io.ktor.utils.io.ByteReadChannel import io.ktor.utils.io.core.isNotEmpty import io.ktor.utils.io.core.readBytes +import io.ktor.utils.io.exhausted +import io.ktor.utils.io.readRemaining import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext +import kotlinx.io.asSink import kotlinx.serialization.json.Json import java.io.File import java.io.OutputStream @@ -69,14 +72,12 @@ class HttpService( ) { http.prepareGet(builder).execute { httpResponse -> if (httpResponse.status.isSuccess()) { - val channel: ByteReadChannel = httpResponse.body() withContext(Dispatchers.IO) { - while (!channel.isClosedForRead) { + val channel: ByteReadChannel = httpResponse.body() + val sink = outputStream.asSink() + while (!channel.exhausted()) { val packet = channel.readRemaining(DEFAULT_BUFFER_SIZE.toLong()) - while (packet.isNotEmpty) { - val bytes = packet.readBytes() - outputStream.write(bytes) - } + packet.transferTo(sink) } } diff --git a/app/src/main/java/app/revanced/manager/ui/component/AppIcon.kt b/app/src/main/java/app/revanced/manager/ui/component/AppIcon.kt index 0d8cd822..6ee1c406 100644 --- a/app/src/main/java/app/revanced/manager/ui/component/AppIcon.kt +++ b/app/src/main/java/app/revanced/manager/ui/component/AppIcon.kt @@ -16,7 +16,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.vector.rememberVectorPainter import coil.compose.AsyncImage -import io.github.fornewid.placeholder.material3.placeholder +import com.eygraber.compose.placeholder.material3.placeholder @Composable fun AppIcon( diff --git a/app/src/main/java/app/revanced/manager/ui/component/AppLabel.kt b/app/src/main/java/app/revanced/manager/ui/component/AppLabel.kt index 33a1e201..4c19d65a 100644 --- a/app/src/main/java/app/revanced/manager/ui/component/AppLabel.kt +++ b/app/src/main/java/app/revanced/manager/ui/component/AppLabel.kt @@ -16,7 +16,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextStyle import app.revanced.manager.R -import io.github.fornewid.placeholder.material3.placeholder +import com.eygraber.compose.placeholder.material3.placeholder import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext diff --git a/app/src/main/java/app/revanced/manager/ui/component/LoadingIndicator.kt b/app/src/main/java/app/revanced/manager/ui/component/LoadingIndicator.kt index 44d5c9cd..e6d8f243 100644 --- a/app/src/main/java/app/revanced/manager/ui/component/LoadingIndicator.kt +++ b/app/src/main/java/app/revanced/manager/ui/component/LoadingIndicator.kt @@ -14,7 +14,7 @@ fun LoadingIndicator( progress: () -> Float? = { null }, color: Color = ProgressIndicatorDefaults.circularColor, strokeWidth: Dp = ProgressIndicatorDefaults.CircularStrokeWidth, - trackColor: Color = ProgressIndicatorDefaults.circularTrackColor, + trackColor: Color = ProgressIndicatorDefaults.circularIndeterminateTrackColor, strokeCap: StrokeCap = ProgressIndicatorDefaults.CircularDeterminateStrokeCap ) { progress()?.let { diff --git a/app/src/main/java/app/revanced/manager/ui/component/Markdown.kt b/app/src/main/java/app/revanced/manager/ui/component/Markdown.kt index 2b5b276e..e640c222 100644 --- a/app/src/main/java/app/revanced/manager/ui/component/Markdown.kt +++ b/app/src/main/java/app/revanced/manager/ui/component/Markdown.kt @@ -18,8 +18,6 @@ fun Markdown( colors = markdownColor( text = MaterialTheme.colorScheme.onSurfaceVariant, codeBackground = MaterialTheme.colorScheme.secondaryContainer, - codeText = MaterialTheme.colorScheme.onSecondaryContainer, - linkText = MaterialTheme.colorScheme.primary ), typography = markdownTypography( h1 = MaterialTheme.typography.headlineSmall.copy(fontWeight = FontWeight.Bold), diff --git a/app/src/main/java/app/revanced/manager/ui/component/SearchBar.kt b/app/src/main/java/app/revanced/manager/ui/component/SearchBar.kt index 7c48b812..de77a3ff 100644 --- a/app/src/main/java/app/revanced/manager/ui/component/SearchBar.kt +++ b/app/src/main/java/app/revanced/manager/ui/component/SearchBar.kt @@ -29,7 +29,8 @@ fun SearchBar( ) { val colors = SearchBarColors( containerColor = MaterialTheme.colorScheme.surfaceContainerHigh, - dividerColor = MaterialTheme.colorScheme.outline + dividerColor = MaterialTheme.colorScheme.outline, + inputFieldColors = SearchBarDefaults.inputFieldColors() ) val keyboardController = LocalSoftwareKeyboardController.current diff --git a/app/src/main/java/app/revanced/manager/ui/component/SearchView.kt b/app/src/main/java/app/revanced/manager/ui/component/SearchView.kt index 04b5b589..0a231f11 100644 --- a/app/src/main/java/app/revanced/manager/ui/component/SearchView.kt +++ b/app/src/main/java/app/revanced/manager/ui/component/SearchView.kt @@ -31,7 +31,8 @@ fun SearchView( ) { val colors = SearchBarColors( containerColor = MaterialTheme.colorScheme.surfaceContainerHigh, - dividerColor = MaterialTheme.colorScheme.outline + dividerColor = MaterialTheme.colorScheme.outline, + inputFieldColors = SearchBarDefaults.inputFieldColors() ) val focusRequester = remember { FocusRequester() } val keyboardController = LocalSoftwareKeyboardController.current diff --git a/app/src/main/java/app/revanced/manager/ui/model/PatcherStep.kt b/app/src/main/java/app/revanced/manager/ui/model/PatcherStep.kt index 46403d72..db5205cd 100644 --- a/app/src/main/java/app/revanced/manager/ui/model/PatcherStep.kt +++ b/app/src/main/java/app/revanced/manager/ui/model/PatcherStep.kt @@ -6,7 +6,7 @@ import app.revanced.manager.R import app.revanced.manager.patcher.StepId import kotlinx.parcelize.Parcelize -enum class StepCategory(@StringRes val displayName: Int) { +enum class StepCategory(@param:StringRes val displayName: Int) { PREPARING(R.string.patcher_step_group_preparing), PATCHING(R.string.patcher_step_group_patching), SAVING(R.string.patcher_step_group_saving) diff --git a/app/src/main/java/app/revanced/manager/ui/screen/DashboardScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/DashboardScreen.kt index 0496c1a9..102adeca 100644 --- a/app/src/main/java/app/revanced/manager/ui/screen/DashboardScreen.kt +++ b/app/src/main/java/app/revanced/manager/ui/screen/DashboardScreen.kt @@ -36,7 +36,7 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold -import androidx.compose.material3.TabRow +import androidx.compose.material3.SecondaryTabRow import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.surfaceColorAtElevation @@ -53,6 +53,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalResources import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -100,6 +101,7 @@ fun DashboardScreen( false ) val androidContext = LocalContext.current + val resources = LocalResources.current val composableScope = rememberCoroutineScope() val pagerState = rememberPagerState( initialPage = DashboardPage.DASHBOARD.ordinal, @@ -234,7 +236,7 @@ fun DashboardScreen( when (pagerState.currentPage) { DashboardPage.DASHBOARD.ordinal -> { if (availablePatches < 1) { - androidContext.toast(androidContext.getString(R.string.no_patch_found)) + androidContext.toast(resources.getString(R.string.no_patch_found)) composableScope.launch { pagerState.animateScrollToPage( DashboardPage.BUNDLES.ordinal @@ -259,7 +261,7 @@ fun DashboardScreen( } ) { paddingValues -> Column(Modifier.padding(paddingValues)) { - TabRow( + SecondaryTabRow( selectedTabIndex = pagerState.currentPage, containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(3.0.dp) ) { diff --git a/app/src/main/java/app/revanced/manager/ui/screen/PatcherScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/PatcherScreen.kt index f3a9f059..f74970ee 100644 --- a/app/src/main/java/app/revanced/manager/ui/screen/PatcherScreen.kt +++ b/app/src/main/java/app/revanced/manager/ui/screen/PatcherScreen.kt @@ -40,6 +40,7 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalResources import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import app.revanced.manager.R @@ -69,6 +70,7 @@ fun PatcherScreen( } val context = LocalContext.current + val resources = LocalResources.current val exportApkLauncher = rememberLauncherForActivityResult(CreateDocument(APK_MIMETYPE), viewModel::export) @@ -79,7 +81,7 @@ fun PatcherScreen( fun onPageBack() = when { patcherSucceeded == null -> showDismissConfirmationDialog = true - viewModel.isInstalling -> context.toast(context.getString(R.string.patcher_install_in_progress)) + viewModel.isInstalling -> context.toast(resources.getString(R.string.patcher_install_in_progress)) else -> onLeave() } diff --git a/app/src/main/java/app/revanced/manager/ui/screen/PatchesSelectorScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/PatchesSelectorScreen.kt index 035c862e..284fa50b 100644 --- a/app/src/main/java/app/revanced/manager/ui/screen/PatchesSelectorScreen.kt +++ b/app/src/main/java/app/revanced/manager/ui/screen/PatchesSelectorScreen.kt @@ -40,7 +40,7 @@ import androidx.compose.material3.ListItem import androidx.compose.material3.MaterialTheme import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.Scaffold -import androidx.compose.material3.ScrollableTabRow +import androidx.compose.material3.SecondaryScrollableTabRow import androidx.compose.material3.SmallFloatingActionButton import androidx.compose.material3.Text import androidx.compose.material3.TextButton @@ -392,7 +392,7 @@ fun PatchesSelectorScreen( .padding(top = 16.dp) ) { if (bundles.size > 1) { - ScrollableTabRow( + SecondaryScrollableTabRow( selectedTabIndex = pagerState.currentPage, containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(3.0.dp) ) { diff --git a/app/src/main/java/app/revanced/manager/ui/screen/RequiredOptionsScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/RequiredOptionsScreen.kt index 459e61ea..4006980c 100644 --- a/app/src/main/java/app/revanced/manager/ui/screen/RequiredOptionsScreen.kt +++ b/app/src/main/java/app/revanced/manager/ui/screen/RequiredOptionsScreen.kt @@ -13,7 +13,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold -import androidx.compose.material3.ScrollableTabRow +import androidx.compose.material3.SecondaryScrollableTabRow import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.rememberTopAppBarState @@ -106,7 +106,7 @@ fun RequiredOptionsScreen( .padding(paddingValues) ) { if (list.isEmpty()) return@Column - else if (list.size > 1) ScrollableTabRow( + else if (list.size > 1) SecondaryScrollableTabRow( selectedTabIndex = pagerState.currentPage, containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(3.0.dp) ) { diff --git a/app/src/main/java/app/revanced/manager/ui/screen/SelectedAppInfoScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/SelectedAppInfoScreen.kt index 6c668870..094e928e 100644 --- a/app/src/main/java/app/revanced/manager/ui/screen/SelectedAppInfoScreen.kt +++ b/app/src/main/java/app/revanced/manager/ui/screen/SelectedAppInfoScreen.kt @@ -32,6 +32,7 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalResources import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -68,6 +69,7 @@ fun SelectedAppInfoScreen( vm: SelectedAppInfoViewModel ) { val context = LocalContext.current + val resources = LocalResources.current val networkInfo = koinInject() val networkConnected = remember { networkInfo.isConnected() } val networkMetered = remember { !networkInfo.isUnmetered() } @@ -118,7 +120,7 @@ fun SelectedAppInfoScreen( }, onClick = patchClick@{ if (selectedPatchCount == 0) { - context.toast(context.getString(R.string.no_patches_selected)) + context.toast(resources.getString(R.string.no_patches_selected)) return@patchClick } diff --git a/app/src/main/java/app/revanced/manager/ui/screen/SettingsScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/SettingsScreen.kt index 24b756d2..a597ddbb 100644 --- a/app/src/main/java/app/revanced/manager/ui/screen/SettingsScreen.kt +++ b/app/src/main/java/app/revanced/manager/ui/screen/SettingsScreen.kt @@ -22,8 +22,8 @@ import app.revanced.manager.ui.model.navigation.Settings import org.koin.compose.koinInject private data class Section( - @StringRes val name: Int, - @StringRes val description: Int, + @param:StringRes val name: Int, + @param:StringRes val description: Int, val image: ImageVector, val destination: Settings.Destination, ) diff --git a/app/src/main/java/app/revanced/manager/ui/screen/settings/AboutSettingsScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/settings/AboutSettingsScreen.kt index 80fc6636..e020c846 100644 --- a/app/src/main/java/app/revanced/manager/ui/screen/settings/AboutSettingsScreen.kt +++ b/app/src/main/java/app/revanced/manager/ui/screen/settings/AboutSettingsScreen.kt @@ -1,5 +1,6 @@ package app.revanced.manager.ui.screen.settings +import android.annotation.SuppressLint import androidx.appcompat.content.res.AppCompatResources import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.Image @@ -40,6 +41,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalResources import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.hideFromAccessibility import androidx.compose.ui.semantics.semantics @@ -67,8 +69,9 @@ fun AboutSettingsScreen( viewModel: AboutViewModel = koinViewModel() ) { val context = LocalContext.current + val resources = LocalResources.current // painterResource() is broken on release builds for some reason. - val icon = rememberDrawablePainter(drawable = remember { + val icon = rememberDrawablePainter(drawable = remember(resources) { AppCompatResources.getDrawable(context, R.drawable.ic_logo_ring) }) @@ -76,7 +79,7 @@ fun AboutSettingsScreen( viewModel.socials.partition(ReVancedSocial::preferred) } - val preferredSocialButtons = remember(preferredSocials, viewModel.donate, viewModel.contact) { + val preferredSocialButtons = remember(resources, preferredSocials, viewModel.donate, viewModel.contact) { preferredSocials.map { Triple( getSocialIcon(it.name), @@ -89,7 +92,7 @@ fun AboutSettingsScreen( viewModel.donate?.let { Triple( Icons.Outlined.FavoriteBorder, - context.getString(R.string.donate), + resources.getString(R.string.donate), third = { context.openUrl(it) } @@ -98,7 +101,7 @@ fun AboutSettingsScreen( viewModel.contact?.let { Triple( Icons.Outlined.MailOutline, - context.getString(R.string.contact), + resources.getString(R.string.contact), third = { context.openUrl("mailto:$it") } @@ -131,7 +134,7 @@ fun AboutSettingsScreen( stringResource(R.string.contributors_description), third = nav@{ if (!viewModel.isConnected) { - context.toast(context.getString(R.string.no_network_toast)) + context.toast(resources.getString(R.string.no_network_toast)) return@nav } @@ -153,7 +156,7 @@ fun AboutSettingsScreen( LaunchedEffect(developerTaps) { if (developerTaps == 0) return@LaunchedEffect if (showDeveloperSettings) { - snackbarHostState.showSnackbar(context.getString(R.string.developer_options_already_enabled)) + snackbarHostState.showSnackbar(resources.getString(R.string.developer_options_already_enabled)) developerTaps = 0 return@LaunchedEffect } @@ -161,7 +164,7 @@ fun AboutSettingsScreen( val remaining = DEVELOPER_OPTIONS_TAPS - developerTaps if (remaining > 0) { snackbarHostState.showSnackbar( - context.getString( + resources.getString( R.string.developer_options_taps, remaining ), @@ -169,7 +172,7 @@ fun AboutSettingsScreen( ) } else if (remaining == 0) { viewModel.showDeveloperSettings.update(true) - snackbarHostState.showSnackbar(context.getString(R.string.developer_options_enabled)) + snackbarHostState.showSnackbar(resources.getString(R.string.developer_options_enabled)) } // Reset the counter diff --git a/app/src/main/java/app/revanced/manager/ui/screen/settings/AdvancedSettingsScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/settings/AdvancedSettingsScreen.kt index 39d7e9b1..7d4aa4a6 100644 --- a/app/src/main/java/app/revanced/manager/ui/screen/settings/AdvancedSettingsScreen.kt +++ b/app/src/main/java/app/revanced/manager/ui/screen/settings/AdvancedSettingsScreen.kt @@ -38,6 +38,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalResources import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp @@ -64,9 +65,10 @@ fun AdvancedSettingsScreen( viewModel: AdvancedSettingsViewModel = koinViewModel() ) { val context = LocalContext.current - val memoryLimit = remember { + val resources = LocalResources.current + val memoryLimit = remember(resources) { val activityManager = context.getSystemService()!! - context.getString( + resources.getString( R.string.device_memory_limit_format, activityManager.memoryClass, activityManager.largeMemoryClass @@ -183,7 +185,7 @@ fun AdvancedSettingsScreen( ClipData.newPlainText("Device Information", deviceContent) ) - context.toast(context.getString(R.string.toast_copied_to_clipboard)) + context.toast(resources.getString(R.string.toast_copied_to_clipboard)) }.withHapticFeedback(HapticFeedbackConstants.LONG_PRESS) ), headlineContent = stringResource(R.string.about_device), diff --git a/app/src/main/java/app/revanced/manager/ui/screen/settings/ImportExportSettingsScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/settings/ImportExportSettingsScreen.kt index 9e9d75fb..01a2948d 100644 --- a/app/src/main/java/app/revanced/manager/ui/screen/settings/ImportExportSettingsScreen.kt +++ b/app/src/main/java/app/revanced/manager/ui/screen/settings/ImportExportSettingsScreen.kt @@ -36,6 +36,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalResources import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp @@ -64,6 +65,7 @@ fun ImportExportSettingsScreen( vm: ImportExportViewModel = koinViewModel() ) { val context = LocalContext.current + val resources = LocalResources.current val coroutineScope = rememberCoroutineScope() var selectorDialog by rememberSaveable { mutableStateOf<(@Composable () -> Unit)?>(null) } @@ -108,7 +110,7 @@ fun ImportExportSettingsScreen( vm.viewModelScope.launch { uiSafe(context, R.string.failed_to_import_keystore, "Failed to import keystore") { val result = vm.tryKeystoreImport(alias, pass) - if (!result) context.toast(context.getString(R.string.import_keystore_wrong_credentials)) + if (!result) context.toast(resources.getString(R.string.import_keystore_wrong_credentials)) } } } @@ -166,7 +168,7 @@ fun ImportExportSettingsScreen( GroupItem( onClick = { if (!vm.canExport()) { - context.toast(context.getString(R.string.export_keystore_unavailable)) + context.toast(resources.getString(R.string.export_keystore_unavailable)) return@GroupItem } exportKeystoreLauncher.launch("Manager.keystore") diff --git a/app/src/main/java/app/revanced/manager/ui/screen/settings/LicensesSettingsScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/settings/LicensesSettingsScreen.kt index bfd6360b..6a2c06da 100644 --- a/app/src/main/java/app/revanced/manager/ui/screen/settings/LicensesSettingsScreen.kt +++ b/app/src/main/java/app/revanced/manager/ui/screen/settings/LicensesSettingsScreen.kt @@ -7,15 +7,18 @@ import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import app.revanced.manager.R import app.revanced.manager.ui.component.AppScaffold import app.revanced.manager.ui.component.AppTopBar import app.revanced.manager.ui.component.Scrollbar -import com.mikepenz.aboutlibraries.ui.compose.LibrariesContainer import com.mikepenz.aboutlibraries.ui.compose.LibraryDefaults -import com.mikepenz.aboutlibraries.ui.compose.libraryColors +import com.mikepenz.aboutlibraries.ui.compose.android.produceLibraries +import com.mikepenz.aboutlibraries.ui.compose.m3.LibrariesContainer +import com.mikepenz.aboutlibraries.ui.compose.m3.chipColors +import com.mikepenz.aboutlibraries.ui.compose.m3.libraryColors @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -33,16 +36,23 @@ fun LicensesSettingsScreen( ) { paddingValues -> Column(modifier = Modifier.padding(paddingValues)) { val lazyListState = rememberLazyListState() + val libraries by produceLibraries(R.raw.aboutlibraries) + val chipColors = LibraryDefaults.chipColors( + containerColor = MaterialTheme.colorScheme.primary, + contentColor = MaterialTheme.colorScheme.onPrimary, + ) LibrariesContainer( modifier = Modifier .fillMaxSize(), + libraries = libraries, lazyListState = lazyListState, colors = LibraryDefaults.libraryColors( - backgroundColor = MaterialTheme.colorScheme.background, - contentColor = MaterialTheme.colorScheme.onBackground, - badgeBackgroundColor = MaterialTheme.colorScheme.primary, - badgeContentColor = MaterialTheme.colorScheme.onPrimary, + libraryBackgroundColor = MaterialTheme.colorScheme.background, + libraryContentColor = MaterialTheme.colorScheme.onBackground, + versionChipColors = chipColors, + licenseChipColors = chipColors, + fundingChipColors = chipColors, ) ) Scrollbar(lazyListState = lazyListState, modifier = Modifier.padding(paddingValues)) diff --git a/app/src/main/java/app/revanced/manager/ui/screen/settings/update/UpdatesSettingsScreen.kt b/app/src/main/java/app/revanced/manager/ui/screen/settings/update/UpdatesSettingsScreen.kt index c46d5b25..5943ee8a 100644 --- a/app/src/main/java/app/revanced/manager/ui/screen/settings/update/UpdatesSettingsScreen.kt +++ b/app/src/main/java/app/revanced/manager/ui/screen/settings/update/UpdatesSettingsScreen.kt @@ -12,6 +12,7 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalResources import androidx.compose.ui.res.stringResource import app.revanced.manager.R import app.revanced.manager.ui.component.AppTopBar @@ -33,6 +34,7 @@ fun UpdatesSettingsScreen( vm: UpdatesSettingsViewModel = koinViewModel(), ) { val context = LocalContext.current + val resources = LocalResources.current val coroutineScope = rememberCoroutineScope() val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState()) @@ -57,7 +59,7 @@ fun UpdatesSettingsScreen( modifier = Modifier.clickable { coroutineScope.launch { if (!vm.isConnected) { - context.toast(context.getString(R.string.no_network_toast)) + context.toast(resources.getString(R.string.no_network_toast)) return@launch } if (vm.checkForUpdates()) onUpdateClick() @@ -70,7 +72,7 @@ fun UpdatesSettingsScreen( SettingsListItem( modifier = Modifier.clickable { if (!vm.isConnected) { - context.toast(context.getString(R.string.no_network_toast)) + context.toast(resources.getString(R.string.no_network_toast)) return@clickable } onChangelogClick() diff --git a/app/src/main/java/app/revanced/manager/ui/viewmodel/ImportExportViewModel.kt b/app/src/main/java/app/revanced/manager/ui/viewmodel/ImportExportViewModel.kt index 7ad3f2c5..562de02d 100644 --- a/app/src/main/java/app/revanced/manager/ui/viewmodel/ImportExportViewModel.kt +++ b/app/src/main/java/app/revanced/manager/ui/viewmodel/ImportExportViewModel.kt @@ -36,8 +36,8 @@ import kotlin.io.path.deleteExisting import kotlin.io.path.inputStream sealed class ResetDialogState( - @StringRes val titleResId: Int, - @StringRes val descriptionResId: Int, + @param:StringRes val titleResId: Int, + @param:StringRes val descriptionResId: Int, val onConfirm: () -> Unit, val dialogOptionName: String? = null ) { diff --git a/app/src/main/java/app/revanced/manager/ui/viewmodel/UpdateViewModel.kt b/app/src/main/java/app/revanced/manager/ui/viewmodel/UpdateViewModel.kt index 321bf94f..c9f1051b 100644 --- a/app/src/main/java/app/revanced/manager/ui/viewmodel/UpdateViewModel.kt +++ b/app/src/main/java/app/revanced/manager/ui/viewmodel/UpdateViewModel.kt @@ -90,8 +90,10 @@ class UpdateViewModel( http.download(location) { url(release.downloadUrl) onDownload { bytesSentTotal, contentLength -> - downloadedSize = bytesSentTotal - totalSize = contentLength + withContext(Dispatchers.Main) { + downloadedSize = bytesSentTotal + contentLength?.let { totalSize = it } + } } } installUpdate() diff --git a/app/src/main/java/app/revanced/manager/util/Util.kt b/app/src/main/java/app/revanced/manager/util/Util.kt index 95b6ed0e..a2706976 100644 --- a/app/src/main/java/app/revanced/manager/util/Util.kt +++ b/app/src/main/java/app/revanced/manager/util/Util.kt @@ -43,7 +43,6 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.launch -import kotlinx.datetime.Clock import kotlinx.datetime.LocalDateTime import kotlinx.datetime.TimeZone import kotlinx.datetime.format.MonthNames @@ -54,6 +53,7 @@ import java.util.Locale import kotlin.properties.PropertyDelegateProvider import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty +import kotlin.time.Clock typealias PatchSelection = Map> typealias Options = Map>> @@ -169,7 +169,7 @@ fun LocalDateTime.relativeTime(context: Context): String { else -> LocalDateTime.Format { monthName(MonthNames.ENGLISH_ABBREVIATED) char(' ') - dayOfMonth() + day() if (now.toLocalDateTime(TimeZone.UTC).year != this@relativeTime.year) { chars(", ") year() diff --git a/build.gradle.kts b/build.gradle.kts index c543b2fa..9728ef0d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,5 +6,6 @@ plugins { alias(libs.plugins.kotlin.serialization) apply false alias(libs.plugins.kotlin.parcelize) apply false alias(libs.plugins.about.libraries) apply false + alias(libs.plugins.about.libraries.android) apply false alias(libs.plugins.compose.compiler) apply false } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1ca390cd..3f66bbb6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,32 +1,32 @@ [versions] -ktx = "1.16.0" -material3 = "1.3.2" -ui-tooling = "1.8.1" -viewmodel-lifecycle = "2.9.0" -splash-screen = "1.0.1" -activity = "1.10.1" -appcompat = "1.7.0" -preferences-datastore = "1.1.2" -work-runtime = "2.10.1" -compose-bom = "2025.05.00" -navigation = "2.8.6" -accompanist = "0.37.0" -placeholder = "1.1.2" -reorderable = "2.4.3" -serialization = "1.8.0" -collection = "0.3.8" -datetime = "0.6.1" -room-version = "2.7.1" +ktx = "1.17.0" +material3 = "1.4.0" +ui-tooling = "1.10.0" +viewmodel-lifecycle = "2.10.0" +splash-screen = "1.2.0" +activity = "1.12.2" +appcompat = "1.7.1" +preferences-datastore = "1.2.0" +work-runtime = "2.11.0" +compose-bom = "2025.12.01" +navigation = "2.9.6" +accompanist = "0.37.3" +placeholder = "1.0.12" +reorderable = "3.0.0" +serialization = "1.9.0" +collection = "0.4.0" +datetime = "0.7.1" +room-version = "2.8.4" revanced-patcher = "21.0.0" revanced-library = "3.0.2" -koin = "3.5.3" -ktor = "2.3.9" -markdown-renderer = "0.30.0" +koin = "4.1.1" +ktor = "3.3.3" +markdown-renderer = "0.39.0" fading-edges = "1.0.4" -kotlin = "2.1.10" -android-gradle-plugin = "8.9.1" -dev-tools-gradle-plugin = "2.1.10-1.0.29" -about-libraries-gradle-plugin = "12.1.2" +kotlin = "2.3.0" +android-gradle-plugin = "8.13.2" +dev-tools-gradle-plugin = "2.3.4" +about-libraries = "13.2.1" coil = "2.7.0" app-icon-loader-coil = "1.5.0" libsu = "6.0.0" @@ -34,10 +34,10 @@ scrollbars = "1.0.4" enumutil = "1.1.1" compose-icons = "1.2.4" kotlin-process = "1.5.1" -hidden-api-stub = "4.3.3" -binary-compatibility-validator = "0.17.0" +hidden-api-stub = "4.4.0" +binary-compatibility-validator = "0.18.1" semver-parser = "3.0.0" -ackpine = "0.18.5" +ackpine = "0.19.1" [libraries] # AndroidX Core @@ -68,7 +68,7 @@ coil-appiconloader = { group = "me.zhanghai.android.appiconloader", name = "appi accompanist-drawablepainter = { group = "com.google.accompanist", name = "accompanist-drawablepainter", version.ref = "accompanist" } # Placeholder -placeholder-material3 = { group = "io.github.fornewid", name = "placeholder-material3", version.ref = "placeholder"} +placeholder-material3 = { group = "com.eygraber", name = "compose-placeholder-material3", version.ref = "placeholder" } # Kotlinx kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "serialization" } @@ -91,7 +91,8 @@ koin-compose-navigation = { group = "io.insert-koin", name = "koin-androidx-comp koin-workmanager = { group = "io.insert-koin", name = "koin-androidx-workmanager", version.ref = "koin" } # About Libraries -about-libraries = { group = "com.mikepenz", name = "aboutlibraries-compose", version.ref = "about-libraries-gradle-plugin" } +about-libraries-core = { group = "com.mikepenz", name = "aboutlibraries-compose-core", version.ref = "about-libraries" } +about-libraries-m3 = { group = "com.mikepenz", name = "aboutlibraries-compose-m3", version.ref = "about-libraries" } # Ktor ktor-core = { group = "io.ktor", name = "ktor-client-core", version.ref = "ktor" } @@ -146,5 +147,6 @@ kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", versi kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" } compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } devtools = { id = "com.google.devtools.ksp", version.ref = "dev-tools-gradle-plugin" } -about-libraries = { id = "com.mikepenz.aboutlibraries.plugin", version.ref = "about-libraries-gradle-plugin" } +about-libraries = { id = "com.mikepenz.aboutlibraries.plugin", version.ref = "about-libraries" } +about-libraries-android = { id = "com.mikepenz.aboutlibraries.plugin.android", version.ref = "about-libraries" } binary-compatibility-validator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "binary-compatibility-validator" }