refactor modals hierarchy

This commit is contained in:
Evgeny @ SimpleX Chat
2026-05-21 09:17:32 +00:00
parent 3f4b002b29
commit cb94a321c7
41 changed files with 490 additions and 469 deletions
@@ -1,7 +1,7 @@
package chat.simplex.common.views.usersettings
import SectionBottomSpacer
import SectionSpacer
import SectionDividerSpaced
import SectionView
import android.app.Activity
import android.content.ComponentName
@@ -76,9 +76,9 @@ fun AppearanceScope.AppearanceLayout(
systemDarkTheme: SharedPreference<String?>,
changeIcon: (AppIcon) -> Unit,
) {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
AppBarTitle(stringResource(MR.strings.appearance_settings))
SectionView(stringResource(MR.strings.settings_section_title_interface), contentPadding = PaddingValues(), card = true) {
SectionView(stringResource(MR.strings.settings_section_title_interface), contentPadding = PaddingValues()) {
val context = LocalContext.current
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
// SectionItemWithValue(
@@ -113,21 +113,21 @@ fun AppearanceScope.AppearanceLayout(
}
}
SectionSpacer()
SectionDividerSpaced()
ThemesSection(systemDarkTheme)
SectionSpacer()
SectionDividerSpaced()
AppToolbarsSection()
SectionSpacer()
SectionDividerSpaced()
MessageShapeSection()
SectionSpacer()
SectionDividerSpaced()
ProfileImageSection()
SectionSpacer()
SectionDividerSpaced()
SectionView(stringResource(MR.strings.settings_section_title_icon), contentPadding = PaddingValues(horizontal = DEFAULT_PADDING_HALF, vertical = DEFAULT_PADDING_HALF), card = true) {
SectionView(stringResource(MR.strings.settings_section_title_icon), contentPadding = PaddingValues(horizontal = DEFAULT_PADDING_HALF, vertical = DEFAULT_PADDING_HALF)) {
LazyRow {
items(AppIcon.values().size, { index -> AppIcon.values()[index] }) { index ->
val item = AppIcon.values()[index]
@@ -151,7 +151,7 @@ fun AppearanceScope.AppearanceLayout(
}
}
SectionSpacer()
SectionDividerSpaced()
FontScaleSection()
SectionBottomSpacer()
@@ -16,7 +16,7 @@ actual fun SettingsSectionApp(
showVersion: () -> Unit,
withAuth: (title: String, desc: String, block: () -> Unit) -> Unit
) {
SectionView(stringResource(MR.strings.settings_section_title_app), card = true) {
SectionView(stringResource(MR.strings.settings_section_title_app)) {
SettingsActionItem(painterResource(MR.images.ic_restart_alt), stringResource(MR.strings.settings_restart_app), ::restartApp)
SettingsActionItem(painterResource(MR.images.ic_power_settings_new), stringResource(MR.strings.settings_shutdown), { shutdownAppAlert(::shutdownApp) })
SettingsActionItem(painterResource(MR.images.ic_code), stringResource(MR.strings.settings_developer_tools), showSettingsModal { DeveloperView(withAuth) })
@@ -5,7 +5,7 @@ import InfoRowEllipsis
import SectionBottomSpacer
import SectionItemView
import SectionItemViewSpaceBetween
import SectionSpacer
import SectionDividerSpaced
import SectionTextFooter
import SectionView
import androidx.compose.desktop.ui.tooling.preview.Preview
@@ -542,7 +542,7 @@ fun ChatInfoLayout(
KeyChangeEffect(chat.id) {
scope.launch { scrollState.scrollTo(0) }
}
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
Row(
Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.Center
@@ -552,7 +552,7 @@ fun ChatInfoLayout(
LocalAliasEditor(chat.id, localAlias, updateValue = onLocalAliasChanged)
SectionSpacer()
SectionDividerSpaced()
Box(
Modifier.fillMaxWidth(),
@@ -572,19 +572,19 @@ fun ChatInfoLayout(
}
}
SectionSpacer()
SectionDividerSpaced()
if (customUserProfile != null) {
SectionView(generalGetString(MR.strings.incognito), card = true) {
SectionView(generalGetString(MR.strings.incognito)) {
SectionItemViewSpaceBetween {
Text(generalGetString(MR.strings.incognito_random_profile))
Text(customUserProfile.chatViewName, color = Indigo)
}
}
SectionSpacer()
SectionDividerSpaced()
}
SectionView(card = true) {
SectionView {
if (contact.ready && contact.active) {
if (connectionCode != null) {
VerifyCodeButton(contact.verified, verifyClicked)
@@ -609,34 +609,34 @@ fun ChatInfoLayout(
}
}
}
SectionSpacer()
SectionDividerSpaced()
SectionView(card = true) {
SectionView {
ChatTTLOption(chatItemTTL, setChatItemTTL, deletingItems)
}
SectionTextFooter(stringResource(MR.strings.chat_ttl_options_footer))
SectionSpacer()
SectionDividerSpaced()
val conn = contact.activeConn
if (conn != null) {
SectionView(card = true) {
SectionView {
InfoRow("E2E encryption", if (conn.connPQEnabled) "Quantum resistant" else "Standard")
SectionSpacer()
SectionDividerSpaced()
}
}
if (contact.contactLink != null) {
SectionView(stringResource(MR.strings.address_section_title), card = true) {
SectionView(stringResource(MR.strings.address_section_title)) {
SimpleXLinkQRCode(contact.contactLink)
val clipboard = LocalClipboardManager.current
ShareAddressButton { clipboard.shareText(simplexChatLink(contact.contactLink)) }
}
SectionTextFooter(stringResource(MR.strings.you_can_share_this_address_with_your_contacts).format(contact.displayName))
SectionSpacer()
SectionDividerSpaced()
}
if (contact.ready && contact.active) {
SectionView(title = stringResource(MR.strings.conn_stats_section_title_servers), card = true) {
SectionView(title = stringResource(MR.strings.conn_stats_section_title_servers)) {
val chatSubStatus = chatModel.chatSubStatus.value
if (chatSubStatus != null) {
SectionItemView({
@@ -669,17 +669,17 @@ fun ChatInfoLayout(
}
}
}
SectionSpacer()
SectionDividerSpaced()
}
SectionView(card = true) {
SectionView {
ClearChatButton(clearChat)
DeleteContactButton(deleteContact)
}
if (developerTools) {
SectionSpacer()
SectionView(title = stringResource(MR.strings.section_title_for_console), card = true) {
SectionDividerSpaced()
SectionView(title = stringResource(MR.strings.section_title_for_console)) {
InfoRow(stringResource(MR.strings.info_row_local_name), chat.chatInfo.localDisplayName)
InfoRow(stringResource(MR.strings.info_row_database_id), chat.chatInfo.apiId.toString())
SectionItemView({
@@ -406,7 +406,7 @@ fun ChatView(
val selectedItems: MutableState<Set<Long>?> = mutableStateOf(null)
ModalManager.end.showCustomModal { close ->
val appBar = remember { mutableStateOf(null as @Composable (BoxScope.() -> Unit)?) }
ModalView(close, appBar = appBar.value) {
ModalView(close, cardScreen = true, appBar = appBar.value) {
val chatInfo = remember { activeChat }.value?.chatInfo
if (chatInfo is ChatInfo.Direct) {
var contactInfo: Pair<ConnectionStats?, Profile?>? by remember { mutableStateOf(preloadedContactInfo) }
@@ -509,7 +509,7 @@ fun ChatView(
if (chatsCtx.secondaryContextFilter == null) {
ModalManager.end.closeModals()
}
ModalManager.end.showModalCloseable(true) { close ->
ModalManager.end.showModalCloseable(showClose = true, cardScreen = true) { close ->
remember { derivedStateOf { chatModel.getGroupMember(member.groupMemberId) } }.value?.let { mem ->
GroupMemberInfoView(chatRh, groupInfo, mem, scrollToItemId, stats, code, chatModel, openedFromSupportChat = false, close = close, closeAll = close)
}
@@ -801,7 +801,7 @@ fun ChatView(
}
is ChatInfo.ContactConnection -> {
val close = { chatModel.chatId.value = null }
ModalView(close, showClose = appPlatform.isAndroid, content = {
ModalView(close, showClose = appPlatform.isAndroid, cardScreen = true, content = {
ContactConnectionInfoView(chatModel, chatRh, chatInfo.contactConnection.connLinkInv, chatInfo.contactConnection, false, close)
})
LaunchedEffect(chatInfo.id) {
@@ -3,7 +3,7 @@ package chat.simplex.common.views.chat
import InfoRow
import SectionBottomSpacer
import SectionItemView
import SectionSpacer
import SectionDividerSpaced
import SectionTextFooter
import SectionView
import androidx.compose.foundation.*
@@ -55,6 +55,7 @@ fun ContactPreferencesView(
if (featuresAllowed == currentFeaturesAllowed) close()
else showUnsavedChangesAlert({ savePrefs(close) }, close)
},
cardScreen = true,
) {
ContactPreferencesLayout(
featuresAllowed,
@@ -82,7 +83,7 @@ private fun ContactPreferencesLayout(
reset: () -> Unit,
savePrefs: () -> Unit,
) {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
AppBarTitle(stringResource(MR.strings.contact_preferences))
val timedMessages: MutableState<Boolean> = remember(featuresAllowed) { mutableStateOf(featuresAllowed.timedMessagesAllowed) }
val onTTLUpdated = { ttl: Int? ->
@@ -91,27 +92,27 @@ private fun ContactPreferencesLayout(
TimedMessagesFeatureSection(featuresAllowed, contact.mergedPreferences.timedMessages, timedMessages, onTTLUpdated) { allowed, ttl ->
applyPrefs(featuresAllowed.copy(timedMessagesAllowed = allowed, timedMessagesTTL = ttl ?: currentFeaturesAllowed.timedMessagesTTL))
}
SectionSpacer()
SectionDividerSpaced()
val allowFullDeletion: MutableState<ContactFeatureAllowed> = remember(featuresAllowed) { mutableStateOf(featuresAllowed.fullDelete) }
FeatureSection(ChatFeature.FullDelete, user.fullPreferences.fullDelete.allow, contact.mergedPreferences.fullDelete, allowFullDeletion) {
applyPrefs(featuresAllowed.copy(fullDelete = it))
}
SectionSpacer()
SectionDividerSpaced()
val allowReactions: MutableState<ContactFeatureAllowed> = remember(featuresAllowed) { mutableStateOf(featuresAllowed.reactions) }
FeatureSection(ChatFeature.Reactions, user.fullPreferences.reactions.allow, contact.mergedPreferences.reactions, allowReactions) {
applyPrefs(featuresAllowed.copy(reactions = it))
}
SectionSpacer()
SectionDividerSpaced()
val allowVoice: MutableState<ContactFeatureAllowed> = remember(featuresAllowed) { mutableStateOf(featuresAllowed.voice) }
FeatureSection(ChatFeature.Voice, user.fullPreferences.voice.allow, contact.mergedPreferences.voice, allowVoice) {
applyPrefs(featuresAllowed.copy(voice = it))
}
SectionSpacer()
SectionDividerSpaced()
val allowCalls: MutableState<ContactFeatureAllowed> = remember(featuresAllowed) { mutableStateOf(featuresAllowed.calls) }
FeatureSection(ChatFeature.Calls, user.fullPreferences.calls.allow, contact.mergedPreferences.calls, allowCalls) {
applyPrefs(featuresAllowed.copy(calls = it))
}
SectionSpacer()
SectionDividerSpaced()
ResetSaveButtons(
reset = reset,
save = savePrefs,
@@ -140,7 +141,6 @@ private fun FeatureSection(
icon = feature.iconFilled(),
iconTint = if (enabled.forUser) SimplexGreen else if (enabled.forContact) WarningYellow else Color.Red,
leadingIcon = true,
card = true,
) {
ExposedDropDownSettingRow(
generalGetString(MR.strings.chat_preferences_you_allow),
@@ -176,7 +176,6 @@ private fun TimedMessagesFeatureSection(
icon = ChatFeature.TimedMessages.iconFilled(),
iconTint = if (enabled.forUser) SimplexGreen else if (enabled.forContact) WarningYellow else Color.Red,
leadingIcon = true,
card = true,
) {
PreferenceToggle(
generalGetString(MR.strings.chat_preferences_you_allow),
@@ -208,7 +207,7 @@ private fun TimedMessagesFeatureSection(
@Composable
private fun ResetSaveButtons(reset: () -> Unit, save: () -> Unit, disabled: Boolean) {
SectionView(card = true) {
SectionView {
SectionItemView(reset, disabled = disabled) {
Text(stringResource(MR.strings.reset_verb), color = if (disabled) MaterialTheme.colors.secondary else MaterialTheme.colors.primary)
}
@@ -2,7 +2,7 @@ package chat.simplex.common.views.chat.group
import SectionBottomSpacer
import SectionCustomFooter
import SectionSpacer
import SectionDividerSpaced
import SectionItemView
import SectionItemViewWithoutMinPadding
import SectionView
@@ -146,7 +146,7 @@ fun AddGroupMembersLayout(
}
}
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
AppBarTitle(stringResource(MR.strings.button_add_members))
profileText()
Spacer(Modifier.size(DEFAULT_PADDING))
@@ -160,7 +160,7 @@ fun AddGroupMembersLayout(
iconColor = if (isInDarkTheme()) GroupDark else SettingsSecondaryLight
)
}
SectionSpacer()
SectionDividerSpaced()
if (contactsToAdd.isEmpty() && searchText.value.text.isEmpty()) {
Row(
@@ -174,7 +174,7 @@ fun AddGroupMembersLayout(
)
}
} else {
SectionView(card = true) {
SectionView {
if (creatingGroup) {
SectionItemView(openMemberAdmission) {
Text(stringResource(MR.strings.set_member_admission))
@@ -194,8 +194,8 @@ fun AddGroupMembersLayout(
SectionCustomFooter {
InviteSectionFooter(selectedContactsCount = selectedContacts.size, allowModifyMembers, clearSelection)
}
SectionSpacer()
SectionView(stringResource(MR.strings.select_contacts), card = true) {
SectionDividerSpaced()
SectionView(stringResource(MR.strings.select_contacts)) {
SectionItemView(padding = PaddingValues(start = DEFAULT_PADDING, end = DEFAULT_PADDING_HALF)) {
SearchRowView(searchText)
}
@@ -2,7 +2,7 @@ package chat.simplex.common.views.chat.group
import SectionBottomSpacer
import SectionCustomFooter
import SectionSpacer
import SectionDividerSpaced
import SectionItemView
import SectionView
import androidx.compose.foundation.background
@@ -99,7 +99,7 @@ private fun AddGroupRelayLayout(
onToggleRelay: (Long) -> Unit,
onAddRelays: () -> Unit
) {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
AppBarTitle(generalGetString(MR.strings.add_relays_title))
if (isLoading) {
@@ -107,7 +107,7 @@ private fun AddGroupRelayLayout(
CircularProgressIndicator()
}
} else if (availableRelays.isEmpty()) {
SectionView(card = true) {
SectionView {
SectionItemView(padding = PaddingValues(horizontal = DEFAULT_PADDING)) {
Text(
generalGetString(MR.strings.no_available_relays),
@@ -116,7 +116,7 @@ private fun AddGroupRelayLayout(
}
}
} else {
SectionView(card = true) {
SectionView {
AddRelaysButton(
onClick = onAddRelays,
disabled = selectedRelayIds.isEmpty() || isAdding
@@ -132,8 +132,8 @@ private fun AddGroupRelayLayout(
fontSize = 14.sp
)
}
SectionSpacer()
SectionView(generalGetString(MR.strings.select_relays), card = true) {
SectionDividerSpaced()
SectionView(generalGetString(MR.strings.select_relays)) {
availableRelays.forEach { item ->
val selected = item.relayId in selectedRelayIds
SectionItemView(
@@ -6,7 +6,7 @@ import SectionBottomSpacer
import SectionItemView
import SectionItemViewLongClickable
import SectionItemViewSpaceBetween
import SectionSpacer
import SectionDividerSpaced
import SectionTextFooter
import SectionView
import androidx.compose.animation.*
@@ -130,7 +130,7 @@ fun ModalData.GroupChatInfoView(
} else {
member to null
}
ModalManager.end.showModalCloseable(true) { closeCurrent ->
ModalManager.end.showModalCloseable(showClose = true, cardScreen = true) { closeCurrent ->
remember { derivedStateOf { chatModel.getGroupMember(member.groupMemberId) } }.value?.let { mem ->
GroupMemberInfoView(rhId, groupInfo, mem, scrollToItemId, stats, code, chatModel, openedFromSupportChat = false, groupRelay = groupRelay, close = closeCurrent) {
closeCurrent()
@@ -524,7 +524,6 @@ fun ModalData.GroupChatInfoLayout(
val navBarPadding = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding()
val imePadding = WindowInsets.ime.asPaddingValues().calculateBottomPadding()
LazyColumnWithScrollBar(
modifier = Modifier.background(canvasColorForCurrentTheme()),
state = listState,
contentPadding = if (oneHandUI.value) {
PaddingValues(
@@ -557,7 +556,7 @@ fun ModalData.GroupChatInfoLayout(
LocalAliasEditor(chat.id, groupInfo.localAlias, isContact = false, updateValue = onLocalAliasChanged)
SectionSpacer()
SectionDividerSpaced()
Box(
Modifier.fillMaxWidth(),
@@ -586,16 +585,16 @@ fun ModalData.GroupChatInfoLayout(
}
}
SectionSpacer()
SectionDividerSpaced()
if (groupInfo.useRelays && groupInfo.membership.memberIncognito) {
SectionView(generalGetString(MR.strings.incognito), card = true) {
SectionView(generalGetString(MR.strings.incognito)) {
SectionItemViewSpaceBetween {
Text(generalGetString(MR.strings.incognito_random_profile))
Text(groupInfo.membership.chatViewName, color = Indigo)
}
}
SectionSpacer()
SectionDividerSpaced()
}
var anyTopSectionRowShow = false
@@ -605,7 +604,7 @@ fun ModalData.GroupChatInfoLayout(
|| groupInfo.membership.supportChat != null)
if (groupInfo.useRelays) {
SectionView(card = true) {
SectionView {
if (groupInfo.isOwner && groupLink != null) {
anyTopSectionRowShow = true
ChannelLinkButton(manageGroupLink)
@@ -635,7 +634,7 @@ fun ModalData.GroupChatInfoLayout(
SectionTextFooter(stringResource(MR.strings.you_can_share_channel_link_anybody_will_be_able_to_connect))
}
} else {
SectionView(card = true) {
SectionView {
if (groupInfo.canAddMembers && groupInfo.businessChat == null) {
anyTopSectionRowShow = true
if (groupLink == null) {
@@ -663,9 +662,9 @@ fun ModalData.GroupChatInfoLayout(
}
}
if (anyTopSectionRowShow) {
SectionSpacer()
SectionDividerSpaced()
}
SectionView(card = true) {
SectionView {
if (groupInfo.isOwner && groupInfo.businessChat?.chatType == null) {
val editProfileTitleId = if (groupInfo.useRelays) MR.strings.button_edit_channel_profile else MR.strings.button_edit_group_profile
EditGroupProfileButton(editProfileTitleId, editGroupProfile)
@@ -682,9 +681,9 @@ fun ModalData.GroupChatInfoLayout(
else if (groupInfo.businessChat == null) MR.strings.only_group_owners_can_change_prefs
else MR.strings.only_chat_owners_can_change_prefs
SectionTextFooter(stringResource(footerId))
SectionSpacer()
SectionDividerSpaced()
SectionView(card = true) {
SectionView {
if (!groupInfo.useRelays) {
if (activeSortedMembers.filter { it.memberCurrent }.size <= SMALL_GROUPS_RCPS_MEM_LIMIT) {
SendReceiptsOption(currentUser, sendReceipts, setSendReceipts)
@@ -704,10 +703,10 @@ fun ModalData.GroupChatInfoLayout(
ChatTTLOption(chatItemTTL, setChatItemTTL, deletingItems)
}
SectionTextFooter(stringResource(MR.strings.chat_ttl_options_footer))
SectionSpacer()
SectionDividerSpaced()
if (!groupInfo.nextConnectPrepared && !groupInfo.useRelays) {
SectionView(title = String.format(generalGetString(MR.strings.group_info_section_title_num_members), activeSortedMembers.count() + 1), card = true, cardShape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp)) {
SectionView(title = String.format(generalGetString(MR.strings.group_info_section_title_num_members), activeSortedMembers.count() + 1), cardShape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp)) {
if (groupInfo.canAddMembers) {
val onAddMembersClick = if (chat.chatInfo.incognito) ::cantInviteIncognitoAlert else addMembers
val tint = if (chat.chatInfo.incognito) MaterialTheme.colors.secondary else MaterialTheme.colors.primary
@@ -767,9 +766,9 @@ fun ModalData.GroupChatInfoLayout(
}
item {
if (!groupInfo.nextConnectPrepared && !groupInfo.useRelays) {
SectionSpacer()
SectionDividerSpaced()
}
SectionView(card = true) {
SectionView {
if (groupInfo.useRelays && (groupInfo.isOwner || activeSortedMembers.any { it.memberRole == GroupMemberRole.Relay })) {
ChannelRelaysButton(chat.remoteHostId, groupInfo, showMemberInfo)
}
@@ -794,8 +793,8 @@ fun ModalData.GroupChatInfoLayout(
}
if (developerTools) {
SectionSpacer()
SectionView(title = stringResource(MR.strings.section_title_for_console), card = true) {
SectionDividerSpaced()
SectionView(title = stringResource(MR.strings.section_title_for_console)) {
InfoRow(stringResource(MR.strings.info_row_local_name), groupInfo.localDisplayName)
InfoRow(stringResource(MR.strings.info_row_database_id), groupInfo.apiId.toString())
}
@@ -3,7 +3,7 @@ package chat.simplex.common.views.chat.group
import InfoRow
import SectionBottomSpacer
import SectionItemView
import SectionSpacer
import SectionDividerSpaced
import SectionTextFooter
import SectionView
import androidx.compose.desktop.ui.tooling.preview.Preview
@@ -423,8 +423,8 @@ fun GroupMemberInfoLayout(
// TODO [relays] re-enable when relay management ships
val canRemove = member.canBeRemoved(groupInfo) && member.memberRole != GroupMemberRole.Relay
if (canBlockForAll || canRemove) {
SectionSpacer()
SectionView(card = true) {
SectionDividerSpaced()
SectionView {
if (canBlockForAll) {
if (member.blockedByAdmin) {
UnblockForAllButton(unblockForAll)
@@ -445,8 +445,8 @@ fun GroupMemberInfoLayout(
@Composable
fun NonAdminBlockSection() {
SectionSpacer()
SectionView(card = true) {
SectionDividerSpaced()
SectionView {
if (member.blockedByAdmin) {
SettingsActionItem(
painterResource(MR.images.ic_back_hand),
@@ -462,14 +462,14 @@ fun GroupMemberInfoLayout(
}
}
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
Row(
Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.Center
) {
GroupMemberInfoHeader(member)
}
SectionSpacer()
SectionDividerSpaced()
val contactId = member.memberContactId
@@ -533,7 +533,7 @@ fun GroupMemberInfoLayout(
}
}
SectionSpacer()
SectionDividerSpaced()
}
val showMemberSupportChat = !openedFromSupportChat &&
@@ -543,7 +543,7 @@ fun GroupMemberInfoLayout(
|| member.supportChat != null)
if (member.memberActive) {
SectionView(card = true) {
SectionView {
if (showMemberSupportChat) {
SupportChatButton()
}
@@ -557,16 +557,16 @@ fun GroupMemberInfoLayout(
// SynchronizeConnectionButtonForce(syncMemberConnectionForce)
// }
}
SectionSpacer()
SectionDividerSpaced()
} else if (groupInfo.useRelays && member.memberCurrent && showMemberSupportChat) {
SectionView(card = true) {
SectionView {
SupportChatButton()
}
SectionSpacer()
SectionDividerSpaced()
}
if (member.contactLink != null) {
SectionView(stringResource(MR.strings.address_section_title), card = true) {
SectionView(stringResource(MR.strings.address_section_title)) {
SimpleXLinkQRCode(member.contactLink)
val clipboard = LocalClipboardManager.current
ShareAddressButton { clipboard.shareText(simplexChatLink(member.contactLink)) }
@@ -579,7 +579,7 @@ fun GroupMemberInfoLayout(
}
}
SectionTextFooter(stringResource(MR.strings.you_can_share_this_address_with_your_contacts).format(member.displayName))
SectionSpacer()
SectionDividerSpaced()
}
val memberSectionTitle = if (groupInfo.useRelays) {
@@ -591,7 +591,7 @@ fun GroupMemberInfoLayout(
} else {
stringResource(MR.strings.member_info_section_title_member)
}
SectionView(title = memberSectionTitle, card = true) {
SectionView(title = memberSectionTitle) {
val titleId = if (groupInfo.useRelays) MR.strings.info_row_channel
else if (groupInfo.businessChat == null) MR.strings.info_row_group
else MR.strings.info_row_chat
@@ -627,8 +627,8 @@ fun GroupMemberInfoLayout(
)
}
if (cStats != null) {
SectionSpacer()
SectionView(title = stringResource(MR.strings.conn_stats_section_title_servers), card = true) {
SectionDividerSpaced()
SectionView(title = stringResource(MR.strings.conn_stats_section_title_servers)) {
val subStatus = cStats.subStatus
if (subStatus != null) {
SectionItemView({
@@ -663,8 +663,8 @@ fun GroupMemberInfoLayout(
val connFailedErr = member.activeConn?.connFailedErr
if (connFailedErr != null) {
SectionSpacer()
SectionView(title = stringResource(MR.strings.info_row_connection_failed), icon = painterResource(MR.images.ic_warning), iconTint = Color.Red, leadingIcon = true, card = true) {
SectionDividerSpaced()
SectionView(title = stringResource(MR.strings.info_row_connection_failed), icon = painterResource(MR.images.ic_warning), iconTint = Color.Red, leadingIcon = true) {
SectionItemView {
Text(
connFailedErr,
@@ -681,8 +681,8 @@ fun GroupMemberInfoLayout(
}
if (developerTools) {
SectionSpacer()
SectionView(title = stringResource(MR.strings.section_title_for_console), card = true) {
SectionDividerSpaced()
SectionView(title = stringResource(MR.strings.section_title_for_console)) {
InfoRow(stringResource(MR.strings.info_row_local_name), member.localDisplayName)
InfoRow(stringResource(MR.strings.info_row_database_id), member.groupMemberId.toString())
val conn = member.activeConn
@@ -2,7 +2,7 @@ package chat.simplex.common.views.chat.group
import InfoRow
import SectionBottomSpacer
import SectionSpacer
import SectionDividerSpaced
import SectionItemView
import SectionTextFooter
import SectionView
@@ -66,6 +66,7 @@ fun GroupPreferencesView(m: ChatModel, rhId: Long?, chatId: String, close: () ->
if (preferences == currentPreferences) close()
else showUnsavedChangesAlert({ savePrefs(close) }, close, saveTextId)
},
cardScreen = true,
) {
GroupPreferencesLayout(
preferences,
@@ -177,7 +178,7 @@ private fun GroupPreferencesLayout(
}
}
}
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
val titleId = if (groupInfo.useRelays) MR.strings.channel_preferences
else if (groupInfo.businessChat == null) MR.strings.group_preferences
else MR.strings.chat_preferences
@@ -185,36 +186,36 @@ private fun GroupPreferencesLayout(
if (!groupInfo.useRelays) {
if (groupInfo.businessChat == null) {
MemberAdmissionButton(openMemberAdmission)
SectionSpacer()
SectionDividerSpaced()
}
TimedMessagesPreference()
SectionSpacer()
SectionDividerSpaced()
DirectMessagesPreference()
SectionSpacer()
SectionDividerSpaced()
FullDeletePreference()
SectionSpacer()
SectionDividerSpaced()
ReactionsPreference()
SectionSpacer()
SectionDividerSpaced()
VoicePreference()
SectionSpacer()
SectionDividerSpaced()
FilesPreference()
SectionSpacer()
SectionDividerSpaced()
SimplexLinksPreference()
SectionSpacer()
SectionDividerSpaced()
ReportsPreference()
SectionSpacer()
SectionDividerSpaced()
HistoryPreference()
SectionSpacer()
SectionDividerSpaced()
SupportPreference(disabled = true)
} else {
TimedMessagesPreference()
SectionSpacer()
SectionDividerSpaced()
FullDeletePreference()
SectionSpacer()
SectionDividerSpaced()
ReactionsPreference()
SectionSpacer()
SectionDividerSpaced()
HistoryPreference()
SectionSpacer()
SectionDividerSpaced()
SupportPreference(notice = generalGetString(MR.strings.chat_with_admins_relay_note), onEnable = { revert ->
AlertManager.shared.showAlertDialog(
title = generalGetString(MR.strings.enable_chats_with_admins_question),
@@ -227,7 +228,7 @@ private fun GroupPreferencesLayout(
})
}
if (groupInfo.isOwner) {
SectionSpacer()
SectionDividerSpaced()
val saveTextId = if (groupInfo.useRelays) MR.strings.save_and_notify_channel_subscribers
else MR.strings.save_and_notify_group_members
ResetSaveButtons(
@@ -262,7 +263,7 @@ private fun FeatureSection(
notice: String? = null,
onSelected: (GroupFeatureEnabled, GroupMemberRole?) -> Unit
) {
SectionView(card = true) {
SectionView {
val on = enableFeature.value == GroupFeatureEnabled.ON
val icon = if (on) feature.iconFilled() else feature.icon
val iconTint = if (on) SimplexGreen else MaterialTheme.colors.secondary
@@ -327,7 +328,7 @@ private fun FeatureSection(
@Composable
private fun ResetSaveButtons(reset: () -> Unit, save: () -> Unit, disabled: Boolean, saveTextId: StringResource) {
SectionView(card = true) {
SectionView {
SectionItemView(reset, disabled = disabled) {
Text(stringResource(MR.strings.reset_verb), color = if (disabled) MaterialTheme.colors.secondary else MaterialTheme.colors.primary)
}
@@ -2,7 +2,7 @@ package chat.simplex.common.views.chat.group
import InfoRow
import SectionBottomSpacer
import SectionSpacer
import SectionDividerSpaced
import SectionItemView
import SectionTextFooter
import SectionView
@@ -52,6 +52,7 @@ fun MemberAdmissionView(m: ChatModel, rhId: Long?, chatId: String, close: () ->
if (admission == currentAdmission) close()
else showUnsavedChangesAlert({ saveAdmission(close) }, close)
},
cardScreen = true,
) {
MemberAdmissionLayout(
admission,
@@ -77,7 +78,7 @@ private fun MemberAdmissionLayout(
reset: () -> Unit,
saveAdmission: () -> Unit,
) {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
AppBarTitle(stringResource(MR.strings.member_admission))
val review = remember(admission) { mutableStateOf(admission?.review) }
AdmissionSection(MR.strings.admission_stage_review, MR.strings.admission_stage_review_descr, review, groupInfo) { criteria ->
@@ -88,7 +89,7 @@ private fun MemberAdmissionLayout(
}
}
if (groupInfo.isOwner) {
SectionSpacer()
SectionDividerSpaced()
ResetSaveButtons(
reset = reset,
save = saveAdmission,
@@ -112,7 +113,7 @@ private fun AdmissionSection(
groupInfo: GroupInfo,
onSelected: (MemberCriteria?) -> Unit
) {
SectionView(card = true) {
SectionView {
if (groupInfo.isOwner) {
ExposedDropDownSettingRow(
generalGetString(admissionStageStrId),
@@ -134,7 +135,7 @@ private fun AdmissionSection(
@Composable
private fun ResetSaveButtons(reset: () -> Unit, save: () -> Unit, disabled: Boolean) {
SectionView(card = true) {
SectionView {
SectionItemView(reset, disabled = disabled) {
Text(stringResource(MR.strings.reset_verb), color = if (disabled) MaterialTheme.colors.secondary else MaterialTheme.colors.primary)
}
@@ -85,7 +85,7 @@ fun MemberSupportChatAppBar(
} else {
null
}
ModalManager.end.showModalCloseable(true) { closeCurrent ->
ModalManager.end.showModalCloseable(showClose = true, cardScreen = true) { closeCurrent ->
remember { derivedStateOf { chatModel.getGroupMember(scopeMember_.groupMemberId) } }.value?.let { mem ->
GroupMemberInfoView(rhId, groupInfo, mem, scrollToItemId, stats, code, chatModel, openedFromSupportChat = true, close = closeCurrent) {
closeCurrent()
@@ -583,7 +583,7 @@ fun ContactConnectionMenuItems(rhId: Long?, chatInfo: ChatInfo.ContactConnection
onClick = {
ModalManager.center.closeModals()
ModalManager.end.closeModals()
ModalManager.center.showModalCloseable(true, showClose = appPlatform.isAndroid) { close ->
ModalManager.center.showModalCloseable(settings = true, showClose = appPlatform.isAndroid, cardScreen = true) { close ->
ContactConnectionInfoView(chatModel, rhId, chatInfo.contactConnection.connLinkInv, chatInfo.contactConnection, true, close)
}
showMenu.value = false
@@ -1,5 +1,6 @@
package chat.simplex.common.views.chatlist
import LocalCardScreen
import androidx.compose.foundation.*
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsHoveredAsState
@@ -572,7 +573,7 @@ private fun ChatListToolbar(userPickerState: MutableStateFlow<AnimatedViewState>
navigationButton = {
if (chatModel.users.isEmpty() && !chatModel.desktopNoUserNoRemote) {
NavigationButtonMenu {
ModalManager.start.showModalCloseable(background = canvasColorForCurrentTheme()) { close ->
ModalManager.start.showModalCloseable(cardScreen = true) { close ->
SettingsView(chatModel, setPerformLA, close)
}
}
@@ -854,8 +855,8 @@ enum class ScrollDirection {
@Composable
fun BoxScope.StatusBarBackground() {
if (appPlatform.isAndroid) {
val finalColor = MaterialTheme.colors.background.copy(0.88f)
Box(Modifier.fillMaxWidth().windowInsetsTopHeight(WindowInsets.statusBars).background(finalColor))
val bg = if (LocalCardScreen.current) canvasColorForCurrentTheme() else MaterialTheme.colors.background
Box(Modifier.fillMaxWidth().windowInsetsTopHeight(WindowInsets.statusBars).background(bg.copy(0.88f)))
}
}
@@ -3,7 +3,7 @@ package chat.simplex.common.views.chatlist
import InfoRow
import InfoRowTwoValues
import SectionBottomSpacer
import SectionSpacer
import SectionDividerSpaced
import SectionItemView
import SectionTextFooter
import SectionView
@@ -152,7 +152,7 @@ enum class PresentedServerType {
@Composable
private fun ServerSessionsView(sess: ServerSessions) {
SectionView(generalGetString(MR.strings.servers_info_transport_sessions_section_header), card = true) {
SectionView(generalGetString(MR.strings.servers_info_transport_sessions_section_header)) {
InfoRow(
generalGetString(MR.strings.servers_info_sessions_connected),
numOrDash(sess.ssConnected)
@@ -219,7 +219,7 @@ private fun SMPServersListView(servers: List<SMPServerSummary>, statsStartedAt:
val sortedServers = servers.sortedWith(compareBy<SMPServerSummary> { !it.hasSubs }
.thenBy { serverAddress(it.smpServer) })
SectionView(header, card = true) {
SectionView(header) {
sortedServers.map { svr -> SMPServerView(srvSumm = svr, statsStartedAt = statsStartedAt, rh = rh) }
}
if (footer != null) {
@@ -287,14 +287,14 @@ private fun XFTPServerInProgressIcon(srvSumm: XFTPServerSummary) {
private fun XFTPServersListView(servers: List<XFTPServerSummary>, statsStartedAt: Instant, header: String? = null, rh: RemoteHostInfo?) {
val sortedServers = servers.sortedBy { serverAddress(it.xftpServer) }
SectionView(header, card = true) {
SectionView(header) {
sortedServers.map { svr -> XFTPServerView(svr, statsStartedAt, rh) }
}
}
@Composable
private fun SMPStatsView(stats: AgentSMPServerStatsData, statsStartedAt: Instant, remoteHostInfo: RemoteHostInfo?) {
SectionView(generalGetString(MR.strings.servers_info_statistics_section_header), card = true) {
SectionView(generalGetString(MR.strings.servers_info_statistics_section_header)) {
InfoRow(
generalGetString(MR.strings.servers_info_messages_sent),
numOrDash(stats._sentDirect + stats._sentViaProxy)
@@ -416,7 +416,7 @@ private fun reconnectServerAlert(rh: RemoteHostInfo?, server: String) {
@Composable
fun XFTPStatsView(stats: AgentXFTPServerStatsData, statsStartedAt: Instant, rh: RemoteHostInfo?) {
SectionView(generalGetString(MR.strings.servers_info_statistics_section_header), card = true) {
SectionView(generalGetString(MR.strings.servers_info_statistics_section_header)) {
InfoRow(
generalGetString(MR.strings.servers_info_uploaded),
prettySize(stats._uploadsSize)
@@ -450,7 +450,7 @@ private fun IndentedInfoRow(title: String, desc: String) {
@Composable
fun DetailedSMPStatsLayout(stats: AgentSMPServerStatsData, statsStartedAt: Instant) {
SectionView(generalGetString(MR.strings.servers_info_detailed_statistics_sent_messages_header), card = true) {
SectionView(generalGetString(MR.strings.servers_info_detailed_statistics_sent_messages_header)) {
InfoRow(generalGetString(MR.strings.servers_info_detailed_statistics_sent_messages_total), numOrDash(stats._sentDirect + stats._sentViaProxy))
InfoRowTwoValues(generalGetString(MR.strings.sent_directly), generalGetString(MR.strings.attempts_label), stats._sentDirect, stats._sentDirectAttempts)
InfoRowTwoValues(generalGetString(MR.strings.sent_via_proxy), generalGetString(MR.strings.attempts_label), stats._sentViaProxy, stats._sentViaProxyAttempts)
@@ -464,9 +464,9 @@ fun DetailedSMPStatsLayout(stats: AgentSMPServerStatsData, statsStartedAt: Insta
IndentedInfoRow(generalGetString(MR.strings.other_label), numOrDash(stats._sentOtherErrs))
}
SectionSpacer()
SectionDividerSpaced()
SectionView(generalGetString(MR.strings.servers_info_detailed_statistics_received_messages_header), card = true) {
SectionView(generalGetString(MR.strings.servers_info_detailed_statistics_received_messages_header)) {
InfoRow(generalGetString(MR.strings.servers_info_detailed_statistics_received_total), numOrDash(stats._recvMsgs))
SectionItemView {
Text(generalGetString(MR.strings.servers_info_detailed_statistics_receive_errors), color = MaterialTheme.colors.onBackground)
@@ -482,9 +482,9 @@ fun DetailedSMPStatsLayout(stats: AgentSMPServerStatsData, statsStartedAt: Insta
IndentedInfoRow(generalGetString(MR.strings.other_errors), numOrDash(stats._ackOtherErrs))
}
SectionSpacer()
SectionDividerSpaced()
SectionView(generalGetString(MR.strings.connections), card = true) {
SectionView(generalGetString(MR.strings.connections)) {
InfoRow(generalGetString(MR.strings.created), numOrDash(stats._connCreated))
InfoRow(generalGetString(MR.strings.secured), numOrDash(stats._connSecured))
InfoRow(generalGetString(MR.strings.completed), numOrDash(stats._connCompleted))
@@ -503,15 +503,15 @@ fun DetailedSMPStatsLayout(stats: AgentSMPServerStatsData, statsStartedAt: Insta
@Composable
fun DetailedXFTPStatsLayout(stats: AgentXFTPServerStatsData, statsStartedAt: Instant) {
SectionView(generalGetString(MR.strings.uploaded_files), card = true) {
SectionView(generalGetString(MR.strings.uploaded_files)) {
InfoRow(generalGetString(MR.strings.size), prettySize(stats._uploadsSize))
InfoRowTwoValues(generalGetString(MR.strings.chunks_uploaded), generalGetString(MR.strings.attempts_label), stats._uploads, stats._uploadAttempts)
InfoRow(generalGetString(MR.strings.upload_errors), numOrDash(stats._uploadErrs))
InfoRowTwoValues(generalGetString(MR.strings.chunks_deleted), generalGetString(MR.strings.attempts_label), stats._deletions, stats._deleteAttempts)
InfoRow(generalGetString(MR.strings.deletion_errors), numOrDash(stats._deleteErrs))
}
SectionSpacer()
SectionView(generalGetString(MR.strings.downloaded_files), card = true) {
SectionDividerSpaced()
SectionView(generalGetString(MR.strings.downloaded_files)) {
InfoRow(generalGetString(MR.strings.size), prettySize(stats._downloadsSize))
InfoRowTwoValues(generalGetString(MR.strings.chunks_downloaded), generalGetString(MR.strings.attempts_label), stats._downloads, stats._downloadAttempts)
SectionItemView {
@@ -529,7 +529,7 @@ fun DetailedXFTPStatsLayout(stats: AgentXFTPServerStatsData, statsStartedAt: Ins
@Composable
fun XFTPServerSummaryLayout(summary: XFTPServerSummary, statsStartedAt: Instant, rh: RemoteHostInfo?) {
SectionView(generalGetString(MR.strings.server_address), card = true) {
SectionView(generalGetString(MR.strings.server_address)) {
SelectionContainer {
Text(
summary.xftpServer,
@@ -541,13 +541,13 @@ fun XFTPServerSummaryLayout(summary: XFTPServerSummary, statsStartedAt: Instant,
)
}
if (summary.stats != null || summary.sessions != null) {
SectionSpacer()
SectionDividerSpaced()
}
if (summary.stats != null) {
XFTPStatsView(stats = summary.stats, rh = rh, statsStartedAt = statsStartedAt)
if (summary.sessions != null) {
SectionSpacer()
SectionDividerSpaced()
}
}
@@ -561,7 +561,7 @@ fun XFTPServerSummaryLayout(summary: XFTPServerSummary, statsStartedAt: Instant,
@Composable
fun SMPServerSummaryLayout(summary: SMPServerSummary, statsStartedAt: Instant, rh: RemoteHostInfo?) {
SectionView(generalGetString(MR.strings.server_address), card = true) {
SectionView(generalGetString(MR.strings.server_address)) {
SelectionContainer {
Text(
summary.smpServer,
@@ -573,20 +573,20 @@ fun SMPServerSummaryLayout(summary: SMPServerSummary, statsStartedAt: Instant, r
)
}
if (summary.stats != null || summary.subs != null || summary.sessions != null) {
SectionSpacer()
SectionDividerSpaced()
}
if (summary.stats != null) {
SMPStatsView(stats = summary.stats, remoteHostInfo = rh, statsStartedAt = statsStartedAt)
if (summary.subs != null || summary.sessions != null) {
SectionSpacer()
SectionDividerSpaced()
}
}
if (summary.subs != null) {
SMPSubscriptionsSection(subs = summary.subs, summary = summary, rh = rh)
if (summary.sessions != null) {
SectionSpacer()
SectionDividerSpaced()
}
}
@@ -606,9 +606,10 @@ fun ModalData.SMPServerSummaryView(
statsStartedAt: Instant
) {
ModalView(
close = close
close = close,
cardScreen = true,
) {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
val bottomPadding = DEFAULT_PADDING
AppBarTitle(
stringResource(MR.strings.smp_server),
@@ -629,9 +630,10 @@ fun ModalData.DetailedXFTPStatsView(
statsStartedAt: Instant
) {
ModalView(
close = close
close = close,
cardScreen = true,
) {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
Box(contentAlignment = Alignment.Center) {
val bottomPadding = DEFAULT_PADDING
AppBarTitle(
@@ -653,9 +655,10 @@ fun ModalData.DetailedSMPStatsView(
statsStartedAt: Instant
) {
ModalView(
close = close
close = close,
cardScreen = true,
) {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
Box(contentAlignment = Alignment.Center) {
val bottomPadding = DEFAULT_PADDING
AppBarTitle(
@@ -677,9 +680,10 @@ fun ModalData.XFTPServerSummaryView(
statsStartedAt: Instant
) {
ModalView(
close = close
close = close,
cardScreen = true,
) {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
Box(contentAlignment = Alignment.Center) {
val bottomPadding = DEFAULT_PADDING
AppBarTitle(
@@ -695,7 +699,7 @@ fun ModalData.XFTPServerSummaryView(
@Composable
fun ModalData.ServersSummaryView(rh: RemoteHostInfo?, serversSummary: MutableState<PresentedServersSummary?>) {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
var showUserSelection by remember { mutableStateOf(false) }
val selectedUserCategory =
remember { stateGetOrPut("selectedUserCategory") { PresentedUserCategory.ALL_USERS } }
@@ -826,7 +830,7 @@ fun ModalData.ServersSummaryView(rh: RemoteHostInfo?, serversSummary: MutableSta
selectedUserCategory.value = it
}
)
SectionSpacer()
SectionDividerSpaced()
}
when (index) {
PresentedServerType.SMP.ordinal -> {
@@ -840,9 +844,9 @@ fun ModalData.ServersSummaryView(rh: RemoteHostInfo?, serversSummary: MutableSta
val statsStartedAt = it.statsStartedAt
SMPStatsView(totals.stats, statsStartedAt, rh)
SectionSpacer()
SectionDividerSpaced()
SMPSubscriptionsSection(totals)
SectionSpacer()
SectionDividerSpaced()
if (currentlyUsedSMPServers.isNotEmpty()) {
SMPServersListView(
@@ -851,7 +855,7 @@ fun ModalData.ServersSummaryView(rh: RemoteHostInfo?, serversSummary: MutableSta
header = generalGetString(MR.strings.servers_info_connected_servers_section_header),
rh = rh
)
SectionSpacer()
SectionDividerSpaced()
}
if (previouslyUsedSMPServers.isNotEmpty()) {
@@ -861,7 +865,7 @@ fun ModalData.ServersSummaryView(rh: RemoteHostInfo?, serversSummary: MutableSta
header = generalGetString(MR.strings.servers_info_previously_connected_servers_section_header),
rh = rh
)
SectionSpacer()
SectionDividerSpaced()
}
if (proxySMPServers.isNotEmpty()) {
@@ -872,7 +876,7 @@ fun ModalData.ServersSummaryView(rh: RemoteHostInfo?, serversSummary: MutableSta
footer = generalGetString(MR.strings.servers_info_proxied_servers_section_footer),
rh = rh
)
SectionSpacer()
SectionDividerSpaced()
}
ServerSessionsView(totals.sessions)
@@ -889,7 +893,7 @@ fun ModalData.ServersSummaryView(rh: RemoteHostInfo?, serversSummary: MutableSta
val previouslyUsedXFTPServers = xftpSummary.previouslyUsedXFTPServers
XFTPStatsView(totals.stats, statsStartedAt, rh)
SectionSpacer()
SectionDividerSpaced()
if (currentlyUsedXFTPServers.isNotEmpty()) {
XFTPServersListView(
@@ -898,7 +902,7 @@ fun ModalData.ServersSummaryView(rh: RemoteHostInfo?, serversSummary: MutableSta
generalGetString(MR.strings.servers_info_connected_servers_section_header),
rh
)
SectionSpacer()
SectionDividerSpaced()
}
if (previouslyUsedXFTPServers.isNotEmpty()) {
@@ -908,7 +912,7 @@ fun ModalData.ServersSummaryView(rh: RemoteHostInfo?, serversSummary: MutableSta
generalGetString(MR.strings.servers_info_previously_connected_servers_section_header),
rh
)
SectionSpacer()
SectionDividerSpaced()
}
ServerSessionsView(totals.sessions)
@@ -916,9 +920,9 @@ fun ModalData.ServersSummaryView(rh: RemoteHostInfo?, serversSummary: MutableSta
}
}
SectionSpacer()
SectionDividerSpaced()
SectionView(card = true) {
SectionView {
ReconnectAllServersButton(rh)
ResetStatisticsButton(rh, resetStats = { resetStats() })
}
@@ -380,7 +380,7 @@ private fun GlobalSettingsSection(
SectionItemView(
click = {
ModalManager.start.showModalCloseable(background = canvasColorForCurrentTheme()) { close ->
ModalManager.start.showModalCloseable(cardScreen = true) { close ->
SettingsView(chatModel, setPerformLA, close)
}
},
@@ -119,7 +119,7 @@ fun DatabaseEncryptionLayout(
ChatStoppedView()
SectionSpacer()
}
SectionView(if (migration) generalGetString(MR.strings.database_passphrase) else null, card = true) {
SectionView(if (migration) generalGetString(MR.strings.database_passphrase) else null) {
SavePassphraseSetting(
useKeychain.value,
initialRandomDBPassphrase.value,
@@ -206,7 +206,7 @@ fun DatabaseEncryptionLayout(
Layout()
}
} else {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme()), maxIntrinsicSize = true) {
ColumnWithScrollBar(maxIntrinsicSize = true) {
Layout()
}
}
@@ -1,7 +1,7 @@
package chat.simplex.common.views.database
import SectionBottomSpacer
import SectionSpacer
import SectionDividerSpaced
import SectionTextFooter
import SectionItemView
import SectionView
@@ -167,11 +167,11 @@ fun DatabaseLayout(
) {
val operationsDisabled = progressIndicator && !chatModel.desktopNoUserNoRemote
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
AppBarTitle(stringResource(MR.strings.your_chat_database))
if (!chatModel.desktopNoUserNoRemote) {
SectionView(stringResource(MR.strings.messages_section_title), card = true) {
SectionView(stringResource(MR.strings.messages_section_title)) {
TtlOptions(chatItemTTL, enabled = rememberUpdatedState(!stopped && !progressIndicator), onChatItemTTLSelected)
}
SectionTextFooter(
@@ -185,14 +185,14 @@ fun DatabaseLayout(
}
}
)
SectionSpacer()
SectionDividerSpaced()
}
val toggleEnabled = remember { chatModel.remoteHosts }.none { it.sessionState is RemoteHostSessionState.Connected }
if (chatModel.localUserCreated.value == true) {
// still show the toggle in case database was stopped when the user opened this screen because it can be in the following situations:
// - database was stopped after migration and the app relaunched
// - something wrong happened with database operations and the database couldn't be launched when it should
SectionView(stringResource(MR.strings.run_chat_section), card = true) {
SectionView(stringResource(MR.strings.run_chat_section)) {
if (!toggleEnabled) {
SectionItemView(disconnectAllHosts) {
Text(generalGetString(MR.strings.disconnect_remote_hosts), Modifier.fillMaxWidth(), color = WarningOrange)
@@ -201,10 +201,10 @@ fun DatabaseLayout(
RunChatSetting(stopped, toggleEnabled && !progressIndicator, startChat, stopChatAlert)
}
if (stopped) SectionTextFooter(stringResource(MR.strings.you_must_use_the_most_recent_version_of_database))
SectionSpacer()
SectionDividerSpaced()
}
SectionView(stringResource(MR.strings.chat_database_section), card = true) {
SectionView(stringResource(MR.strings.chat_database_section)) {
if (chatModel.localUserCreated.value != true && !toggleEnabled) {
SectionItemView(disconnectAllHosts) {
Text(generalGetString(MR.strings.disconnect_remote_hosts), Modifier.fillMaxWidth(), color = WarningOrange)
@@ -215,7 +215,7 @@ fun DatabaseLayout(
if (unencrypted) painterResource(MR.images.ic_lock_open_right) else if (useKeyChain) painterResource(MR.images.ic_vpn_key_filled)
else painterResource(MR.images.ic_lock),
stringResource(MR.strings.database_passphrase),
click = { ModalManager.start.showModal { DatabaseEncryptionView(chatModel, false) } },
click = { ModalManager.start.showModal(cardScreen = true) { DatabaseEncryptionView(chatModel, false) } },
iconColor = if (unencrypted || (appPlatform.isDesktop && passphraseSaved)) WarningOrange else MaterialTheme.colors.secondary,
disabled = operationsDisabled
)
@@ -261,9 +261,9 @@ fun DatabaseLayout(
disabled = operationsDisabled
)
}
SectionSpacer()
SectionDividerSpaced()
SectionView(stringResource(MR.strings.files_and_media_section), card = true) {
SectionView(stringResource(MR.strings.files_and_media_section)) {
val deleteFilesDisabled = operationsDisabled || appFilesCountAndSize.value.first == 0
SectionItemView(
deleteAppFilesAndMedia,
@@ -12,6 +12,7 @@ import androidx.compose.ui.graphics.Color
import chat.simplex.common.model.ChatController.appPrefs
import chat.simplex.common.model.ChatModel
import chat.simplex.common.platform.*
import LocalCardScreen
import chat.simplex.common.ui.theme.*
import chat.simplex.common.views.chatlist.StatusBarBackground
import chat.simplex.common.views.onboarding.OnboardingStage
@@ -27,6 +28,7 @@ fun ModalView(
showAppBar: Boolean = true,
enableClose: Boolean = true,
background: Color = Color.Unspecified,
cardScreen: Boolean = false,
modifier: Modifier = Modifier,
showSearch: Boolean = false,
searchAlwaysVisible: Boolean = false,
@@ -40,7 +42,9 @@ fun ModalView(
}
val oneHandUI = remember { derivedStateOf { if (appPrefs.onboardingStage.state.value == OnboardingStage.OnboardingComplete) appPrefs.oneHandUI.state.value else false } }
Surface(Modifier.fillMaxSize(), contentColor = LocalContentColor.current) {
Box(Modifier.themedBackground(bgLayerSize = LocalAppBarHandler.current?.backgroundGraphicsLayerSize, bgLayer = LocalAppBarHandler.current?.backgroundGraphicsLayer, overrideColor = if (background != Color.Unspecified) background else null)) {
val bgOverride = if (cardScreen) canvasColorForCurrentTheme() else if (background != Color.Unspecified) background else null
CompositionLocalProvider(LocalCardScreen provides cardScreen) {
Box(Modifier.themedBackground(bgLayerSize = LocalAppBarHandler.current?.backgroundGraphicsLayerSize, bgLayer = LocalAppBarHandler.current?.backgroundGraphicsLayer, overrideColor = bgOverride)) {
Box(modifier = modifier) {
content()
}
@@ -66,6 +70,7 @@ fun ModalView(
}
}
}
}
}
}
@@ -111,15 +116,15 @@ class ModalManager(private val placement: ModalPlacement? = null) {
fun isLastModalOpen(id: ModalViewId): Boolean = modalViews.lastOrNull()?.id == id
fun showModal(settings: Boolean = false, showClose: Boolean = true, id: ModalViewId? = null, forceAnimated: Boolean = false, endButtons: @Composable RowScope.() -> Unit = {}, content: @Composable ModalData.() -> Unit) {
fun showModal(settings: Boolean = false, showClose: Boolean = true, id: ModalViewId? = null, forceAnimated: Boolean = false, cardScreen: Boolean = false, endButtons: @Composable RowScope.() -> Unit = {}, content: @Composable ModalData.() -> Unit) {
showCustomModal(id = id, forceAnimated = forceAnimated) { close ->
ModalView(close, showClose = showClose, endButtons = endButtons, content = { content() })
ModalView(close, showClose = showClose, cardScreen = cardScreen, endButtons = endButtons, content = { content() })
}
}
fun showModalCloseable(settings: Boolean = false, showClose: Boolean = true, id: ModalViewId? = null, background: Color = Color.Unspecified, endButtons: @Composable RowScope.() -> Unit = {}, content: @Composable ModalData.(close: () -> Unit) -> Unit) {
fun showModalCloseable(settings: Boolean = false, showClose: Boolean = true, id: ModalViewId? = null, cardScreen: Boolean = false, endButtons: @Composable RowScope.() -> Unit = {}, content: @Composable ModalData.(close: () -> Unit) -> Unit) {
showCustomModal(id = id) { close ->
ModalView(close, showClose = showClose, background = background, endButtons = endButtons, content = { content(close) })
ModalView(close, showClose = showClose, cardScreen = cardScreen, endButtons = endButtons, content = { content(close) })
}
}
@@ -31,10 +31,10 @@ private val SectionCardShape = RoundedCornerShape(16.dp)
val CARD_PADDING = 18.dp
val ICON_TEXT_SPACING = 8.dp
internal val LocalInCard = staticCompositionLocalOf { false }
val LocalCardScreen = staticCompositionLocalOf { false }
val itemHPadding: Dp
@Composable get() = if (LocalInCard.current) CARD_PADDING else DEFAULT_PADDING
@Composable get() = if (LocalCardScreen.current) CARD_PADDING else DEFAULT_PADDING
@Composable
private fun CardColumnLayout(
@@ -46,7 +46,7 @@ private fun CardColumnLayout(
val dividerPx = with(LocalDensity.current) { 2.dp.toPx() }
val childBottoms = remember { mutableListOf<Float>() }
Layout(
content = { CompositionLocalProvider(LocalInCard provides true, content = content) },
content = content,
modifier = Modifier
.padding(horizontal = CARD_PADDING)
.fillMaxWidth()
@@ -79,12 +79,11 @@ private fun CardColumnLayout(
@Composable
private fun CardColumn(
card: Boolean,
contentPadding: PaddingValues = PaddingValues(),
cardShape: Shape = SectionCardShape,
content: @Composable () -> Unit
) {
if (card) {
if (LocalCardScreen.current) {
CardColumnLayout(contentPadding, cardShape, content)
} else {
Column(Modifier.padding(contentPadding).fillMaxWidth()) { content() }
@@ -92,7 +91,8 @@ private fun CardColumn(
}
@Composable
fun SectionView(title: String? = null, contentPadding: PaddingValues = PaddingValues(), headerBottomPadding: Dp = DEFAULT_PADDING, card: Boolean = false, cardShape: Shape = SectionCardShape, content: (@Composable ColumnScope.() -> Unit)) {
fun SectionView(title: String? = null, contentPadding: PaddingValues = PaddingValues(), headerBottomPadding: Dp = DEFAULT_PADDING, cardShape: Shape = SectionCardShape, content: (@Composable ColumnScope.() -> Unit)) {
val card = LocalCardScreen.current
Column {
if (title != null) {
Text(
@@ -102,7 +102,7 @@ fun SectionView(title: String? = null, contentPadding: PaddingValues = PaddingVa
fontWeight = if (card) FontWeight.Medium else FontWeight.Normal
)
}
CardColumn(card, contentPadding, cardShape) { content() }
CardColumn(contentPadding, cardShape) { content() }
}
}
@@ -113,9 +113,9 @@ fun SectionView(
iconTint: Color = MaterialTheme.colors.secondary,
leadingIcon: Boolean = false,
padding: PaddingValues = PaddingValues(),
card: Boolean = false,
content: (@Composable ColumnScope.() -> Unit)
) {
val card = LocalCardScreen.current
Column {
val iconSize = with(LocalDensity.current) { 21.sp.toDp() }
Row(Modifier.padding(start = if (card) DEFAULT_PADDING + DEFAULT_PADDING_HALF else DEFAULT_PADDING, bottom = 5.dp), verticalAlignment = Alignment.CenterVertically) {
@@ -123,12 +123,13 @@ fun SectionView(
Text(title, color = MaterialTheme.colors.secondary, style = MaterialTheme.typography.body2, fontSize = if (card) 14.sp else 12.sp, fontWeight = if (card) FontWeight.Medium else FontWeight.Normal)
if (!leadingIcon) Icon(icon, null, Modifier.padding(start = DEFAULT_PADDING_HALF).size(iconSize), tint = iconTint)
}
CardColumn(card, padding) { content() }
CardColumn(padding) { content() }
}
}
@Composable
fun SectionViewWithButton(title: String? = null, titleButton: (@Composable () -> Unit)?, contentPadding: PaddingValues = PaddingValues(), headerBottomPadding: Dp = DEFAULT_PADDING, card: Boolean = false, content: (@Composable ColumnScope.() -> Unit)) {
fun SectionViewWithButton(title: String? = null, titleButton: (@Composable () -> Unit)?, contentPadding: PaddingValues = PaddingValues(), headerBottomPadding: Dp = DEFAULT_PADDING, content: (@Composable ColumnScope.() -> Unit)) {
val card = LocalCardScreen.current
Column {
if (title != null || titleButton != null) {
val hPadding = if (card) DEFAULT_PADDING + DEFAULT_PADDING_HALF else DEFAULT_PADDING
@@ -142,7 +143,7 @@ fun SectionViewWithButton(title: String? = null, titleButton: (@Composable () ->
}
}
}
CardColumn(card, contentPadding) { content() }
CardColumn(contentPadding) { content() }
}
}
@@ -333,13 +334,17 @@ fun SectionCustomFooter(padding: PaddingValues = PaddingValues(start = DEFAULT_P
@Composable
fun SectionDividerSpaced(maxTopPadding: Boolean = false, maxBottomPadding: Boolean = true) {
Divider(
Modifier.padding(
start = DEFAULT_PADDING_HALF,
top = if (maxTopPadding) DEFAULT_PADDING + 18.dp else DEFAULT_PADDING + 2.dp,
end = DEFAULT_PADDING_HALF,
bottom = if (maxBottomPadding) DEFAULT_PADDING + 18.dp else DEFAULT_PADDING + 2.dp)
)
if (LocalCardScreen.current) {
Spacer(Modifier.height(30.dp))
} else {
Divider(
Modifier.padding(
start = DEFAULT_PADDING_HALF,
top = if (maxTopPadding) DEFAULT_PADDING + 18.dp else DEFAULT_PADDING + 2.dp,
end = DEFAULT_PADDING_HALF,
bottom = if (maxBottomPadding) DEFAULT_PADDING + 18.dp else DEFAULT_PADDING + 2.dp)
)
}
}
@Composable
@@ -354,7 +359,7 @@ fun SectionBottomSpacer() {
@Composable
fun TextIconSpaced(extraPadding: Boolean = false) {
Spacer(Modifier.padding(horizontal = if (extraPadding) 17.dp else if (LocalInCard.current) ICON_TEXT_SPACING else DEFAULT_PADDING_HALF))
Spacer(Modifier.padding(horizontal = if (extraPadding) 17.dp else if (LocalCardScreen.current) ICON_TEXT_SPACING else DEFAULT_PADDING_HALF))
}
@Composable
@@ -1,7 +1,7 @@
package chat.simplex.common.views.helpers
import SectionBottomSpacer
import SectionSpacer
import SectionDividerSpaced
import SectionItemView
import SectionView
import androidx.compose.foundation.background
@@ -32,7 +32,7 @@ fun ModalData.UserWallpaperEditor(
globalThemeUsed: MutableState<Boolean>,
save: suspend (applyToMode: DefaultThemeMode?, ThemeModeOverride?) -> Unit
) {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
val applyToMode = remember { stateGetOrPutNullable("applyToMode") { applyToMode } }
var showMore by remember { stateGetOrPut("showMore") { false } }
val themeModeOverride = remember { stateGetOrPut("themeModeOverride") { theme } }
@@ -133,7 +133,7 @@ fun ModalData.UserWallpaperEditor(
onTypeChange = onTypeChange,
)
SectionSpacer()
SectionDividerSpaced()
if (!globalThemeUsed.value) {
ResetToGlobalThemeButton(true) {
@@ -174,7 +174,7 @@ fun ModalData.UserWallpaperEditor(
}
}
SectionSpacer()
SectionDividerSpaced()
if (showMore) {
val values by remember { mutableStateOf(
@@ -201,11 +201,11 @@ fun ModalData.UserWallpaperEditor(
}
)
SectionSpacer()
SectionDividerSpaced()
AppearanceScope.CustomizeThemeColorsSection(currentTheme, editColor = editColor)
SectionSpacer()
SectionDividerSpaced()
ImportExportThemeSection(null, remember { chatModel.currentUser }.value?.uiThemes) {
withBGApi {
@@ -228,7 +228,7 @@ fun ModalData.ChatWallpaperEditor(
globalThemeUsed: MutableState<Boolean>,
save: suspend (applyToMode: DefaultThemeMode?, ThemeModeOverride?) -> Unit
) {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
val applyToMode = remember { stateGetOrPutNullable("applyToMode") { applyToMode } }
var showMore by remember { stateGetOrPut("showMore") { false } }
val themeModeOverride = remember { stateGetOrPut("themeModeOverride") { theme } }
@@ -368,7 +368,7 @@ fun ModalData.ChatWallpaperEditor(
onTypeChange = onTypeChange,
)
SectionSpacer()
SectionDividerSpaced()
if (!globalThemeUsed.value) {
ResetToGlobalThemeButton(remember { chatModel.currentUser }.value?.uiThemes?.preferredMode(isInDarkTheme()) == null) {
@@ -409,7 +409,7 @@ fun ModalData.ChatWallpaperEditor(
}
}
SectionSpacer()
SectionDividerSpaced()
if (showMore) {
val values by remember { mutableStateOf(
@@ -436,11 +436,11 @@ fun ModalData.ChatWallpaperEditor(
}
)
SectionSpacer()
SectionDividerSpaced()
AppearanceScope.CustomizeThemeColorsSection(currentTheme, editColor = editColor)
SectionSpacer()
SectionDividerSpaced()
ImportExportThemeSection(themeModeOverride.value, remember { chatModel.currentUser }.value?.uiThemes) {
withBGApi {
themeModeOverride.value = it
@@ -457,7 +457,7 @@ fun ModalData.ChatWallpaperEditor(
@Composable
private fun ImportExportThemeSection(perChat: ThemeModeOverride?, perUser: ThemeModeOverrides?, save: (ThemeModeOverride) -> Unit) {
SectionView(card = true) {
SectionView {
val theme = remember { mutableStateOf(null as String?) }
val exportThemeLauncher = rememberFileChooserLauncher(false) { to: URI? ->
val themeValue = theme.value
@@ -1,7 +1,7 @@
package chat.simplex.common.views.migration
import SectionBottomSpacer
import SectionSpacer
import SectionDividerSpaced
import SectionTextFooter
import SectionView
import androidx.compose.foundation.layout.*
@@ -135,6 +135,7 @@ fun MigrateFromDeviceView(close: () -> Unit) {
}
close()
},
cardScreen = true,
) {
MigrateFromDeviceLayout(
migrationState = migrationState,
@@ -150,7 +151,7 @@ private fun MigrateFromDeviceLayout(
) {
val tempDatabaseFile = rememberSaveable { mutableStateOf(fileForTemporaryDatabase()) }
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme()), maxIntrinsicSize = true) {
ColumnWithScrollBar(maxIntrinsicSize = true) {
AppBarTitle(stringResource(MR.strings.migrate_from_device_title))
SectionByState(migrationState, tempDatabaseFile.value, chatReceiver)
SectionBottomSpacer()
@@ -183,7 +184,7 @@ private fun SectionByState(
@Composable
private fun MutableState<MigrationFromState>.ChatStopInProgressView() {
Box {
SectionView(stringResource(MR.strings.migrate_from_device_stopping_chat), card = true) {}
SectionView(stringResource(MR.strings.migrate_from_device_stopping_chat)) {}
ProgressView()
}
LaunchedEffect(Unit) {
@@ -193,9 +194,9 @@ private fun MutableState<MigrationFromState>.ChatStopInProgressView() {
@Composable
private fun MutableState<MigrationFromState>.ChatStopFailedView(reason: String) {
SectionView(stringResource(MR.strings.error_stopping_chat), card = true) {
SectionView(stringResource(MR.strings.error_stopping_chat)) {
Text(reason)
SectionSpacer()
SectionDividerSpaced()
SettingsActionItemWithContent(
icon = painterResource(MR.images.ic_report_filled),
text = stringResource(MR.strings.auth_stop_chat),
@@ -225,9 +226,9 @@ private fun MutableState<MigrationFromState>.PassphraseConfirmationView() {
val view = LocalMultiplatformView()
Column {
ChatStoppedView()
SectionSpacer()
SectionDividerSpaced()
SectionView(stringResource(MR.strings.migrate_from_device_verify_database_passphrase), card = true) {
SectionView(stringResource(MR.strings.migrate_from_device_verify_database_passphrase)) {
PassphraseField(currentKey, placeholder = stringResource(MR.strings.current_passphrase), Modifier.padding(horizontal = DEFAULT_PADDING), isValid = ::validKey, requestFocus = true)
SettingsActionItemWithContent(
@@ -255,7 +256,7 @@ private fun MutableState<MigrationFromState>.PassphraseConfirmationView() {
@Composable
private fun MutableState<MigrationFromState>.UploadConfirmationView() {
SectionView(stringResource(MR.strings.migrate_from_device_confirm_upload), card = true) {
SectionView(stringResource(MR.strings.migrate_from_device_confirm_upload)) {
SettingsActionItemWithContent(
icon = painterResource(MR.images.ic_ios_share),
text = stringResource(MR.strings.migrate_from_device_archive_and_upload),
@@ -269,7 +270,7 @@ private fun MutableState<MigrationFromState>.UploadConfirmationView() {
@Composable
private fun MutableState<MigrationFromState>.ArchivingView() {
Box {
SectionView(stringResource(MR.strings.migrate_from_device_archiving_database), card = true) {}
SectionView(stringResource(MR.strings.migrate_from_device_archiving_database)) {}
ProgressView()
}
LaunchedEffect(Unit) {
@@ -280,7 +281,7 @@ private fun MutableState<MigrationFromState>.ArchivingView() {
@Composable
private fun MutableState<MigrationFromState>.DatabaseInitView(tempDatabaseFile: File, totalBytes: Long, archivePath: String) {
Box {
SectionView(stringResource(MR.strings.migrate_from_device_database_init), card = true) {}
SectionView(stringResource(MR.strings.migrate_from_device_database_init)) {}
ProgressView()
}
LaunchedEffect(Unit) {
@@ -299,7 +300,7 @@ private fun MutableState<MigrationFromState>.UploadProgressView(
archivePath: String,
) {
Box {
SectionView(stringResource(MR.strings.migrate_from_device_uploading_archive), card = true) {
SectionView(stringResource(MR.strings.migrate_from_device_uploading_archive)) {
val ratio = uploadedBytes.toFloat() / max(totalBytes, 1)
LargeProgressView(ratio, "${(ratio * 100).toInt()}%", stringResource(MR.strings.migrate_from_device_bytes_uploaded).format(formatBytes(uploadedBytes)))
}
@@ -311,7 +312,7 @@ private fun MutableState<MigrationFromState>.UploadProgressView(
@Composable
private fun MutableState<MigrationFromState>.UploadFailedView(totalBytes: Long, archivePath: String, chatReceiver: MigrationFromChatReceiver?) {
SectionView(stringResource(MR.strings.migrate_from_device_upload_failed), card = true) {
SectionView(stringResource(MR.strings.migrate_from_device_upload_failed)) {
SettingsActionItemWithContent(
icon = painterResource(MR.images.ic_ios_share),
text = stringResource(MR.strings.migrate_from_device_repeat_upload),
@@ -330,14 +331,14 @@ private fun MutableState<MigrationFromState>.UploadFailedView(totalBytes: Long,
@Composable
private fun LinkCreationView() {
Box {
SectionView(stringResource(MR.strings.migrate_from_device_creating_archive_link), card = true) {}
SectionView(stringResource(MR.strings.migrate_from_device_creating_archive_link)) {}
ProgressView()
}
}
@Composable
private fun MutableState<MigrationFromState>.LinkShownView(fileId: Long, link: String, ctrl: ChatCtrl, chatReceiver: MigrationFromChatReceiver?) {
SectionView(card = true) {
SectionView {
SettingsActionItemWithContent(
icon = painterResource(MR.images.ic_close),
text = stringResource(MR.strings.migrate_from_device_cancel_migration),
@@ -365,12 +366,12 @@ private fun MutableState<MigrationFromState>.LinkShownView(fileId: Long, link: S
}
SectionTextFooter(annotatedStringResource(MR.strings.migrate_from_device_archive_will_be_deleted))
SectionTextFooter(annotatedStringResource(MR.strings.migrate_from_device_choose_migrate_from_another_device))
SectionSpacer()
SectionView(stringResource(MR.strings.show_QR_code), card = true) {
SectionDividerSpaced()
SectionView(stringResource(MR.strings.show_QR_code)) {
SimpleXLinkQRCode(link, onShare = {})
}
SectionSpacer()
SectionView(stringResource(MR.strings.migrate_from_device_or_share_this_file_link), card = true) {
SectionDividerSpaced()
SectionView(stringResource(MR.strings.migrate_from_device_or_share_this_file_link)) {
LinkTextView(link, true)
}
}
@@ -378,7 +379,7 @@ private fun MutableState<MigrationFromState>.LinkShownView(fileId: Long, link: S
@Composable
private fun MutableState<MigrationFromState>.FinishedView(chatDeletion: Boolean) {
Box {
SectionView(stringResource(MR.strings.migrate_from_device_migration_complete), card = true) {
SectionView(stringResource(MR.strings.migrate_from_device_migration_complete)) {
SettingsActionItemWithContent(
icon = painterResource(MR.images.ic_play_arrow_filled),
text = stringResource(MR.strings.migrate_from_device_start_chat),
@@ -2,6 +2,7 @@ package chat.simplex.common.views.migration
import SectionBottomSpacer
import SectionItemView
import SectionDividerSpaced
import SectionSpacer
import SectionTextFooter
import SectionView
@@ -149,6 +150,7 @@ fun ModalData.MigrateToDeviceView(close: () -> Unit) {
close()
}
},
cardScreen = true,
) {
MigrateToDeviceLayout(
migrationState = migrationState,
@@ -165,7 +167,7 @@ private fun ModalData.MigrateToDeviceLayout(
close: () -> Unit,
) {
val tempDatabaseFile = rememberSaveable { mutableStateOf(fileForTemporaryDatabase()) }
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme()), maxIntrinsicSize = true) {
ColumnWithScrollBar(maxIntrinsicSize = true) {
AppBarTitle(stringResource(MR.strings.migrate_to_device_title))
SectionByState(migrationState, tempDatabaseFile.value, chatReceiver, close)
SectionBottomSpacer()
@@ -202,7 +204,7 @@ private fun MutableState<MigrationToState?>.PasteOrScanLinkView(close: () -> Uni
val progressIndicator = remember { mutableStateOf(false) }
Column {
if (appPlatform.isAndroid) {
SectionView(stringResource(MR.strings.scan_QR_code).replace('\n', ' '), card = true) {
SectionView(stringResource(MR.strings.scan_QR_code).replace('\n', ' ')) {
QRCodeScanner(showQRCodeScanner = remember { mutableStateOf(true) }) { text ->
checkUserLink(text)
}
@@ -210,12 +212,12 @@ private fun MutableState<MigrationToState?>.PasteOrScanLinkView(close: () -> Uni
SectionSpacer()
}
SectionView(stringResource(if (appPlatform.isAndroid) MR.strings.or_paste_archive_link else MR.strings.paste_archive_link), card = true) {
SectionView(stringResource(if (appPlatform.isAndroid) MR.strings.or_paste_archive_link else MR.strings.paste_archive_link)) {
PasteLinkView()
}
SectionSpacer()
SectionView(stringResource(MR.strings.chat_archive), card = true) {
SectionView(stringResource(MR.strings.chat_archive)) {
ArchiveImportView(progressIndicator, close)
}
}
@@ -281,7 +283,7 @@ private fun ModalData.OnionView(link: String, legacyLinkSocksProxy: String?, lin
mutableStateOf(getNetCfg().withOnionHosts(onionHosts.value).copy(socksProxy = linkNetworkProxy?.toProxyString() ?: legacyLinkSocksProxy, sessionMode = sessionMode.value))
}
SectionView(stringResource(MR.strings.migrate_to_device_confirm_network_settings), card = true) {
SectionView(stringResource(MR.strings.migrate_to_device_confirm_network_settings)) {
SettingsActionItemWithContent(
icon = painterResource(MR.images.ic_check),
text = stringResource(MR.strings.migrate_to_device_apply_onion),
@@ -306,7 +308,7 @@ private fun ModalData.OnionView(link: String, legacyLinkSocksProxy: String?, lin
val networkProxyPref = SharedPreference(get = { networkProxy.value }, set = {
networkProxy.value = it
})
SectionView(stringResource(MR.strings.network_settings_title), card = true) {
SectionView(stringResource(MR.strings.network_settings_title)) {
OnionRelatedLayout(
appPreferences.developerTools.get(),
networkUseSocksProxy,
@@ -326,7 +328,7 @@ private fun ModalData.OnionView(link: String, legacyLinkSocksProxy: String?, lin
@Composable
private fun MutableState<MigrationToState?>.DatabaseInitView(link: String, tempDatabaseFile: File, netCfg: NetCfg, networkProxy: NetworkProxy?) {
Box {
SectionView(stringResource(MR.strings.migrate_to_device_database_init), card = true) {}
SectionView(stringResource(MR.strings.migrate_to_device_database_init)) {}
ProgressView()
}
LaunchedEffect(Unit) {
@@ -346,7 +348,7 @@ private fun MutableState<MigrationToState?>.LinkDownloadingView(
networkProxy: NetworkProxy?
) {
Box {
SectionView(stringResource(MR.strings.migrate_to_device_downloading_details), card = true) {}
SectionView(stringResource(MR.strings.migrate_to_device_downloading_details)) {}
ProgressView()
}
LaunchedEffect(Unit) {
@@ -357,7 +359,7 @@ private fun MutableState<MigrationToState?>.LinkDownloadingView(
@Composable
private fun DownloadProgressView(downloadedBytes: Long, totalBytes: Long) {
Box {
SectionView(stringResource(MR.strings.migrate_to_device_downloading_archive), card = true) {
SectionView(stringResource(MR.strings.migrate_to_device_downloading_archive)) {
val ratio = downloadedBytes.toFloat() / max(totalBytes, 1)
LargeProgressView(ratio, "${(ratio * 100).toInt()}%", stringResource(MR.strings.migrate_to_device_bytes_downloaded).format(formatBytes(downloadedBytes)))
}
@@ -366,7 +368,7 @@ private fun DownloadProgressView(downloadedBytes: Long, totalBytes: Long) {
@Composable
private fun MutableState<MigrationToState?>.DownloadFailedView(link: String, chatReceiver: MigrationToChatReceiver?, archivePath: String, netCfg: NetCfg, networkProxy: NetworkProxy?) {
SectionView(stringResource(MR.strings.migrate_to_device_download_failed), card = true) {
SectionView(stringResource(MR.strings.migrate_to_device_download_failed)) {
SettingsActionItemWithContent(
icon = painterResource(MR.images.ic_download),
text = stringResource(MR.strings.migrate_to_device_repeat_download),
@@ -387,7 +389,7 @@ private fun MutableState<MigrationToState?>.DownloadFailedView(link: String, cha
@Composable
private fun MutableState<MigrationToState?>.ArchiveImportView(archivePath: String, netCfg: NetCfg, networkProxy: NetworkProxy?) {
Box {
SectionView(stringResource(MR.strings.migrate_to_device_importing_archive), card = true) {}
SectionView(stringResource(MR.strings.migrate_to_device_importing_archive)) {}
ProgressView()
}
LaunchedEffect(Unit) {
@@ -397,7 +399,7 @@ private fun MutableState<MigrationToState?>.ArchiveImportView(archivePath: Strin
@Composable
private fun MutableState<MigrationToState?>.ArchiveImportFailedView(archivePath: String, netCfg: NetCfg, networkProxy: NetworkProxy?) {
SectionView(stringResource(MR.strings.migrate_to_device_import_failed), card = true) {
SectionView(stringResource(MR.strings.migrate_to_device_import_failed)) {
SettingsActionItemWithContent(
icon = painterResource(MR.images.ic_download),
text = stringResource(MR.strings.migrate_to_device_repeat_import),
@@ -418,7 +420,7 @@ private fun MutableState<MigrationToState?>.PassphraseEnteringView(currentKey: S
Box {
val view = LocalMultiplatformView()
SectionView(stringResource(MR.strings.migrate_to_device_enter_passphrase), card = true) {
SectionView(stringResource(MR.strings.migrate_to_device_enter_passphrase)) {
SavePassphraseSetting(
useKeychain.value,
false,
@@ -490,7 +492,7 @@ private fun MutableState<MigrationToState?>.MigrationConfirmationView(status: DB
}
else -> Tuple4(generalGetString(MR.strings.error), null, generalGetString(MR.strings.unknown_error), null)
}
SectionView(header, card = true) {
SectionView(header) {
if (button != null && confirmation != null) {
SettingsActionItemWithContent(
icon = painterResource(MR.images.ic_download),
@@ -508,7 +510,7 @@ private fun MutableState<MigrationToState?>.MigrationConfirmationView(status: DB
@Composable
private fun MigrationView(passphrase: String, confirmation: MigrationConfirmation, useKeychain: Boolean, netCfg: NetCfg, networkProxy: NetworkProxy?, close: () -> Unit) {
Box {
SectionView(stringResource(MR.strings.migrate_to_device_migrating), card = true) {}
SectionView(stringResource(MR.strings.migrate_to_device_migrating)) {}
ProgressView()
}
LaunchedEffect(Unit) {
@@ -1,7 +1,7 @@
package chat.simplex.common.views.newchat
import SectionBottomSpacer
import SectionSpacer
import SectionDividerSpaced
import SectionTextFooter
import SectionView
import SectionViewWithButton
@@ -106,7 +106,7 @@ private fun ContactConnectionInfoLayout(
}
}
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
AppBarTitle(
stringResource(
if (contactConnection.initiated) MR.strings.you_invited_a_contact
@@ -132,8 +132,7 @@ private fun ContactConnectionInfoLayout(
Spacer(Modifier.height(DEFAULT_PADDING))
SectionViewWithButton(
stringResource(MR.strings.one_time_link),
titleButton = if (connLink.connShortLink == null) null else {{ ToggleShortLinkButton(showShortLink) }},
card = true
titleButton = if (connLink.connShortLink == null) null else {{ ToggleShortLinkButton(showShortLink) }}
) {
SimpleXCreatedLinkQRCode(connLink, short = showShortLink.value)
incognitoEnabled()
@@ -141,14 +140,14 @@ private fun ContactConnectionInfoLayout(
OneTimeLinkLearnMoreButton(learnMore)
}
} else {
SectionView(card = true) {
SectionView {
incognitoEnabled()
OneTimeLinkLearnMoreButton(learnMore)
}
}
SectionTextFooter(sharedProfileInfo(chatModel, contactConnection.incognito))
SectionSpacer()
SectionDividerSpaced()
DeleteButton(deleteConnection)
@@ -1,7 +1,7 @@
package chat.simplex.common.views.onboarding
import SectionBottomSpacer
import SectionSpacer
import SectionDividerSpaced
import SectionItemView
import SectionTextFooter
import SectionView
@@ -55,7 +55,7 @@ fun OnboardingConditionsView(chatModel: ChatModel) {
OnboardingConditionsDesktop(selectedOperatorIds)
} else {
CompositionLocalProvider(LocalAppBarHandler provides rememberAppBarHandler()) {
ModalView({}, showClose = false, showAppBar = false) {
ModalView({}, showClose = false, showAppBar = false, cardScreen = true) {
OnboardingShrinkingLayout(
modifier = Modifier.fillMaxSize().themedBackground(bgLayerSize = LocalAppBarHandler.current?.backgroundGraphicsLayerSize, bgLayer = LocalAppBarHandler.current?.backgroundGraphicsLayer)
.systemBarsPadding()
@@ -133,8 +133,8 @@ fun OnboardingConditionsView(chatModel: ChatModel) {
@Composable
private fun OnboardingConditionsDesktop(selectedOperatorIds: MutableState<Set<Long>>) {
CompositionLocalProvider(LocalAppBarHandler provides rememberAppBarHandler()) {
ModalView({}, showClose = false) {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme()), horizontalAlignment = Alignment.CenterHorizontally) {
ModalView({}, showClose = false, cardScreen = true) {
ColumnWithScrollBar(horizontalAlignment = Alignment.CenterHorizontally) {
Column(Modifier.widthIn(max = 600.dp).fillMaxHeight().padding(horizontal = DEFAULT_PADDING).align(Alignment.CenterHorizontally), horizontalAlignment = Alignment.CenterHorizontally) {
Box(Modifier.align(Alignment.CenterHorizontally)) {
AppBarTitle(stringResource(MR.strings.onboarding_network_commitments), bottomPadding = DEFAULT_PADDING, withPadding = false, overrideTitleColor = MaterialTheme.colors.onBackground, textAlign = TextAlign.Center, lineHeight = 42.sp)
@@ -184,7 +184,7 @@ fun ModalData.ChooseServerOperators(
prepareChatBeforeFinishingOnboarding()
}
CompositionLocalProvider(LocalAppBarHandler provides rememberAppBarHandler()) {
ModalView(close, enableClose = selectedOperatorIds.value.isNotEmpty()) {
ModalView(close, enableClose = selectedOperatorIds.value.isNotEmpty(), cardScreen = true) {
ColumnWithScrollBar(
Modifier
.themedBackground(bgLayerSize = LocalAppBarHandler.current?.backgroundGraphicsLayerSize, bgLayer = LocalAppBarHandler.current?.backgroundGraphicsLayer),
@@ -360,7 +360,7 @@ private fun enabledOperators(operators: List<ServerOperator>, selectedOperatorId
@Composable
private fun ChooseServerOperatorsInfoView() {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
AppBarTitle(stringResource(MR.strings.onboarding_network_operators))
Column(
@@ -371,9 +371,9 @@ private fun ChooseServerOperatorsInfoView() {
ReadableText(stringResource(MR.strings.onboarding_network_operators_app_will_use_for_routing))
}
SectionSpacer()
SectionDividerSpaced()
SectionView(title = stringResource(MR.strings.onboarding_network_about_operators), card = true) {
SectionView(title = stringResource(MR.strings.onboarding_network_about_operators)) {
chatModel.conditions.value.serverOperators.forEach { op ->
ServerOperatorRow(op)
}
@@ -1,7 +1,7 @@
package chat.simplex.common.views.remote
import SectionBottomSpacer
import SectionSpacer
import SectionDividerSpaced
import SectionItemView
import SectionItemViewLongClickable
import SectionView
@@ -52,7 +52,7 @@ fun ConnectDesktopView(close: () -> Unit) {
showDisconnectDesktopAlert(close)
}
}
ModalView(close = closeWithAlert) {
ModalView(close = closeWithAlert, cardScreen = true) {
ConnectDesktopLayout(
deviceName = deviceName.value!!,
close
@@ -75,7 +75,7 @@ private fun ConnectDesktopLayout(deviceName: String, close: () -> Unit) {
val sessionAddress = remember { mutableStateOf("") }
val remoteCtrls = remember { mutableStateListOf<RemoteCtrlInfo>() }
val session = remember { chatModel.remoteCtrlSession }.value
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
val discovery = if (session == null) null else session.sessionState is UIRemoteCtrlSessionState.Searching
if (discovery == true || (discovery == null && !showConnectScreen.value)) {
SearchingDesktop(deviceName, remoteCtrls)
@@ -127,7 +127,7 @@ private fun ConnectDesktopLayout(deviceName: String, close: () -> Unit) {
@Composable
private fun ConnectDesktop(deviceName: String, remoteCtrls: SnapshotStateList<RemoteCtrlInfo>, sessionAddress: MutableState<String>) {
AppBarTitle(stringResource(MR.strings.connect_to_desktop))
SectionView(stringResource(MR.strings.this_device_name), card = true) {
SectionView(stringResource(MR.strings.this_device_name)) {
DevicesView(deviceName, remoteCtrls) {
if (it != "") {
setDeviceName(it)
@@ -135,10 +135,10 @@ private fun ConnectDesktop(deviceName: String, remoteCtrls: SnapshotStateList<Re
}
}
}
SectionSpacer()
SectionDividerSpaced()
ScanDesktopAddressView(sessionAddress)
if (controller.appPrefs.developerTools.get()) {
SectionSpacer()
SectionDividerSpaced()
DesktopAddressView(sessionAddress)
}
}
@@ -146,22 +146,22 @@ private fun ConnectDesktop(deviceName: String, remoteCtrls: SnapshotStateList<Re
@Composable
private fun ConnectingDesktop(session: RemoteCtrlSession, rc: RemoteCtrlInfo?) {
AppBarTitle(stringResource(MR.strings.connecting_to_desktop))
SectionView(stringResource(MR.strings.connecting_to_desktop), contentPadding = PaddingValues(horizontal = DEFAULT_PADDING), card = true) {
SectionView(stringResource(MR.strings.connecting_to_desktop), contentPadding = PaddingValues(horizontal = DEFAULT_PADDING)) {
CtrlDeviceNameText(session, rc)
Spacer(Modifier.height(DEFAULT_PADDING_HALF))
CtrlDeviceVersionText(session)
}
if (session.sessionCode != null) {
SectionSpacer()
SectionView(stringResource(MR.strings.session_code), card = true) {
SectionDividerSpaced()
SectionView(stringResource(MR.strings.session_code)) {
SessionCodeText(session.sessionCode!!)
}
}
SectionSpacer()
SectionDividerSpaced()
SectionView(card = true) {
SectionView {
DisconnectButton(onClick = ::disconnectDesktop)
}
@@ -187,7 +187,7 @@ private fun ProgressIndicator() {
@Composable
private fun SearchingDesktop(deviceName: String, remoteCtrls: SnapshotStateList<RemoteCtrlInfo>) {
AppBarTitle(stringResource(MR.strings.connecting_to_desktop))
SectionView(stringResource(MR.strings.this_device_name), card = true) {
SectionView(stringResource(MR.strings.this_device_name)) {
DevicesView(deviceName, remoteCtrls) {
if (it != "") {
setDeviceName(it)
@@ -195,11 +195,11 @@ private fun SearchingDesktop(deviceName: String, remoteCtrls: SnapshotStateList<
}
}
}
SectionSpacer()
SectionView(stringResource(MR.strings.found_desktop), contentPadding = PaddingValues(horizontal = DEFAULT_PADDING), card = true) {
SectionDividerSpaced()
SectionView(stringResource(MR.strings.found_desktop), contentPadding = PaddingValues(horizontal = DEFAULT_PADDING)) {
Text(stringResource(MR.strings.waiting_for_desktop), fontStyle = FontStyle.Italic)
}
SectionSpacer()
SectionDividerSpaced()
DisconnectButton(stringResource(MR.strings.scan_QR_code).replace('\n', ' '), MR.images.ic_qr_code, ::disconnectDesktop)
}
@@ -214,7 +214,7 @@ private fun FoundDesktop(
sessionAddress: MutableState<String>,
) {
AppBarTitle(stringResource(MR.strings.found_desktop))
SectionView(stringResource(MR.strings.this_device_name), card = true) {
SectionView(stringResource(MR.strings.this_device_name)) {
DevicesView(deviceName, remoteCtrls) {
if (it != "") {
setDeviceName(it)
@@ -222,8 +222,8 @@ private fun FoundDesktop(
}
}
}
SectionSpacer()
SectionView(stringResource(MR.strings.found_desktop), contentPadding = PaddingValues(horizontal = DEFAULT_PADDING), card = true) {
SectionDividerSpaced()
SectionView(stringResource(MR.strings.found_desktop), contentPadding = PaddingValues(horizontal = DEFAULT_PADDING)) {
CtrlDeviceNameText(session, rc)
CtrlDeviceVersionText(session)
if (!compatible) {
@@ -231,7 +231,7 @@ private fun FoundDesktop(
}
}
SectionSpacer()
SectionDividerSpaced()
if (compatible) {
SectionItemView({ withBGApi { confirmKnownDesktop(sessionAddress, rc) } }) {
@@ -255,19 +255,19 @@ private fun FoundDesktop(
@Composable
private fun VerifySession(session: RemoteCtrlSession, rc: RemoteCtrlInfo?, sessCode: String, remoteCtrls: SnapshotStateList<RemoteCtrlInfo>) {
AppBarTitle(stringResource(MR.strings.verify_connection))
SectionView(stringResource(MR.strings.connected_to_desktop), contentPadding = PaddingValues(horizontal = DEFAULT_PADDING), card = true) {
SectionView(stringResource(MR.strings.connected_to_desktop), contentPadding = PaddingValues(horizontal = DEFAULT_PADDING)) {
CtrlDeviceNameText(session, rc)
Spacer(Modifier.height(DEFAULT_PADDING_HALF))
CtrlDeviceVersionText(session)
}
SectionSpacer()
SectionDividerSpaced()
SectionView(stringResource(MR.strings.verify_code_with_desktop), card = true) {
SectionView(stringResource(MR.strings.verify_code_with_desktop)) {
SessionCodeText(sessCode)
}
SectionSpacer()
SectionDividerSpaced()
SectionItemView({ verifyDesktopSessionCode(remoteCtrls, sessCode) }) {
Icon(painterResource(MR.images.ic_check), generalGetString(MR.strings.confirm_verb), tint = MaterialTheme.colors.secondary)
@@ -275,7 +275,7 @@ private fun VerifySession(session: RemoteCtrlSession, rc: RemoteCtrlInfo?, sessC
Text(generalGetString(MR.strings.confirm_verb))
}
SectionView(card = true) {
SectionView {
DisconnectButton(onClick = ::disconnectDesktop)
}
}
@@ -310,22 +310,22 @@ private fun CtrlDeviceVersionText(session: RemoteCtrlSession) {
@Composable
private fun ActiveSession(session: RemoteCtrlSession, rc: RemoteCtrlInfo, close: () -> Unit) {
AppBarTitle(stringResource(MR.strings.connected_to_desktop))
SectionView(stringResource(MR.strings.connected_desktop), contentPadding = PaddingValues(horizontal = DEFAULT_PADDING), card = true) {
SectionView(stringResource(MR.strings.connected_desktop), contentPadding = PaddingValues(horizontal = DEFAULT_PADDING)) {
Text(rc.deviceViewName)
Spacer(Modifier.height(DEFAULT_PADDING_HALF))
CtrlDeviceVersionText(session)
}
if (session.sessionCode != null) {
SectionSpacer()
SectionView(stringResource(MR.strings.session_code), card = true) {
SectionDividerSpaced()
SectionView(stringResource(MR.strings.session_code)) {
SessionCodeText(session.sessionCode!!)
}
}
SectionSpacer()
SectionDividerSpaced()
SectionView(card = true) {
SectionView {
DisconnectButton { disconnectDesktop(close) }
}
}
@@ -354,7 +354,7 @@ private fun DevicesView(deviceName: String, remoteCtrls: SnapshotStateList<Remot
@Composable
private fun ScanDesktopAddressView(sessionAddress: MutableState<String>) {
SectionView(stringResource(MR.strings.scan_qr_code_from_desktop), card = true) {
SectionView(stringResource(MR.strings.scan_qr_code_from_desktop)) {
QRCodeScanner { text ->
sessionAddress.value = text
connectDesktopAddress(sessionAddress, text)
@@ -365,7 +365,7 @@ private fun ScanDesktopAddressView(sessionAddress: MutableState<String>) {
@Composable
private fun DesktopAddressView(sessionAddress: MutableState<String>) {
val clipboard = LocalClipboardManager.current
SectionView(stringResource(MR.strings.desktop_address), card = true) {
SectionView(stringResource(MR.strings.desktop_address)) {
if (sessionAddress.value.isEmpty()) {
SettingsActionItem(
painterResource(MR.images.ic_content_paste),
@@ -407,9 +407,9 @@ private fun DesktopAddressView(sessionAddress: MutableState<String>) {
@Composable
private fun LinkedDesktopsView(remoteCtrls: SnapshotStateList<RemoteCtrlInfo>) {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
AppBarTitle(stringResource(MR.strings.linked_desktops))
SectionView(stringResource(MR.strings.desktop_devices), card = true) {
SectionView(stringResource(MR.strings.desktop_devices)) {
remoteCtrls.forEach { rc ->
val showMenu = rememberSaveable { mutableStateOf(false) }
SectionItemViewLongClickable(click = {}, longClick = { showMenu.value = true }) {
@@ -424,9 +424,9 @@ private fun LinkedDesktopsView(remoteCtrls: SnapshotStateList<RemoteCtrlInfo>) {
}
}
SectionSpacer()
SectionDividerSpaced()
SectionView(stringResource(MR.strings.linked_desktop_options), card = true) {
SectionView(stringResource(MR.strings.linked_desktop_options)) {
PreferenceToggle(stringResource(MR.strings.verify_connections), checked = remember { controller.appPrefs.confirmRemoteSessions.state }.value) {
controller.appPrefs.confirmRemoteSessions.set(it)
}
@@ -2,7 +2,7 @@ package chat.simplex.common.views.usersettings
import CARD_PADDING
import SectionBottomSpacer
import SectionSpacer
import SectionDividerSpaced
import SectionItemView
import itemHPadding
import SectionItemViewSpaceBetween
@@ -59,7 +59,7 @@ expect fun AppearanceView(m: ChatModel)
object AppearanceScope {
@Composable
fun ProfileImageSection() {
SectionView(stringResource(MR.strings.settings_section_title_profile_images), contentPadding = PaddingValues(horizontal = CARD_PADDING), card = true) {
SectionView(stringResource(MR.strings.settings_section_title_profile_images), contentPadding = PaddingValues(horizontal = CARD_PADDING)) {
val image = remember { chatModel.currentUser }.value?.image
Row(Modifier.padding(vertical = 10.dp), horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically) {
val size = 60
@@ -92,7 +92,7 @@ object AppearanceScope {
@Composable
fun AppToolbarsSection() {
BoxWithConstraints {
SectionView(stringResource(MR.strings.appearance_app_toolbars), card = true) {
SectionView(stringResource(MR.strings.appearance_app_toolbars)) {
SectionItemViewWithoutMinPadding {
Box(Modifier.weight(1f)) {
var fontScale by remember { mutableStateOf(1f) }
@@ -179,7 +179,7 @@ object AppearanceScope {
@Composable
fun MessageShapeSection() {
BoxWithConstraints {
SectionView(stringResource(MR.strings.settings_section_title_message_shape), card = true) {
SectionView(stringResource(MR.strings.settings_section_title_message_shape)) {
SectionItemViewWithoutMinPadding {
Text(stringResource(MR.strings.settings_message_shape_corner), Modifier.weight(1f))
Spacer(Modifier.width(10.dp))
@@ -209,7 +209,7 @@ object AppearanceScope {
@Composable
fun FontScaleSection() {
val localFontScale = remember { mutableStateOf(appPrefs.fontScale.get()) }
SectionView(stringResource(MR.strings.appearance_font_size), contentPadding = PaddingValues(horizontal = CARD_PADDING), card = true) {
SectionView(stringResource(MR.strings.appearance_font_size), contentPadding = PaddingValues(horizontal = CARD_PADDING)) {
Row(Modifier.padding(vertical = 10.dp), verticalAlignment = Alignment.CenterVertically) {
Box(Modifier.size(50.dp)
.background(MaterialTheme.colors.surface, RoundedCornerShape(percent = 22))
@@ -524,7 +524,7 @@ object AppearanceScope {
}
}
SectionView(stringResource(MR.strings.settings_section_title_themes), card = true) {
SectionView(stringResource(MR.strings.settings_section_title_themes)) {
ThemeDestinationPicker(themeUserDestination)
val importWallpaperLauncher = rememberFileChooserLauncher(true) { to: URI? ->
@@ -557,7 +557,7 @@ object AppearanceScope {
color = if (chatModel.remoteHostId != null && themeUserDestination.value != null) MaterialTheme.colors.secondary else MaterialTheme.colors.primary
)
}
SectionSpacer()
SectionDividerSpaced()
}
val state: State<DefaultThemeMode?> = remember(appPrefs.currentTheme.get()) {
@@ -608,7 +608,7 @@ object AppearanceScope {
@Composable
fun CustomizeThemeView(onChooseType: (WallpaperType?) -> Unit) {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
val currentTheme by CurrentColors.collectAsState()
AppBarTitle(stringResource(MR.strings.customize_theme_title))
@@ -651,10 +651,10 @@ object AppearanceScope {
color = if (chatModel.remoteHostId == null) MaterialTheme.colors.primary else MaterialTheme.colors.secondary
)
}
SectionSpacer()
SectionDividerSpaced()
}
SectionView(stringResource(MR.strings.settings_section_title_chat_colors), card = true) {
SectionView(stringResource(MR.strings.settings_section_title_chat_colors)) {
WallpaperSetupView(
wallpaperType,
baseTheme,
@@ -672,13 +672,13 @@ object AppearanceScope {
},
)
}
SectionSpacer()
SectionDividerSpaced()
CustomizeThemeColorsSection(currentTheme) { name ->
editColor(name)
}
SectionSpacer()
SectionDividerSpaced()
val currentOverrides = remember(currentTheme) { ThemeManager.defaultActiveTheme(appPrefs.themeOverrides.get()) }
val canResetColors = currentTheme.base.hasChangedAnyColor(currentOverrides)
@@ -689,10 +689,10 @@ object AppearanceScope {
}) {
Text(generalGetString(MR.strings.reset_color), color = colors.primary)
}
SectionSpacer()
SectionDividerSpaced()
}
SectionView(card = true) {
SectionView {
val theme = remember { mutableStateOf(null as String?) }
val exportThemeLauncher = rememberFileChooserLauncher(false) { to: URI? ->
val themeValue = theme.value
@@ -945,7 +945,7 @@ object AppearanceScope {
@Composable
fun CustomizeThemeColorsSection(currentTheme: ThemeManager.ActiveTheme, editColor: (ThemeColor) -> Unit) {
SectionView(stringResource(MR.strings.theme_colors_section_title), card = true) {
SectionView(stringResource(MR.strings.theme_colors_section_title)) {
SectionItemViewSpaceBetween({ editColor(ThemeColor.PRIMARY) }) {
val title = generalGetString(MR.strings.color_primary)
Text(title)
@@ -1009,7 +1009,7 @@ object AppearanceScope {
SimpleXThemeOverride(currentColors()) {
ChatThemePreview(theme, wallpaperImage, wallpaperType, previewBackgroundColor, previewTintColor)
}
SectionSpacer()
SectionDividerSpaced()
}
var currentColor by remember { mutableStateOf(initialColor) }
@@ -1086,7 +1086,7 @@ object AppearanceScope {
}) {
Text(generalGetString(MR.strings.reset_single_color), color = colors.primary)
}
SectionSpacer()
SectionDividerSpaced()
}
}
@@ -1237,7 +1237,7 @@ fun WallpaperSetupView(
Text(title)
Icon(painterResource(MR.images.ic_circle_filled), title, tint = wallpaperTintColor)
}
SectionSpacer()
SectionDividerSpaced()
}
SectionItemViewSpaceBetween({ editColor(ThemeColor.SENT_MESSAGE) }) {
@@ -1,7 +1,7 @@
package chat.simplex.common.views.usersettings
import SectionBottomSpacer
import SectionSpacer
import SectionDividerSpaced
import SectionTextFooter
import SectionView
import androidx.compose.foundation.background
@@ -21,13 +21,13 @@ import chat.simplex.res.MR
fun DeveloperView(withAuth: (title: String, desc: String, block: () -> Unit) -> Unit
) {
val m = chatModel
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
val uriHandler = LocalUriHandler.current
AppBarTitle(stringResource(MR.strings.settings_developer_tools))
val developerTools = m.controller.appPrefs.developerTools
val devTools = remember { developerTools.state }
val unchangedHints = mutableStateOf(unchangedHintPreferences())
SectionView(card = true) {
SectionView {
InstallTerminalAppItem(uriHandler)
ChatConsoleItem { withAuth(generalGetString(MR.strings.auth_open_chat_console), generalGetString(MR.strings.auth_log_in_using_credential)) { ModalManager.start.showModalCloseable { TerminalView(false) } } }
ResetHintsItem(unchangedHints)
@@ -38,8 +38,8 @@ fun DeveloperView(withAuth: (title: String, desc: String, block: () -> Unit) ->
generalGetString(MR.strings.developer_options)
)
if (devTools.value) {
SectionSpacer()
SectionView(stringResource(MR.strings.developer_options_section), card = true) {
SectionDividerSpaced()
SectionView(stringResource(MR.strings.developer_options_section)) {
SettingsActionItemWithContent(painterResource(MR.images.ic_breaking_news), stringResource(MR.strings.debug_logs)) {
DefaultSwitch(
checked = remember { appPrefs.logLevel.state }.value <= LogLevel.DEBUG,
@@ -62,8 +62,8 @@ fun DeveloperView(withAuth: (title: String, desc: String, block: () -> Unit) ->
SettingsPreferenceItem(painterResource(MR.images.ic_avg_pace), stringResource(MR.strings.show_slow_api_calls), appPreferences.showSlowApiCalls)
}
}
SectionSpacer()
SectionView(stringResource(MR.strings.deprecated_options_section), card = true) {
SectionDividerSpaced()
SectionView(stringResource(MR.strings.deprecated_options_section)) {
val simplexLinkMode = chatModel.controller.appPrefs.simplexLinkMode
SimpleXLinkOptions(chatModel.simplexLinkMode, onSelected = {
simplexLinkMode.set(it)
@@ -56,9 +56,9 @@ fun NotificationsSettingsLayout(
val modes = remember { notificationModes() }
val previewModes = remember { notificationPreviewModes() }
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
AppBarTitle(stringResource(MR.strings.notifications))
SectionView(null, card = true) {
SectionView(null) {
if (appPlatform == AppPlatform.ANDROID) {
SettingsActionItemWithContent(null, stringResource(MR.strings.settings_notifications_mode_title), { showPage(CurrentPage.NOTIFICATIONS_MODE) }) {
Text(
@@ -2,7 +2,7 @@ package chat.simplex.common.views.usersettings
import SectionBottomSpacer
import SectionItemView
import SectionSpacer
import SectionDividerSpaced
import SectionTextFooter
import SectionView
import androidx.compose.foundation.*
@@ -49,6 +49,7 @@ fun PreferencesView(m: ChatModel, user: User, close: () -> Unit,) {
if (preferences == currentPreferences) close()
else showUnsavedChangesAlert({ savePrefs(close) }, close)
},
cardScreen = true,
) {
PreferencesLayout(
preferences,
@@ -68,7 +69,7 @@ private fun PreferencesLayout(
reset: () -> Unit,
savePrefs: () -> Unit,
) {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
AppBarTitle(stringResource(MR.strings.your_preferences))
val timedMessages = remember(preferences) { mutableStateOf(preferences.timedMessages.allow) }
val onTTLUpdated = { ttl: Int? ->
@@ -83,27 +84,27 @@ private fun PreferencesLayout(
onTTLUpdated = onTTLUpdated
)
SectionSpacer()
SectionDividerSpaced()
val allowFullDeletion = remember(preferences) { mutableStateOf(preferences.fullDelete.allow) }
FeatureSection(ChatFeature.FullDelete, allowFullDeletion) {
applyPrefs(preferences.copy(fullDelete = SimpleChatPreference(allow = it)))
}
SectionSpacer()
SectionDividerSpaced()
val allowReactions = remember(preferences) { mutableStateOf(preferences.reactions.allow) }
FeatureSection(ChatFeature.Reactions, allowReactions) {
applyPrefs(preferences.copy(reactions = SimpleChatPreference(allow = it)))
}
SectionSpacer()
SectionDividerSpaced()
val allowVoice = remember(preferences) { mutableStateOf(preferences.voice.allow) }
FeatureSection(ChatFeature.Voice, allowVoice) {
applyPrefs(preferences.copy(voice = SimpleChatPreference(allow = it)))
}
SectionSpacer()
SectionDividerSpaced()
val allowCalls = remember(preferences) { mutableStateOf(preferences.calls.allow) }
FeatureSection(ChatFeature.Calls, allowCalls) {
applyPrefs(preferences.copy(calls = SimpleChatPreference(allow = it)))
}
SectionSpacer()
SectionDividerSpaced()
ResetSaveButtons(
reset = reset,
save = savePrefs,
@@ -115,7 +116,7 @@ private fun PreferencesLayout(
@Composable
private fun FeatureSection(feature: ChatFeature, allowFeature: State<FeatureAllowed>, onSelected: (FeatureAllowed) -> Unit) {
SectionView(card = true) {
SectionView {
ExposedDropDownSettingRow(
feature.text,
FeatureAllowed.values().map { it to it.text },
@@ -135,7 +136,7 @@ private fun TimedMessagesFeatureSection(
onTTLUpdated: (Int?) -> Unit
) {
val ttl = rememberSaveable(preferences) { mutableStateOf(preferences.timedMessages.ttl) }
SectionView(card = true) {
SectionView {
PreferenceToggleWithIcon(
ChatFeature.TimedMessages.text,
ChatFeature.TimedMessages.icon,
@@ -165,7 +166,7 @@ private fun TimedMessagesFeatureSection(
@Composable
private fun ResetSaveButtons(reset: () -> Unit, save: () -> Unit, disabled: Boolean) {
SectionView(card = true) {
SectionView {
SectionItemView(reset, disabled = disabled) {
Text(stringResource(MR.strings.reset_verb), color = if (disabled) MaterialTheme.colors.secondary else MaterialTheme.colors.primary)
}
@@ -2,7 +2,7 @@ package chat.simplex.common.views.usersettings
import SectionBottomSpacer
import SectionItemView
import SectionSpacer
import SectionDividerSpaced
import SectionTextFooter
import SectionView
import androidx.compose.foundation.background
@@ -56,12 +56,12 @@ fun PrivacySettingsView(
showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit),
setPerformLA: (Boolean) -> Unit
) {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
AppBarTitle(stringResource(MR.strings.your_privacy))
PrivacyDeviceSection(showSettingsModal, setPerformLA)
SectionSpacer()
SectionDividerSpaced()
SectionView(stringResource(MR.strings.settings_section_title_chats), card = true) {
SectionView(stringResource(MR.strings.settings_section_title_chats)) {
SettingsPreferenceItem(
painterResource(MR.images.ic_travel_explore),
stringResource(MR.strings.send_link_previews),
@@ -92,9 +92,9 @@ fun PrivacySettingsView(
}
})
}
SectionSpacer()
SectionDividerSpaced()
SectionView(stringResource(MR.strings.settings_section_title_files), card = true) {
SectionView(stringResource(MR.strings.settings_section_title_files)) {
SettingsPreferenceItem(painterResource(MR.images.ic_lock), stringResource(MR.strings.encrypt_local_files), chatModel.controller.appPrefs.privacyEncryptLocalFiles, onChange = { enable ->
withBGApi { chatModel.controller.apiSetEncryptLocalFiles(enable) }
})
@@ -172,7 +172,7 @@ fun PrivacySettingsView(
}
if (!chatModel.desktopNoUserNoRemote) {
SectionSpacer()
SectionDividerSpaced()
ContacRequestsFromGroupsSection(
currentUser = currentUser,
setAutoAcceptGrpDirectInvs = { enable ->
@@ -180,7 +180,7 @@ fun PrivacySettingsView(
}
)
SectionSpacer()
SectionDividerSpaced()
DeliveryReceiptsSection(
currentUser = currentUser,
setOrAskSendReceiptsContacts = { enable ->
@@ -278,7 +278,7 @@ private fun ContacRequestsFromGroupsSection(
currentUser: User,
setAutoAcceptGrpDirectInvs: (Boolean) -> Unit
) {
SectionView(stringResource(MR.strings.settings_section_title_contact_requests_from_groups), card = true) {
SectionView(stringResource(MR.strings.settings_section_title_contact_requests_from_groups)) {
SettingsActionItemWithContent(painterResource(MR.images.ic_check), stringResource(MR.strings.auto_accept_contact)) {
DefaultSwitch(
checked = currentUser.autoAcceptMemberContacts,
@@ -307,7 +307,7 @@ private fun DeliveryReceiptsSection(
setOrAskSendReceiptsContacts: (Boolean) -> Unit,
setOrAskSendReceiptsGroups: (Boolean) -> Unit,
) {
SectionView(stringResource(MR.strings.settings_section_title_delivery_receipts), card = true) {
SectionView(stringResource(MR.strings.settings_section_title_delivery_receipts)) {
SettingsActionItemWithContent(painterResource(MR.images.ic_person), stringResource(MR.strings.receipts_section_contacts)) {
DefaultSwitch(
checked = currentUser.sendRcptsContacts,
@@ -561,9 +561,9 @@ fun SimplexLockView(
}
}
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
AppBarTitle(stringResource(MR.strings.chat_lock))
SectionView(card = true) {
SectionView {
EnableLock(remember { appPrefs.performLA.state }) { performLAToggle ->
showAuthScreen.value = performLAToggle
chatModel.controller.appPrefs.laNoticeShown.set(true)
@@ -619,8 +619,8 @@ fun SimplexLockView(
}
}
if (performLA.value && laMode.value == LAMode.PASSCODE) {
SectionSpacer()
SectionView(stringResource(MR.strings.self_destruct_passcode), card = true) {
SectionDividerSpaced()
SectionView(stringResource(MR.strings.self_destruct_passcode)) {
val openInfo = {
ModalManager.start.showModal {
SelfDestructInfoView()
@@ -3,7 +3,7 @@ package chat.simplex.common.views.usersettings
import SectionBottomSpacer
import itemHPadding
import SectionItemView
import SectionSpacer
import SectionDividerSpaced
import SectionView
import TextIconSpaced
import androidx.compose.desktop.ui.tooling.preview.Preview
@@ -47,12 +47,13 @@ fun SettingsView(chatModel: ChatModel, setPerformLA: (Boolean) -> Unit, close: (
user?.displayName,
setPerformLA = setPerformLA,
showModal = { modalView -> { ModalManager.start.showModal { modalView(chatModel) } } },
showSettingsModal = { modalView -> { ModalManager.start.showModal(true) { modalView(chatModel) } } },
showSettingsModal = { modalView -> { ModalManager.start.showModal(settings = true, cardScreen = true) { modalView(chatModel) } } },
showSettingsModalWithSearch = { modalView ->
ModalManager.start.showCustomModal { close ->
val search = rememberSaveable { mutableStateOf("") }
ModalView(
{ close() },
cardScreen = true,
showSearch = true,
searchAlwaysVisible = true,
onSearchValueChanged = { search.value = it },
@@ -98,26 +99,26 @@ fun SettingsLayout(
hideKeyboard(view)
}
val uriHandler = LocalUriHandler.current
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
AppBarTitle(stringResource(MR.strings.your_settings))
SectionView(stringResource(MR.strings.settings_section_title_settings), card = true) {
SectionView(stringResource(MR.strings.settings_section_title_settings)) {
SettingsActionItem(painterResource(if (notificationsMode.value == NotificationsMode.OFF) MR.images.ic_bolt_off else MR.images.ic_bolt), stringResource(MR.strings.notifications), showSettingsModal { NotificationsSettingsView(it) }, disabled = stopped)
SettingsActionItem(painterResource(MR.images.ic_wifi_tethering), stringResource(MR.strings.network_and_servers), showCustomModal { _, close -> NetworkAndServersView(close) }, disabled = stopped)
SettingsActionItem(painterResource(MR.images.ic_videocam), stringResource(MR.strings.settings_audio_video_calls), showSettingsModal { CallSettingsView(it, showModal) }, disabled = stopped)
SettingsActionItem(painterResource(MR.images.ic_lock), stringResource(MR.strings.privacy_and_security), showSettingsModal { PrivacySettingsView(it, showSettingsModal, setPerformLA) }, disabled = stopped)
SettingsActionItem(painterResource(MR.images.ic_light_mode), stringResource(MR.strings.appearance_settings), showSettingsModal { AppearanceView(it) })
}
SectionSpacer()
SectionDividerSpaced()
SectionView(stringResource(MR.strings.settings_section_title_chat_database), card = true) {
SectionView(stringResource(MR.strings.settings_section_title_chat_database)) {
DatabaseItem(encrypted, passphraseSaved, showSettingsModal { DatabaseView() }, stopped)
SettingsActionItem(painterResource(MR.images.ic_ios_share), stringResource(MR.strings.migrate_from_device_to_another_device), { withAuth(generalGetString(MR.strings.auth_open_migration_to_another_device), generalGetString(MR.strings.auth_log_in_using_credential)) { ModalManager.fullscreen.showCustomModal { close -> MigrateFromDeviceView(close) } } }, disabled = stopped)
}
SectionSpacer()
SectionDividerSpaced()
SectionView(stringResource(MR.strings.settings_section_title_help), card = true) {
SectionView(stringResource(MR.strings.settings_section_title_help)) {
SettingsActionItem(painterResource(MR.images.ic_help), stringResource(MR.strings.how_to_use_simplex_chat), showModal { HelpView(userDisplayName ?: "") }, disabled = stopped)
SettingsActionItem(painterResource(MR.images.ic_add), stringResource(MR.strings.whats_new), showCustomModal { _, close -> WhatsNewView(viaSettings = true, close = close) }, disabled = stopped)
SettingsActionItem(painterResource(MR.images.ic_info), stringResource(MR.strings.about_simplex_chat), showModal { SimpleXInfo(it, onboarding = false) })
@@ -126,16 +127,16 @@ fun SettingsLayout(
}
SettingsActionItem(painterResource(MR.images.ic_mail), stringResource(MR.strings.send_us_an_email), { uriHandler.openUriCatching("mailto:chat@simplex.chat") }, textColor = MaterialTheme.colors.primary)
}
SectionSpacer()
SectionDividerSpaced()
SectionView(stringResource(MR.strings.settings_section_title_support), card = true) {
SectionView(stringResource(MR.strings.settings_section_title_support)) {
if (!BuildConfigCommon.ANDROID_BUNDLE) {
ContributeItem(uriHandler)
}
RateAppItem(uriHandler)
StarOnGithubItem(uriHandler)
}
SectionSpacer()
SectionDividerSpaced()
SettingsSectionApp(showSettingsModal, showVersion, withAuth)
SectionBottomSpacer()
@@ -1,7 +1,7 @@
package chat.simplex.common.views.usersettings
import SectionBottomSpacer
import SectionSpacer
import SectionDividerSpaced
import SectionItemView
import SectionTextFooter
import SectionView
@@ -172,7 +172,7 @@ fun UserAddressView(
)
}
ModalView(close = close) {
ModalView(close = close, cardScreen = true) {
showLayout()
}
@@ -279,7 +279,7 @@ private fun UserAddressLayout(
deleteAddress: () -> Unit,
saveAddressSettings: (AddressSettingsState, MutableState<AddressSettingsState>) -> Unit,
) {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
if (!onboarding) {
AppBarTitle(stringResource(MR.strings.simplex_address), hostDevice(user?.remoteHostId))
}
@@ -302,17 +302,17 @@ private fun UserAddressLayout(
) {
if (userAddress == null) {
if (!onboarding) {
SectionView(generalGetString(MR.strings.for_social_media), card = true) {
SectionView(generalGetString(MR.strings.for_social_media)) {
CreateAddressButton(createAddress)
}
SectionSpacer()
SectionView(generalGetString(MR.strings.or_to_share_privately), card = true) {
SectionDividerSpaced()
SectionView(generalGetString(MR.strings.or_to_share_privately)) {
CreateOneTimeLinkButton()
}
SectionSpacer()
SectionView(card = true) {
SectionDividerSpaced()
SectionView {
LearnMoreButton(learnMore)
}
}
@@ -338,8 +338,7 @@ private fun UserAddressLayout(
SectionViewWithButton(
stringResource(MR.strings.for_social_media),
titleButton = if (userAddress.connLinkContact.connShortLink != null) {{ ToggleShortLinkButton(showShortLink) }} else null,
card = true
titleButton = if (userAddress.connLinkContact.connShortLink != null) {{ ToggleShortLinkButton(showShortLink) }} else null
) {
SimpleXCreatedLinkQRCode(userAddress.connLinkContact, short = showShortLink.value)
if (userAddress.shouldBeUpgraded) {
@@ -360,17 +359,17 @@ private fun UserAddressLayout(
SectionTextFooter(stringResource(MR.strings.add_your_team_members_to_conversations))
}
SectionSpacer()
SectionView(generalGetString(MR.strings.or_to_share_privately), card = true) {
SectionDividerSpaced()
SectionView(generalGetString(MR.strings.or_to_share_privately)) {
CreateOneTimeLinkButton()
}
SectionSpacer()
SectionView(card = true) {
SectionDividerSpaced()
SectionView {
LearnMoreButton(learnMore)
}
SectionSpacer()
SectionView(card = true) {
SectionDividerSpaced()
SectionView {
DeleteAddressButton(deleteAddress)
}
SectionTextFooter(stringResource(MR.strings.your_contacts_will_remain_connected))
@@ -496,27 +495,27 @@ private fun ModalData.UserAddressSettings(
}
}
ModalView(close = { onClose(close) }) {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ModalView(close = { onClose(close) }, cardScreen = true) {
ColumnWithScrollBar {
AppBarTitle(stringResource(MR.strings.address_settings), hostDevice(user?.remoteHostId))
Column(
Modifier.fillMaxWidth().padding(bottom = DEFAULT_PADDING_HALF),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.SpaceEvenly
) {
SectionView(card = true) {
SectionView {
ShareWithContactsButton(shareViaProfile, setProfileAddress)
AutoAcceptToggle(addressSettingsState) { saveAddressSettings(addressSettingsState.value, savedAddressSettingsState) }
if (addressSettingsState.value.autoAccept && !chatModel.addressShortLinkDataSet() && !addressSettingsState.value.businessAddress) {
AcceptIncognitoToggle(addressSettingsState)
}
}
SectionSpacer()
SectionDividerSpaced()
SectionView(stringResource(MR.strings.address_welcome_message), card = true) {
SectionView(stringResource(MR.strings.address_welcome_message)) {
AutoReplyEditor(addressSettingsState)
}
SectionSpacer()
SectionDividerSpaced()
saveAddressSettingsButton(addressSettingsState.value == savedAddressSettingsState.value) {
saveAddressSettings(addressSettingsState.value, savedAddressSettingsState)
@@ -1,7 +1,7 @@
package chat.simplex.common.views.usersettings.networkAndServers
import SectionBottomSpacer
import SectionSpacer
import SectionDividerSpaced
import SectionItemView
import SectionItemWithValue
import SectionTextFooter
@@ -159,6 +159,7 @@ fun ModalData.AdvancedNetworkSettingsView(showModal: (@Composable ModalData.() -
}, close)
}
},
cardScreen = true,
) {
AdvancedNetworkSettingsLayout(
currentRemoteHost = currentRemoteHost,
@@ -225,23 +226,23 @@ fun ModalData.AdvancedNetworkSettingsView(showModal: (@Composable ModalData.() -
) {
val secondsLabel = stringResource(MR.strings.network_option_seconds_label)
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
AppBarTitle(stringResource(MR.strings.network_settings_title))
if (currentRemoteHost == null) {
SectionView(generalGetString(MR.strings.settings_section_title_private_message_routing), card = true) {
SectionView(generalGetString(MR.strings.settings_section_title_private_message_routing)) {
SMPProxyModePicker(smpProxyMode, showModal, updateSMPProxyMode)
SMPProxyFallbackPicker(smpProxyFallback, showModal, updateSMPProxyFallback, enabled = remember { derivedStateOf { smpProxyMode.value != SMPProxyMode.Never } })
SettingsPreferenceItem(painterResource(MR.images.ic_arrow_forward), stringResource(MR.strings.private_routing_show_message_status), chatModel.controller.appPrefs.showSentViaProxy)
}
SectionTextFooter(stringResource(MR.strings.private_routing_explanation))
SectionSpacer()
SectionDividerSpaced()
SectionView(stringResource(MR.strings.network_session_mode_transport_isolation), card = true) {
SectionView(stringResource(MR.strings.network_session_mode_transport_isolation)) {
SessionModePicker(sessionMode, showModal, updateSessionMode)
}
SectionSpacer()
SectionView(stringResource(MR.strings.network_smp_web_port_section_title), card = true) {
SectionDividerSpaced()
SectionView(stringResource(MR.strings.network_smp_web_port_section_title)) {
ExposedDropDownSettingRow(
stringResource(MR.strings.network_smp_web_port_toggle),
SMPWebPortServers.entries.map { it to stringResource(it.text) },
@@ -252,9 +253,9 @@ fun ModalData.AdvancedNetworkSettingsView(showModal: (@Composable ModalData.() -
if (smpWebPortServers.value == SMPWebPortServers.Preset) stringResource(MR.strings.network_smp_web_port_preset_footer)
else String.format(stringResource(MR.strings.network_smp_web_port_footer), if (smpWebPortServers.value == SMPWebPortServers.All) "443" else "5223")
)
SectionSpacer()
SectionDividerSpaced()
SectionView(stringResource(MR.strings.network_option_tcp_connection), card = true) {
SectionView(stringResource(MR.strings.network_option_tcp_connection)) {
SectionItemView {
TimeoutSettingRow(
stringResource(MR.strings.network_option_tcp_connection_timeout), networkTCPConnectTimeoutInteractive,
@@ -331,9 +332,9 @@ fun ModalData.AdvancedNetworkSettingsView(showModal: (@Composable ModalData.() -
}
}
SectionSpacer()
SectionDividerSpaced()
SectionView(card = true) {
SectionView {
SectionItemView(reset, disabled = resetDisabled) {
Text(stringResource(MR.strings.network_options_reset_to_defaults), color = if (resetDisabled) MaterialTheme.colors.secondary else MaterialTheme.colors.primary)
}
@@ -149,7 +149,8 @@ fun ChatRelayView(
text = generalGetString(MR.strings.check_relay_address)
)
}
}
},
cardScreen = true,
) {
ChatRelayLayout(
relayToEdit,
@@ -377,7 +378,7 @@ fun ModalData.NewChatRelayView(
ModalView(close = {
addChatRelay(relayToEdit.value, userServers, serverErrors, serverWarnings, rhId, close)
}) {
}, cardScreen = true) {
NewChatRelayLayout(relayToEdit)
}
}
@@ -2,7 +2,7 @@ package chat.simplex.common.views.usersettings.networkAndServers
import SectionBottomSpacer
import SectionCustomFooter
import SectionSpacer
import SectionDividerSpaced
import SectionItemView
import SectionItemWithValue
import SectionTextFooter
@@ -85,7 +85,7 @@ fun ModalData.NetworkAndServersView(closeNetworkAndServers: () -> Unit) {
onClose(close = { ModalManager.start.closeModals() })
}
}
ModalView(close = { onClose(closeNetworkAndServers) }) {
ModalView(close = { onClose(closeNetworkAndServers) }, cardScreen = true) {
NetworkAndServersLayout(
currentRemoteHost = currentRemoteHost,
networkUseSocksProxy = networkUseSocksProxy,
@@ -204,14 +204,14 @@ fun ModalData.NetworkAndServersView(closeNetworkAndServers: () -> Unit) {
}
}
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
val showModal = { it: @Composable ModalData.() -> Unit -> ModalManager.start.showModal(content = it) }
val showCustomModal = { it: @Composable (close: () -> Unit) -> Unit -> ModalManager.start.showCustomModal { close -> it(close) } }
AppBarTitle(stringResource(MR.strings.network_and_servers))
// TODO: Review this and socks.
if (!chatModel.desktopNoUserNoRemote) {
SectionView(generalGetString(MR.strings.network_preset_servers_title), card = true) {
SectionView(generalGetString(MR.strings.network_preset_servers_title)) {
userServers.value.forEachIndexed { index, srv ->
srv.operator?.let { ServerOperatorRow(index, it, currUserServers, userServers, serverErrors, serverWarnings, currentRemoteHost?.remoteHostId) }
}
@@ -226,10 +226,10 @@ fun ModalData.NetworkAndServersView(closeNetworkAndServers: () -> Unit) {
if (footerText != null) {
SectionTextFooter(footerText)
}
SectionSpacer()
SectionDividerSpaced()
}
SectionView(generalGetString(MR.strings.settings_section_title_messages), card = true) {
SectionView(generalGetString(MR.strings.settings_section_title_messages)) {
val nullOperatorIndex = userServers.value.indexOfFirst { it.operator == null }
if (nullOperatorIndex != -1) {
@@ -293,15 +293,15 @@ fun ModalData.NetworkAndServersView(closeNetworkAndServers: () -> Unit) {
}
}
SectionSpacer()
SectionDividerSpaced()
SectionView(generalGetString(MR.strings.settings_section_title_calls), card = true) {
SectionView(generalGetString(MR.strings.settings_section_title_calls)) {
SettingsActionItem(painterResource(MR.images.ic_electrical_services), stringResource(MR.strings.webrtc_ice_servers), { ModalManager.start.showModal { RTCServersView(m) } })
}
if (appPlatform.isAndroid) {
SectionSpacer()
SectionView(generalGetString(MR.strings.settings_section_title_network_connection), card = true) {
SectionDividerSpaced()
SectionView(generalGetString(MR.strings.settings_section_title_network_connection)) {
val info = remember { chatModel.networkInfo }.value
SettingsActionItemWithContent(icon = null, info.networkType.text) {
Icon(painterResource(MR.images.ic_circle_filled), stringResource(MR.strings.icon_descr_server_status_connected), tint = if (info.online) Color.Green else MaterialTheme.colors.error)
@@ -464,10 +464,11 @@ fun SocksProxySettings(
)
}
},
cardScreen = true,
) {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
AppBarTitle(generalGetString(MR.strings.network_socks_proxy_settings))
SectionView(stringResource(MR.strings.network_socks_proxy), card = true) {
SectionView(stringResource(MR.strings.network_socks_proxy)) {
Column(Modifier.padding(horizontal = DEFAULT_PADDING)) {
DefaultConfigurableTextField(
hostUnsaved,
@@ -493,9 +494,9 @@ fun SocksProxySettings(
SectionTextFooter(annotatedStringResource(MR.strings.disable_onion_hosts_when_not_supported))
}
SectionSpacer()
SectionDividerSpaced()
SectionView(stringResource(MR.strings.network_proxy_auth), card = true) {
SectionView(stringResource(MR.strings.network_proxy_auth)) {
PreferenceToggle(
stringResource(MR.strings.network_proxy_random_credentials),
checked = proxyAuthRandomUnsaved.value,
@@ -524,9 +525,9 @@ fun SocksProxySettings(
SectionTextFooter(proxyAuthFooter(usernameUnsaved.value.text, passwordUnsaved.value.text, proxyAuthModeUnsaved.value, sessionMode))
}
SectionSpacer()
SectionDividerSpaced()
SectionView(card = true) {
SectionView {
SectionItemView({
hostUnsaved.value = hostUnsaved.value.copy("localhost", TextRange(9))
portUnsaved.value = portUnsaved.value.copy("9050", TextRange(4))
@@ -2,7 +2,7 @@ package chat.simplex.common.views.usersettings.networkAndServers
import SectionBottomSpacer
import SectionCustomFooter
import SectionSpacer
import SectionDividerSpaced
import SectionItemView
import SectionTextFooter
import SectionView
@@ -64,7 +64,7 @@ fun OperatorView(
}
Box {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme()).alpha(if (testing.value) 0.6f else 1f)) {
ColumnWithScrollBar(Modifier.alpha(if (testing.value) 0.6f else 1f)) {
AppBarTitle(String.format(stringResource(MR.strings.operator_servers_title), operator.tradeName))
OperatorViewLayout(
currUserServers,
@@ -182,7 +182,7 @@ fun OperatorViewLayout(
val duplicateHosts = findDuplicateHosts(serverErrors.value)
Column {
SectionView(generalGetString(MR.strings.operator), card = true) {
SectionView(generalGetString(MR.strings.operator)) {
SectionItemView({ ModalManager.start.showModalCloseable { _ -> OperatorInfoView(operator) } }) {
Row(
Modifier.fillMaxWidth(),
@@ -238,8 +238,8 @@ fun OperatorViewLayout(
if (operator.enabled) {
if (userServers.value[operatorIndex].chatRelays.any { !it.deleted }) {
val duplicateRelayAddresses = findDuplicateRelayAddresses(serverErrors.value)
SectionSpacer()
SectionView(generalGetString(MR.strings.chat_relays), card = true) {
SectionDividerSpaced()
SectionView(generalGetString(MR.strings.chat_relays)) {
userServers.value[operatorIndex].chatRelays.forEachIndexed { index, relay ->
if (!relay.deleted) {
ChatRelayViewLink(relay, duplicateRelayAddresses) {
@@ -252,8 +252,8 @@ fun OperatorViewLayout(
}
if (userServers.value[operatorIndex].smpServers.any { !it.deleted }) {
SectionSpacer()
SectionView(generalGetString(MR.strings.operator_use_for_messages), card = true) {
SectionDividerSpaced()
SectionView(generalGetString(MR.strings.operator_use_for_messages)) {
SectionItemView(padding = PaddingValues(horizontal = DEFAULT_PADDING)) {
Text(
stringResource(MR.strings.operator_use_for_messages_receiving),
@@ -306,8 +306,8 @@ fun OperatorViewLayout(
// Preset servers can't be deleted
if (userServers.value[operatorIndex].smpServers.any { it.preset }) {
SectionSpacer()
SectionView(generalGetString(MR.strings.message_servers), card = true) {
SectionDividerSpaced()
SectionView(generalGetString(MR.strings.message_servers)) {
userServers.value[operatorIndex].smpServers.forEachIndexed { i, server ->
if (!server.preset) return@forEachIndexed
SectionItemView({ navigateToProtocolView(i, server, ServerProtocol.SMP) }) {
@@ -340,8 +340,8 @@ fun OperatorViewLayout(
}
if (userServers.value[operatorIndex].smpServers.any { !it.preset && !it.deleted }) {
SectionSpacer()
SectionView(generalGetString(MR.strings.operator_added_message_servers), card = true) {
SectionDividerSpaced()
SectionView(generalGetString(MR.strings.operator_added_message_servers)) {
userServers.value[operatorIndex].smpServers.forEachIndexed { i, server ->
if (server.deleted || server.preset) return@forEachIndexed
SectionItemView({ navigateToProtocolView(i, server, ServerProtocol.SMP) }) {
@@ -356,8 +356,8 @@ fun OperatorViewLayout(
}
if (userServers.value[operatorIndex].xftpServers.any { !it.deleted }) {
SectionSpacer()
SectionView(generalGetString(MR.strings.operator_use_for_files), card = true) {
SectionDividerSpaced()
SectionView(generalGetString(MR.strings.operator_use_for_files)) {
SectionItemView(padding = PaddingValues(horizontal = DEFAULT_PADDING)) {
Text(
stringResource(MR.strings.operator_use_for_sending),
@@ -389,8 +389,8 @@ fun OperatorViewLayout(
// Preset servers can't be deleted
if (userServers.value[operatorIndex].xftpServers.any { it.preset }) {
SectionSpacer()
SectionView(generalGetString(MR.strings.media_and_file_servers), card = true) {
SectionDividerSpaced()
SectionView(generalGetString(MR.strings.media_and_file_servers)) {
userServers.value[operatorIndex].xftpServers.forEachIndexed { i, server ->
if (!server.preset) return@forEachIndexed
SectionItemView({ navigateToProtocolView(i, server, ServerProtocol.XFTP) }) {
@@ -423,8 +423,8 @@ fun OperatorViewLayout(
}
if (userServers.value[operatorIndex].xftpServers.any { !it.preset && !it.deleted}) {
SectionSpacer()
SectionView(generalGetString(MR.strings.operator_added_xftp_servers), card = true) {
SectionDividerSpaced()
SectionView(generalGetString(MR.strings.operator_added_xftp_servers)) {
userServers.value[operatorIndex].xftpServers.forEachIndexed { i, server ->
if (server.deleted || server.preset) return@forEachIndexed
SectionItemView({ navigateToProtocolView(i, server, ServerProtocol.XFTP) }) {
@@ -438,8 +438,8 @@ fun OperatorViewLayout(
}
}
SectionSpacer()
SectionView(card = true) {
SectionDividerSpaced()
SectionView {
TestServersButton(
testing = testing,
smpServers = userServers.value[operatorIndex].smpServers,
@@ -477,10 +477,10 @@ fun OperatorViewLayout(
@Composable
fun OperatorInfoView(serverOperator: ServerOperator) {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
AppBarTitle(stringResource(MR.strings.operator_info_title))
SectionView(card = true) {
SectionView {
SectionItemView {
Column(verticalArrangement = Arrangement.spacedBy(10.dp)) {
Image(painterResource(serverOperator.largeLogo), null, Modifier.height(48.dp))
@@ -491,10 +491,10 @@ fun OperatorInfoView(serverOperator: ServerOperator) {
}
}
SectionSpacer()
SectionDividerSpaced()
val uriHandler = LocalUriHandler.current
SectionView(card = true) {
SectionView {
SectionItemView {
Column(verticalArrangement = Arrangement.spacedBy(10.dp)) {
serverOperator.info.description.forEach { d ->
@@ -508,8 +508,8 @@ fun OperatorInfoView(serverOperator: ServerOperator) {
val selfhost = serverOperator.info.selfhost
if (selfhost != null) {
SectionSpacer()
SectionView(card = true) {
SectionDividerSpaced()
SectionView {
SectionItemView {
val (text, link) = selfhost
Text(text, color = MaterialTheme.colors.primary, modifier = Modifier.clickable { uriHandler.openExternalLink(link) })
@@ -1,7 +1,7 @@
package chat.simplex.common.views.usersettings.networkAndServers
import SectionBottomSpacer
import SectionSpacer
import SectionDividerSpaced
import SectionItemView
import SectionItemViewSpaceBetween
import SectionView
@@ -81,7 +81,8 @@ fun ProtocolServerView(
)
}
}
}
},
cardScreen = true,
) {
Box {
ProtocolServerLayout(
@@ -123,7 +124,7 @@ private fun ProtocolServerLayout(
testServer: () -> Unit,
onDelete: () -> Unit,
) {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
AppBarTitle(stringResource(if (serverProtocol == ServerProtocol.XFTP) MR.strings.xftp_server else MR.strings.smp_server))
if (server.value.preset) {
@@ -141,7 +142,7 @@ private fun PresetServer(
testing: Boolean,
testServer: () -> Unit
) {
SectionView(stringResource(MR.strings.smp_servers_preset_address), card = true) {
SectionView(stringResource(MR.strings.smp_servers_preset_address)) {
SelectionContainer {
Text(
server.value.server,
@@ -153,7 +154,7 @@ private fun PresetServer(
)
}
}
SectionSpacer()
SectionDividerSpaced()
UseServerSection(server, true, testing, testServer)
}
@@ -176,7 +177,6 @@ fun CustomServer(
stringResource(MR.strings.smp_servers_your_server_address),
icon = painterResource(MR.images.ic_error),
iconTint = if (!valid.value) MaterialTheme.colors.error else Color.Transparent,
card = true,
) {
val testedPreviously = remember { mutableMapOf<String, Boolean?>() }
TextEditor(
@@ -192,13 +192,13 @@ fun CustomServer(
}
}
}
SectionSpacer()
SectionDividerSpaced()
UseServerSection(server, valid.value, testing, testServer, onDelete)
if (valid.value) {
SectionSpacer()
SectionView(stringResource(MR.strings.smp_servers_add_to_another_device), card = true) {
SectionDividerSpaced()
SectionView(stringResource(MR.strings.smp_servers_add_to_another_device)) {
QRCode(serverAddress.value, small = true)
}
}
@@ -212,7 +212,7 @@ private fun UseServerSection(
testServer: () -> Unit,
onDelete: (() -> Unit)? = null,
) {
SectionView(stringResource(MR.strings.smp_servers_use_server), card = true) {
SectionView(stringResource(MR.strings.smp_servers_use_server)) {
SectionItemViewSpaceBetween(testServer, disabled = !valid || testing) {
Text(stringResource(MR.strings.smp_servers_test_server), color = if (valid && !testing) MaterialTheme.colors.onBackground else MaterialTheme.colors.secondary)
ShowTestStatus(server.value)
@@ -2,7 +2,7 @@ package chat.simplex.common.views.usersettings.networkAndServers
import SectionBottomSpacer
import SectionCustomFooter
import SectionSpacer
import SectionDividerSpaced
import SectionItemView
import SectionTextFooter
import SectionView
@@ -48,7 +48,7 @@ fun ModalData.YourServersView(
}
Box {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
AppBarTitle(stringResource(MR.strings.your_servers))
YourServersViewLayout(
scope,
@@ -88,7 +88,7 @@ fun YourServersViewLayout(
Column {
if (userServers.value[operatorIndex].chatRelays.any { !it.deleted }) {
val duplicateRelayAddresses = findDuplicateRelayAddresses(serverErrors.value)
SectionView(generalGetString(MR.strings.chat_relays), card = true) {
SectionView(generalGetString(MR.strings.chat_relays)) {
userServers.value[operatorIndex].chatRelays.forEachIndexed { i, relay ->
if (relay.deleted) return@forEachIndexed
ChatRelayViewLink(relay, duplicateRelayAddresses) {
@@ -100,8 +100,8 @@ fun YourServersViewLayout(
}
if (userServers.value[operatorIndex].smpServers.any { !it.deleted }) {
SectionSpacer()
SectionView(generalGetString(MR.strings.message_servers), card = true) {
SectionDividerSpaced()
SectionView(generalGetString(MR.strings.message_servers)) {
userServers.value[operatorIndex].smpServers.forEachIndexed { i, server ->
if (server.deleted) return@forEachIndexed
SectionItemView({ navigateToProtocolView(i, server, ServerProtocol.SMP) }) {
@@ -134,8 +134,8 @@ fun YourServersViewLayout(
}
if (userServers.value[operatorIndex].xftpServers.any { !it.deleted }) {
SectionSpacer()
SectionView(generalGetString(MR.strings.media_and_file_servers), card = true) {
SectionDividerSpaced()
SectionView(generalGetString(MR.strings.media_and_file_servers)) {
userServers.value[operatorIndex].xftpServers.forEachIndexed { i, server ->
if (server.deleted) return@forEachIndexed
SectionItemView({ navigateToProtocolView(i, server, ServerProtocol.XFTP) }) {
@@ -172,10 +172,10 @@ fun YourServersViewLayout(
userServers.value[operatorIndex].xftpServers.any { !it.deleted } ||
userServers.value[operatorIndex].chatRelays.any { !it.deleted }
) {
SectionSpacer()
SectionDividerSpaced()
}
SectionView(card = true) {
SectionView {
SettingsActionItem(
painterResource(MR.images.ic_add),
stringResource(MR.strings.smp_servers_add),
@@ -197,9 +197,9 @@ fun YourServersViewLayout(
ServersWarningFooter(serversWarn)
}
}
SectionSpacer()
SectionDividerSpaced()
SectionView(card = true) {
SectionView {
TestServersButton(
testing = testing,
smpServers = userServers.value[operatorIndex].smpServers,
@@ -2,7 +2,7 @@ package chat.simplex.common.views.usersettings
import CARD_PADDING
import SectionBottomSpacer
import SectionSpacer
import SectionDividerSpaced
import SectionTextFooter
import SectionView
import itemHPadding
@@ -44,9 +44,9 @@ fun AppearanceScope.AppearanceLayout(
languagePref: SharedPreference<String?>,
systemDarkTheme: SharedPreference<String?>,
) {
ColumnWithScrollBar(Modifier.background(canvasColorForCurrentTheme())) {
ColumnWithScrollBar {
AppBarTitle(stringResource(MR.strings.appearance_settings))
SectionView(stringResource(MR.strings.settings_section_title_language), contentPadding = PaddingValues(), card = true) {
SectionView(stringResource(MR.strings.settings_section_title_language), contentPadding = PaddingValues()) {
val state = rememberSaveable { mutableStateOf(languagePref.get() ?: "system") }
LangSelector(state) {
state.value = it
@@ -66,27 +66,27 @@ fun AppearanceScope.AppearanceLayout(
SettingsPreferenceItem(icon = null, stringResource(MR.strings.chat_bottom_bar), ChatModel.controller.appPrefs.chatBottomBar)
}
}
SectionSpacer()
SectionDividerSpaced()
ThemesSection(systemDarkTheme)
if (trayIsAvailable) {
SectionSpacer()
SectionDividerSpaced()
MinimizeToTraySection()
}
SectionSpacer()
SectionDividerSpaced()
AppToolbarsSection()
SectionSpacer()
SectionDividerSpaced()
MessageShapeSection()
SectionSpacer()
SectionDividerSpaced()
ProfileImageSection()
SectionSpacer()
SectionDividerSpaced()
FontScaleSection()
SectionSpacer()
SectionDividerSpaced()
DensityScaleSection()
SectionBottomSpacer()
@@ -97,7 +97,7 @@ fun AppearanceScope.AppearanceLayout(
private fun MinimizeToTraySection() {
val pref = remember { appPrefs.closeBehavior.state }
val on = pref.value == CloseBehavior.MinimizeToTray
SectionView(card = true) {
SectionView {
PreferenceToggle(
stringResource(MR.strings.appearance_minimize_to_tray),
checked = on,
@@ -111,7 +111,7 @@ private fun MinimizeToTraySection() {
@Composable
fun DensityScaleSection() {
val localDensityScale = remember { mutableStateOf(appPrefs.densityScale.get()) }
SectionView(stringResource(MR.strings.appearance_zoom), contentPadding = PaddingValues(horizontal = CARD_PADDING), card = true) {
SectionView(stringResource(MR.strings.appearance_zoom), contentPadding = PaddingValues(horizontal = CARD_PADDING)) {
Row(Modifier.padding(vertical = 10.dp), verticalAlignment = Alignment.CenterVertically) {
Box(Modifier.size(50.dp)
.background(MaterialTheme.colors.surface, RoundedCornerShape(percent = 22))
@@ -21,7 +21,7 @@ actual fun SettingsSectionApp(
showVersion: () -> Unit,
withAuth: (title: String, desc: String, block: () -> Unit) -> Unit
) {
SectionView(stringResource(MR.strings.settings_section_title_app), card = true) {
SectionView(stringResource(MR.strings.settings_section_title_app)) {
SettingsActionItem(painterResource(MR.images.ic_code), stringResource(MR.strings.settings_developer_tools), showSettingsModal { DeveloperView(withAuth) })
val selectedChannel = remember { appPrefs.appUpdateChannel.state }
val values = AppUpdatesChannel.entries.map { it to it.text }