Add QR code scan button for sync API key (jobobby04/tachiyomiSY#1430)
* Add dependency com.journeyapps:zxing-android-embedded:4.3.0 * Add widget parameter to EditTextPreferenceWidget * Add QR code scanner icon button to sync API key preference which launches a ScanContract * Remove screenOrientation property from CaptureActivity manifest * Allow scanning both normal and inverted codes * store values and make code more concise Co-authored-by: jobobby04 <jobobby04@users.noreply.github.com> * Import local context --------- Co-authored-by: jobobby04 <jobobby04@users.noreply.github.com> (cherry picked from commit 84c7da5a7d244ffc0cd7155d15e0a200f548ad35)
This commit is contained in:
parent
b2f90d19c3
commit
3f2eb75b71
6 changed files with 60 additions and 5 deletions
|
|
@ -327,6 +327,9 @@ dependencies {
|
||||||
|
|
||||||
// Google drive
|
// Google drive
|
||||||
implementation(sylibs.google.api.services.drive)
|
implementation(sylibs.google.api.services.drive)
|
||||||
|
|
||||||
|
// ZXing Android Embedded
|
||||||
|
implementation(sylibs.zxing.android.embedded)
|
||||||
}
|
}
|
||||||
|
|
||||||
androidComponents {
|
androidComponents {
|
||||||
|
|
|
||||||
|
|
@ -406,6 +406,10 @@
|
||||||
android:scheme="tachiyomisy" />
|
android:scheme="tachiyomisy" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name="com.journeyapps.barcodescanner.CaptureActivity"
|
||||||
|
tools:remove="screenOrientation" />
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.outlined.HelpOutline
|
import androidx.compose.material.icons.automirrored.outlined.HelpOutline
|
||||||
|
import androidx.compose.material.icons.filled.QrCodeScanner
|
||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.Checkbox
|
import androidx.compose.material3.Checkbox
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
|
|
@ -41,7 +42,10 @@ import androidx.compose.ui.platform.LocalUriHandler
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||||
|
import com.google.zxing.client.android.Intents
|
||||||
import com.hippo.unifile.UniFile
|
import com.hippo.unifile.UniFile
|
||||||
|
import com.journeyapps.barcodescanner.ScanContract
|
||||||
|
import com.journeyapps.barcodescanner.ScanOptions
|
||||||
import eu.kanade.domain.sync.SyncPreferences
|
import eu.kanade.domain.sync.SyncPreferences
|
||||||
import eu.kanade.presentation.more.settings.Preference
|
import eu.kanade.presentation.more.settings.Preference
|
||||||
import eu.kanade.presentation.more.settings.screen.data.CreateBackupScreen
|
import eu.kanade.presentation.more.settings.screen.data.CreateBackupScreen
|
||||||
|
|
@ -50,7 +54,9 @@ import eu.kanade.presentation.more.settings.screen.data.StorageInfo
|
||||||
import eu.kanade.presentation.more.settings.screen.data.SyncSettingsSelector
|
import eu.kanade.presentation.more.settings.screen.data.SyncSettingsSelector
|
||||||
import eu.kanade.presentation.more.settings.screen.data.SyncTriggerOptionsScreen
|
import eu.kanade.presentation.more.settings.screen.data.SyncTriggerOptionsScreen
|
||||||
import eu.kanade.presentation.more.settings.widget.BasePreferenceWidget
|
import eu.kanade.presentation.more.settings.widget.BasePreferenceWidget
|
||||||
|
import eu.kanade.presentation.more.settings.widget.EditTextPreferenceWidget
|
||||||
import eu.kanade.presentation.more.settings.widget.PrefsHorizontalPadding
|
import eu.kanade.presentation.more.settings.widget.PrefsHorizontalPadding
|
||||||
|
import eu.kanade.presentation.more.settings.widget.TrailingWidgetBuffer
|
||||||
import eu.kanade.presentation.util.relativeTimeSpanString
|
import eu.kanade.presentation.util.relativeTimeSpanString
|
||||||
import eu.kanade.tachiyomi.data.backup.create.BackupCreateJob
|
import eu.kanade.tachiyomi.data.backup.create.BackupCreateJob
|
||||||
import eu.kanade.tachiyomi.data.backup.restore.BackupRestoreJob
|
import eu.kanade.tachiyomi.data.backup.restore.BackupRestoreJob
|
||||||
|
|
@ -697,6 +703,22 @@ object SettingsDataScreen : SearchableSettings {
|
||||||
@Composable
|
@Composable
|
||||||
private fun getSelfHostPreferences(syncPreferences: SyncPreferences): List<Preference> {
|
private fun getSelfHostPreferences(syncPreferences: SyncPreferences): List<Preference> {
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
val qrScanLauncher = rememberLauncherForActivityResult(ScanContract()) {
|
||||||
|
if (it.contents != null && it.contents.isNotEmpty()) {
|
||||||
|
syncPreferences.clientAPIKey().set(it.contents)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val context = LocalContext.current
|
||||||
|
val scanOptions = remember {
|
||||||
|
ScanOptions().apply {
|
||||||
|
setDesiredBarcodeFormats(ScanOptions.QR_CODE)
|
||||||
|
setOrientationLocked(false)
|
||||||
|
setPrompt(SYMR.strings.scan_qr_code.getString(context))
|
||||||
|
addExtra(Intents.Scan.SCAN_TYPE, Intents.Scan.MIXED_SCAN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return listOf(
|
return listOf(
|
||||||
Preference.PreferenceItem.EditTextPreference(
|
Preference.PreferenceItem.EditTextPreference(
|
||||||
preference = syncPreferences.clientHost(),
|
preference = syncPreferences.clientHost(),
|
||||||
|
|
@ -712,11 +734,32 @@ object SettingsDataScreen : SearchableSettings {
|
||||||
true
|
true
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
Preference.PreferenceItem.EditTextPreference(
|
Preference.PreferenceItem.CustomPreference(
|
||||||
preference = syncPreferences.clientAPIKey(),
|
|
||||||
title = stringResource(SYMR.strings.pref_sync_api_key),
|
title = stringResource(SYMR.strings.pref_sync_api_key),
|
||||||
subtitle = stringResource(SYMR.strings.pref_sync_api_key_summ),
|
) {
|
||||||
),
|
val values by syncPreferences.clientAPIKey().collectAsState()
|
||||||
|
EditTextPreferenceWidget(
|
||||||
|
title = stringResource(SYMR.strings.pref_sync_api_key),
|
||||||
|
subtitle = stringResource(SYMR.strings.pref_sync_api_key_summ),
|
||||||
|
onConfirm = {
|
||||||
|
syncPreferences.clientAPIKey().set(it)
|
||||||
|
true
|
||||||
|
},
|
||||||
|
icon = null,
|
||||||
|
value = values,
|
||||||
|
widget = {
|
||||||
|
IconButton(
|
||||||
|
onClick = { qrScanLauncher.launch(scanOptions) },
|
||||||
|
modifier = Modifier.padding(start = TrailingWidgetBuffer),
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
Icons.Filled.QrCodeScanner,
|
||||||
|
contentDescription = stringResource(SYMR.strings.scan_qr_code),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ fun EditTextPreferenceWidget(
|
||||||
subtitle: String?,
|
subtitle: String?,
|
||||||
icon: ImageVector?,
|
icon: ImageVector?,
|
||||||
value: String,
|
value: String,
|
||||||
|
widget: @Composable (() -> Unit)? = null,
|
||||||
onConfirm: suspend (String) -> Boolean,
|
onConfirm: suspend (String) -> Boolean,
|
||||||
) {
|
) {
|
||||||
var isDialogShown by remember { mutableStateOf(false) }
|
var isDialogShown by remember { mutableStateOf(false) }
|
||||||
|
|
@ -39,6 +40,7 @@ fun EditTextPreferenceWidget(
|
||||||
title = title,
|
title = title,
|
||||||
subtitle = subtitle?.format(value),
|
subtitle = subtitle?.format(value),
|
||||||
icon = icon,
|
icon = icon,
|
||||||
|
widget = widget,
|
||||||
onPreferenceClick = { isDialogShown = true },
|
onPreferenceClick = { isDialogShown = true },
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,4 +13,6 @@ sqlcipher = "net.zetetic:sqlcipher-android:4.9.0"
|
||||||
|
|
||||||
exifinterface = "androidx.exifinterface:exifinterface:1.4.1"
|
exifinterface = "androidx.exifinterface:exifinterface:1.4.1"
|
||||||
|
|
||||||
google-api-services-drive = "com.google.apis:google-api-services-drive:v3-rev20250511-2.0.0"
|
google-api-services-drive = "com.google.apis:google-api-services-drive:v3-rev20250511-2.0.0"
|
||||||
|
|
||||||
|
zxing-android-embedded = "com.journeyapps:zxing-android-embedded:4.3.0"
|
||||||
|
|
|
||||||
|
|
@ -229,6 +229,7 @@
|
||||||
<string name="pref_sync_interval">Synchronization frequency</string>
|
<string name="pref_sync_interval">Synchronization frequency</string>
|
||||||
<string name="pref_choose_what_to_sync">Choose what to sync</string>
|
<string name="pref_choose_what_to_sync">Choose what to sync</string>
|
||||||
<string name="syncyomi">SyncYomi</string>
|
<string name="syncyomi">SyncYomi</string>
|
||||||
|
<string name="scan_qr_code">Scan a QR code</string>
|
||||||
<string name="last_synchronization">Last Synchronization: %1$s</string>
|
<string name="last_synchronization">Last Synchronization: %1$s</string>
|
||||||
<string name="google_drive">Google Drive</string>
|
<string name="google_drive">Google Drive</string>
|
||||||
<string name="pref_google_drive_sign_in">Sign in</string>
|
<string name="pref_google_drive_sign_in">Sign in</string>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue