diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.android.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.android.kt index 24f2f62620..54e3061d25 100644 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.android.kt +++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.android.kt @@ -34,6 +34,7 @@ private val USER_PICKER_ROW_PADDING = 16.dp @Composable actual fun UserPickerUsersSection( users: List, + iconColor: Color, stopped: Boolean, onUserClicked: (user: User) -> Unit, ) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/App.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/App.kt index 6709af8e33..411448b7c8 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/App.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/App.kt @@ -151,7 +151,9 @@ fun MainScreen() { } SetupClipboardListener() if (appPlatform.isAndroid) { - AndroidScreen(userPickerState) + AndroidWrapInCallLayout { + AndroidScreen(userPickerState) + } } else { DesktopScreen(userPickerState) } @@ -183,7 +185,9 @@ fun MainScreen() { } } if (appPlatform.isAndroid) { - ModalManager.fullscreen.showInView() + AndroidWrapInCallLayout { + ModalManager.fullscreen.showInView() + } SwitchingUsersView() } @@ -250,11 +254,23 @@ fun MainScreen() { val ANDROID_CALL_TOP_PADDING = 40.dp +@Composable +fun AndroidWrapInCallLayout(content: @Composable () -> Unit) { + val call = remember { chatModel.activeCall}.value + val showCallArea = call != null && call.callState != CallState.WaitCapabilities && call.callState != CallState.InvitationAccepted + Box { + Box(Modifier.padding(top = if (showCallArea) ANDROID_CALL_TOP_PADDING else 0.dp)) { + content() + } + if (call != null && showCallArea) { + ActiveCallInteractiveArea(call) + } + } +} + @Composable fun AndroidScreen(userPickerState: MutableStateFlow) { BoxWithConstraints { - val call = remember { chatModel.activeCall} .value - val showCallArea = call != null && call.callState != CallState.WaitCapabilities && call.callState != CallState.InvitationAccepted val currentChatId = remember { mutableStateOf(chatModel.chatId.value) } val offset = remember { Animatable(if (chatModel.chatId.value == null) 0f else maxWidth.value) } Box( @@ -265,7 +281,6 @@ fun AndroidScreen(userPickerState: MutableStateFlow) { // But offset is remembered already, so this is a better way than dropping a value of offset translationX = -minOf(offset.value.dp, maxWidth).toPx() } - .padding(top = if (showCallArea) ANDROID_CALL_TOP_PADDING else 0.dp) ) { StartPartOfScreen(userPickerState) } @@ -294,15 +309,11 @@ fun AndroidScreen(userPickerState: MutableStateFlow) { } Box(Modifier .graphicsLayer { translationX = maxWidth.toPx() - minOf(offset.value.dp, maxWidth).toPx() } - .padding(top = if (showCallArea) ANDROID_CALL_TOP_PADDING else 0.dp) ) Box2@{ currentChatId.value?.let { ChatView(currentChatId, onComposed) } } - if (call != null && showCallArea) { - ActiveCallInteractiveArea(call) - } } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/WelcomeView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/WelcomeView.kt index 632aaf6c7c..0741eeef91 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/WelcomeView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/WelcomeView.kt @@ -52,7 +52,7 @@ fun CreateProfile(chatModel: ChatModel, close: () -> Unit) { modifier = Modifier.fillMaxSize() ) { Column(Modifier.padding(horizontal = DEFAULT_PADDING)) { - AppBarTitle(stringResource(MR.strings.create_profile), bottomPadding = DEFAULT_PADDING) + AppBarTitle(stringResource(MR.strings.create_profile), withPadding = false, bottomPadding = DEFAULT_PADDING) Row(Modifier.padding(bottom = DEFAULT_PADDING_HALF).fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) { Text( stringResource(MR.strings.display_name), diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt index 375989c9ad..257a20a115 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt @@ -864,11 +864,14 @@ fun ColumnScope.ChatInfoToolbar( onSearchValueChanged = onSearchValueChanged, buttons = barButtons ) - Box(Modifier - .fillMaxWidth() - .wrapContentSize(Alignment.TopEnd) - ) { - DefaultDropdownMenu(showMenu) { + Box(Modifier.fillMaxWidth().wrapContentSize(Alignment.TopEnd)) { + val density = LocalDensity.current + val width = remember { mutableStateOf(250.dp) } + DefaultDropdownMenu( + showMenu, + modifier = Modifier.onSizeChanged { with(density) { width.value = it.width.toDp().coerceAtLeast(250.dp) } }, + offset = DpOffset(-width.value, 0.dp) + ) { menuItems.forEach { it() } } } @@ -1373,8 +1376,14 @@ fun BoxScope.FloatingButtons( onLongClick = { showDropDown.value = true } ) - Box(Modifier.align(Alignment.TopEnd)) { - DefaultDropdownMenu(showDropDown, offset = DpOffset(-DEFAULT_PADDING, 24.dp + fabSize + topPaddingToContent())) { + Box(Modifier.fillMaxWidth().wrapContentSize(Alignment.TopEnd)) { + val density = LocalDensity.current + val width = remember { mutableStateOf(250.dp) } + DefaultDropdownMenu( + showDropDown, + modifier = Modifier.onSizeChanged { with(density) { width.value = it.width.toDp().coerceAtLeast(250.dp) } }, + offset = DpOffset(-DEFAULT_PADDING - width.value, 24.dp + fabSize + topPaddingToContent()) + ) { ItemAction( generalGetString(MR.strings.mark_read), painterResource(MR.images.ic_check), diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ScanCodeView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ScanCodeView.kt index 73017c3d42..6399adbdd0 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ScanCodeView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ScanCodeView.kt @@ -1,9 +1,11 @@ package chat.simplex.common.views.chat +import SectionBottomSpacer import androidx.compose.foundation.layout.* import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import chat.simplex.common.platform.ColumnWithScrollBar import chat.simplex.common.ui.theme.DEFAULT_PADDING import chat.simplex.common.views.helpers.* import chat.simplex.common.views.newchat.QRCodeScanner @@ -12,7 +14,7 @@ import dev.icerock.moko.resources.compose.stringResource @Composable fun ScanCodeView(verifyCode: (String?, cb: (Boolean) -> Unit) -> Unit, close: () -> Unit) { - Column( + ColumnWithScrollBar( Modifier.fillMaxSize() ) { AppBarTitle(stringResource(MR.strings.scan_code)) @@ -28,5 +30,6 @@ fun ScanCodeView(verifyCode: (String?, cb: (Boolean) -> Unit) -> Unit, close: () } } Text(stringResource(MR.strings.scan_code_from_contacts_app), Modifier.padding(horizontal = DEFAULT_PADDING)) + SectionBottomSpacer() } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.kt index 4a3bce7752..455d68fb79 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.kt @@ -23,6 +23,7 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.* import chat.simplex.common.model.* +import chat.simplex.common.model.ChatController.appPrefs import chat.simplex.common.model.ChatController.stopRemoteHostAndReloadHosts import chat.simplex.common.model.ChatModel.controller import chat.simplex.common.ui.theme.* @@ -137,12 +138,17 @@ fun UserPicker( } } + val oneHandUI = remember { appPrefs.oneHandUI.state } + val shouldDrawProfilePicturesDarker = appPlatform.isDesktop && MaterialTheme.colors.secondaryVariant == LightColorPalette.secondaryVariant && MaterialTheme.colors.background == LightColorPalette.background + val iconColor = if (shouldDrawProfilePicturesDarker) MaterialTheme.colors.secondaryVariant.darker(0.05f) else MaterialTheme.colors.secondaryVariant + val background = MaterialTheme.colors.background.mixWith(MaterialTheme.colors.onBackground, alpha = 1 - userPickerAlpha()) PlatformUserPicker( modifier = Modifier .height(IntrinsicSize.Min) .fillMaxWidth() - .then(if (newChat.isVisible()) Modifier.shadow(8.dp, clip = true) else Modifier) - .background(if (appPlatform.isAndroid) MaterialTheme.colors.background.mixWith(MaterialTheme.colors.onBackground, alpha = 1 - userPickerAlpha()) else MaterialTheme.colors.surface) + .then(if (newChat.isVisible()) Modifier.shadow(8.dp, clip = true, ambientColor = background) else Modifier) + .padding(top = if (appPlatform.isDesktop && oneHandUI.value) 14.dp else 0.dp) + .background(background) .padding(bottom = USER_PICKER_SECTION_SPACING - DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL), pickerState = userPickerState ) { @@ -198,12 +204,13 @@ fun UserPicker( UserPickerUsersSection( users = users, onUserClicked = onUserClicked, + iconColor = iconColor, stopped = stopped ) } } else if (currentUser != null) { SectionItemView({ onUserClicked(currentUser) }, 80.dp, padding = PaddingValues(start = 16.dp, end = DEFAULT_PADDING), disabled = stopped) { - ProfilePreview(currentUser.profile, stopped = stopped) + ProfilePreview(currentUser.profile, iconColor = iconColor, stopped = stopped) } } } @@ -234,6 +241,7 @@ fun UserPicker( Column(modifier = Modifier.padding(vertical = DEFAULT_MIN_SECTION_ITEM_PADDING_VERTICAL)) { UserPickerUsersSection( users = inactiveUsers, + iconColor = iconColor, onUserClicked = onUserClicked, stopped = stopped ) @@ -519,6 +527,7 @@ private fun DevicePickerRow( @Composable expect fun UserPickerUsersSection( users: List, + iconColor: Color, stopped: Boolean, onUserClicked: (user: User) -> Unit, ) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/DefaultDropdownMenu.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/DefaultDropdownMenu.kt index 267fc86462..1f00af2809 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/DefaultDropdownMenu.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/DefaultDropdownMenu.kt @@ -14,6 +14,7 @@ import androidx.compose.ui.unit.dp @Composable fun DefaultDropdownMenu( showMenu: MutableState, + modifier: Modifier = Modifier, offset: DpOffset = DpOffset(0.dp, 0.dp), dropdownMenuItems: (@Composable () -> Unit)? ) { @@ -23,7 +24,7 @@ fun DefaultDropdownMenu( DropdownMenu( expanded = showMenu.value, onDismissRequest = { showMenu.value = false }, - modifier = Modifier + modifier = modifier .widthIn(min = 250.dp) .background(MaterialTheme.colors.surface) .padding(vertical = 4.dp), diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ContactConnectionInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ContactConnectionInfoView.kt index 64ff7e4f40..e091490877 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ContactConnectionInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ContactConnectionInfoView.kt @@ -89,7 +89,7 @@ private fun ContactConnectionInfoLayout( SettingsActionItemWithContent( icon = painterResource(MR.images.ic_theater_comedy_filled), text = null, - click = { ModalManager.start.showModal { IncognitoView() } }, + click = { ModalManager.end.showModal { IncognitoView() } }, iconColor = Indigo, extraPadding = false ) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatView.kt index 4260191d74..a7f9a90552 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatView.kt @@ -33,6 +33,7 @@ import chat.simplex.common.model.ChatModel.controller import chat.simplex.common.model.ChatModel.withChats import chat.simplex.common.platform.* import chat.simplex.common.ui.theme.* +import chat.simplex.common.views.chat.topPaddingToContent import chat.simplex.common.views.helpers.* import chat.simplex.common.views.usersettings.* import chat.simplex.res.MR @@ -398,7 +399,7 @@ fun ActiveProfilePicker( .fillMaxSize() .alpha(if (progressByTimeout) 0.6f else 1f) ) { - LazyColumnWithScrollBar(userScrollEnabled = !switchingProfile.value) { + LazyColumnWithScrollBar(Modifier.padding(top = topPaddingToContent()), userScrollEnabled = !switchingProfile.value) { item { AppBarTitle(stringResource(MR.strings.select_chat_profile), hostDevice(rhId), bottomPadding = DEFAULT_PADDING) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/ScanProtocolServer.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/ScanProtocolServer.kt index 7c2c578d6a..659e61b335 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/ScanProtocolServer.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/ScanProtocolServer.kt @@ -7,6 +7,7 @@ import dev.icerock.moko.resources.compose.stringResource import androidx.compose.ui.unit.dp import chat.simplex.common.model.ServerAddress.Companion.parseServerAddress import chat.simplex.common.model.ServerCfg +import chat.simplex.common.platform.ColumnWithScrollBar import chat.simplex.common.ui.theme.DEFAULT_PADDING import chat.simplex.common.views.helpers.* import chat.simplex.common.views.newchat.QRCodeScanner @@ -17,7 +18,7 @@ expect fun ScanProtocolServer(rhId: Long?, onNext: (ServerCfg) -> Unit) @Composable fun ScanProtocolServerLayout(rhId: Long?, onNext: (ServerCfg) -> Unit) { - Column( + ColumnWithScrollBar( Modifier .fillMaxSize() ) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/VersionInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/VersionInfoView.kt index 06a4762210..52addd146b 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/VersionInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/VersionInfoView.kt @@ -1,6 +1,5 @@ package chat.simplex.common.views.usersettings -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.material.Text import androidx.compose.runtime.Composable @@ -8,6 +7,7 @@ import androidx.compose.ui.Modifier import dev.icerock.moko.resources.compose.stringResource import chat.simplex.common.BuildConfigCommon import chat.simplex.common.model.CoreVersionInfo +import chat.simplex.common.platform.ColumnWithScrollBar import chat.simplex.common.platform.appPlatform import chat.simplex.common.ui.theme.DEFAULT_PADDING import chat.simplex.common.views.helpers.AppBarTitle @@ -15,7 +15,7 @@ import chat.simplex.res.MR @Composable fun VersionInfoView(info: CoreVersionInfo) { - Column( + ColumnWithScrollBar( Modifier.padding(horizontal = DEFAULT_PADDING), ) { AppBarTitle(stringResource(MR.strings.app_version_title), withPadding = false) diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.desktop.kt index bf2e118cd1..fda666250e 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.desktop.kt @@ -10,6 +10,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp +import chat.simplex.common.model.ChatController.appPrefs import chat.simplex.common.platform.* import chat.simplex.common.ui.theme.* import chat.simplex.common.views.call.Call @@ -27,14 +28,15 @@ actual fun ActiveCallInteractiveArea(call: Call) { CompositionLocalProvider( LocalIndication provides NoIndication ) { + val oneHandUI = remember { appPrefs.oneHandUI.state } Box( Modifier .fillMaxSize(), - contentAlignment = Alignment.BottomEnd + contentAlignment = if (oneHandUI.value) Alignment.TopEnd else Alignment.BottomEnd ) { Box( Modifier - .padding(end = 15.dp, bottom = 92.dp) + .padding(end = 15.dp, top = if (oneHandUI.value) 15.dp else 0.dp, bottom = if (oneHandUI.value) 0.dp else 92.dp) .size(67.dp) .combinedClickable(onClick = { val chat = chatModel.getChat(call.contact.id) diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.desktop.kt index 29f38d1b03..eb77c1029b 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.desktop.kt @@ -10,6 +10,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow @@ -26,6 +27,7 @@ import kotlinx.coroutines.flow.MutableStateFlow @Composable actual fun UserPickerUsersSection( users: List, + iconColor: Color, stopped: Boolean, onUserClicked: (user: User) -> Unit, ) { @@ -58,7 +60,7 @@ actual fun UserPickerUsersSection( ) { val user = u.user Box { - ProfileImage(size = 55.dp, image = user.profile.image, color = MaterialTheme.colors.secondaryVariant) + ProfileImage(size = 55.dp, image = user.profile.image, color = iconColor) if (u.unreadCount > 0 && !user.activeUser) { unreadBadge(u.unreadCount, user.showNtfs, true)