diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsTrackingScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsTrackingScreen.kt index bcc5108bd..4de5fbde8 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsTrackingScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsTrackingScreen.kt @@ -1,15 +1,16 @@ package eu.kanade.presentation.more.settings.screen import android.content.Context -import android.view.LayoutInflater -import android.view.View import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.outlined.HelpOutline +import androidx.compose.material.icons.filled.Visibility +import androidx.compose.material.icons.filled.VisibilityOff import androidx.compose.material.icons.outlined.Close import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button @@ -18,6 +19,7 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.ReadOnlyComposable @@ -28,19 +30,19 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalUriHandler +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.input.PasswordVisualTransformation +import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import androidx.compose.ui.viewinterop.AndroidView -import androidx.core.widget.doAfterTextChanged import dev.icerock.moko.resources.StringResource import eu.kanade.domain.track.model.AutoTrackState import eu.kanade.domain.track.service.TrackPreferences import eu.kanade.presentation.more.settings.Preference -import eu.kanade.presentation.theme.colorscheme.AndroidViewColorScheme import eu.kanade.tachiyomi.data.track.EnhancedTracker import eu.kanade.tachiyomi.data.track.Tracker import eu.kanade.tachiyomi.data.track.TrackerManager @@ -48,7 +50,6 @@ import eu.kanade.tachiyomi.data.track.anilist.AnilistApi import eu.kanade.tachiyomi.data.track.bangumi.BangumiApi import eu.kanade.tachiyomi.data.track.myanimelist.MyAnimeListApi import eu.kanade.tachiyomi.data.track.shikimori.ShikimoriApi -import eu.kanade.tachiyomi.databinding.DialogTrackingLoginBinding import eu.kanade.tachiyomi.util.system.openInBrowser import eu.kanade.tachiyomi.util.system.toast import kotlinx.collections.immutable.persistentListOf @@ -61,7 +62,6 @@ import tachiyomi.i18n.MR import tachiyomi.i18n.kmk.KMR import tachiyomi.presentation.core.components.material.padding import tachiyomi.presentation.core.i18n.stringResource -import tachiyomi.presentation.core.screens.LoadingScreen import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -89,6 +89,7 @@ object SettingsTrackingScreen : SearchableSettings { val trackPreferences = remember { Injekt.get() } val trackerManager = remember { Injekt.get() } val sourceManager = remember { Injekt.get() } + val autoTrackStatePref = trackPreferences.autoUpdateTrackOnMarkRead() var dialog by remember { mutableStateOf(null) } dialog?.run { @@ -203,19 +204,10 @@ object SettingsTrackingScreen : SearchableSettings { val context = LocalContext.current val scope = rememberCoroutineScope() - // KMK --> - val usernameHint = stringResource(uNameStringRes) - - var username by remember(tracker) { mutableStateOf(tracker.getUsername()) } - var password by remember(tracker) { mutableStateOf(tracker.getPassword()) } + var username by remember { mutableStateOf(TextFieldValue(tracker.getUsername())) } + var password by remember { mutableStateOf(TextFieldValue(tracker.getPassword())) } var processing by remember { mutableStateOf(false) } var inputError by remember { mutableStateOf(false) } - val colorScheme = AndroidViewColorScheme(MaterialTheme.colorScheme) - - val configuration = LocalConfiguration.current - val density = LocalDensity.current - var measuredHeightDp by remember(configuration) { mutableStateOf(0.dp) } - // KMK <-- AlertDialog( onDismissRequest = onDismissRequest, @@ -234,97 +226,70 @@ object SettingsTrackingScreen : SearchableSettings { } }, text = { - // KMK --> - if (processing) { - LoadingScreen( - modifier = Modifier.heightIn(max = measuredHeightDp), - ) - } else { - AndroidView( - factory = { factoryContext -> - val binding = DialogTrackingLoginBinding.inflate(LayoutInflater.from(factoryContext)) - - // Measure dialog height for loading state - if (measuredHeightDp == 0.dp) { - val widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED) - val heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED) - binding.root.measure(widthMeasureSpec, heightMeasureSpec) - with(density) { measuredHeightDp = binding.root.measuredHeight.toDp() } - } - - val usernameInputLayout = binding.usernameInputLayout - val usernameEditText = binding.usernameEditText - val passwordEditText = binding.passwordEditText - - listOf( - usernameEditText, - passwordEditText, - ).forEach { - colorScheme.setEditTextColor(it) - } - - usernameInputLayout.hint = usernameHint - usernameEditText.setText(username) - passwordEditText.setText(password) - - // Clear errors and update Compose state on text change - usernameEditText.doAfterTextChanged { - val newValue = it?.toString().orEmpty() - if (username != newValue) { - username = newValue - inputError = false - } - } - passwordEditText.doAfterTextChanged { - val newValue = it?.toString().orEmpty() - if (password != newValue) { - password = newValue - inputError = false - } - } - - binding.root - }, - update = { view -> - val binding = DialogTrackingLoginBinding.bind(view) - val usernameInputLayout = binding.usernameInputLayout - val passwordInputLayout = binding.passwordInputLayout - - listOf( - usernameInputLayout, - passwordInputLayout, - ).forEach { - colorScheme.setTextInputLayoutColor(it, inputError) - } - }, + Column(verticalArrangement = Arrangement.spacedBy(12.dp)) { + OutlinedTextField( modifier = Modifier.fillMaxWidth(), + value = username, + onValueChange = { username = it }, + label = { Text(text = stringResource(uNameStringRes)) }, + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next), + singleLine = true, + isError = inputError && !processing, + ) + + var hidePassword by remember { mutableStateOf(true) } + OutlinedTextField( + modifier = Modifier.fillMaxWidth(), + value = password, + onValueChange = { password = it }, + label = { Text(text = stringResource(MR.strings.password)) }, + trailingIcon = { + IconButton(onClick = { hidePassword = !hidePassword }) { + Icon( + imageVector = if (hidePassword) { + Icons.Filled.Visibility + } else { + Icons.Filled.VisibilityOff + }, + contentDescription = null, + ) + } + }, + visualTransformation = if (hidePassword) { + PasswordVisualTransformation() + } else { + VisualTransformation.None + }, + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Password, + imeAction = ImeAction.Done, + ), + singleLine = true, + isError = inputError && !processing, ) } - // KMK <-- }, confirmButton = { Button( modifier = Modifier.fillMaxWidth(), - enabled = !processing && username.isNotBlank() && password.isNotBlank(), + enabled = !processing && username.text.isNotBlank() && password.text.isNotBlank(), onClick = { - // KMK --> - processing = true - inputError = false // Clear previous error before check - // KMK <-- scope.launchIO { - val success = checkLogin( + processing = true + val result = checkLogin( context = context, tracker = tracker, - username = username, - password = password, + username = username.text, + password = password.text, ) - inputError = !success - if (success) onDismissRequest() + inputError = !result + if (result) onDismissRequest() processing = false } }, ) { - Text(text = stringResource(if (processing) MR.strings.loading else MR.strings.login)) + val id = if (processing) MR.strings.loading else MR.strings.login + Text(text = stringResource(id)) } }, ) diff --git a/app/src/main/res/layout/dialog_tracking_login.xml b/app/src/main/res/layout/dialog_tracking_login.xml deleted file mode 100644 index 63c958571..000000000 --- a/app/src/main/res/layout/dialog_tracking_login.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - -