Initial support of adaptive landscape layout with

jetpack compose.
This commit is contained in:
hathlife authored and tarsin committed 2023-03-26 17:39:38 +08:00
1 parent 8746f04030
commit 3519756da3
9 files changed
+599 -131

No files matched your search

@@ -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
}
}
@@ -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()
)
}
)
}
}}
}
@@ -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) {
@@ -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()
)
}
)
}
}
}
}
@@ -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"
}
}
@@ -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)
@@ -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