Compare commits

...

1 Commits

Author SHA1 Message Date
Avently
95f4a8c906 desktop: responsive design for large and small screens 2023-07-28 18:14:36 +07:00
10 changed files with 61 additions and 29 deletions

View File

@@ -50,4 +50,7 @@ actual fun screenWidth(): Dp = LocalConfiguration.current.screenWidthDp.dp
actual fun desktopExpandWindowToWidth(width: Dp) {}
@Composable
actual fun allowToShowBackButtonInCenter(): Boolean = true
actual fun isRtl(text: CharSequence): Boolean = BidiFormatter.getInstance().isRtl(text)

View File

@@ -274,26 +274,44 @@ fun EndPartOfScreen() {
@Composable
fun DesktopScreen(settingsState: SettingsViewState) {
Box {
// 56.dp is a size of unused space of settings drawer
Box(Modifier.width(DEFAULT_START_MODAL_WIDTH + 56.dp)) {
StartPartOfScreen(settingsState)
}
Box(Modifier.widthIn(max = DEFAULT_START_MODAL_WIDTH)) {
ModalManager.start.showInView()
}
Row(Modifier.padding(start = DEFAULT_START_MODAL_WIDTH).clipToBounds()) {
Box(Modifier.widthIn(min = DEFAULT_MIN_CENTER_MODAL_WIDTH).weight(1f)) {
CenterPartOfScreen()
BoxWithConstraints {
Box {
val maxWidth = this@BoxWithConstraints.maxWidth
// 56.dp is a size of unused space of settings drawer
val startMaxWidth = when {
maxWidth >= DEFAULT_START_MODAL_WIDTH + DEFAULT_MIN_CENTER_MODAL_WIDTH -> DEFAULT_START_MODAL_WIDTH + 56.dp
ChatModel.chatId.value == null && !ModalManager.center.hasModalsOpen() -> maxWidth
else -> DEFAULT_START_MODAL_WIDTH
}
if (ModalManager.end.hasModalsOpen()) {
VerticalDivider()
val startModalMaxWidth = when {
maxWidth >= DEFAULT_START_MODAL_WIDTH + DEFAULT_MIN_CENTER_MODAL_WIDTH -> DEFAULT_START_MODAL_WIDTH
ChatModel.chatId.value == null && !ModalManager.center.hasModalsOpen() -> maxWidth
else -> DEFAULT_START_MODAL_WIDTH
}
Box(Modifier.widthIn(max = DEFAULT_END_MODAL_WIDTH).clipToBounds()) {
EndPartOfScreen()
Box(Modifier.widthIn(max = startMaxWidth)) {
StartPartOfScreen(settingsState)
Box(Modifier.widthIn(max = startModalMaxWidth)) {
ModalManager.start.showInView()
}
}
val centerMaxWidth = when {
maxWidth >= DEFAULT_START_MODAL_WIDTH + DEFAULT_MIN_CENTER_MODAL_WIDTH -> maxWidth - DEFAULT_START_MODAL_WIDTH
ChatModel.chatId.value != null || ModalManager.center.hasModalsOpen() -> maxOf(DEFAULT_START_MODAL_WIDTH, maxWidth) - 1.dp
else -> 0.dp
}
Row(Modifier.padding(start = maxOf(maxWidth - centerMaxWidth, 0.dp))) {
Box(Modifier.widthIn(min = DEFAULT_MIN_CENTER_MODAL_WIDTH).weight(1f)) {
CenterPartOfScreen()
}
if (ModalManager.end.hasModalsOpen() && maxWidth >= DEFAULT_START_MODAL_WIDTH + DEFAULT_MIN_CENTER_MODAL_WIDTH + DEFAULT_END_MODAL_WIDTH) {
VerticalDivider()
}
Box(Modifier.widthIn(max = if (centerMaxWidth < DEFAULT_MIN_CENTER_MODAL_WIDTH + DEFAULT_END_MODAL_WIDTH) centerMaxWidth else DEFAULT_END_MODAL_WIDTH).clipToBounds()) {
EndPartOfScreen()
}
}
}
val (userPickerState, scaffoldState, switchingUsers ) = settingsState
val (userPickerState, scaffoldState, switchingUsers) = settingsState
val scope = rememberCoroutineScope()
if (scaffoldState.drawerState.isOpen) {
Box(
@@ -306,7 +324,9 @@ fun DesktopScreen(settingsState: SettingsViewState) {
})
)
}
VerticalDivider(Modifier.padding(start = DEFAULT_START_MODAL_WIDTH))
if (maxWidth >= DEFAULT_START_MODAL_WIDTH + DEFAULT_MIN_CENTER_MODAL_WIDTH) {
VerticalDivider(Modifier.padding(start = DEFAULT_START_MODAL_WIDTH))
}
UserPicker(chatModel, userPickerState, switchingUsers) {
scope.launch { if (scaffoldState.drawerState.isOpen) scaffoldState.drawerState.close() else scaffoldState.drawerState.open() }
}

View File

@@ -5,6 +5,7 @@ import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.Dp
import chat.simplex.common.ui.theme.DEFAULT_MIN_CENTER_MODAL_WIDTH
import com.russhwolf.settings.Settings
import dev.icerock.moko.resources.StringResource
@@ -30,4 +31,7 @@ expect fun screenWidth(): Dp
expect fun desktopExpandWindowToWidth(width: Dp)
@Composable
expect fun allowToShowBackButtonInCenter(): Boolean
expect fun isRtl(text: CharSequence): Boolean

View File

@@ -474,7 +474,7 @@ fun ChatInfoToolbar(
showSearch = false
}
}
if (appPlatform.isAndroid) {
if (allowToShowBackButtonInCenter()) {
BackHandler(onBack = onBackClicked)
}
val barButtons = arrayListOf<@Composable RowScope.() -> Unit>()
@@ -534,7 +534,7 @@ fun ChatInfoToolbar(
}
DefaultTopAppBar(
navigationButton = { if (appPlatform.isAndroid || showSearch) { NavigationButtonBack(onBackClicked) } },
navigationButton = { if (allowToShowBackButtonInCenter() || showSearch) { Box(Modifier.offset(y = 4.dp)) { NavigationButtonBack(onBackClicked) } } },
title = { ChatInfoToolbarTitle(chat.chatInfo) },
onTitleClick = info,
showSearch = showSearch,

View File

@@ -16,6 +16,7 @@ import androidx.compose.desktop.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import chat.simplex.common.model.*
import chat.simplex.common.platform.*
import chat.simplex.common.ui.theme.*
import chat.simplex.common.views.chat.*
import chat.simplex.common.views.chat.group.deleteGroupDialog
@@ -24,8 +25,6 @@ import chat.simplex.common.views.chat.item.InvalidJSONView
import chat.simplex.common.views.chat.item.ItemAction
import chat.simplex.common.views.helpers.*
import chat.simplex.common.views.newchat.ContactConnectionInfoView
import chat.simplex.common.platform.appPlatform
import chat.simplex.common.platform.ntfManager
import chat.simplex.res.MR
import kotlinx.coroutines.delay
import kotlinx.datetime.Clock
@@ -42,6 +41,7 @@ fun ChatListNavLinkView(chat: Chat, chatModel: ChatModel) {
showMenu.value = false
delay(500L)
}
val showClose = allowToShowBackButtonInCenter()
when (chat.chatInfo) {
is ChatInfo.Direct -> {
val contactNetworkStatus = chatModel.contactNetworkStatus(chat.chatInfo.contact)
@@ -75,7 +75,7 @@ fun ChatListNavLinkView(chat: Chat, chatModel: ChatModel) {
click = {
ModalManager.center.closeModals()
ModalManager.end.closeModals()
ModalManager.center.showModalCloseable(true, showClose = appPlatform.isAndroid) { close ->
ModalManager.center.showModalCloseable(true, showClose = showClose) { close ->
ContactConnectionInfoView(chatModel, chat.chatInfo.contactConnection.connReqInv, chat.chatInfo.contactConnection, false, close)
}
},
@@ -341,13 +341,14 @@ fun ContactRequestMenuItems(chatInfo: ChatInfo.ContactRequest, chatModel: ChatMo
@Composable
fun ContactConnectionMenuItems(chatInfo: ChatInfo.ContactConnection, chatModel: ChatModel, showMenu: MutableState<Boolean>) {
val showClose = allowToShowBackButtonInCenter()
ItemAction(
stringResource(MR.strings.set_contact_name),
painterResource(MR.images.ic_edit),
onClick = {
ModalManager.center.closeModals()
ModalManager.end.closeModals()
ModalManager.center.showModalCloseable(true, showClose = appPlatform.isAndroid) { close ->
ModalManager.center.showModalCloseable(true, showClose = showClose) { close ->
ContactConnectionInfoView(chatModel, chatInfo.contactConnection.connReqInv, chatInfo.contactConnection, true, close)
}
showMenu.value = false

View File

@@ -58,7 +58,7 @@ fun ChatListView(chatModel: ChatModel, settingsState: SettingsViewState, setPerf
connectIfOpenedViaUri(url, chatModel)
}
}
val endPadding = if (appPlatform.isDesktop) 56.dp else 0.dp
val endPadding = if (appPlatform.isDesktop && !allowToShowBackButtonInCenter()) 56.dp else 0.dp
var searchInList by rememberSaveable { mutableStateOf("") }
val scope = rememberCoroutineScope()
val (userPickerState, scaffoldState, switchingUsers ) = settingsState

View File

@@ -18,8 +18,7 @@ import chat.simplex.common.ui.theme.*
import chat.simplex.common.views.helpers.*
import chat.simplex.common.model.Chat
import chat.simplex.common.model.ChatModel
import chat.simplex.common.platform.BackHandler
import chat.simplex.common.platform.appPlatform
import chat.simplex.common.platform.*
import chat.simplex.res.MR
import kotlinx.coroutines.flow.MutableStateFlow
@@ -27,7 +26,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
fun ShareListView(chatModel: ChatModel, settingsState: SettingsViewState, stopped: Boolean) {
var searchInList by rememberSaveable { mutableStateOf("") }
val (userPickerState, scaffoldState, switchingUsers) = settingsState
val endPadding = if (appPlatform.isDesktop) 56.dp else 0.dp
val endPadding = if (appPlatform.isDesktop && !allowToShowBackButtonInCenter()) 56.dp else 0.dp
Scaffold(
Modifier.padding(end = endPadding),
scaffoldState = scaffoldState,

View File

@@ -96,7 +96,7 @@ private fun NewChatSheetLayout(
}
}
}
val endPadding = if (appPlatform.isDesktop) 56.dp else 0.dp
val endPadding = if (appPlatform.isDesktop && !allowToShowBackButtonInCenter()) 56.dp else 0.dp
val maxWidth = with(LocalDensity.current) { screenWidth() * density }
Column(
Modifier

View File

@@ -73,7 +73,7 @@ private fun SetDeliveryReceiptsLayout(
skip: () -> Unit,
userCount: Int,
) {
val endPadding = if (appPlatform.isDesktop) 56.dp else 0.dp
val endPadding = if (appPlatform.isDesktop && !allowToShowBackButtonInCenter()) 56.dp else 0.dp
Column(
Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(top = DEFAULT_PADDING, end = endPadding),
horizontalAlignment = Alignment.CenterHorizontally,

View File

@@ -6,6 +6,8 @@ import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.*
import chat.simplex.common.simplexWindowState
import chat.simplex.common.ui.theme.DEFAULT_MIN_CENTER_MODAL_WIDTH
import chat.simplex.common.ui.theme.DEFAULT_START_MODAL_WIDTH
import com.russhwolf.settings.*
import dev.icerock.moko.resources.StringResource
import dev.icerock.moko.resources.desc.desc
@@ -54,6 +56,9 @@ actual fun desktopExpandWindowToWidth(width: Dp) {
simplexWindowState.windowState.size = simplexWindowState.windowState.size.copy(width = width)
}
@Composable
actual fun allowToShowBackButtonInCenter(): Boolean = simplexWindowState.windowState.size.width < DEFAULT_START_MODAL_WIDTH + DEFAULT_MIN_CENTER_MODAL_WIDTH
actual fun isRtl(text: CharSequence): Boolean {
if (text.isEmpty()) return false
return text.any { char ->