mirror of
https://github.com/ReVanced/revanced-manager.git
synced 2026-01-17 16:23:57 +00:00
Compare commits
10 Commits
v1.26.0-de
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7615453eec | ||
|
|
4c0b6b02e9 | ||
|
|
fe84b22b6f | ||
|
|
1b21f5d4ab | ||
|
|
72b1db9a2f | ||
|
|
2805ac6540 | ||
|
|
b16931ca79 | ||
|
|
dfeca09d00 | ||
|
|
44c06e2197 | ||
|
|
df31b39cc8 |
43
.github/workflows/pull_strings.yml
vendored
Normal file
43
.github/workflows/pull_strings.yml
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
name: Pull strings
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 0 * * 0"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
pull:
|
||||||
|
name: Pull strings
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
pull-requests: write
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
with:
|
||||||
|
ref: dev
|
||||||
|
clean: true
|
||||||
|
|
||||||
|
- name: Pull strings
|
||||||
|
uses: crowdin/github-action@v2
|
||||||
|
with:
|
||||||
|
config: crowdin.yml
|
||||||
|
upload_sources: false
|
||||||
|
download_translations: true
|
||||||
|
skip_ref_checkout: true
|
||||||
|
localization_branch_name: feat/translations
|
||||||
|
create_pull_request: false
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
|
||||||
|
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
|
||||||
|
|
||||||
|
- name: Open pull request
|
||||||
|
if: github.event_name == 'workflow_dispatch'
|
||||||
|
uses: repo-sync/pull-request@v2
|
||||||
|
with:
|
||||||
|
source_branch: feat/translations
|
||||||
|
destination_branch: dev
|
||||||
|
pr_title: "chore: Sync translations"
|
||||||
|
pr_body: "Sync translations from [crowdin.com/project/revanced](https://crowdin.com/project/revanced)"
|
||||||
26
.github/workflows/push_strings.yml
vendored
Normal file
26
.github/workflows/push_strings.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
name: Push strings
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- dev
|
||||||
|
paths:
|
||||||
|
- app/src/main/res/values/strings.xml
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
push:
|
||||||
|
name: Push strings
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Push strings
|
||||||
|
uses: crowdin/github-action@v2
|
||||||
|
with:
|
||||||
|
config: crowdin.yml
|
||||||
|
upload_sources: true
|
||||||
|
env:
|
||||||
|
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
|
||||||
|
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
|
||||||
@@ -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 fun writeToParcel (Landroid/os/Parcel;I)V
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class app/revanced/manager/plugin/downloader/DownloadUrl$Creator : android/os/Parcelable$Creator {
|
|
||||||
public fun <init> ()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 final class app/revanced/manager/plugin/downloader/Downloader {
|
||||||
public static final field $stable I
|
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 fun writeToParcel (Landroid/os/Parcel;I)V
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class app/revanced/manager/plugin/downloader/Package$Creator : android/os/Parcelable$Creator {
|
|
||||||
public fun <init> ()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 {
|
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 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 <init> ()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 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 finish (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||||
public abstract fun load (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
public abstract fun load (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.android.library)
|
alias(libs.plugins.android.library)
|
||||||
alias(libs.plugins.kotlin.android)
|
alias(libs.plugins.kotlin.android)
|
||||||
@@ -17,9 +19,16 @@ dependencies {
|
|||||||
implementation(libs.appcompat)
|
implementation(libs.appcompat)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
jvmToolchain(17)
|
||||||
|
compilerOptions {
|
||||||
|
jvmTarget = JvmTarget.JVM_17
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "app.revanced.manager.plugin.downloader"
|
namespace = "app.revanced.manager.plugin.downloader"
|
||||||
compileSdk = 35
|
compileSdk = 36
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk = 26
|
minSdk = 26
|
||||||
@@ -42,10 +51,6 @@ android {
|
|||||||
targetCompatibility = JavaVersion.VERSION_17
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlinOptions {
|
|
||||||
jvmTarget = "17"
|
|
||||||
}
|
|
||||||
|
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
aidl = true
|
aidl = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,29 @@
|
|||||||
|
# app [1.26.0-dev.20](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.19...v1.26.0-dev.20) (2026-01-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Save FAB freaking out in select patches screen ([4c0b6b0](https://github.com/ReVanced/revanced-manager/commit/4c0b6b02e95a8d6f655bcf5c25493b1f9a4a4dcd))
|
||||||
|
|
||||||
|
# app [1.26.0-dev.19](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.18...v1.26.0-dev.19) (2026-01-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **locales:** use buildconfig instead of generating kt file ([72b1db9](https://github.com/ReVanced/revanced-manager/commit/72b1db9a2f33ab5d5fffd8ba83c05901eff19bea))
|
||||||
|
|
||||||
|
# app [1.26.0-dev.18](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.17...v1.26.0-dev.18) (2026-01-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Prevent trailing comma when no locales are generated ([b16931c](https://github.com/ReVanced/revanced-manager/commit/b16931ca79d5ce4d17c75f6dd3bf6f976b8ff7be))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Add language settings ([#2913](https://github.com/ReVanced/revanced-manager/issues/2913)) ([df31b39](https://github.com/ReVanced/revanced-manager/commit/df31b39cc8c1fbf00bc3301468e8e7e4b283caf2))
|
||||||
|
|
||||||
# app [1.26.0-dev.17](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.16...v1.26.0-dev.17) (2026-01-06)
|
# app [1.26.0-dev.17](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.16...v1.26.0-dev.17) (2026-01-06)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
|
import com.mikepenz.aboutlibraries.plugin.DuplicateMode
|
||||||
|
import com.mikepenz.aboutlibraries.plugin.DuplicateRule
|
||||||
import io.github.z4kn4fein.semver.toVersion
|
import io.github.z4kn4fein.semver.toVersion
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
@@ -9,6 +12,7 @@ plugins {
|
|||||||
alias(libs.plugins.compose.compiler)
|
alias(libs.plugins.compose.compiler)
|
||||||
alias(libs.plugins.devtools)
|
alias(libs.plugins.devtools)
|
||||||
alias(libs.plugins.about.libraries)
|
alias(libs.plugins.about.libraries)
|
||||||
|
alias(libs.plugins.about.libraries.android)
|
||||||
signing
|
signing
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +85,8 @@ dependencies {
|
|||||||
implementation(libs.koin.workmanager)
|
implementation(libs.koin.workmanager)
|
||||||
|
|
||||||
// Licenses
|
// Licenses
|
||||||
implementation(libs.about.libraries)
|
implementation(libs.about.libraries.core)
|
||||||
|
implementation(libs.about.libraries.m3)
|
||||||
|
|
||||||
// Ktor
|
// Ktor
|
||||||
implementation(libs.ktor.core)
|
implementation(libs.ktor.core)
|
||||||
@@ -126,7 +131,7 @@ buildscript {
|
|||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "app.revanced.manager"
|
namespace = "app.revanced.manager"
|
||||||
compileSdk = 35
|
compileSdk = 36
|
||||||
buildToolsVersion = "35.0.1"
|
buildToolsVersion = "35.0.1"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
@@ -143,13 +148,25 @@ android {
|
|||||||
(preRelease?.substringAfterLast('.')?.toInt() ?: 99)
|
(preRelease?.substringAfterLast('.')?.toInt() ?: 99)
|
||||||
}
|
}
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
|
|
||||||
|
val resDir = file("src/main/res")
|
||||||
|
val locales = resDir.listFiles()
|
||||||
|
.orEmpty()
|
||||||
|
//noinspection WrongGradleMethod
|
||||||
|
.filter { it.isDirectory && it.name.matches(Regex("values-[a-z]{2}(-r[A-Z]{2})?")) }
|
||||||
|
//noinspection WrongGradleMethod
|
||||||
|
.map { it.name.removePrefix("values-").replace("-r", "-") }
|
||||||
|
.sorted()
|
||||||
|
//noinspection WrongGradleMethod
|
||||||
|
.joinToString(prefix = "{", separator = ",", postfix = "}") { "\"$it\"" }
|
||||||
|
|
||||||
|
buildConfigField("String[]", "SUPPORTED_LOCALES", locales)
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
debug {
|
debug {
|
||||||
applicationIdSuffix = ".debug"
|
applicationIdSuffix = ".debug"
|
||||||
resValue("string", "app_name", "ReVanced Manager (Debug)")
|
resValue("string", "app_name", "ReVanced Manager (Debug)")
|
||||||
isPseudoLocalesEnabled = true
|
|
||||||
|
|
||||||
buildConfigField("long", "BUILD_ID", "${Random.nextLong()}L")
|
buildConfigField("long", "BUILD_ID", "${Random.nextLong()}L")
|
||||||
}
|
}
|
||||||
@@ -221,20 +238,14 @@ android {
|
|||||||
arg("room.schemaLocation", "$projectDir/schemas")
|
arg("room.schemaLocation", "$projectDir/schemas")
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlinOptions {
|
|
||||||
jvmTarget = "17"
|
|
||||||
}
|
|
||||||
|
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
compose = true
|
compose = true
|
||||||
aidl = true
|
aidl = true
|
||||||
buildConfig = true
|
buildConfig = true
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
androidResources {
|
||||||
androidResources {
|
generateLocaleConfig = true
|
||||||
generateLocaleConfig = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
@@ -247,6 +258,18 @@ android {
|
|||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
jvmToolchain(17)
|
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 {
|
tasks {
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
version = 1.26.0-dev.17
|
version = 1.26.0-dev.20
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ package app.revanced.manager
|
|||||||
import android.content.ActivityNotFoundException
|
import android.content.ActivityNotFoundException
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import androidx.activity.ComponentActivity
|
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.activity.enableEdgeToEdge
|
import androidx.activity.enableEdgeToEdge
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.compose.animation.ExperimentalAnimationApi
|
import androidx.compose.animation.ExperimentalAnimationApi
|
||||||
import androidx.compose.animation.slideInHorizontally
|
import androidx.compose.animation.slideInHorizontally
|
||||||
import androidx.compose.animation.slideOutHorizontally
|
import androidx.compose.animation.slideOutHorizontally
|
||||||
@@ -59,11 +59,10 @@ import app.revanced.manager.ui.viewmodel.SelectedAppInfoViewModel
|
|||||||
import app.revanced.manager.util.EventEffect
|
import app.revanced.manager.util.EventEffect
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
import org.koin.androidx.compose.navigation.koinNavViewModel
|
|
||||||
import org.koin.core.parameter.parametersOf
|
import org.koin.core.parameter.parametersOf
|
||||||
import org.koin.androidx.viewmodel.ext.android.getViewModel as getActivityViewModel
|
import org.koin.androidx.viewmodel.ext.android.getViewModel as getActivityViewModel
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
@ExperimentalAnimationApi
|
@ExperimentalAnimationApi
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@@ -185,7 +184,7 @@ private fun ReVancedManager(vm: MainViewModel) {
|
|||||||
val data =
|
val data =
|
||||||
parentBackStackEntry.getComplexArg<SelectedApplicationInfo.ViewModelParams>()
|
parentBackStackEntry.getComplexArg<SelectedApplicationInfo.ViewModelParams>()
|
||||||
val viewModel =
|
val viewModel =
|
||||||
koinNavViewModel<SelectedAppInfoViewModel>(viewModelStoreOwner = parentBackStackEntry) {
|
koinViewModel<SelectedAppInfoViewModel>(viewModelStoreOwner = parentBackStackEntry) {
|
||||||
parametersOf(data)
|
parametersOf(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,7 +225,7 @@ private fun ReVancedManager(vm: MainViewModel) {
|
|||||||
composable<SelectedApplicationInfo.PatchesSelector> {
|
composable<SelectedApplicationInfo.PatchesSelector> {
|
||||||
val data =
|
val data =
|
||||||
it.getComplexArg<SelectedApplicationInfo.PatchesSelector.ViewModelParams>()
|
it.getComplexArg<SelectedApplicationInfo.PatchesSelector.ViewModelParams>()
|
||||||
val selectedAppInfoVm = koinNavViewModel<SelectedAppInfoViewModel>(
|
val selectedAppInfoVm = koinViewModel<SelectedAppInfoViewModel>(
|
||||||
viewModelStoreOwner = navController.navGraphEntry(it)
|
viewModelStoreOwner = navController.navGraphEntry(it)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -243,7 +242,7 @@ private fun ReVancedManager(vm: MainViewModel) {
|
|||||||
composable<SelectedApplicationInfo.RequiredOptions> {
|
composable<SelectedApplicationInfo.RequiredOptions> {
|
||||||
val data =
|
val data =
|
||||||
it.getComplexArg<SelectedApplicationInfo.PatchesSelector.ViewModelParams>()
|
it.getComplexArg<SelectedApplicationInfo.PatchesSelector.ViewModelParams>()
|
||||||
val selectedAppInfoVm = koinNavViewModel<SelectedAppInfoViewModel>(
|
val selectedAppInfoVm = koinViewModel<SelectedAppInfoViewModel>(
|
||||||
viewModelStoreOwner = navController.navGraphEntry(it)
|
viewModelStoreOwner = navController.navGraphEntry(it)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package app.revanced.manager.di
|
package app.revanced.manager.di
|
||||||
|
|
||||||
import app.revanced.manager.ui.viewmodel.*
|
import app.revanced.manager.ui.viewmodel.*
|
||||||
import org.koin.androidx.viewmodel.dsl.viewModelOf
|
import org.koin.core.module.dsl.*
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
val viewModelModule = module {
|
val viewModelModule = module {
|
||||||
|
|||||||
@@ -16,8 +16,11 @@ import io.ktor.http.isSuccess
|
|||||||
import io.ktor.utils.io.ByteReadChannel
|
import io.ktor.utils.io.ByteReadChannel
|
||||||
import io.ktor.utils.io.core.isNotEmpty
|
import io.ktor.utils.io.core.isNotEmpty
|
||||||
import io.ktor.utils.io.core.readBytes
|
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.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import kotlinx.io.asSink
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
@@ -69,14 +72,12 @@ class HttpService(
|
|||||||
) {
|
) {
|
||||||
http.prepareGet(builder).execute { httpResponse ->
|
http.prepareGet(builder).execute { httpResponse ->
|
||||||
if (httpResponse.status.isSuccess()) {
|
if (httpResponse.status.isSuccess()) {
|
||||||
val channel: ByteReadChannel = httpResponse.body()
|
|
||||||
withContext(Dispatchers.IO) {
|
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())
|
val packet = channel.readRemaining(DEFAULT_BUFFER_SIZE.toLong())
|
||||||
while (packet.isNotEmpty) {
|
packet.transferTo(sink)
|
||||||
val bytes = packet.readBytes()
|
|
||||||
outputStream.write(bytes)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.graphics.ColorFilter
|
import androidx.compose.ui.graphics.ColorFilter
|
||||||
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import io.github.fornewid.placeholder.material3.placeholder
|
import com.eygraber.compose.placeholder.material3.placeholder
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AppIcon(
|
fun AppIcon(
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import androidx.compose.ui.platform.LocalContext
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import app.revanced.manager.R
|
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.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ fun LoadingIndicator(
|
|||||||
progress: () -> Float? = { null },
|
progress: () -> Float? = { null },
|
||||||
color: Color = ProgressIndicatorDefaults.circularColor,
|
color: Color = ProgressIndicatorDefaults.circularColor,
|
||||||
strokeWidth: Dp = ProgressIndicatorDefaults.CircularStrokeWidth,
|
strokeWidth: Dp = ProgressIndicatorDefaults.CircularStrokeWidth,
|
||||||
trackColor: Color = ProgressIndicatorDefaults.circularTrackColor,
|
trackColor: Color = ProgressIndicatorDefaults.circularIndeterminateTrackColor,
|
||||||
strokeCap: StrokeCap = ProgressIndicatorDefaults.CircularDeterminateStrokeCap
|
strokeCap: StrokeCap = ProgressIndicatorDefaults.CircularDeterminateStrokeCap
|
||||||
) {
|
) {
|
||||||
progress()?.let {
|
progress()?.let {
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ fun Markdown(
|
|||||||
colors = markdownColor(
|
colors = markdownColor(
|
||||||
text = MaterialTheme.colorScheme.onSurfaceVariant,
|
text = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
codeBackground = MaterialTheme.colorScheme.secondaryContainer,
|
codeBackground = MaterialTheme.colorScheme.secondaryContainer,
|
||||||
codeText = MaterialTheme.colorScheme.onSecondaryContainer,
|
|
||||||
linkText = MaterialTheme.colorScheme.primary
|
|
||||||
),
|
),
|
||||||
typography = markdownTypography(
|
typography = markdownTypography(
|
||||||
h1 = MaterialTheme.typography.headlineSmall.copy(fontWeight = FontWeight.Bold),
|
h1 = MaterialTheme.typography.headlineSmall.copy(fontWeight = FontWeight.Bold),
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ fun SearchBar(
|
|||||||
) {
|
) {
|
||||||
val colors = SearchBarColors(
|
val colors = SearchBarColors(
|
||||||
containerColor = MaterialTheme.colorScheme.surfaceContainerHigh,
|
containerColor = MaterialTheme.colorScheme.surfaceContainerHigh,
|
||||||
dividerColor = MaterialTheme.colorScheme.outline
|
dividerColor = MaterialTheme.colorScheme.outline,
|
||||||
|
inputFieldColors = SearchBarDefaults.inputFieldColors()
|
||||||
)
|
)
|
||||||
val keyboardController = LocalSoftwareKeyboardController.current
|
val keyboardController = LocalSoftwareKeyboardController.current
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ fun SearchView(
|
|||||||
) {
|
) {
|
||||||
val colors = SearchBarColors(
|
val colors = SearchBarColors(
|
||||||
containerColor = MaterialTheme.colorScheme.surfaceContainerHigh,
|
containerColor = MaterialTheme.colorScheme.surfaceContainerHigh,
|
||||||
dividerColor = MaterialTheme.colorScheme.outline
|
dividerColor = MaterialTheme.colorScheme.outline,
|
||||||
|
inputFieldColors = SearchBarDefaults.inputFieldColors()
|
||||||
)
|
)
|
||||||
val focusRequester = remember { FocusRequester() }
|
val focusRequester = remember { FocusRequester() }
|
||||||
val keyboardController = LocalSoftwareKeyboardController.current
|
val keyboardController = LocalSoftwareKeyboardController.current
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import app.revanced.manager.R
|
|||||||
import app.revanced.manager.patcher.StepId
|
import app.revanced.manager.patcher.StepId
|
||||||
import kotlinx.parcelize.Parcelize
|
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),
|
PREPARING(R.string.patcher_step_group_preparing),
|
||||||
PATCHING(R.string.patcher_step_group_patching),
|
PATCHING(R.string.patcher_step_group_patching),
|
||||||
SAVING(R.string.patcher_step_group_saving)
|
SAVING(R.string.patcher_step_group_saving)
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import androidx.compose.material3.Icon
|
|||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.TabRow
|
import androidx.compose.material3.SecondaryTabRow
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.surfaceColorAtElevation
|
import androidx.compose.material3.surfaceColorAtElevation
|
||||||
@@ -53,6 +53,7 @@ import androidx.compose.runtime.setValue
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalResources
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
@@ -100,6 +101,7 @@ fun DashboardScreen(
|
|||||||
false
|
false
|
||||||
)
|
)
|
||||||
val androidContext = LocalContext.current
|
val androidContext = LocalContext.current
|
||||||
|
val resources = LocalResources.current
|
||||||
val composableScope = rememberCoroutineScope()
|
val composableScope = rememberCoroutineScope()
|
||||||
val pagerState = rememberPagerState(
|
val pagerState = rememberPagerState(
|
||||||
initialPage = DashboardPage.DASHBOARD.ordinal,
|
initialPage = DashboardPage.DASHBOARD.ordinal,
|
||||||
@@ -234,7 +236,7 @@ fun DashboardScreen(
|
|||||||
when (pagerState.currentPage) {
|
when (pagerState.currentPage) {
|
||||||
DashboardPage.DASHBOARD.ordinal -> {
|
DashboardPage.DASHBOARD.ordinal -> {
|
||||||
if (availablePatches < 1) {
|
if (availablePatches < 1) {
|
||||||
androidContext.toast(androidContext.getString(R.string.no_patch_found))
|
androidContext.toast(resources.getString(R.string.no_patch_found))
|
||||||
composableScope.launch {
|
composableScope.launch {
|
||||||
pagerState.animateScrollToPage(
|
pagerState.animateScrollToPage(
|
||||||
DashboardPage.BUNDLES.ordinal
|
DashboardPage.BUNDLES.ordinal
|
||||||
@@ -259,7 +261,7 @@ fun DashboardScreen(
|
|||||||
}
|
}
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
Column(Modifier.padding(paddingValues)) {
|
Column(Modifier.padding(paddingValues)) {
|
||||||
TabRow(
|
SecondaryTabRow(
|
||||||
selectedTabIndex = pagerState.currentPage,
|
selectedTabIndex = pagerState.currentPage,
|
||||||
containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(3.0.dp)
|
containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(3.0.dp)
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalResources
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import app.revanced.manager.R
|
import app.revanced.manager.R
|
||||||
@@ -69,6 +70,7 @@ fun PatcherScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
val resources = LocalResources.current
|
||||||
val exportApkLauncher =
|
val exportApkLauncher =
|
||||||
rememberLauncherForActivityResult(CreateDocument(APK_MIMETYPE), viewModel::export)
|
rememberLauncherForActivityResult(CreateDocument(APK_MIMETYPE), viewModel::export)
|
||||||
|
|
||||||
@@ -79,7 +81,7 @@ fun PatcherScreen(
|
|||||||
|
|
||||||
fun onPageBack() = when {
|
fun onPageBack() = when {
|
||||||
patcherSucceeded == null -> showDismissConfirmationDialog = true
|
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()
|
else -> onLeave()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ import androidx.compose.material3.ListItem
|
|||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.ModalBottomSheet
|
import androidx.compose.material3.ModalBottomSheet
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.ScrollableTabRow
|
import androidx.compose.material3.SecondaryScrollableTabRow
|
||||||
import androidx.compose.material3.SmallFloatingActionButton
|
import androidx.compose.material3.SmallFloatingActionButton
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
@@ -49,10 +49,12 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.produceState
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.runtime.snapshotFlow
|
||||||
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
|
||||||
@@ -81,9 +83,11 @@ import app.revanced.manager.util.Options
|
|||||||
import app.revanced.manager.util.PatchSelection
|
import app.revanced.manager.util.PatchSelection
|
||||||
import app.revanced.manager.util.isScrollingUp
|
import app.revanced.manager.util.isScrollingUp
|
||||||
import app.revanced.manager.util.transparentListItemColors
|
import app.revanced.manager.util.transparentListItemColors
|
||||||
|
import kotlinx.coroutines.FlowPreview
|
||||||
|
import kotlinx.coroutines.flow.sample
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class, FlowPreview::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun PatchesSelectorScreen(
|
fun PatchesSelectorScreen(
|
||||||
onSave: (PatchSelection?, Options) -> Unit,
|
onSave: (PatchSelection?, Options) -> Unit,
|
||||||
@@ -231,7 +235,8 @@ fun PatchesSelectorScreen(
|
|||||||
viewModel.selectionWarningEnabled -> showSelectionWarning = true
|
viewModel.selectionWarningEnabled -> showSelectionWarning = true
|
||||||
|
|
||||||
// Show universal warning if universal patch is selected and the toggle is off
|
// Show universal warning if universal patch is selected and the toggle is off
|
||||||
patch.compatiblePackages == null && viewModel.universalPatchWarningEnabled -> showUniversalWarning = true
|
patch.compatiblePackages == null && viewModel.universalPatchWarningEnabled -> showUniversalWarning =
|
||||||
|
true
|
||||||
|
|
||||||
// Toggle the patch otherwise
|
// Toggle the patch otherwise
|
||||||
else -> viewModel.togglePatch(uid, patch)
|
else -> viewModel.togglePatch(uid, patch)
|
||||||
@@ -360,6 +365,21 @@ fun PatchesSelectorScreen(
|
|||||||
) {
|
) {
|
||||||
Icon(Icons.Outlined.Restore, stringResource(R.string.reset))
|
Icon(Icons.Outlined.Restore, stringResource(R.string.reset))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val isScrollingUp =
|
||||||
|
patchLazyListStates.getOrNull(pagerState.currentPage)?.isScrollingUp()
|
||||||
|
val expanded by produceState(true, isScrollingUp) {
|
||||||
|
val state = isScrollingUp ?: return@produceState
|
||||||
|
value = state.value
|
||||||
|
|
||||||
|
// Use snapshotFlow and sample to prevent the value from changing too often.
|
||||||
|
snapshotFlow { state.value }
|
||||||
|
.sample(333L)
|
||||||
|
.collect {
|
||||||
|
value = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HapticExtendedFloatingActionButton(
|
HapticExtendedFloatingActionButton(
|
||||||
text = {
|
text = {
|
||||||
Text(
|
Text(
|
||||||
@@ -375,8 +395,7 @@ fun PatchesSelectorScreen(
|
|||||||
contentDescription = stringResource(R.string.save)
|
contentDescription = stringResource(R.string.save)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
expanded = patchLazyListStates.getOrNull(pagerState.currentPage)?.isScrollingUp
|
expanded = expanded,
|
||||||
?: true,
|
|
||||||
onClick = {
|
onClick = {
|
||||||
onSave(viewModel.getCustomSelection(), viewModel.getOptions())
|
onSave(viewModel.getCustomSelection(), viewModel.getOptions())
|
||||||
}
|
}
|
||||||
@@ -392,7 +411,7 @@ fun PatchesSelectorScreen(
|
|||||||
.padding(top = 16.dp)
|
.padding(top = 16.dp)
|
||||||
) {
|
) {
|
||||||
if (bundles.size > 1) {
|
if (bundles.size > 1) {
|
||||||
ScrollableTabRow(
|
SecondaryScrollableTabRow(
|
||||||
selectedTabIndex = pagerState.currentPage,
|
selectedTabIndex = pagerState.currentPage,
|
||||||
containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(3.0.dp)
|
containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(3.0.dp)
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
|||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.ScrollableTabRow
|
import androidx.compose.material3.SecondaryScrollableTabRow
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.material3.rememberTopAppBarState
|
import androidx.compose.material3.rememberTopAppBarState
|
||||||
@@ -106,7 +106,7 @@ fun RequiredOptionsScreen(
|
|||||||
.padding(paddingValues)
|
.padding(paddingValues)
|
||||||
) {
|
) {
|
||||||
if (list.isEmpty()) return@Column
|
if (list.isEmpty()) return@Column
|
||||||
else if (list.size > 1) ScrollableTabRow(
|
else if (list.size > 1) SecondaryScrollableTabRow(
|
||||||
selectedTabIndex = pagerState.currentPage,
|
selectedTabIndex = pagerState.currentPage,
|
||||||
containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(3.0.dp)
|
containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(3.0.dp)
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import androidx.compose.runtime.rememberCoroutineScope
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalResources
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
@@ -68,6 +69,7 @@ fun SelectedAppInfoScreen(
|
|||||||
vm: SelectedAppInfoViewModel
|
vm: SelectedAppInfoViewModel
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
val resources = LocalResources.current
|
||||||
val networkInfo = koinInject<NetworkInfo>()
|
val networkInfo = koinInject<NetworkInfo>()
|
||||||
val networkConnected = remember { networkInfo.isConnected() }
|
val networkConnected = remember { networkInfo.isConnected() }
|
||||||
val networkMetered = remember { !networkInfo.isUnmetered() }
|
val networkMetered = remember { !networkInfo.isUnmetered() }
|
||||||
@@ -118,7 +120,7 @@ fun SelectedAppInfoScreen(
|
|||||||
},
|
},
|
||||||
onClick = patchClick@{
|
onClick = patchClick@{
|
||||||
if (selectedPatchCount == 0) {
|
if (selectedPatchCount == 0) {
|
||||||
context.toast(context.getString(R.string.no_patches_selected))
|
context.toast(resources.getString(R.string.no_patches_selected))
|
||||||
|
|
||||||
return@patchClick
|
return@patchClick
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ import app.revanced.manager.ui.model.navigation.Settings
|
|||||||
import org.koin.compose.koinInject
|
import org.koin.compose.koinInject
|
||||||
|
|
||||||
private data class Section(
|
private data class Section(
|
||||||
@StringRes val name: Int,
|
@param:StringRes val name: Int,
|
||||||
@StringRes val description: Int,
|
@param:StringRes val description: Int,
|
||||||
val image: ImageVector,
|
val image: ImageVector,
|
||||||
val destination: Settings.Destination,
|
val destination: Settings.Destination,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package app.revanced.manager.ui.screen.settings
|
package app.revanced.manager.ui.screen.settings
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import androidx.appcompat.content.res.AppCompatResources
|
import androidx.appcompat.content.res.AppCompatResources
|
||||||
import androidx.compose.foundation.BorderStroke
|
import androidx.compose.foundation.BorderStroke
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
@@ -40,6 +41,7 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalResources
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.semantics.hideFromAccessibility
|
import androidx.compose.ui.semantics.hideFromAccessibility
|
||||||
import androidx.compose.ui.semantics.semantics
|
import androidx.compose.ui.semantics.semantics
|
||||||
@@ -67,8 +69,9 @@ fun AboutSettingsScreen(
|
|||||||
viewModel: AboutViewModel = koinViewModel()
|
viewModel: AboutViewModel = koinViewModel()
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
val resources = LocalResources.current
|
||||||
// painterResource() is broken on release builds for some reason.
|
// 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)
|
AppCompatResources.getDrawable(context, R.drawable.ic_logo_ring)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -76,7 +79,7 @@ fun AboutSettingsScreen(
|
|||||||
viewModel.socials.partition(ReVancedSocial::preferred)
|
viewModel.socials.partition(ReVancedSocial::preferred)
|
||||||
}
|
}
|
||||||
|
|
||||||
val preferredSocialButtons = remember(preferredSocials, viewModel.donate, viewModel.contact) {
|
val preferredSocialButtons = remember(resources, preferredSocials, viewModel.donate, viewModel.contact) {
|
||||||
preferredSocials.map {
|
preferredSocials.map {
|
||||||
Triple(
|
Triple(
|
||||||
getSocialIcon(it.name),
|
getSocialIcon(it.name),
|
||||||
@@ -89,7 +92,7 @@ fun AboutSettingsScreen(
|
|||||||
viewModel.donate?.let {
|
viewModel.donate?.let {
|
||||||
Triple(
|
Triple(
|
||||||
Icons.Outlined.FavoriteBorder,
|
Icons.Outlined.FavoriteBorder,
|
||||||
context.getString(R.string.donate),
|
resources.getString(R.string.donate),
|
||||||
third = {
|
third = {
|
||||||
context.openUrl(it)
|
context.openUrl(it)
|
||||||
}
|
}
|
||||||
@@ -98,7 +101,7 @@ fun AboutSettingsScreen(
|
|||||||
viewModel.contact?.let {
|
viewModel.contact?.let {
|
||||||
Triple(
|
Triple(
|
||||||
Icons.Outlined.MailOutline,
|
Icons.Outlined.MailOutline,
|
||||||
context.getString(R.string.contact),
|
resources.getString(R.string.contact),
|
||||||
third = {
|
third = {
|
||||||
context.openUrl("mailto:$it")
|
context.openUrl("mailto:$it")
|
||||||
}
|
}
|
||||||
@@ -131,7 +134,7 @@ fun AboutSettingsScreen(
|
|||||||
stringResource(R.string.contributors_description),
|
stringResource(R.string.contributors_description),
|
||||||
third = nav@{
|
third = nav@{
|
||||||
if (!viewModel.isConnected) {
|
if (!viewModel.isConnected) {
|
||||||
context.toast(context.getString(R.string.no_network_toast))
|
context.toast(resources.getString(R.string.no_network_toast))
|
||||||
return@nav
|
return@nav
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +156,7 @@ fun AboutSettingsScreen(
|
|||||||
LaunchedEffect(developerTaps) {
|
LaunchedEffect(developerTaps) {
|
||||||
if (developerTaps == 0) return@LaunchedEffect
|
if (developerTaps == 0) return@LaunchedEffect
|
||||||
if (showDeveloperSettings) {
|
if (showDeveloperSettings) {
|
||||||
snackbarHostState.showSnackbar(context.getString(R.string.developer_options_already_enabled))
|
snackbarHostState.showSnackbar(resources.getString(R.string.developer_options_already_enabled))
|
||||||
developerTaps = 0
|
developerTaps = 0
|
||||||
return@LaunchedEffect
|
return@LaunchedEffect
|
||||||
}
|
}
|
||||||
@@ -161,7 +164,7 @@ fun AboutSettingsScreen(
|
|||||||
val remaining = DEVELOPER_OPTIONS_TAPS - developerTaps
|
val remaining = DEVELOPER_OPTIONS_TAPS - developerTaps
|
||||||
if (remaining > 0) {
|
if (remaining > 0) {
|
||||||
snackbarHostState.showSnackbar(
|
snackbarHostState.showSnackbar(
|
||||||
context.getString(
|
resources.getString(
|
||||||
R.string.developer_options_taps,
|
R.string.developer_options_taps,
|
||||||
remaining
|
remaining
|
||||||
),
|
),
|
||||||
@@ -169,7 +172,7 @@ fun AboutSettingsScreen(
|
|||||||
)
|
)
|
||||||
} else if (remaining == 0) {
|
} else if (remaining == 0) {
|
||||||
viewModel.showDeveloperSettings.update(true)
|
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
|
// Reset the counter
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import androidx.compose.runtime.setValue
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalResources
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@@ -64,9 +65,10 @@ fun AdvancedSettingsScreen(
|
|||||||
viewModel: AdvancedSettingsViewModel = koinViewModel()
|
viewModel: AdvancedSettingsViewModel = koinViewModel()
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val memoryLimit = remember {
|
val resources = LocalResources.current
|
||||||
|
val memoryLimit = remember(resources) {
|
||||||
val activityManager = context.getSystemService<ActivityManager>()!!
|
val activityManager = context.getSystemService<ActivityManager>()!!
|
||||||
context.getString(
|
resources.getString(
|
||||||
R.string.device_memory_limit_format,
|
R.string.device_memory_limit_format,
|
||||||
activityManager.memoryClass,
|
activityManager.memoryClass,
|
||||||
activityManager.largeMemoryClass
|
activityManager.largeMemoryClass
|
||||||
@@ -183,7 +185,7 @@ fun AdvancedSettingsScreen(
|
|||||||
ClipData.newPlainText("Device Information", deviceContent)
|
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)
|
}.withHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
|
||||||
),
|
),
|
||||||
headlineContent = stringResource(R.string.about_device),
|
headlineContent = stringResource(R.string.about_device),
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import androidx.compose.foundation.layout.Row
|
|||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.FilledTonalButton
|
import androidx.compose.material3.FilledTonalButton
|
||||||
@@ -19,6 +21,7 @@ import androidx.compose.material3.rememberTopAppBarState
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
@@ -38,6 +41,7 @@ import app.revanced.manager.ui.theme.Theme
|
|||||||
import app.revanced.manager.ui.viewmodel.GeneralSettingsViewModel
|
import app.revanced.manager.ui.viewmodel.GeneralSettingsViewModel
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
import org.koin.compose.koinInject
|
import org.koin.compose.koinInject
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -48,6 +52,7 @@ fun GeneralSettingsScreen(
|
|||||||
val prefs = viewModel.prefs
|
val prefs = viewModel.prefs
|
||||||
val coroutineScope = viewModel.viewModelScope
|
val coroutineScope = viewModel.viewModelScope
|
||||||
var showThemePicker by rememberSaveable { mutableStateOf(false) }
|
var showThemePicker by rememberSaveable { mutableStateOf(false) }
|
||||||
|
var showLanguagePicker by rememberSaveable { mutableStateOf(false) }
|
||||||
|
|
||||||
if (showThemePicker) {
|
if (showThemePicker) {
|
||||||
ThemePicker(
|
ThemePicker(
|
||||||
@@ -55,6 +60,17 @@ fun GeneralSettingsScreen(
|
|||||||
onConfirm = { viewModel.setTheme(it) }
|
onConfirm = { viewModel.setTheme(it) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (showLanguagePicker) {
|
||||||
|
LanguagePicker(
|
||||||
|
supportedLocales = viewModel.getSupportedLocales(),
|
||||||
|
currentLocale = viewModel.getCurrentLocale(),
|
||||||
|
onDismiss = { showLanguagePicker = false },
|
||||||
|
onConfirm = { viewModel.setLocale(it) },
|
||||||
|
getDisplayName = { viewModel.getLocaleDisplayName(it) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
|
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
@@ -74,6 +90,24 @@ fun GeneralSettingsScreen(
|
|||||||
) {
|
) {
|
||||||
GroupHeader(stringResource(R.string.appearance))
|
GroupHeader(stringResource(R.string.appearance))
|
||||||
|
|
||||||
|
val currentLocale = viewModel.getCurrentLocale()
|
||||||
|
val currentLanguageDisplay = remember(currentLocale) {
|
||||||
|
currentLocale?.let { viewModel.getLocaleDisplayName(it) }
|
||||||
|
}
|
||||||
|
SettingsListItem(
|
||||||
|
modifier = Modifier.clickable { showLanguagePicker = true },
|
||||||
|
headlineContent = stringResource(R.string.language),
|
||||||
|
supportingContent = stringResource(R.string.language_description),
|
||||||
|
trailingContent = {
|
||||||
|
FilledTonalButton(onClick = { showLanguagePicker = true }) {
|
||||||
|
Text(
|
||||||
|
currentLanguageDisplay
|
||||||
|
?: stringResource(R.string.language_system_default)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
val theme by prefs.theme.getAsState()
|
val theme by prefs.theme.getAsState()
|
||||||
SettingsListItem(
|
SettingsListItem(
|
||||||
modifier = Modifier.clickable { showThemePicker = true },
|
modifier = Modifier.clickable { showThemePicker = true },
|
||||||
@@ -156,4 +190,64 @@ private fun ThemePicker(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun LanguagePicker(
|
||||||
|
supportedLocales: List<Locale>,
|
||||||
|
currentLocale: Locale?,
|
||||||
|
onDismiss: () -> Unit,
|
||||||
|
onConfirm: (Locale?) -> Unit,
|
||||||
|
getDisplayName: (Locale) -> String
|
||||||
|
) {
|
||||||
|
var selectedLocale by remember { mutableStateOf(currentLocale) }
|
||||||
|
val systemDefaultString = stringResource(R.string.language_system_default)
|
||||||
|
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = onDismiss,
|
||||||
|
title = { Text(stringResource(R.string.language)) },
|
||||||
|
text = {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.verticalScroll(rememberScrollState())
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable { selectedLocale = null },
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
HapticRadioButton(
|
||||||
|
selected = selectedLocale == null,
|
||||||
|
onClick = { selectedLocale = null }
|
||||||
|
)
|
||||||
|
Text(systemDefaultString)
|
||||||
|
}
|
||||||
|
|
||||||
|
supportedLocales.forEach { locale ->
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable { selectedLocale = locale },
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
HapticRadioButton(
|
||||||
|
selected = selectedLocale == locale,
|
||||||
|
onClick = { selectedLocale = locale }
|
||||||
|
)
|
||||||
|
Text(getDisplayName(locale))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(
|
||||||
|
onClick = {
|
||||||
|
onConfirm(selectedLocale)
|
||||||
|
onDismiss()
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text(stringResource(R.string.apply))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
@@ -36,6 +36,7 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalResources
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@@ -64,6 +65,7 @@ fun ImportExportSettingsScreen(
|
|||||||
vm: ImportExportViewModel = koinViewModel()
|
vm: ImportExportViewModel = koinViewModel()
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
val resources = LocalResources.current
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
var selectorDialog by rememberSaveable { mutableStateOf<(@Composable () -> Unit)?>(null) }
|
var selectorDialog by rememberSaveable { mutableStateOf<(@Composable () -> Unit)?>(null) }
|
||||||
|
|
||||||
@@ -108,7 +110,7 @@ fun ImportExportSettingsScreen(
|
|||||||
vm.viewModelScope.launch {
|
vm.viewModelScope.launch {
|
||||||
uiSafe(context, R.string.failed_to_import_keystore, "Failed to import keystore") {
|
uiSafe(context, R.string.failed_to_import_keystore, "Failed to import keystore") {
|
||||||
val result = vm.tryKeystoreImport(alias, pass)
|
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(
|
GroupItem(
|
||||||
onClick = {
|
onClick = {
|
||||||
if (!vm.canExport()) {
|
if (!vm.canExport()) {
|
||||||
context.toast(context.getString(R.string.export_keystore_unavailable))
|
context.toast(resources.getString(R.string.export_keystore_unavailable))
|
||||||
return@GroupItem
|
return@GroupItem
|
||||||
}
|
}
|
||||||
exportKeystoreLauncher.launch("Manager.keystore")
|
exportKeystoreLauncher.launch("Manager.keystore")
|
||||||
|
|||||||
@@ -7,15 +7,18 @@ import androidx.compose.foundation.lazy.rememberLazyListState
|
|||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import app.revanced.manager.R
|
import app.revanced.manager.R
|
||||||
import app.revanced.manager.ui.component.AppScaffold
|
import app.revanced.manager.ui.component.AppScaffold
|
||||||
import app.revanced.manager.ui.component.AppTopBar
|
import app.revanced.manager.ui.component.AppTopBar
|
||||||
import app.revanced.manager.ui.component.Scrollbar
|
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.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)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -33,16 +36,23 @@ fun LicensesSettingsScreen(
|
|||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
Column(modifier = Modifier.padding(paddingValues)) {
|
Column(modifier = Modifier.padding(paddingValues)) {
|
||||||
val lazyListState = rememberLazyListState()
|
val lazyListState = rememberLazyListState()
|
||||||
|
val libraries by produceLibraries(R.raw.aboutlibraries)
|
||||||
|
val chipColors = LibraryDefaults.chipColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.primary,
|
||||||
|
contentColor = MaterialTheme.colorScheme.onPrimary,
|
||||||
|
)
|
||||||
|
|
||||||
LibrariesContainer(
|
LibrariesContainer(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize(),
|
.fillMaxSize(),
|
||||||
|
libraries = libraries,
|
||||||
lazyListState = lazyListState,
|
lazyListState = lazyListState,
|
||||||
colors = LibraryDefaults.libraryColors(
|
colors = LibraryDefaults.libraryColors(
|
||||||
backgroundColor = MaterialTheme.colorScheme.background,
|
libraryBackgroundColor = MaterialTheme.colorScheme.background,
|
||||||
contentColor = MaterialTheme.colorScheme.onBackground,
|
libraryContentColor = MaterialTheme.colorScheme.onBackground,
|
||||||
badgeBackgroundColor = MaterialTheme.colorScheme.primary,
|
versionChipColors = chipColors,
|
||||||
badgeContentColor = MaterialTheme.colorScheme.onPrimary,
|
licenseChipColors = chipColors,
|
||||||
|
fundingChipColors = chipColors,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
Scrollbar(lazyListState = lazyListState, modifier = Modifier.padding(paddingValues))
|
Scrollbar(lazyListState = lazyListState, modifier = Modifier.padding(paddingValues))
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import androidx.compose.runtime.rememberCoroutineScope
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalResources
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import app.revanced.manager.R
|
import app.revanced.manager.R
|
||||||
import app.revanced.manager.ui.component.AppTopBar
|
import app.revanced.manager.ui.component.AppTopBar
|
||||||
@@ -33,6 +34,7 @@ fun UpdatesSettingsScreen(
|
|||||||
vm: UpdatesSettingsViewModel = koinViewModel(),
|
vm: UpdatesSettingsViewModel = koinViewModel(),
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
val resources = LocalResources.current
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
|
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
|
||||||
|
|
||||||
@@ -57,7 +59,7 @@ fun UpdatesSettingsScreen(
|
|||||||
modifier = Modifier.clickable {
|
modifier = Modifier.clickable {
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
if (!vm.isConnected) {
|
if (!vm.isConnected) {
|
||||||
context.toast(context.getString(R.string.no_network_toast))
|
context.toast(resources.getString(R.string.no_network_toast))
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
if (vm.checkForUpdates()) onUpdateClick()
|
if (vm.checkForUpdates()) onUpdateClick()
|
||||||
@@ -70,7 +72,7 @@ fun UpdatesSettingsScreen(
|
|||||||
SettingsListItem(
|
SettingsListItem(
|
||||||
modifier = Modifier.clickable {
|
modifier = Modifier.clickable {
|
||||||
if (!vm.isConnected) {
|
if (!vm.isConnected) {
|
||||||
context.toast(context.getString(R.string.no_network_toast))
|
context.toast(resources.getString(R.string.no_network_toast))
|
||||||
return@clickable
|
return@clickable
|
||||||
}
|
}
|
||||||
onChangelogClick()
|
onChangelogClick()
|
||||||
|
|||||||
@@ -1,17 +1,26 @@
|
|||||||
package app.revanced.manager.ui.viewmodel
|
package app.revanced.manager.ui.viewmodel
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import app.revanced.manager.domain.manager.PreferencesManager
|
import app.revanced.manager.domain.manager.PreferencesManager
|
||||||
import app.revanced.manager.ui.theme.Theme
|
import app.revanced.manager.ui.theme.Theme
|
||||||
|
import app.revanced.manager.util.SupportedLocales
|
||||||
import app.revanced.manager.util.resetListItemColorsCached
|
import app.revanced.manager.util.resetListItemColorsCached
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
class GeneralSettingsViewModel(
|
class GeneralSettingsViewModel(
|
||||||
|
private val app: Application,
|
||||||
val prefs: PreferencesManager
|
val prefs: PreferencesManager
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
fun setTheme(theme: Theme) = viewModelScope.launch {
|
fun setTheme(theme: Theme) = viewModelScope.launch {
|
||||||
prefs.theme.update(theme)
|
prefs.theme.update(theme)
|
||||||
resetListItemColorsCached()
|
resetListItemColorsCached()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getSupportedLocales() = SupportedLocales.getSupportedLocales(app)
|
||||||
|
fun getCurrentLocale() = SupportedLocales.getCurrentLocale()
|
||||||
|
fun setLocale(locale: Locale?) = SupportedLocales.setLocale(locale)
|
||||||
|
fun getLocaleDisplayName(locale: Locale) = SupportedLocales.getDisplayName(locale)
|
||||||
}
|
}
|
||||||
@@ -36,8 +36,8 @@ import kotlin.io.path.deleteExisting
|
|||||||
import kotlin.io.path.inputStream
|
import kotlin.io.path.inputStream
|
||||||
|
|
||||||
sealed class ResetDialogState(
|
sealed class ResetDialogState(
|
||||||
@StringRes val titleResId: Int,
|
@param:StringRes val titleResId: Int,
|
||||||
@StringRes val descriptionResId: Int,
|
@param:StringRes val descriptionResId: Int,
|
||||||
val onConfirm: () -> Unit,
|
val onConfirm: () -> Unit,
|
||||||
val dialogOptionName: String? = null
|
val dialogOptionName: String? = null
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -90,8 +90,10 @@ class UpdateViewModel(
|
|||||||
http.download(location) {
|
http.download(location) {
|
||||||
url(release.downloadUrl)
|
url(release.downloadUrl)
|
||||||
onDownload { bytesSentTotal, contentLength ->
|
onDownload { bytesSentTotal, contentLength ->
|
||||||
downloadedSize = bytesSentTotal
|
withContext(Dispatchers.Main) {
|
||||||
totalSize = contentLength
|
downloadedSize = bytesSentTotal
|
||||||
|
contentLength?.let { totalSize = it }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
installUpdate()
|
installUpdate()
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package app.revanced.manager.util
|
||||||
|
|
||||||
|
import android.app.LocaleConfig
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.LocaleList
|
||||||
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
|
import androidx.core.os.LocaleListCompat
|
||||||
|
import app.revanced.manager.BuildConfig
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
object SupportedLocales {
|
||||||
|
fun getSupportedLocales(context: Context): List<Locale> {
|
||||||
|
var result: List<Locale>? = null
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) result = runCatching {
|
||||||
|
LocaleConfig(context).supportedLocales?.toList()
|
||||||
|
}.getOrNull()
|
||||||
|
|
||||||
|
return result ?: generated
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getCurrentLocale(): Locale? =
|
||||||
|
AppCompatDelegate.getApplicationLocales().takeIf { !it.isEmpty }?.get(0)
|
||||||
|
|
||||||
|
fun setLocale(locale: Locale?) = AppCompatDelegate.setApplicationLocales(
|
||||||
|
locale?.let { LocaleListCompat.create(it) } ?: LocaleListCompat.getEmptyLocaleList()
|
||||||
|
)
|
||||||
|
|
||||||
|
fun getDisplayName(locale: Locale) =
|
||||||
|
locale.getDisplayName(locale).replaceFirstChar { it.uppercase(locale) }
|
||||||
|
|
||||||
|
private fun LocaleList.toList() = (0 until size()).map { get(it) }
|
||||||
|
|
||||||
|
private val generated by lazy {
|
||||||
|
listOf(
|
||||||
|
Locale.ENGLISH,
|
||||||
|
*BuildConfig.SUPPORTED_LOCALES.map(Locale::forLanguageTag).toTypedArray()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,12 +15,10 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.ReadOnlyComposable
|
import androidx.compose.runtime.ReadOnlyComposable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.State
|
import androidx.compose.runtime.State
|
||||||
import androidx.compose.runtime.derivedStateOf
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
import androidx.compose.runtime.produceState
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.rememberUpdatedState
|
import androidx.compose.runtime.rememberUpdatedState
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.snapshotFlow
|
||||||
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.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
@@ -43,7 +41,6 @@ import kotlinx.coroutines.flow.Flow
|
|||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.flatMapLatest
|
import kotlinx.coroutines.flow.flatMapLatest
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.datetime.Clock
|
|
||||||
import kotlinx.datetime.LocalDateTime
|
import kotlinx.datetime.LocalDateTime
|
||||||
import kotlinx.datetime.TimeZone
|
import kotlinx.datetime.TimeZone
|
||||||
import kotlinx.datetime.format.MonthNames
|
import kotlinx.datetime.format.MonthNames
|
||||||
@@ -51,9 +48,11 @@ import kotlinx.datetime.format.char
|
|||||||
import kotlinx.datetime.toInstant
|
import kotlinx.datetime.toInstant
|
||||||
import kotlinx.datetime.toLocalDateTime
|
import kotlinx.datetime.toLocalDateTime
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
import kotlin.math.abs
|
||||||
import kotlin.properties.PropertyDelegateProvider
|
import kotlin.properties.PropertyDelegateProvider
|
||||||
import kotlin.properties.ReadWriteProperty
|
import kotlin.properties.ReadWriteProperty
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
import kotlin.time.Clock
|
||||||
|
|
||||||
typealias PatchSelection = Map<Int, Set<String>>
|
typealias PatchSelection = Map<Int, Set<String>>
|
||||||
typealias Options = Map<Int, Map<String, Map<String, Any?>>>
|
typealias Options = Map<Int, Map<String, Map<String, Any?>>>
|
||||||
@@ -169,7 +168,7 @@ fun LocalDateTime.relativeTime(context: Context): String {
|
|||||||
else -> LocalDateTime.Format {
|
else -> LocalDateTime.Format {
|
||||||
monthName(MonthNames.ENGLISH_ABBREVIATED)
|
monthName(MonthNames.ENGLISH_ABBREVIATED)
|
||||||
char(' ')
|
char(' ')
|
||||||
dayOfMonth()
|
day()
|
||||||
if (now.toLocalDateTime(TimeZone.UTC).year != this@relativeTime.year) {
|
if (now.toLocalDateTime(TimeZone.UTC).year != this@relativeTime.year) {
|
||||||
chars(", ")
|
chars(", ")
|
||||||
year()
|
year()
|
||||||
@@ -196,7 +195,12 @@ val transparentListItemColors
|
|||||||
.also { transparentListItemColorsCached = it }
|
.also { transparentListItemColorsCached = it }
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun <T> EventEffect(flow: Flow<T>, vararg keys: Any?, state: Lifecycle.State = Lifecycle.State.STARTED, block: suspend (T) -> Unit) {
|
fun <T> EventEffect(
|
||||||
|
flow: Flow<T>,
|
||||||
|
vararg keys: Any?,
|
||||||
|
state: Lifecycle.State = Lifecycle.State.STARTED,
|
||||||
|
block: suspend (T) -> Unit
|
||||||
|
) {
|
||||||
val lifecycleOwner = LocalLifecycleOwner.current
|
val lifecycleOwner = LocalLifecycleOwner.current
|
||||||
val currentBlock by rememberUpdatedState(block)
|
val currentBlock by rememberUpdatedState(block)
|
||||||
|
|
||||||
@@ -212,40 +216,36 @@ fun <T> EventEffect(flow: Flow<T>, vararg keys: Any?, state: Lifecycle.State = L
|
|||||||
const val isScrollingUpSensitivity = 10
|
const val isScrollingUpSensitivity = 10
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LazyListState.isScrollingUp(): State<Boolean> {
|
fun LazyListState.isScrollingUp() = produceState(true, this) {
|
||||||
return remember(this) {
|
var previousIndex = firstVisibleItemIndex
|
||||||
var previousIndex by mutableIntStateOf(firstVisibleItemIndex)
|
var previousScrollOffset = firstVisibleItemScrollOffset
|
||||||
var previousScrollOffset by mutableIntStateOf(firstVisibleItemScrollOffset)
|
|
||||||
|
|
||||||
derivedStateOf {
|
snapshotFlow {
|
||||||
val indexChanged = previousIndex != firstVisibleItemIndex
|
firstVisibleItemIndex to firstVisibleItemScrollOffset
|
||||||
val offsetChanged =
|
}.collect { (index, scrollOffset) ->
|
||||||
kotlin.math.abs(previousScrollOffset - firstVisibleItemScrollOffset) > isScrollingUpSensitivity
|
val indexChanged = previousIndex != index
|
||||||
|
val offsetChanged = abs(previousScrollOffset - scrollOffset) > isScrollingUpSensitivity
|
||||||
|
|
||||||
if (indexChanged) {
|
value = when {
|
||||||
previousIndex > firstVisibleItemIndex
|
indexChanged -> previousIndex > index
|
||||||
} else if (offsetChanged) {
|
offsetChanged -> previousScrollOffset > scrollOffset
|
||||||
previousScrollOffset > firstVisibleItemScrollOffset
|
else -> value
|
||||||
} else {
|
|
||||||
true
|
|
||||||
}.also {
|
|
||||||
previousIndex = firstVisibleItemIndex
|
|
||||||
previousScrollOffset = firstVisibleItemScrollOffset
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
previousIndex = index
|
||||||
|
previousScrollOffset = scrollOffset
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: support sensitivity
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ScrollState.isScrollingUp(): State<Boolean> {
|
fun ScrollState.isScrollingUp() = produceState(true, this) {
|
||||||
return remember(this) {
|
var previousScrollOffset = this@isScrollingUp.value
|
||||||
var previousScrollOffset by mutableIntStateOf(value)
|
|
||||||
derivedStateOf {
|
snapshotFlow { this@isScrollingUp.value }.collect { scrollOffset ->
|
||||||
(previousScrollOffset >= value).also {
|
if (abs(previousScrollOffset - scrollOffset) > isScrollingUpSensitivity) {
|
||||||
previousScrollOffset = value
|
value = previousScrollOffset >= scrollOffset
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
previousScrollOffset = scrollOffset
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ Second \"item\" text"</string>
|
|||||||
-->
|
-->
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">ReVanced Manager</string>
|
<string name="app_name">ReVanced Manager</string>
|
||||||
<string name="patcher">Patcher</string>
|
<string name="patcher">Patcher test</string>
|
||||||
<string name="patches">Patches</string>
|
<string name="patches">Patches</string>
|
||||||
<string name="cli">CLI</string>
|
<string name="cli">CLI</string>
|
||||||
<string name="manager">Manager</string>
|
<string name="manager">Manager</string>
|
||||||
@@ -83,7 +83,7 @@ Second \"item\" text"</string>
|
|||||||
<string name="auto_updates_dialog_note">These settings can be changed later.</string>
|
<string name="auto_updates_dialog_note">These settings can be changed later.</string>
|
||||||
|
|
||||||
<string name="general">General</string>
|
<string name="general">General</string>
|
||||||
<string name="general_description">Theme, dynamic color</string>
|
<string name="general_description">Language, theme, dynamic color</string>
|
||||||
<string name="updates">Updates</string>
|
<string name="updates">Updates</string>
|
||||||
<string name="updates_description">Check for updates and view changelogs</string>
|
<string name="updates_description">Check for updates and view changelogs</string>
|
||||||
<string name="downloads">Downloads</string>
|
<string name="downloads">Downloads</string>
|
||||||
@@ -104,6 +104,9 @@ Second \"item\" text"</string>
|
|||||||
<string name="pure_black_theme_description">Use pure black backgrounds for dark theme</string>
|
<string name="pure_black_theme_description">Use pure black backgrounds for dark theme</string>
|
||||||
<string name="theme">Theme</string>
|
<string name="theme">Theme</string>
|
||||||
<string name="theme_description">Choose between light or dark theme</string>
|
<string name="theme_description">Choose between light or dark theme</string>
|
||||||
|
<string name="language">Language</string>
|
||||||
|
<string name="language_description">Choose the app display language</string>
|
||||||
|
<string name="language_system_default">System default</string>
|
||||||
<string name="safeguards">Safeguards</string>
|
<string name="safeguards">Safeguards</string>
|
||||||
<string name="patch_compat_check">Disable version compatibility check</string>
|
<string name="patch_compat_check">Disable version compatibility check</string>
|
||||||
<string name="patch_compat_check_description">Do not restrict patches to compatible app versions</string>
|
<string name="patch_compat_check_description">Do not restrict patches to compatible app versions</string>
|
||||||
|
|||||||
@@ -6,5 +6,6 @@ plugins {
|
|||||||
alias(libs.plugins.kotlin.serialization) apply false
|
alias(libs.plugins.kotlin.serialization) apply false
|
||||||
alias(libs.plugins.kotlin.parcelize) apply false
|
alias(libs.plugins.kotlin.parcelize) apply false
|
||||||
alias(libs.plugins.about.libraries) apply false
|
alias(libs.plugins.about.libraries) apply false
|
||||||
|
alias(libs.plugins.about.libraries.android) apply false
|
||||||
alias(libs.plugins.compose.compiler) apply false
|
alias(libs.plugins.compose.compiler) apply false
|
||||||
}
|
}
|
||||||
|
|||||||
9
crowdin.yml
Normal file
9
crowdin.yml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
project_id_env: "CROWDIN_PROJECT_ID"
|
||||||
|
api_token_env: "CROWDIN_PERSONAL_TOKEN"
|
||||||
|
|
||||||
|
preserve_hierarchy: true
|
||||||
|
files:
|
||||||
|
- source: app/src/main/res/values/strings.xml
|
||||||
|
dest: manager.xml
|
||||||
|
translation: app/src/main/res/values-%android_code%/strings.xml
|
||||||
|
skip_untranslated_strings: true
|
||||||
@@ -1,32 +1,32 @@
|
|||||||
[versions]
|
[versions]
|
||||||
ktx = "1.16.0"
|
ktx = "1.17.0"
|
||||||
material3 = "1.3.2"
|
material3 = "1.4.0"
|
||||||
ui-tooling = "1.8.1"
|
ui-tooling = "1.10.0"
|
||||||
viewmodel-lifecycle = "2.9.0"
|
viewmodel-lifecycle = "2.10.0"
|
||||||
splash-screen = "1.0.1"
|
splash-screen = "1.2.0"
|
||||||
activity = "1.10.1"
|
activity = "1.12.2"
|
||||||
appcompat = "1.7.0"
|
appcompat = "1.7.1"
|
||||||
preferences-datastore = "1.1.2"
|
preferences-datastore = "1.2.0"
|
||||||
work-runtime = "2.10.1"
|
work-runtime = "2.11.0"
|
||||||
compose-bom = "2025.05.00"
|
compose-bom = "2025.12.01"
|
||||||
navigation = "2.8.6"
|
navigation = "2.9.6"
|
||||||
accompanist = "0.37.0"
|
accompanist = "0.37.3"
|
||||||
placeholder = "1.1.2"
|
placeholder = "1.0.12"
|
||||||
reorderable = "2.4.3"
|
reorderable = "3.0.0"
|
||||||
serialization = "1.8.0"
|
serialization = "1.9.0"
|
||||||
collection = "0.3.8"
|
collection = "0.4.0"
|
||||||
datetime = "0.6.1"
|
datetime = "0.7.1"
|
||||||
room-version = "2.7.1"
|
room-version = "2.8.4"
|
||||||
revanced-patcher = "21.0.0"
|
revanced-patcher = "21.0.0"
|
||||||
revanced-library = "3.0.2"
|
revanced-library = "3.0.2"
|
||||||
koin = "3.5.3"
|
koin = "4.1.1"
|
||||||
ktor = "2.3.9"
|
ktor = "3.3.3"
|
||||||
markdown-renderer = "0.30.0"
|
markdown-renderer = "0.39.0"
|
||||||
fading-edges = "1.0.4"
|
fading-edges = "1.0.4"
|
||||||
kotlin = "2.1.10"
|
kotlin = "2.3.0"
|
||||||
android-gradle-plugin = "8.9.1"
|
android-gradle-plugin = "8.13.2"
|
||||||
dev-tools-gradle-plugin = "2.1.10-1.0.29"
|
dev-tools-gradle-plugin = "2.3.4"
|
||||||
about-libraries-gradle-plugin = "12.1.2"
|
about-libraries = "13.2.1"
|
||||||
coil = "2.7.0"
|
coil = "2.7.0"
|
||||||
app-icon-loader-coil = "1.5.0"
|
app-icon-loader-coil = "1.5.0"
|
||||||
libsu = "6.0.0"
|
libsu = "6.0.0"
|
||||||
@@ -34,10 +34,10 @@ scrollbars = "1.0.4"
|
|||||||
enumutil = "1.1.1"
|
enumutil = "1.1.1"
|
||||||
compose-icons = "1.2.4"
|
compose-icons = "1.2.4"
|
||||||
kotlin-process = "1.5.1"
|
kotlin-process = "1.5.1"
|
||||||
hidden-api-stub = "4.3.3"
|
hidden-api-stub = "4.4.0"
|
||||||
binary-compatibility-validator = "0.17.0"
|
binary-compatibility-validator = "0.18.1"
|
||||||
semver-parser = "3.0.0"
|
semver-parser = "3.0.0"
|
||||||
ackpine = "0.18.5"
|
ackpine = "0.19.1"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
# AndroidX Core
|
# 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" }
|
accompanist-drawablepainter = { group = "com.google.accompanist", name = "accompanist-drawablepainter", version.ref = "accompanist" }
|
||||||
|
|
||||||
# Placeholder
|
# 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
|
||||||
kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "serialization" }
|
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" }
|
koin-workmanager = { group = "io.insert-koin", name = "koin-androidx-workmanager", version.ref = "koin" }
|
||||||
|
|
||||||
# About Libraries
|
# 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
|
||||||
ktor-core = { group = "io.ktor", name = "ktor-client-core", version.ref = "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" }
|
kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" }
|
||||||
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", 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" }
|
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" }
|
binary-compatibility-validator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "binary-compatibility-validator" }
|
||||||
|
|||||||
Reference in New Issue
Block a user