feat: Compose 登录

This commit is contained in:
HuanCheng65 2024-01-30 13:47:40 +08:00
parent 7eac0d1edc
commit 197d0626a7
No known key found for this signature in database
GPG Key ID: 5EC9DD60A32C7360
8 changed files with 361 additions and 37 deletions

View File

@ -127,7 +127,6 @@ dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2' implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2'
implementation 'org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.7' implementation 'org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.7'
// implementation 'androidx.compose.material3:material3:1.0.0'
def media3_version = "1.2.1" def media3_version = "1.2.1"
implementation "androidx.media3:media3-exoplayer:$media3_version" implementation "androidx.media3:media3-exoplayer:$media3_version"
@ -176,6 +175,7 @@ dependencies {
// Optional - Add full set of material icons // Optional - Add full set of material icons
implementation 'androidx.compose.material:material-icons-extended' implementation 'androidx.compose.material:material-icons-extended'
implementation 'androidx.compose.ui:ui-util' implementation 'androidx.compose.ui:ui-util'
// implementation 'androidx.compose.material3:material3:1.0.0'
// Android Studio Preview support // Android Studio Preview support
implementation 'androidx.compose.ui:ui-tooling-preview' implementation 'androidx.compose.ui:ui-tooling-preview'

View File

@ -0,0 +1,322 @@
package com.huanchengfly.tieba.post.ui.page.login
import android.annotation.SuppressLint
import android.webkit.CookieManager
import android.webkit.WebView
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.DropdownMenuItem
import androidx.compose.material.Icon
import androidx.compose.material.LinearProgressIndicator
import androidx.compose.material.MaterialTheme
import androidx.compose.material.SnackbarDuration
import androidx.compose.material.SnackbarHostState
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.MoreVert
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.core.net.toUri
import com.huanchengfly.tieba.post.R
import com.huanchengfly.tieba.post.api.retrofit.exception.getErrorMessage
import com.huanchengfly.tieba.post.ui.common.theme.compose.ExtendedTheme
import com.huanchengfly.tieba.post.ui.page.webview.MyWebChromeClient
import com.huanchengfly.tieba.post.ui.page.webview.MyWebViewClient
import com.huanchengfly.tieba.post.ui.page.webview.isInternalHost
import com.huanchengfly.tieba.post.ui.widgets.compose.BackNavigationIcon
import com.huanchengfly.tieba.post.ui.widgets.compose.ClickMenu
import com.huanchengfly.tieba.post.ui.widgets.compose.LazyLoad
import com.huanchengfly.tieba.post.ui.widgets.compose.LoadingState
import com.huanchengfly.tieba.post.ui.widgets.compose.LocalSnackbarHostState
import com.huanchengfly.tieba.post.ui.widgets.compose.MyScaffold
import com.huanchengfly.tieba.post.ui.widgets.compose.Toolbar
import com.huanchengfly.tieba.post.ui.widgets.compose.WebView
import com.huanchengfly.tieba.post.ui.widgets.compose.rememberMenuState
import com.huanchengfly.tieba.post.ui.widgets.compose.rememberSaveableWebViewState
import com.huanchengfly.tieba.post.ui.widgets.compose.rememberWebViewNavigator
import com.huanchengfly.tieba.post.utils.AccountUtil
import com.huanchengfly.tieba.post.utils.AccountUtil.parseCookie
import com.huanchengfly.tieba.post.utils.ClientUtils
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.cancellable
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.launch
const val LOGIN_URL =
"https://wappass.baidu.com/passport?login&u=https%3A%2F%2Ftieba.baidu.com%2Findex%2Ftbwise%2Fmine"
@SuppressLint("SetJavaScriptEnabled")
@Destination
@Composable
fun LoginPage(
navigator: DestinationsNavigator,
) {
val context = LocalContext.current
val coroutineScope = rememberCoroutineScope()
val webViewState = rememberSaveableWebViewState()
val webViewNavigator = rememberWebViewNavigator()
var loaded by rememberSaveable {
mutableStateOf(false)
}
var pageTitle by rememberSaveable {
mutableStateOf("")
}
val displayPageTitle by remember {
derivedStateOf {
pageTitle.ifEmpty {
context.getString(R.string.title_default)
}
}
}
val currentHost by remember {
derivedStateOf {
webViewState.lastLoadedUrl?.toUri()?.host.orEmpty().lowercase()
}
}
val isExternalHost by remember {
derivedStateOf {
currentHost.isNotEmpty() && !isInternalHost(currentHost)
}
}
DisposableEffect(Unit) {
val job = coroutineScope.launch {
snapshotFlow { webViewState.pageTitle }
.filterNotNull()
.filter { it.isNotEmpty() }
.cancellable()
.collect {
pageTitle = it
}
}
onDispose {
job.cancel()
}
}
LazyLoad(loaded = loaded) {
webViewNavigator.loadUrl(LOGIN_URL)
loaded = true
}
val isLoading by remember {
derivedStateOf {
webViewState.loadingState is LoadingState.Loading
}
}
val progress by remember {
derivedStateOf {
webViewState.loadingState.let {
if (it is LoadingState.Loading) {
it.progress
} else {
0f
}
}
}
}
val animatedProgress by animateFloatAsState(targetValue = progress, label = "progress")
MyScaffold(
topBar = {
Toolbar(
title = {
Column {
Text(
text = displayPageTitle,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
if (isExternalHost) {
Text(
text = currentHost,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
color = ExtendedTheme.colors.onTopBarSecondary,
style = MaterialTheme.typography.caption
)
}
}
},
navigationIcon = { BackNavigationIcon(onBackPressed = { navigator.navigateUp() }) },
actions = {
val menuState = rememberMenuState()
ClickMenu(
menuContent = {
DropdownMenuItem(
onClick = {
webViewNavigator.reload()
dismiss()
}
) {
Text(text = stringResource(id = R.string.title_refresh))
}
},
menuState = menuState,
triggerShape = CircleShape
) {
Box(
modifier = Modifier.size(48.dp),
contentAlignment = Alignment.Center
) {
Icon(
imageVector = Icons.Rounded.MoreVert,
contentDescription = stringResource(id = R.string.btn_more)
)
}
}
},
)
}
) { paddingValues ->
Box {
val snackbarHostState = LocalSnackbarHostState.current
WebView(
state = webViewState,
modifier = Modifier
.fillMaxSize()
.padding(paddingValues),
navigator = webViewNavigator,
onCreated = {
it.settings.apply {
javaScriptEnabled = true
domStorageEnabled = true
setSupportZoom(true)
builtInZoomControls = true
displayZoomControls = false
}
},
client = remember(navigator) {
LoginWebViewClient(
navigator,
coroutineScope,
snackbarHostState
)
},
chromeClient = remember { MyWebChromeClient(context, coroutineScope) }
)
if (isLoading) {
LinearProgressIndicator(
progress = animatedProgress,
modifier = Modifier.fillMaxWidth()
)
}
}
}
}
class LoginWebViewClient(
nativeNavigator: DestinationsNavigator? = null,
val coroutineScope: CoroutineScope,
val snackbarHostState: SnackbarHostState,
) : MyWebViewClient(nativeNavigator) {
private var isLoadingAccount = false
override fun injectCookies(url: String) {}
override fun onPageFinished(view: WebView, url: String?) {
super.onPageFinished(view, url)
if (url == null) {
return
}
if (isLoadingAccount) {
return
}
val cookieStr = CookieManager.getInstance().getCookie(url) ?: return
val cookies = parseCookie(cookieStr).mapKeys { it.key.uppercase() }
val bduss = cookies["BDUSS"]
val sToken = cookies["STOKEN"]
val baiduId = cookies["BAIDUID"]
if (url.startsWith("https://tieba.baidu.com/index/tbwise/") || url.startsWith("https://tiebac.baidu.com/index/tbwise/")) {
if (bduss == null || sToken == null) {
return
}
if (!baiduId.isNullOrEmpty() && ClientUtils.baiduId.isNullOrEmpty()) {
coroutineScope.launch {
ClientUtils.saveBaiduId(context, baiduId)
}
}
coroutineScope.launch {
snackbarHostState.showSnackbar(
context.getString(R.string.text_please_wait),
duration = SnackbarDuration.Indefinite
)
}
coroutineScope.launch {
AccountUtil.fetchAccountFlow(bduss, sToken, cookieStr)
.catch {
coroutineScope.launch {
snackbarHostState.currentSnackbarData?.dismiss()
snackbarHostState.showSnackbar(
context.getString(
R.string.text_login_failed,
it.getErrorMessage()
), duration = SnackbarDuration.Short
)
}
navigator.loadUrl(LOGIN_URL)
isLoadingAccount = false
}
.flowOn(Dispatchers.Main)
.collect { account ->
isLoadingAccount = false
AccountUtil.newAccount(account.uid, account) {
if (it) {
AccountUtil.switchAccount(context, account.id)
coroutineScope.launch {
snackbarHostState.currentSnackbarData?.dismiss()
snackbarHostState.showSnackbar(
context.getString(R.string.text_login_success),
duration = SnackbarDuration.Short
)
}
coroutineScope.launch {
delay(1500L)
nativeNavigator?.navigateUp()
}
} else {
coroutineScope.launch {
snackbarHostState.currentSnackbarData?.dismiss()
snackbarHostState.showSnackbar(
context.getString(R.string.text_login_failed_default),
duration = SnackbarDuration.Short
)
}
view.loadUrl(LOGIN_URL)
}
}
}
}
}
}
}

View File

@ -64,16 +64,15 @@ import com.airbnb.lottie.compose.rememberLottieComposition
import com.google.accompanist.drawablepainter.rememberDrawablePainter import com.google.accompanist.drawablepainter.rememberDrawablePainter
import com.google.accompanist.placeholder.placeholder import com.google.accompanist.placeholder.placeholder
import com.huanchengfly.tieba.post.R import com.huanchengfly.tieba.post.R
import com.huanchengfly.tieba.post.activities.LoginActivity
import com.huanchengfly.tieba.post.arch.GlobalEvent import com.huanchengfly.tieba.post.arch.GlobalEvent
import com.huanchengfly.tieba.post.arch.collectPartialAsState import com.huanchengfly.tieba.post.arch.collectPartialAsState
import com.huanchengfly.tieba.post.arch.onGlobalEvent import com.huanchengfly.tieba.post.arch.onGlobalEvent
import com.huanchengfly.tieba.post.arch.pageViewModel import com.huanchengfly.tieba.post.arch.pageViewModel
import com.huanchengfly.tieba.post.goToActivity
import com.huanchengfly.tieba.post.ui.common.theme.compose.ExtendedTheme import com.huanchengfly.tieba.post.ui.common.theme.compose.ExtendedTheme
import com.huanchengfly.tieba.post.ui.common.theme.compose.pullRefreshIndicator import com.huanchengfly.tieba.post.ui.common.theme.compose.pullRefreshIndicator
import com.huanchengfly.tieba.post.ui.page.LocalNavigator import com.huanchengfly.tieba.post.ui.page.LocalNavigator
import com.huanchengfly.tieba.post.ui.page.destinations.ForumPageDestination import com.huanchengfly.tieba.post.ui.page.destinations.ForumPageDestination
import com.huanchengfly.tieba.post.ui.page.destinations.LoginPageDestination
import com.huanchengfly.tieba.post.ui.page.destinations.SearchPageDestination import com.huanchengfly.tieba.post.ui.page.destinations.SearchPageDestination
import com.huanchengfly.tieba.post.ui.widgets.Chip import com.huanchengfly.tieba.post.ui.widgets.Chip
import com.huanchengfly.tieba.post.ui.widgets.compose.ActionItem import com.huanchengfly.tieba.post.ui.widgets.compose.ActionItem
@ -638,7 +637,7 @@ fun EmptyScreen(
canOpenExplore: Boolean, canOpenExplore: Boolean,
onOpenExplore: () -> Unit onOpenExplore: () -> Unit
) { ) {
val context = LocalContext.current val navigator = LocalNavigator.current
TipScreen( TipScreen(
title = { title = {
if (!loggedIn) { if (!loggedIn) {
@ -671,7 +670,7 @@ fun EmptyScreen(
if (!loggedIn) { if (!loggedIn) {
Button( Button(
onClick = { onClick = {
context.goToActivity<LoginActivity>() navigator.navigate(LoginPageDestination)
}, },
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()

View File

@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.width
import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.LocalContentColor import androidx.compose.material.LocalContentColor
import androidx.compose.material.MaterialTheme import androidx.compose.material.MaterialTheme
import androidx.compose.material.Scaffold
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.AccountCircle import androidx.compose.material.icons.rounded.AccountCircle
@ -20,11 +21,8 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.google.accompanist.insets.ui.Scaffold
import com.huanchengfly.tieba.post.R import com.huanchengfly.tieba.post.R
import com.huanchengfly.tieba.post.activities.LoginActivity
import com.huanchengfly.tieba.post.dataStore import com.huanchengfly.tieba.post.dataStore
import com.huanchengfly.tieba.post.goToActivity
import com.huanchengfly.tieba.post.models.database.Account import com.huanchengfly.tieba.post.models.database.Account
import com.huanchengfly.tieba.post.ui.common.prefs.PrefsScreen import com.huanchengfly.tieba.post.ui.common.prefs.PrefsScreen
import com.huanchengfly.tieba.post.ui.common.prefs.widgets.TextPref import com.huanchengfly.tieba.post.ui.common.prefs.widgets.TextPref
@ -35,6 +33,7 @@ import com.huanchengfly.tieba.post.ui.page.destinations.AccountManagePageDestina
import com.huanchengfly.tieba.post.ui.page.destinations.BlockSettingsPageDestination import com.huanchengfly.tieba.post.ui.page.destinations.BlockSettingsPageDestination
import com.huanchengfly.tieba.post.ui.page.destinations.CustomSettingsPageDestination import com.huanchengfly.tieba.post.ui.page.destinations.CustomSettingsPageDestination
import com.huanchengfly.tieba.post.ui.page.destinations.HabitSettingsPageDestination import com.huanchengfly.tieba.post.ui.page.destinations.HabitSettingsPageDestination
import com.huanchengfly.tieba.post.ui.page.destinations.LoginPageDestination
import com.huanchengfly.tieba.post.ui.page.destinations.MoreSettingsPageDestination import com.huanchengfly.tieba.post.ui.page.destinations.MoreSettingsPageDestination
import com.huanchengfly.tieba.post.ui.page.destinations.OKSignSettingsPageDestination import com.huanchengfly.tieba.post.ui.page.destinations.OKSignSettingsPageDestination
import com.huanchengfly.tieba.post.ui.widgets.compose.Avatar import com.huanchengfly.tieba.post.ui.widgets.compose.Avatar
@ -63,8 +62,8 @@ fun NowAccountItem(
account: Account?, account: Account?,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
val navigator = LocalNavigator.current
if (account != null) { if (account != null) {
val navigator = LocalNavigator.current
TextPref( TextPref(
title = stringResource(id = R.string.title_account_manage), title = stringResource(id = R.string.title_account_manage),
summary = stringResource(id = R.string.summary_now_account, account.nameShow ?: account.name), summary = stringResource(id = R.string.summary_now_account, account.nameShow ?: account.name),
@ -82,12 +81,11 @@ fun NowAccountItem(
modifier = modifier, modifier = modifier,
) )
} else { } else {
val context = LocalContext.current
TextPref( TextPref(
title = stringResource(id = R.string.title_account_manage), title = stringResource(id = R.string.title_account_manage),
summary = stringResource(id = R.string.summary_not_logged_in), summary = stringResource(id = R.string.summary_not_logged_in),
enabled = true, enabled = true,
onClick = { context.goToActivity<LoginActivity>() }, onClick = { navigator.navigate(LoginPageDestination) },
leadingIcon = { leadingIcon = {
LeadingIcon { LeadingIcon {
AvatarIcon( AvatarIcon(
@ -110,23 +108,23 @@ fun NowAccountItem(
fun SettingsPage( fun SettingsPage(
navigator: DestinationsNavigator, navigator: DestinationsNavigator,
) { ) {
Scaffold( ProvideNavigator(navigator = navigator) {
backgroundColor = Color.Transparent, Scaffold(
topBar = { backgroundColor = Color.Transparent,
TitleCentredToolbar( topBar = {
title = { TitleCentredToolbar(
Text( title = {
text = stringResource(id = R.string.title_settings), Text(
fontWeight = FontWeight.Bold, style = MaterialTheme.typography.h6 text = stringResource(id = R.string.title_settings),
) fontWeight = FontWeight.Bold, style = MaterialTheme.typography.h6
}, )
navigationIcon = { },
BackNavigationIcon(onBackPressed = { navigator.navigateUp() }) navigationIcon = {
} BackNavigationIcon(onBackPressed = { navigator.navigateUp() })
) }
}, )
) { },
ProvideNavigator(navigator = navigator) { ) {
PrefsScreen( PrefsScreen(
dataStore = LocalContext.current.dataStore, dataStore = LocalContext.current.dataStore,
dividerThickness = 0.dp, dividerThickness = 0.dp,

View File

@ -31,14 +31,13 @@ import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.huanchengfly.tieba.post.R import com.huanchengfly.tieba.post.R
import com.huanchengfly.tieba.post.activities.LoginActivity
import com.huanchengfly.tieba.post.dataStore import com.huanchengfly.tieba.post.dataStore
import com.huanchengfly.tieba.post.goToActivity
import com.huanchengfly.tieba.post.ui.common.prefs.PrefsScreen import com.huanchengfly.tieba.post.ui.common.prefs.PrefsScreen
import com.huanchengfly.tieba.post.ui.common.prefs.widgets.DropDownPref import com.huanchengfly.tieba.post.ui.common.prefs.widgets.DropDownPref
import com.huanchengfly.tieba.post.ui.common.prefs.widgets.EditTextPref import com.huanchengfly.tieba.post.ui.common.prefs.widgets.EditTextPref
import com.huanchengfly.tieba.post.ui.common.prefs.widgets.TextPref import com.huanchengfly.tieba.post.ui.common.prefs.widgets.TextPref
import com.huanchengfly.tieba.post.ui.common.theme.compose.ExtendedTheme import com.huanchengfly.tieba.post.ui.common.theme.compose.ExtendedTheme
import com.huanchengfly.tieba.post.ui.page.destinations.LoginPageDestination
import com.huanchengfly.tieba.post.ui.page.settings.LeadingIcon import com.huanchengfly.tieba.post.ui.page.settings.LeadingIcon
import com.huanchengfly.tieba.post.ui.widgets.compose.AvatarIcon import com.huanchengfly.tieba.post.ui.widgets.compose.AvatarIcon
import com.huanchengfly.tieba.post.ui.widgets.compose.BackNavigationIcon import com.huanchengfly.tieba.post.ui.widgets.compose.BackNavigationIcon
@ -130,7 +129,7 @@ fun AccountManagePage(
prefsItem { prefsItem {
TextPref( TextPref(
title = stringResource(id = R.string.title_new_account), title = stringResource(id = R.string.title_new_account),
onClick = { context.goToActivity<LoginActivity>() }, onClick = { navigator.navigate(LoginPageDestination) },
leadingIcon = { leadingIcon = {
LeadingIcon { LeadingIcon {
AvatarIcon( AvatarIcon(

View File

@ -50,13 +50,13 @@ import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.google.accompanist.drawablepainter.rememberDrawablePainter import com.google.accompanist.drawablepainter.rememberDrawablePainter
import com.huanchengfly.tieba.post.R import com.huanchengfly.tieba.post.R
import com.huanchengfly.tieba.post.activities.LoginActivity
import com.huanchengfly.tieba.post.arch.BaseComposeActivity.Companion.LocalWindowSizeClass import com.huanchengfly.tieba.post.arch.BaseComposeActivity.Companion.LocalWindowSizeClass
import com.huanchengfly.tieba.post.arch.GlobalEvent import com.huanchengfly.tieba.post.arch.GlobalEvent
import com.huanchengfly.tieba.post.arch.emitGlobalEvent import com.huanchengfly.tieba.post.arch.emitGlobalEvent
import com.huanchengfly.tieba.post.goToActivity
import com.huanchengfly.tieba.post.ui.common.theme.compose.ExtendedTheme import com.huanchengfly.tieba.post.ui.common.theme.compose.ExtendedTheme
import com.huanchengfly.tieba.post.ui.common.windowsizeclass.WindowWidthSizeClass.Companion.Compact import com.huanchengfly.tieba.post.ui.common.windowsizeclass.WindowWidthSizeClass.Companion.Compact
import com.huanchengfly.tieba.post.ui.page.LocalNavigator
import com.huanchengfly.tieba.post.ui.page.destinations.LoginPageDestination
import com.huanchengfly.tieba.post.utils.AccountUtil import com.huanchengfly.tieba.post.utils.AccountUtil
import com.huanchengfly.tieba.post.utils.AccountUtil.LocalAccount import com.huanchengfly.tieba.post.utils.AccountUtil.LocalAccount
import com.huanchengfly.tieba.post.utils.StringUtil import com.huanchengfly.tieba.post.utils.StringUtil
@ -73,6 +73,7 @@ fun AccountNavIcon(
spacer: Boolean = true, spacer: Boolean = true,
size: Dp = Sizes.Small size: Dp = Sizes.Small
) { ) {
val navigator = LocalNavigator.current
val currentAccount = LocalAccount.current val currentAccount = LocalAccount.current
if (spacer) Spacer(modifier = Modifier.width(12.dp)) if (spacer) Spacer(modifier = Modifier.width(12.dp))
if (currentAccount == null) { if (currentAccount == null) {
@ -125,9 +126,11 @@ fun AccountNavIcon(
VerticalDivider( VerticalDivider(
modifier = Modifier.padding(vertical = 8.dp) modifier = Modifier.padding(vertical = 8.dp)
) )
DropdownMenuItem(onClick = { DropdownMenuItem(
context.goToActivity<LoginActivity>() onClick = {
}) { navigator.navigate(LoginPageDestination)
}
) {
Icon( Icon(
imageVector = Icons.Rounded.Add, imageVector = Icons.Rounded.Add,
contentDescription = stringResource(id = R.string.title_new_account), contentDescription = stringResource(id = R.string.title_new_account),

View File

@ -199,7 +199,7 @@ object AccountUtil {
fun parseCookie(cookie: String): Map<String, String> { fun parseCookie(cookie: String): Map<String, String> {
return cookie return cookie
.split(";") .split(";")
.map { it.split("=") } .map { it.trim().split("=") }
.filter { it.size > 1 } .filter { it.size > 1 }
.associate { it.first() to it.drop(1).joinToString("=") } .associate { it.first() to it.drop(1).joinToString("=") }
} }

View File

@ -761,4 +761,7 @@
<string name="menu_add_user_to_white_list">添加到白名单</string> <string name="menu_add_user_to_white_list">添加到白名单</string>
<string name="btn_block">屏蔽选项</string> <string name="btn_block">屏蔽选项</string>
<string name="text_god_verify">%s领域大神</string> <string name="text_god_verify">%s领域大神</string>
<string name="text_login_failed">登录失败 %s</string>
<string name="text_login_success">登录成功,即将跳转</string>
<string name="text_login_failed_default">登录失败</string>
</resources> </resources>