diff --git a/app/src/main/java/com/hippo/ehviewer/ui/EhActivity.kt b/app/src/main/java/com/hippo/ehviewer/ui/EhActivity.kt index a9d7576b3..281025b9c 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/EhActivity.kt +++ b/app/src/main/java/com/hippo/ehviewer/ui/EhActivity.kt @@ -33,7 +33,10 @@ import eu.kanade.tachiyomi.util.system.isNightMode import eu.kanade.tachiyomi.util.view.setSecureScreen import rikka.insets.WindowInsetsHelper import rikka.layoutinflater.view.LayoutInflaterFactory - +enum class ScreenDimension(val screenDimensionType: Int){ + ScreenRotationLandscape(1), + ScreenRotationPortrait(2) +} abstract class EhActivity : AppCompatActivity() { @StyleRes fun getThemeStyleRes(): Int { @@ -86,4 +89,20 @@ abstract class EhActivity : AppCompatActivity() { if (Settings.notificationRequired) return requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) } + + fun getScreenDimension(): ScreenDimension { + var dm = applicationContext?.resources?.displayMetrics + var screenWidth = dm?.widthPixels + var screenHeight = dm?.heightPixels + var screenDimensionStatus = ScreenDimension.ScreenRotationLandscape + + if (screenWidth != null) { + screenDimensionStatus = if(screenWidth > screenHeight!!) + ScreenDimension.ScreenRotationLandscape + else{ + ScreenDimension.ScreenRotationPortrait + } + } + return screenDimensionStatus + } } diff --git a/app/src/main/java/com/hippo/ehviewer/ui/login/CookieSignInScreen.kt b/app/src/main/java/com/hippo/ehviewer/ui/login/CookieSignInScreen.kt index 40cf6b845..4181f9e2e 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/login/CookieSignInScreen.kt +++ b/app/src/main/java/com/hippo/ehviewer/ui/login/CookieSignInScreen.kt @@ -2,12 +2,15 @@ package com.hippo.ehviewer.ui.login import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions @@ -19,6 +22,7 @@ import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Scaffold import androidx.compose.material3.SnackbarHost @@ -51,6 +55,7 @@ import com.hippo.ehviewer.client.EhCookieStore import com.hippo.ehviewer.client.EhEngine import com.hippo.ehviewer.client.EhUrl import com.hippo.ehviewer.client.EhUtils +import com.hippo.ehviewer.ui.ScreenDimension import com.hippo.util.ExceptionUtils import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.withNonCancellableContext @@ -61,7 +66,7 @@ import okhttp3.Cookie import java.util.Locale @Composable -fun CookieSignInScene() { +fun CookieSignInScene(currentScreenDimension : ScreenDimension) { val navController = LocalNavController.current val clipboardManager = LocalClipboardManager.current val focusManager = LocalFocusManager.current @@ -179,103 +184,104 @@ fun CookieSignInScene() { } } - Box( - contentAlignment = Alignment.Center - ) { + when(currentScreenDimension){ + ScreenDimension.ScreenRotationPortrait->Box( + contentAlignment = Alignment.Center + ) { Scaffold( - snackbarHost = { - SnackbarHost(hostState = snackbarHostState) - } + snackbarHost = { + SnackbarHost(hostState = snackbarHostState) + } ) { padding -> Column( - Modifier - .padding(dimensionResource(id = R.dimen.keyline_margin)) - .padding(padding) - .fillMaxSize() - .verticalScroll(rememberScrollState()), - horizontalAlignment = Alignment.CenterHorizontally + Modifier + .padding(dimensionResource(id = R.dimen.keyline_margin)) + .padding(padding) + .fillMaxSize() + .verticalScroll(rememberScrollState()), + horizontalAlignment = Alignment.CenterHorizontally ) { Icon( - imageVector = Icons.Default.Cookie, - contentDescription = null, - modifier = Modifier - .padding(dimensionResource(id = R.dimen.keyline_margin)) - .size(48.dp), - tint = Color(0xff795548) + imageVector = Icons.Default.Cookie, + contentDescription = null, + modifier = Modifier + .padding(dimensionResource(id = R.dimen.keyline_margin)) + .size(48.dp), + tint = Color(0xff795548) ) Text( - text = stringResource(id = R.string.cookie_explain), - modifier = Modifier - .padding( - horizontal = 32.dp, - vertical = dimensionResource(id = R.dimen.keyline_margin) + text = stringResource(id = R.string.cookie_explain), + modifier = Modifier + .padding( + horizontal = 32.dp, + vertical = dimensionResource(id = R.dimen.keyline_margin) + ), + fontSize = 16.sp + ) + OutlinedTextField( + value = ipbMemberId, + onValueChange = { ipbMemberId = it.trim { char -> char <= ' ' } }, + Modifier.width(dimensionResource(id = R.dimen.single_max_width)), + label = { Text(text = "ipb_member_id") }, + keyboardOptions = KeyboardOptions( + imeAction = ImeAction.Next ), - fontSize = 16.sp + supportingText = { if (ipbMemberIdErrorState) Text(stringResource(R.string.text_is_empty)) }, + trailingIcon = { + if (ipbMemberIdErrorState) Icon( + imageVector = Icons.Filled.Info, + contentDescription = null + ) + }, + isError = ipbMemberIdErrorState, + singleLine = true ) OutlinedTextField( - value = ipbMemberId, - onValueChange = { ipbMemberId = it.trim { char -> char <= ' ' } }, - Modifier.width(dimensionResource(id = R.dimen.single_max_width)), - label = { Text(text = "ipb_member_id") }, - keyboardOptions = KeyboardOptions( - imeAction = ImeAction.Next - ), - supportingText = { if (ipbMemberIdErrorState) Text(stringResource(R.string.text_is_empty)) }, - trailingIcon = { - if (ipbMemberIdErrorState) Icon( - imageVector = Icons.Filled.Info, - contentDescription = null - ) - }, - isError = ipbMemberIdErrorState, - singleLine = true + value = ipbPassHash, + onValueChange = { ipbPassHash = it.trim { char -> char <= ' ' } }, + Modifier.width(dimensionResource(id = R.dimen.single_max_width)), + label = { Text(text = "ipb_pass_hash") }, + keyboardOptions = KeyboardOptions( + imeAction = ImeAction.Next + ), + supportingText = { if (ipbPassHashErrorState) Text(stringResource(R.string.text_is_empty)) }, + trailingIcon = { + if (ipbPassHashErrorState) Icon( + imageVector = Icons.Filled.Info, + contentDescription = null + ) + }, + isError = ipbPassHashErrorState, + singleLine = true ) OutlinedTextField( - value = ipbPassHash, - onValueChange = { ipbPassHash = it.trim { char -> char <= ' ' } }, - Modifier.width(dimensionResource(id = R.dimen.single_max_width)), - label = { Text(text = "ipb_pass_hash") }, - keyboardOptions = KeyboardOptions( - imeAction = ImeAction.Next - ), - supportingText = { if (ipbPassHashErrorState) Text(stringResource(R.string.text_is_empty)) }, - trailingIcon = { - if (ipbPassHashErrorState) Icon( - imageVector = Icons.Filled.Info, - contentDescription = null - ) - }, - isError = ipbPassHashErrorState, - singleLine = true - ) - OutlinedTextField( - value = igneous, - onValueChange = { igneous = it.trim { char -> char <= ' ' } }, - Modifier.width(dimensionResource(id = R.dimen.single_max_width)), - label = { Text(text = "igneous") }, - keyboardActions = KeyboardActions( - onDone = { login() } - ), - singleLine = true + value = igneous, + onValueChange = { igneous = it.trim { char -> char <= ' ' } }, + Modifier.width(dimensionResource(id = R.dimen.single_max_width)), + label = { Text(text = "igneous") }, + keyboardActions = KeyboardActions( + onDone = { login() } + ), + singleLine = true ) Spacer(modifier = Modifier.weight(1f)) Button( - onClick = { login() }, - Modifier.fillMaxWidth() + onClick = { login() }, + Modifier.fillMaxWidth() ) { Text(text = stringResource(id = android.R.string.ok)) } TextButton(onClick = { fillCookiesFromClipboard() }) { Text( - text = buildAnnotatedString { - withStyle( - style = SpanStyle(textDecoration = TextDecoration.Underline) - ) { - append(stringResource(id = R.string.from_clipboard)) - } - }, - modifier = Modifier - .padding(horizontal = 8.dp) + text = buildAnnotatedString { + withStyle( + style = SpanStyle(textDecoration = TextDecoration.Underline) + ) { + append(stringResource(id = R.string.from_clipboard)) + } + }, + modifier = Modifier + .padding(horizontal = 8.dp) ) } } @@ -284,29 +290,166 @@ fun CookieSignInScene() { CircularProgressIndicator() if (showErrorDialog) { AlertDialog( - onDismissRequest = { - showErrorDialog = false - }, - confirmButton = { - TextButton(onClick = { + onDismissRequest = { showErrorDialog = false - }) { - Text(text = stringResource(id = R.string.get_it)) - } - }, - title = { - Text(text = stringResource(id = R.string.sign_in_failed)) - }, - text = { - Text( - text = - """ + }, + confirmButton = { + TextButton(onClick = { + showErrorDialog = false + }) { + Text(text = stringResource(id = R.string.get_it)) + } + }, + title = { + Text(text = stringResource(id = R.string.sign_in_failed)) + }, + text = { + Text( + text = + """ ${ExceptionUtils.getReadableString(loginErrorException!!)} ${stringResource(R.string.wrong_cookie_warning)} """.trimIndent() - ) - } + ) + } ) } } + ScreenDimension.ScreenRotationLandscape->Box( + contentAlignment = Alignment.Center + ) { + Scaffold( + snackbarHost = { + SnackbarHost(hostState = snackbarHostState) + } + ) { padding -> + Row( + Modifier + .padding(dimensionResource(id = R.dimen.keyline_margin)) + .fillMaxSize() + .verticalScroll(rememberScrollState()), + verticalAlignment = Alignment.CenterVertically + ) { + Column( + Modifier + .width(dimensionResource(id = R.dimen.signinscreen_landscape_caption_frame_width)) + .padding(dimensionResource(id = R.dimen.keyline_margin)), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Icon( + imageVector = Icons.Default.Cookie, + contentDescription = null, + modifier = Modifier + .padding(dimensionResource(id = R.dimen.keyline_margin)) + .size(48.dp), + tint = Color(0xff795548) + ) + Text( + text = stringResource(id = R.string.cookie_explain), + Modifier.widthIn(max = dimensionResource(id = R.dimen.signinscreen_landscape_caption_text_width)) + .padding(top = 24.dp), + style = MaterialTheme.typography.labelLarge + ) + } + Column(Modifier.fillMaxWidth()) { + OutlinedTextField( + value = ipbMemberId, + onValueChange = { ipbMemberId = it.trim { char -> char <= ' ' } }, + Modifier.width(dimensionResource(id = R.dimen.single_max_width)), + label = { Text(text = "ipb_member_id") }, + keyboardOptions = KeyboardOptions( + imeAction = ImeAction.Next + ), + supportingText = { if (ipbMemberIdErrorState) Text(stringResource(R.string.text_is_empty)) }, + trailingIcon = { + if (ipbMemberIdErrorState) Icon( + imageVector = Icons.Filled.Info, + contentDescription = null + ) + }, + isError = ipbMemberIdErrorState, + singleLine = true + ) + OutlinedTextField( + value = ipbPassHash, + onValueChange = { ipbPassHash = it.trim { char -> char <= ' ' } }, + Modifier.width(dimensionResource(id = R.dimen.single_max_width)), + label = { Text(text = "ipb_pass_hash") }, + keyboardOptions = KeyboardOptions( + imeAction = ImeAction.Next + ), + supportingText = { if (ipbPassHashErrorState) Text(stringResource(R.string.text_is_empty)) }, + trailingIcon = { + if (ipbPassHashErrorState) Icon( + imageVector = Icons.Filled.Info, + contentDescription = null + ) + }, + isError = ipbPassHashErrorState, + singleLine = true + ) + OutlinedTextField( + value = igneous, + onValueChange = { igneous = it.trim { char -> char <= ' ' } }, + Modifier.width(dimensionResource(id = R.dimen.single_max_width)), + label = { Text(text = "igneous") }, + keyboardActions = KeyboardActions( + onDone = { login() } + ), + singleLine = true + ) + Spacer(modifier = Modifier.height(16.dp)) + Button( + onClick = { login() }, + Modifier.padding(horizontal = 4.dp) + .width(128.dp) + ) { + Text(text = stringResource(id = android.R.string.ok)) + } + Spacer(modifier = Modifier.height(16.dp)) + TextButton(onClick = { fillCookiesFromClipboard() }, modifier = Modifier + .padding(horizontal = 4.dp)) { + Text( + text = buildAnnotatedString { + withStyle( + style = SpanStyle(textDecoration = TextDecoration.Underline) + ) { + append(stringResource(id = R.string.from_clipboard)) + } + } + ) + } + } + } + } + if (isProgressIndicatorVisible) + CircularProgressIndicator() + if (showErrorDialog) { + AlertDialog( + onDismissRequest = { + showErrorDialog = false + }, + confirmButton = { + TextButton(onClick = { + showErrorDialog = false + }) { + Text(text = stringResource(id = R.string.get_it)) + } + }, + title = { + Text(text = stringResource(id = R.string.sign_in_failed)) + }, + text = { + Text( + text = + """ + ${ExceptionUtils.getReadableString(loginErrorException!!)} + ${stringResource(R.string.wrong_cookie_warning)} + """.trimIndent() + ) + } + ) + } + }} + } \ No newline at end of file diff --git a/app/src/main/java/com/hippo/ehviewer/ui/login/LoginActivity.kt b/app/src/main/java/com/hippo/ehviewer/ui/login/LoginActivity.kt index 4002a4563..b9a1889d1 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/login/LoginActivity.kt +++ b/app/src/main/java/com/hippo/ehviewer/ui/login/LoginActivity.kt @@ -1,6 +1,9 @@ package com.hippo.ehviewer.ui.login import android.os.Bundle +import android.content.Context +import android.content.res.Resources +import android.content.res.Resources.Theme import androidx.activity.compose.setContent import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.SideEffect @@ -13,6 +16,7 @@ import androidx.navigation.NavController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController +import androidx.fragment.app.Fragment import com.google.accompanist.themeadapter.material3.Mdc3Theme import com.hippo.ehviewer.Settings import com.hippo.ehviewer.client.EhCookieStore @@ -25,6 +29,7 @@ import kotlinx.coroutines.launch class LoginActivity : EhActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + var currentScreenDimension = getScreenDimension() setContent { Mdc3Theme { val navController = rememberNavController() @@ -32,7 +37,7 @@ class LoginActivity : EhActivity() { CompositionLocalProvider(LocalNavController provides navController) { NavHost(navController = navController, startDestination = SIGN_IN_ROUTE_NAME) { composable(SIGN_IN_ROUTE_NAME) { - SignInScreen() + SignInScreen(currentScreenDimension) } composable(WEBVIEW_SIGN_IN_ROUTE_NAME) { @@ -40,7 +45,7 @@ class LoginActivity : EhActivity() { } composable(COOKIE_SIGN_IN_ROUTE_NAME) { - CookieSignInScene() + CookieSignInScene(currentScreenDimension) } composable(SELECT_SITE_ROUTE_NAME) { diff --git a/app/src/main/java/com/hippo/ehviewer/ui/login/SignInScreen.kt b/app/src/main/java/com/hippo/ehviewer/ui/login/SignInScreen.kt index 30bb9bc00..5f1b57b2b 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/login/SignInScreen.kt +++ b/app/src/main/java/com/hippo/ehviewer/ui/login/SignInScreen.kt @@ -8,6 +8,8 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.widthIn @@ -58,6 +60,7 @@ import com.hippo.ehviewer.UrlOpener import com.hippo.ehviewer.client.EhEngine import com.hippo.ehviewer.client.EhUrl import com.hippo.ehviewer.client.EhUtils +import com.hippo.ehviewer.ui.ScreenDimension import com.hippo.util.ExceptionUtils import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.withNonCancellableContext @@ -66,7 +69,7 @@ import kotlinx.coroutines.Job import rikka.core.util.ContextUtils.requireActivity @Composable -fun SignInScreen() { +fun SignInScreen(currentScreenDimension : ScreenDimension) { val navController = LocalNavController.current val coroutineScope = rememberCoroutineScope() val focusManager = LocalFocusManager.current @@ -126,14 +129,17 @@ fun SignInScreen() { } } - Box( + + + when(currentScreenDimension){ + ScreenDimension.ScreenRotationPortrait -> Box( contentAlignment = Alignment.Center ) { Column( - Modifier - .padding(dimensionResource(id = R.dimen.keyline_margin)) - .fillMaxSize() - .verticalScroll(rememberScrollState()), + Modifier + .padding(dimensionResource(id = R.dimen.keyline_margin)) + .fillMaxSize() + .verticalScroll(rememberScrollState()), horizontalAlignment = Alignment.CenterHorizontally ) { Image( @@ -164,7 +170,7 @@ fun SignInScreen() { OutlinedTextField( value = password, onValueChange = { password = it }, - Modifier.width(dimensionResource(id = R.dimen.single_max_width)), + Modifier.width(dimensionResource(id = R.dimen.single_max_width)), label = { Text(stringResource(R.string.password)) }, visualTransformation = if (passwordHidden) PasswordVisualTransformation() else VisualTransformation.None, supportingText = { if (showPasswordError) Text(stringResource(R.string.error_password_cannot_empty)) }, @@ -188,9 +194,9 @@ fun SignInScreen() { Text( text = stringResource(id = R.string.app_waring), - Modifier - .widthIn(max = dimensionResource(id = R.dimen.single_max_width)) - .padding(top = 24.dp), + Modifier + .widthIn(max = dimensionResource(id = R.dimen.single_max_width)) + .padding(top = 24.dp), style = MaterialTheme.typography.labelLarge ) @@ -205,18 +211,18 @@ fun SignInScreen() { false ) }, - Modifier - .weight(1f) - .padding(horizontal = 4.dp) + Modifier + .weight(1f) + .padding(horizontal = 4.dp) ) { Text(text = stringResource(id = R.string.register)) } Button( onClick = { signIn() }, - Modifier - .weight(1f) - .padding(horizontal = 4.dp) + Modifier + .weight(1f) + .padding(horizontal = 4.dp) ) { Text(text = stringResource(id = R.string.sign_in)) } @@ -304,4 +310,185 @@ fun SignInScreen() { ) } } + ScreenDimension.ScreenRotationLandscape -> Box( + contentAlignment = Alignment.Center + ) { + Row( + Modifier + .padding(dimensionResource(id = R.dimen.keyline_margin)) + .fillMaxSize() + .verticalScroll(rememberScrollState()), + verticalAlignment = Alignment.CenterVertically + ) { + Column( Modifier + .width(dimensionResource(id = R.dimen.signinscreen_landscape_caption_frame_width)) + .padding(dimensionResource(id = R.dimen.keyline_margin)), + horizontalAlignment = Alignment.CenterHorizontally){ + Image( + painter = painterResource(id = R.drawable.ic_launcher_foreground), + contentDescription = null, + alignment = Alignment.Center, + modifier = Modifier.padding(dimensionResource(id = R.dimen.keyline_margin)) + ) + Text( + text = stringResource(id = R.string.app_waring), + Modifier + .widthIn(max = 480.dp) + .padding(top = 24.dp), + style = MaterialTheme.typography.labelLarge + )} + + Column (Modifier.fillMaxWidth()){ + OutlinedTextField( + value = username, + onValueChange = { username = it }, + Modifier.width(dimensionResource(id = R.dimen.single_max_width)), + label = { Text(stringResource(R.string.username)) }, + supportingText = { if (showUsernameError) Text(stringResource(R.string.error_username_cannot_empty)) }, + trailingIcon = { + if (showUsernameError) Icon( + imageVector = Icons.Filled.Info, + contentDescription = null + ) + }, + keyboardOptions = KeyboardOptions( + imeAction = ImeAction.Next + ), + singleLine = true, + isError = showUsernameError + ) + + OutlinedTextField( + value = password, + onValueChange = { password = it }, + Modifier.width(dimensionResource(id = R.dimen.single_max_width)), + label = { Text(stringResource(R.string.password)) }, + visualTransformation = if (passwordHidden) PasswordVisualTransformation() else VisualTransformation.None, + supportingText = { if (showPasswordError) Text(stringResource(R.string.error_password_cannot_empty)) }, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password), + keyboardActions = KeyboardActions( + onDone = { signIn() } + ), + trailingIcon = { + if (showPasswordError) + Icon(imageVector = Icons.Filled.Info, contentDescription = null) + else + IconButton(onClick = { passwordHidden = !passwordHidden }) { + val visibilityIcon = + if (passwordHidden) Icons.Filled.Visibility else Icons.Filled.VisibilityOff + Icon(imageVector = visibilityIcon, contentDescription = null) + } + }, + singleLine = true, + isError = showPasswordError + ) + + Spacer(modifier = Modifier.height(8.dp)) + + Button( + onClick = { signIn() }, + Modifier + .padding(horizontal = 4.dp) + .width(128.dp) + ) { + Text(text = stringResource(id = R.string.sign_in)) + } + FilledTonalButton( + onClick = { + UrlOpener.openUrl( + requireActivity(context), + EhUrl.URL_REGISTER, + false + ) + }, + Modifier + .padding(horizontal = 4.dp) + .width(128.dp) + ) { + Text(text = stringResource(id = R.string.register)) + } + + Spacer(modifier = Modifier.height(8.dp)) + + TextButton( + onClick = { navController.navigate(COOKIE_SIGN_IN_ROUTE_NAME) }, + Modifier.padding(horizontal = 4.dp) + ) { + Text( + text = buildAnnotatedString { + withStyle( + style = SpanStyle(textDecoration = TextDecoration.Underline) + ) { + append(stringResource(id = R.string.sign_in_via_cookies)) + } + } + ) + } + TextButton( + onClick = { navController.navigate(WEBVIEW_SIGN_IN_ROUTE_NAME) }, + Modifier.padding(horizontal = 4.dp) + ) { + Text( + text = buildAnnotatedString { + withStyle( + style = SpanStyle(textDecoration = TextDecoration.Underline) + ) { + append(stringResource(id = R.string.sign_in_via_webview)) + } + } + ) + } + + TextButton( + onClick = { + Settings.putSelectSite(false) + Settings.putGallerySite(EhUrl.SITE_E) + navController.navigate(SELECT_SITE_ROUTE_NAME) + }, + Modifier.padding(horizontal = 4.dp) + ) { + Text( + text = buildAnnotatedString { + withStyle( + style = SpanStyle(textDecoration = TextDecoration.Underline) + ) { + append(stringResource(id = R.string.tourist_mode)) + } + } + ) + } + } + + } + if (isProgressIndicatorVisible) { + CircularProgressIndicator() + } + if (showErrorDialog) { + AlertDialog( + onDismissRequest = { + showErrorDialog = false + }, + confirmButton = { + TextButton(onClick = { + showErrorDialog = false + }) { + Text(text = stringResource(id = R.string.get_it)) + } + }, + title = { + Text(text = stringResource(id = R.string.sign_in_failed)) + }, + text = { + Text( + text = + """ + ${ExceptionUtils.getReadableString(loginErrorException!!)} + ${stringResource(R.string.sign_in_failed_tip)} + """.trimIndent() + ) + } + ) + } + } + } } diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/BaseScene.kt b/app/src/main/java/com/hippo/ehviewer/ui/scene/BaseScene.kt index 1a949cdc9..d27752120 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/BaseScene.kt +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/BaseScene.kt @@ -35,6 +35,7 @@ import androidx.navigation.NavOptions import androidx.navigation.fragment.NavHostFragment import com.hippo.ehviewer.R import com.hippo.ehviewer.ui.MainActivity +import com.hippo.ehviewer.ui.ScreenDimension import rikka.core.res.resolveDrawable abstract class BaseScene : Fragment() { @@ -235,10 +236,27 @@ abstract class BaseScene : Fragment() { .build() NavHostFragment.findNavController(this).navigate(id, args, options) } + fun getScreenDimension(): ScreenDimension { + var dm = context?.resources?.displayMetrics + var screenWidth = dm?.widthPixels + var screenHeight = dm?.heightPixels + var screenDimensionStatus = ScreenDimension.ScreenRotationLandscape + + if (screenWidth != null) { + screenDimensionStatus = if(screenWidth > screenHeight!!) + ScreenDimension.ScreenRotationLandscape + else{ + ScreenDimension.ScreenRotationPortrait + } + } + return screenDimensionStatus + } companion object { const val LENGTH_SHORT = 0 const val LENGTH_LONG = 1 const val KEY_DRAWER_VIEW_STATE = "com.hippo.ehviewer.ui.scene.BaseScene:DRAWER_VIEW_STATE" } + + } \ No newline at end of file diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.kt b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.kt index 1467266a6..1323fbe1b 100755 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.kt +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.kt @@ -53,6 +53,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.GridItemSpan import androidx.compose.foundation.lazy.grid.LazyGridScope @@ -157,6 +158,7 @@ import com.hippo.ehviewer.ui.widget.CrystalCard import com.hippo.ehviewer.ui.widget.EhAsyncPreview import com.hippo.ehviewer.ui.widget.GalleryDetailHeaderCard import com.hippo.ehviewer.ui.widget.GalleryDetailRating +import com.hippo.ehviewer.ui.ScreenDimension import com.hippo.ehviewer.widget.GalleryRatingBar import com.hippo.ehviewer.widget.GalleryRatingBar.OnUserRateListener import com.hippo.text.URLImageGetter @@ -498,6 +500,7 @@ class GalleryDetailScene : BaseScene(), DownloadInfoListener { } } + @Composable private fun GalleryDetailContent( galleryInfo: GalleryInfo, @@ -505,7 +508,8 @@ class GalleryDetailScene : BaseScene(), DownloadInfoListener { contentPadding: PaddingValues, modifier: Modifier ) { - LazyVerticalGrid( + when(getScreenDimension()){ + ScreenDimension.ScreenRotationPortrait ->LazyVerticalGrid( columns = GridCells.Adaptive(Settings.thumbSizeDp), contentPadding = contentPadding, modifier = modifier.padding(horizontal = dimensionResource(id = R.dimen.keyline_margin)) @@ -520,23 +524,23 @@ class GalleryDetailScene : BaseScene(), DownloadInfoListener { onUploaderChipClick = ::onUploaderChipClick, onBlockUploaderIconClick = ::showFilterUploaderDialog, modifier = Modifier - .fillMaxWidth() - .padding(vertical = dimensionResource(id = R.dimen.keyline_margin)) + .fillMaxWidth() + .padding(vertical = dimensionResource(id = R.dimen.keyline_margin)) ) Row { FilledTonalButton( onClick = ::onDownloadButtonClick, modifier = Modifier - .padding(horizontal = 4.dp) - .weight(1F) + .padding(horizontal = 4.dp) + .weight(1F) ) { Text(text = downloadButtonText) } Button( onClick = ::onReadButtonClick, modifier = Modifier - .padding(horizontal = 4.dp) - .weight(1F) + .padding(horizontal = 4.dp) + .weight(1F) ) { Text(text = readButtonText) } @@ -557,6 +561,67 @@ class GalleryDetailScene : BaseScene(), DownloadInfoListener { galleryDetailPreview(galleryDetail) } } + ScreenDimension.ScreenRotationLandscape -> LazyVerticalGrid( + columns = GridCells.Adaptive(Settings.thumbSizeDp), + contentPadding = contentPadding, + modifier = modifier.padding(horizontal = dimensionResource(id = R.dimen.keyline_margin)) + ) { + item(span = { GridItemSpan(maxCurrentLineSpan) }) { + Column { + Row(modifier = Modifier.fillMaxWidth() + ){ + GalleryDetailHeaderCard( + galleryInfo = galleryInfo, + galleryDetail = galleryDetail, + onInfoCardClick = ::onGalleryInfoCardClick, + onCategoryChipClick = ::onCategoryChipClick, + onUploaderChipClick = ::onUploaderChipClick, + onBlockUploaderIconClick = ::showFilterUploaderDialog, + modifier = Modifier + .width(dimensionResource(id = R.dimen.gallery_detail_card_landscape_width)) + .padding(vertical = dimensionResource(id = R.dimen.keyline_margin)) + ) + Column(modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Spacer(modifier = modifier.height(16.dp)) + Button( + onClick = ::onReadButtonClick, + modifier = Modifier + .height(56.dp) + .padding(horizontal = 16.dp) + .width(192.dp) + ) { + Text(text = readButtonText) + } + Spacer(modifier = modifier.height(24.dp)) + FilledTonalButton( + onClick = ::onDownloadButtonClick, + modifier = Modifier + .height(56.dp) + .padding(horizontal = 16.dp) + .width(192.dp) + ) { + Text(text = downloadButtonText) + } + }} + if (galleryDetail != null) { + BelowHeader(galleryDetail) + } else { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + } + } + if (galleryDetail != null) { + galleryDetailPreview(galleryDetail) + } + } + } } private fun LazyGridScope.galleryDetailPreview(gd: GalleryDetail) { @@ -571,8 +636,8 @@ class GalleryDetailScene : BaseScene(), DownloadInfoListener { CrystalCard( onClick = ::navigateToPreview, modifier = Modifier - .fillMaxWidth() - .aspectRatio(0.6666667F) + .fillMaxWidth() + .aspectRatio(0.6666667F) ) {} Text(stringResource(R.string.more_previews)) } @@ -590,8 +655,8 @@ class GalleryDetailScene : BaseScene(), DownloadInfoListener { mainActivity?.startReaderActivity(gd, it.position) }, modifier = Modifier - .fillMaxWidth() - .aspectRatio(0.6666667F) + .fillMaxWidth() + .aspectRatio(0.6666667F) ) { EhAsyncPreview( model = it, @@ -665,8 +730,8 @@ class GalleryDetailScene : BaseScene(), DownloadInfoListener { CrystalCard( onClick = ::showNewerVersionDialog, modifier = Modifier - .fillMaxWidth() - .height(32.dp), + .fillMaxWidth() + .height(32.dp), ) {} Text(text = stringResource(id = R.string.newer_version_avaliable)) } @@ -718,8 +783,8 @@ class GalleryDetailScene : BaseScene(), DownloadInfoListener { ) { Column( modifier = Modifier - .padding(8.dp) - .fillMaxWidth(), + .padding(8.dp) + .fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally ) { GalleryDetailRating(rating = galleryDetail.rating) diff --git a/app/src/main/java/com/hippo/ehviewer/ui/widget/GalleryDetailWidgets.kt b/app/src/main/java/com/hippo/ehviewer/ui/widget/GalleryDetailWidgets.kt index 9affd3dad..c46e93c90 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/widget/GalleryDetailWidgets.kt +++ b/app/src/main/java/com/hippo/ehviewer/ui/widget/GalleryDetailWidgets.kt @@ -137,7 +137,7 @@ fun GalleryDetailHeaderCard( .width(dimensionResource(id = R.dimen.gallery_detail_thumb_width)) ) } - Spacer(modifier = Modifier.weight(1F)) + Spacer(modifier = Modifier.weight(0.5F)) Column( modifier = Modifier.height(dimensionResource(id = R.dimen.gallery_detail_thumb_height)), horizontalAlignment = Alignment.End diff --git a/app/src/main/res/values-television/dimens.xml b/app/src/main/res/values-television/dimens.xml new file mode 100644 index 000000000..2bcf3d703 --- /dev/null +++ b/app/src/main/res/values-television/dimens.xml @@ -0,0 +1,27 @@ + + + + + 256dp + 192dp + 608dp + 640dp + 480dp + + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 1f195b2f7..1b93e3e9a 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -16,6 +16,10 @@ + 480dp + 384dp + 480dp + 16dp 260dp 280dp