Initial support of adaptive landscape layout with
jetpack compose.
This commit is contained in:
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
|
||||
|
||||
Reference in new issue
Block a user