Compare commits

...

6 Commits

Author SHA1 Message Date
semantic-release-bot
95fb97ec31 chore: Release v1.26.0-dev.4 [skip ci]
# app [1.26.0-dev.4](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.3...v1.26.0-dev.4) (2025-10-03)

### Bug Fixes

* add newlines to debug logs ([4753873](4753873866))
2025-10-03 14:34:30 +00:00
Ax333l
4753873866 fix: add newlines to debug logs 2025-10-03 16:26:54 +02:00
semantic-release-bot
ca322f2da8 chore: Release v1.26.0-dev.3 [skip ci]
# app [1.26.0-dev.3](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.2...v1.26.0-dev.3) (2025-10-03)

### Features

* Toggle to use pre-release versions of ReVanced Manager ([#2773](https://github.com/ReVanced/revanced-manager/issues/2773)) ([d758964](d758964742))
2025-10-03 14:26:09 +00:00
Ushie
d758964742 feat: Toggle to use pre-release versions of ReVanced Manager (#2773) 2025-10-03 17:18:27 +03:00
semantic-release-bot
a592e0b302 chore: Release v1.26.0-dev.2 [skip ci]
# app [1.26.0-dev.2](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.1...v1.26.0-dev.2) (2025-10-03)

### Bug Fixes

* Migration of keystore, by fixing mislabeling of alias as cn ([#2769](https://github.com/ReVanced/revanced-manager/issues/2769)) ([aeab639](aeab639b2b))
2025-10-03 13:38:38 +00:00
Ushie
aeab639b2b fix: Migration of keystore, by fixing mislabeling of alias as cn (#2769) 2025-10-03 16:31:05 +03:00
12 changed files with 60 additions and 23 deletions

View File

@@ -1,3 +1,24 @@
# app [1.26.0-dev.4](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.3...v1.26.0-dev.4) (2025-10-03)
### Bug Fixes
* add newlines to debug logs ([4753873](https://github.com/ReVanced/revanced-manager/commit/4753873866b575e2dcb160020df63f63862c8f33))
# app [1.26.0-dev.3](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.2...v1.26.0-dev.3) (2025-10-03)
### Features
* Toggle to use pre-release versions of ReVanced Manager ([#2773](https://github.com/ReVanced/revanced-manager/issues/2773)) ([d758964](https://github.com/ReVanced/revanced-manager/commit/d7589647426b3d3438161a2f0b59bf4f154ac34b))
# app [1.26.0-dev.2](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.1...v1.26.0-dev.2) (2025-10-03)
### Bug Fixes
* Migration of keystore, by fixing mislabeling of alias as cn ([#2769](https://github.com/ReVanced/revanced-manager/issues/2769)) ([aeab639](https://github.com/ReVanced/revanced-manager/commit/aeab639b2b09e8bbd2478cfbf5a518586405c0f7))
# app [1.26.0-dev.1](https://github.com/ReVanced/revanced-manager/compare/v1.25.1...v1.26.0-dev.1) (2025-10-02) # app [1.26.0-dev.1](https://github.com/ReVanced/revanced-manager/compare/v1.25.1...v1.26.0-dev.1) (2025-10-02)

View File

@@ -1 +1 @@
version = 1.26.0-dev.1 version = 1.26.0-dev.4

View File

@@ -27,25 +27,25 @@ class KeystoreManager(app: Application, private val prefs: PreferencesManager) {
private val keystorePath = private val keystorePath =
app.getDir("signing", Context.MODE_PRIVATE).resolve("manager.keystore") app.getDir("signing", Context.MODE_PRIVATE).resolve("manager.keystore")
private suspend fun updatePrefs(cn: String, pass: String) = prefs.edit { private suspend fun updatePrefs(alias: String, pass: String) = prefs.edit {
prefs.keystoreCommonName.value = cn prefs.keystoreAlias.value = alias
prefs.keystorePass.value = pass prefs.keystorePass.value = pass
} }
private suspend fun signingDetails(path: File = keystorePath) = ApkUtils.KeyStoreDetails( private suspend fun signingDetails(path: File = keystorePath) = ApkUtils.KeyStoreDetails(
keyStore = path, keyStore = path,
keyStorePassword = null, keyStorePassword = null,
alias = prefs.keystoreCommonName.get(), alias = prefs.keystoreAlias.get(),
password = prefs.keystorePass.get() password = prefs.keystorePass.get()
) )
suspend fun sign(input: File, output: File) = withContext(Dispatchers.Default) { suspend fun sign(input: File, output: File) = withContext(Dispatchers.Default) {
ApkUtils.signApk(input, output, prefs.keystoreCommonName.get(), signingDetails()) ApkUtils.signApk(input, output, prefs.keystoreAlias.get(), signingDetails())
} }
suspend fun regenerate() = withContext(Dispatchers.Default) { suspend fun regenerate() = withContext(Dispatchers.Default) {
val keyCertPair = ApkSigner.newPrivateKeyCertificatePair( val keyCertPair = ApkSigner.newPrivateKeyCertificatePair(
prefs.keystoreCommonName.get(), prefs.keystoreAlias.get(),
eightYearsFromNow eightYearsFromNow
) )
val ks = ApkSigner.newKeyStore( val ks = ApkSigner.newKeyStore(
@@ -64,13 +64,13 @@ class KeystoreManager(app: Application, private val prefs: PreferencesManager) {
updatePrefs(DEFAULT, DEFAULT) updatePrefs(DEFAULT, DEFAULT)
} }
suspend fun import(cn: String, pass: String, keystore: InputStream): Boolean { suspend fun import(alias: String, pass: String, keystore: InputStream): Boolean {
val keystoreData = withContext(Dispatchers.IO) { keystore.readBytes() } val keystoreData = withContext(Dispatchers.IO) { keystore.readBytes() }
try { try {
val ks = ApkSigner.readKeyStore(ByteArrayInputStream(keystoreData), null) val ks = ApkSigner.readKeyStore(ByteArrayInputStream(keystoreData), null)
ApkSigner.readPrivateKeyCertificatePair(ks, cn, pass) ApkSigner.readPrivateKeyCertificatePair(ks, alias, pass)
} catch (_: UnrecoverableKeyException) { } catch (_: UnrecoverableKeyException) {
return false return false
} catch (_: IllegalArgumentException) { } catch (_: IllegalArgumentException) {
@@ -81,7 +81,7 @@ class KeystoreManager(app: Application, private val prefs: PreferencesManager) {
Files.write(keystorePath.toPath(), keystoreData) Files.write(keystorePath.toPath(), keystoreData)
} }
updatePrefs(cn, pass) updatePrefs(alias, pass)
return true return true
} }

View File

@@ -16,12 +16,13 @@ class PreferencesManager(
val useProcessRuntime = booleanPreference("use_process_runtime", false) val useProcessRuntime = booleanPreference("use_process_runtime", false)
val patcherProcessMemoryLimit = intPreference("process_runtime_memory_limit", 700) val patcherProcessMemoryLimit = intPreference("process_runtime_memory_limit", 700)
val keystoreCommonName = stringPreference("keystore_cn", KeystoreManager.DEFAULT) val keystoreAlias = stringPreference("keystore_alias", KeystoreManager.DEFAULT)
val keystorePass = stringPreference("keystore_pass", KeystoreManager.DEFAULT) val keystorePass = stringPreference("keystore_pass", KeystoreManager.DEFAULT)
val firstLaunch = booleanPreference("first_launch", true) val firstLaunch = booleanPreference("first_launch", true)
val managerAutoUpdates = booleanPreference("manager_auto_updates", false) val managerAutoUpdates = booleanPreference("manager_auto_updates", false)
val showManagerUpdateDialogOnLaunch = booleanPreference("show_manager_update_dialog_on_launch", true) val showManagerUpdateDialogOnLaunch = booleanPreference("show_manager_update_dialog_on_launch", true)
val useManagerPrereleases = booleanPreference("manager_prereleases", false)
val disablePatchVersionCompatCheck = booleanPreference("disable_patch_version_compatibility_check", false) val disablePatchVersionCompatCheck = booleanPreference("disable_patch_version_compatibility_check", false)
val disableSelectionWarning = booleanPreference("disable_selection_warning", false) val disableSelectionWarning = booleanPreference("disable_selection_warning", false)

View File

@@ -32,7 +32,8 @@ class ReVancedAPI(
suspend fun getAppUpdate() = suspend fun getAppUpdate() =
getLatestAppInfo().getOrThrow().takeIf { it.version != Build.VERSION.RELEASE } getLatestAppInfo().getOrThrow().takeIf { it.version != Build.VERSION.RELEASE }
suspend fun getLatestAppInfo() = request<ReVancedAsset>("manager") suspend fun getLatestAppInfo() =
request<ReVancedAsset>("manager?prerelease=${prefs.useManagerPrereleases.get()}")
suspend fun getPatchesUpdate() = request<ReVancedAsset>("patches") suspend fun getPatchesUpdate() = request<ReVancedAsset>("patches")

View File

@@ -104,10 +104,10 @@ fun ImportExportSettingsScreen(
if (vm.showCredentialsDialog) { if (vm.showCredentialsDialog) {
KeystoreCredentialsDialog( KeystoreCredentialsDialog(
onDismissRequest = vm::cancelKeystoreImport, onDismissRequest = vm::cancelKeystoreImport,
onSubmit = { cn, pass -> onSubmit = { alias, pass ->
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(cn, pass) val result = vm.tryKeystoreImport(alias, pass)
if (!result) context.toast(context.getString(R.string.import_keystore_wrong_credentials)) if (!result) context.toast(context.getString(R.string.import_keystore_wrong_credentials))
} }
} }
@@ -382,7 +382,7 @@ fun KeystoreCredentialsDialog(
onDismissRequest: () -> Unit, onDismissRequest: () -> Unit,
onSubmit: (String, String) -> Unit onSubmit: (String, String) -> Unit
) { ) {
var cn by rememberSaveable { mutableStateOf("") } var alias by rememberSaveable { mutableStateOf("") }
var pass by rememberSaveable { mutableStateOf("") } var pass by rememberSaveable { mutableStateOf("") }
AlertDialog( AlertDialog(
@@ -390,7 +390,7 @@ fun KeystoreCredentialsDialog(
confirmButton = { confirmButton = {
TextButton( TextButton(
onClick = { onClick = {
onSubmit(cn, pass) onSubmit(alias, pass)
} }
) { ) {
Text(stringResource(R.string.import_keystore_dialog_button)) Text(stringResource(R.string.import_keystore_dialog_button))
@@ -422,8 +422,8 @@ fun KeystoreCredentialsDialog(
color = MaterialTheme.colorScheme.onSurfaceVariant color = MaterialTheme.colorScheme.onSurfaceVariant
) )
OutlinedTextField( OutlinedTextField(
value = cn, value = alias,
onValueChange = { cn = it }, onValueChange = { alias = it },
label = { Text(stringResource(R.string.import_keystore_dialog_alias_field)) } label = { Text(stringResource(R.string.import_keystore_dialog_alias_field)) }
) )
PasswordField( PasswordField(

View File

@@ -92,6 +92,12 @@ fun UpdatesSettingsScreen(
headline = R.string.show_manager_update_dialog_on_launch, headline = R.string.show_manager_update_dialog_on_launch,
description = R.string.show_manager_update_dialog_on_launch_description description = R.string.show_manager_update_dialog_on_launch_description
) )
BooleanItem(
preference = vm.useManagerPrereleases,
headline = R.string.manager_prereleases,
description = R.string.manager_prereleases_description
)
} }
} }
} }

View File

@@ -47,7 +47,7 @@ class AdvancedSettingsViewModel(
app.contentResolver.openOutputStream(target)!!.bufferedWriter().use { writer -> app.contentResolver.openOutputStream(target)!!.bufferedWriter().use { writer ->
val consumer = Redirect.Consume { flow -> val consumer = Redirect.Consume { flow ->
flow.onEach { flow.onEach {
writer.write(it) writer.write("${it}\n")
}.flowOn(Dispatchers.IO).collect() }.flowOn(Dispatchers.IO).collect()
} }

View File

@@ -154,12 +154,12 @@ class ImportExportViewModel(
keystoreImportPath = null keystoreImportPath = null
} }
suspend fun tryKeystoreImport(cn: String, pass: String) = suspend fun tryKeystoreImport(alias: String, pass: String) =
tryKeystoreImport(cn, pass, keystoreImportPath!!) tryKeystoreImport(alias, pass, keystoreImportPath!!)
private suspend fun tryKeystoreImport(cn: String, pass: String, path: Path): Boolean { private suspend fun tryKeystoreImport(alias: String, pass: String, path: Path): Boolean {
path.inputStream().use { stream -> path.inputStream().use { stream ->
if (keystoreManager.import(cn, pass, stream)) { if (keystoreManager.import(alias, pass, stream)) {
app.toast(app.getString(R.string.import_keystore_success)) app.toast(app.getString(R.string.import_keystore_success))
cancelKeystoreImport() cancelKeystoreImport()
return true return true

View File

@@ -120,6 +120,9 @@ class MainViewModel(
settings.useDynamicTheme?.let { dynamicColor -> settings.useDynamicTheme?.let { dynamicColor ->
prefs.dynamicColor.update(dynamicColor) prefs.dynamicColor.update(dynamicColor)
} }
settings.usePrereleases?.let { prereleases ->
prefs.useManagerPrereleases.update(prereleases)
}
settings.apiUrl?.let { api -> settings.apiUrl?.let { api ->
prefs.api.update(api.removeSuffix("/")) prefs.api.update(api.removeSuffix("/"))
} }
@@ -143,7 +146,7 @@ class MainViewModel(
settings.keystore?.let { keystore -> settings.keystore?.let { keystore ->
val keystoreBytes = Base64.decode(keystore, Base64.DEFAULT) val keystoreBytes = Base64.decode(keystore, Base64.DEFAULT)
keystoreManager.import( keystoreManager.import(
"ReVanced", "alias",
settings.keystorePassword, settings.keystorePassword,
keystoreBytes.inputStream() keystoreBytes.inputStream()
) )
@@ -159,6 +162,7 @@ class MainViewModel(
val keystorePassword: String, val keystorePassword: String,
val themeMode: Int? = null, val themeMode: Int? = null,
val useDynamicTheme: Boolean? = null, val useDynamicTheme: Boolean? = null,
val usePrereleases: Boolean? = null,
val apiUrl: String? = null, val apiUrl: String? = null,
val experimentalPatchesEnabled: Boolean? = null, val experimentalPatchesEnabled: Boolean? = null,
val patchesAutoUpdate: Boolean? = null, val patchesAutoUpdate: Boolean? = null,

View File

@@ -17,6 +17,8 @@ class UpdatesSettingsViewModel(
) : ViewModel() { ) : ViewModel() {
val managerAutoUpdates = prefs.managerAutoUpdates val managerAutoUpdates = prefs.managerAutoUpdates
val showManagerUpdateDialogOnLaunch = prefs.showManagerUpdateDialogOnLaunch val showManagerUpdateDialogOnLaunch = prefs.showManagerUpdateDialogOnLaunch
val useManagerPrereleases = prefs.useManagerPrereleases
val isConnected: Boolean val isConnected: Boolean
get() = network.isConnected() get() = network.isConnected()

View File

@@ -368,6 +368,8 @@
<string name="manual_update_check_description">Manually check for updates</string> <string name="manual_update_check_description">Manually check for updates</string>
<string name="update_checking_manager">Check for updates on launch</string> <string name="update_checking_manager">Check for updates on launch</string>
<string name="update_checking_manager_description">Check for new versions of ReVanced Manager when the application starts</string> <string name="update_checking_manager_description">Check for new versions of ReVanced Manager when the application starts</string>
<string name="manager_prereleases">Use pre-releases</string>
<string name="manager_prereleases_description">Use pre-release versions of ReVanced Manager</string>
<string name="changelog">View changelogs</string> <string name="changelog">View changelogs</string>
<string name="changelog_loading">Loading changelog</string> <string name="changelog_loading">Loading changelog</string>
<string name="changelog_download_fail">Failed to download changelog: %s</string> <string name="changelog_download_fail">Failed to download changelog: %s</string>