This commit is contained in:
Avently
2024-10-23 14:06:20 +07:00
parent 298db13388
commit 2ac0452976
6 changed files with 122 additions and 120 deletions
@@ -677,18 +677,19 @@ fun ChatLayout(
)
}
}
val oneHandUI = remember { appPrefs.oneHandUI.state }
Box(Modifier
.layoutId(CHAT_COMPOSE_LAYOUT_ID)
.align(Alignment.BottomCenter)
.imePadding()
.navigationBarsPadding()
.then(if (oneHandUI.value) Modifier.padding(bottom = AppBarHeight * fontSizeSqrtMultiplier) else Modifier.navigationBarsPadding())
) {
composeView()
}
}
val oneHandUI = remember { appPrefs.oneHandUI.state }
NavigationBarBackground(true, oneHandUI.value)
Column {
Box(if (oneHandUI.value) Modifier.align(Alignment.BottomStart).navigationBarsPadding() else Modifier) {
if (selectedChatItems.value == null) {
if (chatInfo != null) {
ChatInfoToolbar(chatInfo, back, info, startCall, endCall, addMembers, openGroupLink, changeNtfsState, onSearchValueChanged, showSearch)
@@ -703,7 +704,7 @@ fun ChatLayout(
}
@Composable
fun ColumnScope.ChatInfoToolbar(
fun BoxScope.ChatInfoToolbar(
chatInfo: ChatInfo,
back: () -> Unit,
info: () -> Unit,
@@ -855,13 +856,13 @@ fun ColumnScope.ChatInfoToolbar(
}
}
}
val oneHandUI = remember { appPrefs.oneHandUI.state }
DefaultTopAppBar(
navigationButton = { if (appPlatform.isAndroid || showSearch.value) { NavigationButtonBack(onBackClicked) } },
title = { ChatInfoToolbarTitle(chatInfo) },
onTitleClick = if (chatInfo is ChatInfo.Local) null else info,
showSearch = showSearch.value,
onTop = true,
onTop = oneHandUI.value,
onSearchValueChanged = onSearchValueChanged,
buttons = barButtons
)
@@ -871,12 +872,12 @@ fun ColumnScope.ChatInfoToolbar(
DefaultDropdownMenu(
showMenu,
modifier = Modifier.onSizeChanged { with(density) { width.value = it.width.toDp().coerceAtLeast(250.dp) } },
offset = DpOffset(-width.value, 0.dp)
offset = DpOffset(-width.value, AppBarHeight)
) {
menuItems.forEach { it() }
}
}
Divider(Modifier.background(MaterialTheme.colors.background))
Divider(Modifier.background(MaterialTheme.colors.background).align(if (oneHandUI.value) Alignment.TopStart else Alignment.BottomStart))
}
@Composable
@@ -1479,7 +1480,14 @@ private fun TopEndFloatingButton(
}
@Composable
fun topPaddingToContent(): Dp = AppBarHeight * fontSizeSqrtMultiplier + WindowInsets.statusBars.asPaddingValues().calculateTopPadding()
fun topPaddingToContent(): Dp {
val oneHandUI = remember { appPrefs.oneHandUI.state }
return if (oneHandUI.value) {
WindowInsets.statusBars.asPaddingValues().calculateTopPadding()
} else {
AppBarHeight * fontSizeSqrtMultiplier + WindowInsets.statusBars.asPaddingValues().calculateTopPadding()
}
}
@Composable
private fun FloatingDate(
@@ -12,6 +12,7 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import chat.simplex.common.model.*
import chat.simplex.common.model.ChatController.appPrefs
import chat.simplex.common.platform.BackHandler
import chat.simplex.common.platform.chatModel
import chat.simplex.common.views.helpers.*
@@ -20,10 +21,11 @@ import chat.simplex.res.MR
import dev.icerock.moko.resources.compose.painterResource
@Composable
fun ColumnScope.SelectedItemsTopToolbar(selectedChatItems: MutableState<Set<Long>?>) {
fun BoxScope.SelectedItemsTopToolbar(selectedChatItems: MutableState<Set<Long>?>) {
val onBackClicked = { selectedChatItems.value = null }
BackHandler(onBack = onBackClicked)
val count = selectedChatItems.value?.size ?: 0
val oneHandUI = remember { appPrefs.oneHandUI.state }
DefaultTopAppBar(
navigationButton = { NavigationButtonClose(onButtonClicked = onBackClicked) },
title = {
@@ -40,10 +42,10 @@ fun ColumnScope.SelectedItemsTopToolbar(selectedChatItems: MutableState<Set<Long
},
onTitleClick = null,
showSearch = false,
onTop = true,
onTop = oneHandUI.value,
onSearchValueChanged = {},
)
Divider()
Divider(Modifier.align(if (oneHandUI.value) Alignment.TopStart else Alignment.BottomStart))
}
@Composable
@@ -488,74 +488,78 @@ fun connectIfOpenedViaUri(rhId: Long?, uri: String, chatModel: ChatModel) {
@Composable
private fun ChatListSearchBar(listState: LazyListState, searchText: MutableState<TextFieldValue>, searchShowingSimplexLink: MutableState<Boolean>, searchChatFilteredBySimplexLink: MutableState<String?>) {
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.fillMaxWidth()) {
val focusRequester = remember { FocusRequester() }
var focused by remember { mutableStateOf(false) }
Icon(
painterResource(MR.images.ic_search),
contentDescription = null,
Modifier.padding(start = DEFAULT_PADDING, end = DEFAULT_PADDING_HALF).size(22.dp * fontSizeSqrtMultiplier),
tint = MaterialTheme.colors.secondary
)
SearchTextField(
Modifier.weight(1f).onFocusChanged { focused = it.hasFocus }.focusRequester(focusRequester),
placeholder = stringResource(MR.strings.search_or_paste_simplex_link),
alwaysVisible = true,
searchText = searchText,
enabled = !remember { searchShowingSimplexLink }.value,
trailingContent = null,
) {
searchText.value = searchText.value.copy(it)
}
val hasText = remember { derivedStateOf { searchText.value.text.isNotEmpty() } }
if (hasText.value) {
val hideSearchOnBack: () -> Unit = { searchText.value = TextFieldValue() }
BackHandler(onBack = hideSearchOnBack)
KeyChangeEffect(chatModel.currentRemoteHost.value) {
hideSearchOnBack()
Box {
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.fillMaxWidth().heightIn(min = AppBarHeight * fontSizeSqrtMultiplier)) {
val focusRequester = remember { FocusRequester() }
var focused by remember { mutableStateOf(false) }
Icon(
painterResource(MR.images.ic_search),
contentDescription = null,
Modifier.padding(start = DEFAULT_PADDING, end = DEFAULT_PADDING_HALF).size(22.dp * fontSizeSqrtMultiplier),
tint = MaterialTheme.colors.secondary
)
SearchTextField(
Modifier.weight(1f).onFocusChanged { focused = it.hasFocus }.focusRequester(focusRequester),
placeholder = stringResource(MR.strings.search_or_paste_simplex_link),
alwaysVisible = true,
searchText = searchText,
enabled = !remember { searchShowingSimplexLink }.value,
trailingContent = null,
) {
searchText.value = searchText.value.copy(it)
}
} else {
val padding = if (appPlatform.isDesktop) 0.dp else 7.dp
if (chatModel.chats.value.isNotEmpty()) {
ToggleFilterEnabledButton()
}
Spacer(Modifier.width(padding))
}
val focusManager = LocalFocusManager.current
val keyboardState = getKeyboardState()
LaunchedEffect(keyboardState.value) {
if (keyboardState.value == KeyboardState.Closed && focused) {
focusManager.clearFocus()
}
}
val view = LocalMultiplatformView()
LaunchedEffect(Unit) {
snapshotFlow { searchText.value.text }
.distinctUntilChanged()
.collect {
val link = strHasSingleSimplexLink(it.trim())
if (link != null) {
// if SimpleX link is pasted, show connection dialogue
hideKeyboard(view)
if (link.format is Format.SimplexLink) {
val linkText = link.simplexLinkText(link.format.linkType, link.format.smpHosts)
searchText.value = searchText.value.copy(linkText, selection = TextRange.Zero)
}
searchShowingSimplexLink.value = true
searchChatFilteredBySimplexLink.value = null
connect(link.text, searchChatFilteredBySimplexLink) { searchText.value = TextFieldValue() }
} else if (!searchShowingSimplexLink.value || it.isEmpty()) {
if (it.isNotEmpty()) {
// if some other text is pasted, enter search mode
focusRequester.requestFocus()
} else if (listState.layoutInfo.totalItemsCount > 0) {
listState.scrollToItem(0)
}
searchShowingSimplexLink.value = false
searchChatFilteredBySimplexLink.value = null
}
val hasText = remember { derivedStateOf { searchText.value.text.isNotEmpty() } }
if (hasText.value) {
val hideSearchOnBack: () -> Unit = { searchText.value = TextFieldValue() }
BackHandler(onBack = hideSearchOnBack)
KeyChangeEffect(chatModel.currentRemoteHost.value) {
hideSearchOnBack()
}
} else {
val padding = if (appPlatform.isDesktop) 0.dp else 7.dp
if (chatModel.chats.value.isNotEmpty()) {
ToggleFilterEnabledButton()
}
Spacer(Modifier.width(padding))
}
val focusManager = LocalFocusManager.current
val keyboardState = getKeyboardState()
LaunchedEffect(keyboardState.value) {
if (keyboardState.value == KeyboardState.Closed && focused) {
focusManager.clearFocus()
}
}
val view = LocalMultiplatformView()
LaunchedEffect(Unit) {
snapshotFlow { searchText.value.text }
.distinctUntilChanged()
.collect {
val link = strHasSingleSimplexLink(it.trim())
if (link != null) {
// if SimpleX link is pasted, show connection dialogue
hideKeyboard(view)
if (link.format is Format.SimplexLink) {
val linkText = link.simplexLinkText(link.format.linkType, link.format.smpHosts)
searchText.value = searchText.value.copy(linkText, selection = TextRange.Zero)
}
searchShowingSimplexLink.value = true
searchChatFilteredBySimplexLink.value = null
connect(link.text, searchChatFilteredBySimplexLink) { searchText.value = TextFieldValue() }
} else if (!searchShowingSimplexLink.value || it.isEmpty()) {
if (it.isNotEmpty()) {
// if some other text is pasted, enter search mode
focusRequester.requestFocus()
} else if (listState.layoutInfo.totalItemsCount > 0) {
listState.scrollToItem(0)
}
searchShowingSimplexLink.value = false
searchChatFilteredBySimplexLink.value = null
}
}
}
}
val oneHandUI = remember { appPrefs.oneHandUI.state }
Divider(Modifier.align(if (oneHandUI.value) Alignment.TopStart else Alignment.BottomStart))
}
}
@@ -685,14 +689,12 @@ private fun BoxScope.ChatList(searchText: MutableState<TextFieldValue>) {
.background(MaterialTheme.colors.background)
) {
if (oneHandUI.value) {
Divider()
Column(Modifier.consumeWindowInsets(WindowInsets.navigationBars).consumeWindowInsets(PaddingValues(bottom = AppBarHeight))) {
ChatListSearchBar(listState, searchText, searchShowingSimplexLink, searchChatFilteredBySimplexLink)
Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime))
}
} else {
ChatListSearchBar(listState, searchText, searchShowingSimplexLink, searchChatFilteredBySimplexLink)
Divider()
}
}
}
@@ -40,7 +40,7 @@ fun CloseSheetBar(
val interactionSource = remember { MutableInteractionSource() }
val oneHandUI = remember { appPrefs.oneHandUI.state }
Column(
Box(
modifier = Modifier
.fillMaxWidth()
.then(if (oneHandUI.value) Modifier.navigationBarsPadding() else Modifier)
@@ -53,9 +53,6 @@ fun CloseSheetBar(
}
}
) {
if (oneHandUI.value && title.value.isNotEmpty()) {
CloseBarDivider(connection)
}
Row(
modifier = Modifier.padding(barPaddingValues),
content = {
@@ -96,19 +93,18 @@ fun CloseSheetBar(
}
}
)
if (!oneHandUI.value && title.value.isNotEmpty()) {
CloseBarDivider(connection)
}
CloseBarDivider(connection)
}
}
@Composable
private fun CloseBarDivider(connection: CollapsingAppBarNestedScrollConnection?) {
private fun BoxScope.CloseBarDivider(connection: CollapsingAppBarNestedScrollConnection?) {
if (connection != null) {
val oneHandUI = remember { appPrefs.oneHandUI.state }
val prefAlpha = appPrefs.inAppBarsAlpha.get()
Divider(
Modifier
.align(if (oneHandUI.value) Alignment.TopStart else Alignment.BottomStart)
.graphicsLayer {
alpha = if (oneHandUI.value) prefAlpha else topTitleAlpha(false, connection)
}
@@ -127,42 +123,39 @@ fun CloseSheetBarBottom(
val background = MaterialTheme.colors.background.mixWith(MaterialTheme.colors.onBackground, 0.97f)
val themeBackgroundMix = background.copy(remember { appPrefs.inAppBarsAlpha.state }.value)
val interactionSource = remember { MutableInteractionSource() }
Column(
Box(
modifier = Modifier
.fillMaxWidth()
.navigationBarsPadding()
.clickable(interactionSource = interactionSource, indication = null) { /* receive clicks to not allow to click through */ }
.heightIn(min = AppBarHeight * fontSizeSqrtMultiplier)
.background(themeBackgroundMix)
) {
Row(
content = {
Row(
Modifier
.fillMaxWidth()
.height(AppBarHeight * fontSizeSqrtMultiplier),
verticalAlignment = Alignment.CenterVertically
) {
if (showClose) {
NavigationButtonBack(tintColor = tintColor, onButtonClicked = close)
}
Row(
Modifier.weight(1f),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
Text(
closeBarTitle,
fontWeight = FontWeight.SemiBold,
maxLines = 1
)
}
Row {
endButtons()
}
}
Modifier
.fillMaxWidth()
.height(AppBarHeight * fontSizeSqrtMultiplier),
verticalAlignment = Alignment.CenterVertically
) {
if (showClose) {
NavigationButtonBack(tintColor = tintColor, onButtonClicked = close)
}
)
Row(
Modifier.weight(1f),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
Text(
closeBarTitle,
fontWeight = FontWeight.SemiBold,
maxLines = 1
)
}
Row {
endButtons()
}
}
val oneHandUI = remember { appPrefs.oneHandUI.state }
Divider(Modifier.align(if (oneHandUI.value) Alignment.TopStart else Alignment.BottomStart))
}
}
@@ -62,11 +62,9 @@ fun ModalData.NewChatSheet(rh: RemoteHostInfo?, close: () -> Unit) {
}
if (oneHandUI.value) {
Column(Modifier.align(Alignment.BottomCenter)) {
Divider()
CloseSheetBarBottom(
close = close,
showClose = true,
endButtons = { Spacer(Modifier.minimumInteractiveComponentSize()) },
closeBarTitle = generalGetString(MR.strings.new_message)
)
}
@@ -726,11 +724,9 @@ private fun ModalData.DeletedContactsView(rh: RemoteHostInfo?, closeDeletedChats
}
if (oneHandUI.value) {
Column(Modifier.align(Alignment.BottomCenter)) {
Divider()
CloseSheetBarBottom(
close = closeDeletedChats,
showClose = true,
endButtons = { Spacer(Modifier.minimumInteractiveComponentSize()) },
closeBarTitle = generalGetString(MR.strings.deleted_chats),
)
}
@@ -101,12 +101,13 @@ private fun ScrollBar(
scrollBarDraggingState: MutableState<Boolean>,
additionalBarHeight: State<Dp>?
) {
val oneHandUI = remember { appPrefs.oneHandUI.state }
val padding = if (additionalBarHeight != null) {
PaddingValues(top = AppBarHeight * fontSizeSqrtMultiplier, bottom = additionalBarHeight.value)
PaddingValues(top = if (oneHandUI.value) 0.dp else AppBarHeight * fontSizeSqrtMultiplier, bottom = additionalBarHeight.value)
} else if (reverseLayout) {
PaddingValues(bottom = AppBarHeight * fontSizeSqrtMultiplier)
} else {
PaddingValues(top = AppBarHeight * fontSizeSqrtMultiplier)
PaddingValues(top = if (oneHandUI.value) 0.dp else AppBarHeight * fontSizeSqrtMultiplier)
}
Box(Modifier.fillMaxSize().padding(padding), contentAlignment = Alignment.CenterEnd) {
DesktopScrollBar(rememberScrollbarAdapter(state), Modifier.fillMaxHeight(), scrollBarAlpha, scrollJob, reverseLayout, scrollBarDraggingState)