From ba24e405127cc8cfda64569a4512e097ac79a7af Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Fri, 21 Apr 2023 22:21:44 +0300 Subject: [PATCH] android: settings refactoring and new design (#2226) * android: settings refactoring and new design * spacers * paddings * paddings * padding * weight * new chat button padding * removed background color * profiles * cancel button function --- .../java/chat/simplex/app/ui/theme/Color.kt | 1 - .../java/chat/simplex/app/ui/theme/Theme.kt | 2 +- .../chat/simplex/app/views/WelcomeView.kt | 2 +- .../chat/simplex/app/views/call/CallView.kt | 2 +- .../app/views/call/IncomingCallActivity.kt | 2 +- .../app/views/call/IncomingCallAlertView.kt | 2 +- .../simplex/app/views/chat/ChatInfoView.kt | 16 +- .../chat/simplex/app/views/chat/ChatView.kt | 4 +- .../app/views/chat/ContactPreferences.kt | 60 ++--- .../views/chat/group/AddGroupMembersView.kt | 13 +- .../app/views/chat/group/GroupChatInfoView.kt | 208 +++++++----------- .../app/views/chat/group/GroupLinkView.kt | 14 +- .../views/chat/group/GroupMemberInfoView.kt | 22 +- .../app/views/chat/group/GroupPreferences.kt | 31 +-- .../views/chat/group/WelcomeMessageView.kt | 1 - .../app/views/chatlist/ChatListView.kt | 4 +- .../simplex/app/views/chatlist/UserPicker.kt | 12 +- .../app/views/database/ChatArchiveView.kt | 3 - .../views/database/DatabaseEncryptionView.kt | 9 - .../app/views/database/DatabaseErrorView.kt | 4 +- .../app/views/database/DatabaseView.kt | 104 ++++----- .../simplex/app/views/helpers/AlertManager.kt | 2 +- .../app/views/helpers/CloseSheetBar.kt | 24 +- .../helpers/ExposedDropDownSettingRow.kt | 19 +- .../simplex/app/views/helpers/ModalView.kt | 5 +- .../chat/simplex/app/views/helpers/Section.kt | 61 +++-- .../app/views/newchat/AddContactView.kt | 5 +- .../simplex/app/views/newchat/AddGroupView.kt | 2 +- .../newchat/ContactConnectionInfoView.kt | 2 - .../simplex/app/views/newchat/NewChatSheet.kt | 2 +- .../app/views/newchat/PasteToConnect.kt | 2 +- .../app/views/onboarding/HowItWorks.kt | 2 +- .../views/onboarding/SetNotificationsMode.kt | 6 +- .../app/views/onboarding/SimpleXInfo.kt | 2 +- .../app/views/onboarding/WhatsNewView.kt | 4 +- .../views/usersettings/AcceptRequestsView.kt | 31 +-- .../usersettings/AdvancedNetworkSettings.kt | 11 - .../app/views/usersettings/Appearance.kt | 49 ++--- .../app/views/usersettings/CallSettings.kt | 41 ++-- .../app/views/usersettings/DeveloperView.kt | 9 +- .../views/usersettings/HiddenProfileView.kt | 5 - .../views/usersettings/NetworkAndServers.kt | 60 ++--- .../usersettings/NotificationsSettingsView.kt | 12 +- .../app/views/usersettings/Preferences.kt | 47 ++-- .../app/views/usersettings/PrivacySettings.kt | 41 ++-- .../views/usersettings/ProtocolServerView.kt | 17 +- .../views/usersettings/ProtocolServersView.kt | 11 +- .../app/views/usersettings/SettingsView.kt | 189 +++++++--------- .../app/views/usersettings/UserAddressView.kt | 2 +- .../app/views/usersettings/UserProfileView.kt | 2 +- .../views/usersettings/UserProfilesView.kt | 2 +- 51 files changed, 457 insertions(+), 726 deletions(-) diff --git a/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Color.kt b/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Color.kt index 29bedfab43..ee2997b428 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Color.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Color.kt @@ -18,7 +18,6 @@ val MessagePreviewDark = Color(179, 175, 174, 255) val MessagePreviewLight = Color(49, 45, 44, 255) val ToolbarLight = Color(220, 220, 220, 12) val ToolbarDark = Color(80, 80, 80, 12) -val SettingsBackgroundLight = Color(220, 216, 215, 90) val SettingsSecondaryLight = Color(200, 196, 195, 90) val GroupDark = Color(80, 80, 80, 60) val IncomingCallLight = Color(239, 237, 236, 255) diff --git a/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Theme.kt b/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Theme.kt index dbd17b94f7..ccd7cce6f2 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Theme.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Theme.kt @@ -14,7 +14,7 @@ enum class DefaultTheme { SYSTEM, DARK, LIGHT } -val DEFAULT_PADDING = 16.dp +val DEFAULT_PADDING = 20.dp val DEFAULT_SPACE_AFTER_ICON = 4.dp val DEFAULT_PADDING_HALF = DEFAULT_PADDING / 2 val DEFAULT_BOTTOM_PADDING = 48.dp diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/WelcomeView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/WelcomeView.kt index 383499e361..623b77fd8f 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/WelcomeView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/WelcomeView.kt @@ -58,7 +58,7 @@ fun CreateProfilePanel(chatModel: ChatModel, close: () -> Unit) { } })*/ Column(Modifier.padding(horizontal = DEFAULT_PADDING * 1f)) { - AppBarTitleCentered(stringResource(R.string.create_profile)) + AppBarTitle(stringResource(R.string.create_profile)) ReadableText(R.string.your_profile_is_stored_on_your_device, TextAlign.Center, padding = PaddingValues()) ReadableText(R.string.profile_is_only_shared_with_your_contacts, TextAlign.Center) Spacer(Modifier.height(DEFAULT_PADDING * 1.5f)) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/call/CallView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/call/CallView.kt index 641cdb930b..015f926631 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/call/CallView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/call/CallView.kt @@ -263,7 +263,7 @@ private fun ActiveCallOverlayLayout( toggleSound: () -> Unit, flipCamera: () -> Unit ) { - Column(Modifier.padding(16.dp)) { + Column(Modifier.padding(DEFAULT_PADDING)) { when (call.peerMedia ?: call.localMedia) { CallMediaType.Video -> { CallInfoView(call, alignment = Alignment.Start) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/call/IncomingCallActivity.kt b/apps/android/app/src/main/java/chat/simplex/app/views/call/IncomingCallActivity.kt index ba8830c533..dee29273ac 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/call/IncomingCallActivity.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/call/IncomingCallActivity.kt @@ -213,7 +213,7 @@ private fun LockScreenCallButton(text: String, icon: ImageVector, color: Color, IconButton(action) { Icon(icon, text, tint = color, modifier = Modifier.scale(1.75f)) } - Spacer(Modifier.height(16.dp)) + Spacer(Modifier.height(DEFAULT_PADDING)) Text(text, style = MaterialTheme.typography.body2, color = HighOrLowlight) } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/call/IncomingCallAlertView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/call/IncomingCallAlertView.kt index 267fd458e7..a869186be9 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/call/IncomingCallAlertView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/call/IncomingCallAlertView.kt @@ -52,7 +52,7 @@ fun IncomingCallAlertLayout( acceptCall: () -> Unit ) { val color = if (isInDarkTheme()) IncomingCallDark else IncomingCallLight - Column(Modifier.fillMaxWidth().background(color).padding(top = 16.dp, bottom = 16.dp, start = 16.dp, end = 8.dp)) { + Column(Modifier.fillMaxWidth().background(color).padding(top = DEFAULT_PADDING, bottom = DEFAULT_PADDING, start = DEFAULT_PADDING, end = 8.dp)) { IncomingCallInfo(invitation, chatModel) Spacer(Modifier.height(8.dp)) Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween) { diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt index dc5286fd6e..3ebb22ea03 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt @@ -2,7 +2,7 @@ package chat.simplex.app.views.chat import InfoRow import InfoRowEllipsis -import SectionDivider +import SectionDividerSpaced import SectionItemView import SectionSpacer import SectionView @@ -191,16 +191,14 @@ fun ChatInfoLayout( SectionView { if (connectionCode != null) { VerifyCodeButton(contact.verified, verifyClicked) - SectionDivider() } ContactPreferencesButton(openPreferences) } - SectionSpacer() + SectionDividerSpaced() SectionView(title = stringResource(R.string.conn_stats_section_title_servers)) { SwitchAddressButton(switchContactAddress) - SectionDivider() if (connStats != null) { SectionItemView({ AlertManager.shared.showAlertMsg( @@ -211,32 +209,28 @@ fun ChatInfoLayout( } val rcvServers = connStats.rcvServers if (rcvServers != null && rcvServers.isNotEmpty()) { - SectionDivider() SimplexServers(stringResource(R.string.receiving_via), rcvServers) } val sndServers = connStats.sndServers if (sndServers != null && sndServers.isNotEmpty()) { - SectionDivider() SimplexServers(stringResource(R.string.sending_via), sndServers) } } } - SectionSpacer() + SectionDividerSpaced() SectionView { ClearChatButton(clearChat) - SectionDivider() DeleteContactButton(deleteContact) } - SectionSpacer() if (developerTools) { + SectionDividerSpaced() SectionView(title = stringResource(R.string.section_title_for_console)) { InfoRow(stringResource(R.string.info_row_local_name), chat.chatInfo.localDisplayName) - SectionDivider() InfoRow(stringResource(R.string.info_row_database_id), chat.chatInfo.apiId.toString()) } - SectionSpacer() } + SectionSpacer() } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt index 841126366a..e18ba990bb 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt @@ -787,14 +787,14 @@ fun BoxWithConstraintsScope.FloatingButtons( val showDropDown = remember { mutableStateOf(false) } TopEndFloatingButton( - Modifier.padding(end = 16.dp, top = 24.dp).align(Alignment.TopEnd), + Modifier.padding(end = DEFAULT_PADDING, top = 24.dp).align(Alignment.TopEnd), topUnreadCount, showButtonWithCounter, onClick = { scope.launch { listState.animateScrollBy(height) } }, onLongClick = { showDropDown.value = true } ) - DefaultDropdownMenu(showDropDown, offset = DpOffset(maxWidth - 16.dp, 24.dp + fabSize)) { + DefaultDropdownMenu(showDropDown, offset = DpOffset(maxWidth - DEFAULT_PADDING, 24.dp + fabSize)) { ItemAction( generalGetString(R.string.mark_read), Icons.Outlined.Check, diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ContactPreferences.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ContactPreferences.kt index 84c9b23362..ab9782a4ea 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ContactPreferences.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ContactPreferences.kt @@ -1,9 +1,8 @@ package chat.simplex.app.views.chat import InfoRow -import SectionDivider +import SectionDividerSpaced import SectionItemView -import SectionSpacer import SectionTextFooter import SectionView import androidx.compose.foundation.* @@ -50,7 +49,6 @@ fun ContactPreferencesView( if (featuresAllowed == currentFeaturesAllowed) close() else showUnsavedChangesAlert({ savePrefs(close) }, close) }, - background = if (isInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight ) { ContactPreferencesLayout( featuresAllowed, @@ -93,22 +91,22 @@ 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 = remember(featuresAllowed) { mutableStateOf(featuresAllowed.fullDelete) } FeatureSection(ChatFeature.FullDelete, user.fullPreferences.fullDelete.allow, contact.mergedPreferences.fullDelete, allowFullDeletion) { applyPrefs(featuresAllowed.copy(fullDelete = it)) } - SectionSpacer() + SectionDividerSpaced() val allowVoice: MutableState = 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 = 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, @@ -137,17 +135,14 @@ private fun FeatureSection( iconTint = if (enabled.forUser) SimplexGreen else if (enabled.forContact) WarningYellow else Color.Red, leadingIcon = true, ) { - SectionItemView { - ExposedDropDownSettingRow( - generalGetString(R.string.chat_preferences_you_allow), - ContactFeatureAllowed.values(userDefault).map { it to it.text }, - allowFeature, - icon = null, - enabled = remember { mutableStateOf(feature != ChatFeature.Calls) }, - onSelected = onSelected - ) - } - SectionDivider() + ExposedDropDownSettingRow( + generalGetString(R.string.chat_preferences_you_allow), + ContactFeatureAllowed.values(userDefault).map { it to it.text }, + allowFeature, + icon = null, + enabled = remember { mutableStateOf(feature != ChatFeature.Calls) }, + onSelected = onSelected + ) InfoRow( generalGetString(R.string.chat_preferences_contact_allows), pref.contactPreference.allow.text @@ -176,20 +171,16 @@ private fun TimedMessagesFeatureSection( iconTint = if (enabled.forUser) SimplexGreen else if (enabled.forContact) WarningYellow else Color.Red, leadingIcon = true, ) { - SectionItemView { - PreferenceToggle( - generalGetString(R.string.chat_preferences_you_allow), - checked = allowFeature.value, - ) { allow -> - onSelected(allow, if (allow) featuresAllowed.timedMessagesTTL ?: 86400 else null) - } + PreferenceToggle( + generalGetString(R.string.chat_preferences_you_allow), + checked = allowFeature.value, + ) { allow -> + onSelected(allow, if (allow) featuresAllowed.timedMessagesTTL ?: 86400 else null) } - SectionDivider() InfoRow( generalGetString(R.string.chat_preferences_contact_allows), pref.contactPreference.allow.text ) - SectionDivider() if (featuresAllowed.timedMessagesAllowed) { val ttl = rememberSaveable(featuresAllowed.timedMessagesTTL) { mutableStateOf(featuresAllowed.timedMessagesTTL) } TimedMessagesTTLPicker(ttl, onTTLUpdated) @@ -206,7 +197,6 @@ private fun ResetSaveButtons(reset: () -> Unit, save: () -> Unit, disabled: Bool SectionItemView(reset, disabled = disabled) { Text(stringResource(R.string.reset_verb), color = if (disabled) HighOrLowlight else MaterialTheme.colors.primary) } - SectionDivider() SectionItemView(save, disabled = disabled) { Text(stringResource(R.string.save_and_notify_contact), color = if (disabled) HighOrLowlight else MaterialTheme.colors.primary) } @@ -217,14 +207,12 @@ private fun ResetSaveButtons(reset: () -> Unit, save: () -> Unit, disabled: Bool fun TimedMessagesTTLPicker(selection: MutableState, onSelected: (Int?) -> Unit) { val ttlValues = TimedMessagesPreference.ttlValues val values = ttlValues + if (ttlValues.contains(selection.value)) listOf() else listOf(selection.value) - SectionItemView { - ExposedDropDownSettingRow( - generalGetString(R.string.delete_after), - values.map { it to TimedMessagesPreference.ttlText(it) }, - selection, - onSelected = onSelected - ) - } + ExposedDropDownSettingRow( + generalGetString(R.string.delete_after), + values.map { it to TimedMessagesPreference.ttlText(it) }, + selection, + onSelected = onSelected + ) } private fun showUnsavedChangesAlert(save: () -> Unit, revert: () -> Unit) { diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/AddGroupMembersView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/AddGroupMembersView.kt index 07b9318ab6..73ddd708fd 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/AddGroupMembersView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/AddGroupMembersView.kt @@ -1,7 +1,7 @@ package chat.simplex.app.views.chat.group import SectionCustomFooter -import SectionDivider +import SectionDividerSpaced import SectionItemView import SectionSpacer import SectionView @@ -145,12 +145,8 @@ fun AddGroupMembersLayout( SectionItemView(openPreferences) { Text(stringResource(R.string.set_group_preferences)) } - SectionDivider() } - SectionItemView { - RoleSelectionRow(groupInfo, selectedRole, allowModifyMembers) - } - SectionDivider() + RoleSelectionRow(groupInfo, selectedRole, allowModifyMembers) if (creatingGroup && selectedContacts.isEmpty()) { SkipInvitingButton(close) } else { @@ -160,7 +156,7 @@ fun AddGroupMembersLayout( SectionCustomFooter { InviteSectionFooter(selectedContactsCount = selectedContacts.size, allowModifyMembers, clearSelection) } - SectionSpacer() + SectionDividerSpaced() SectionView(stringResource(R.string.select_contacts)) { ContactList(contacts = contactsToAdd, selectedContacts, groupInfo, allowModifyMembers, addContact, removeContact) @@ -260,9 +256,6 @@ fun ContactList( checked = selectedContacts.contains(contact.apiId), enabled = enabled, ) - if (index < contacts.lastIndex) { - SectionDivider() - } } } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt index 263798990f..0e7c919e49 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt @@ -1,7 +1,7 @@ package chat.simplex.app.views.chat.group import InfoRow -import SectionDivider +import SectionDividerSpaced import SectionItemView import SectionSpacer import SectionTextFooter @@ -173,63 +173,50 @@ fun GroupChatInfoLayout( SectionView { if (groupInfo.canEdit) { - SectionItemView(editGroupProfile) { EditGroupProfileButton() } - SectionDivider() - SectionItemView(addOrEditWelcomeMessage) { AddOrEditWelcomeMessage(groupInfo.groupProfile.description) } - SectionDivider() + EditGroupProfileButton(editGroupProfile) + AddOrEditWelcomeMessage(groupInfo.groupProfile.description, addOrEditWelcomeMessage) } GroupPreferencesButton(openPreferences) } SectionTextFooter(stringResource(R.string.only_group_owners_can_change_prefs)) - SectionSpacer() + SectionDividerSpaced() SectionView(title = String.format(generalGetString(R.string.group_info_section_title_num_members), members.count() + 1)) { if (groupInfo.canAddMembers) { - SectionItemView(manageGroupLink) { - if (groupLink == null) { - CreateGroupLinkButton() - } else { - GroupLinkButton() - } + if (groupLink == null) { + CreateGroupLinkButton(manageGroupLink) + } else { + GroupLinkButton(manageGroupLink) } - SectionDivider() + val onAddMembersClick = if (chat.chatInfo.incognito) ::cantInviteIncognitoAlert else addMembers - SectionItemView(onAddMembersClick) { - val tint = if (chat.chatInfo.incognito) HighOrLowlight else MaterialTheme.colors.primary - AddMembersButton(tint) - } - SectionDivider() + val tint = if (chat.chatInfo.incognito) HighOrLowlight else MaterialTheme.colors.primary + AddMembersButton(tint, onAddMembersClick) } SectionItemView(minHeight = 50.dp) { MemberRow(groupInfo.membership, user = true) } - if (members.isNotEmpty()) { - SectionDivider() - } MembersList(members, showMemberInfo) } - SectionSpacer() + SectionDividerSpaced() SectionView { ClearChatButton(clearChat) if (groupInfo.canDelete) { - SectionDivider() - SectionItemView(deleteGroup) { DeleteGroupButton() } + DeleteGroupButton(deleteGroup) } if (groupInfo.membership.memberCurrent) { - SectionDivider() - SectionItemView(leaveGroup) { LeaveGroupButton() } + LeaveGroupButton(leaveGroup) + } + } + + if (developerTools) { + SectionDividerSpaced() + SectionView(title = stringResource(R.string.section_title_for_console)) { + InfoRow(stringResource(R.string.info_row_local_name), groupInfo.localDisplayName) + InfoRow(stringResource(R.string.info_row_database_id), groupInfo.apiId.toString()) } } SectionSpacer() - - if (developerTools) { - SectionView(title = stringResource(R.string.section_title_for_console)) { - InfoRow(stringResource(R.string.info_row_local_name), groupInfo.localDisplayName) - SectionDivider() - InfoRow(stringResource(R.string.info_row_database_id), groupInfo.apiId.toString()) - } - SectionSpacer() - } } } @@ -267,19 +254,14 @@ private fun GroupPreferencesButton(onClick: () -> Unit) { } @Composable -private fun AddMembersButton(tint: Color = MaterialTheme.colors.primary) { - Row( - Modifier.fillMaxSize(), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - Icons.Outlined.Add, - stringResource(R.string.button_add_members), - tint = tint - ) - Spacer(Modifier.size(8.dp)) - Text(stringResource(R.string.button_add_members), color = tint) - } +private fun AddMembersButton(tint: Color = MaterialTheme.colors.primary, onClick: () -> Unit) { + SettingsActionItem( + Icons.Outlined.Add, + stringResource(R.string.button_add_members), + onClick, + iconColor = tint, + textColor = tint + ) } @Composable @@ -289,9 +271,6 @@ private fun MembersList(members: List, showMemberInfo: (GroupMember SectionItemView({ showMemberInfo(member) }, minHeight = 50.dp) { MemberRow(member) } - if (index < members.lastIndex) { - SectionDivider() - } } } } @@ -309,6 +288,7 @@ private fun MemberRow(member: GroupMember, user: Boolean = false) { horizontalArrangement = Arrangement.spacedBy(4.dp) ) { ProfileImage(size = 46.dp, member.image) + Spacer(Modifier.width(DEFAULT_PADDING_HALF)) Column { Row(verticalAlignment = Alignment.CenterVertically) { if (member.verified) { @@ -343,108 +323,70 @@ private fun MemberVerifiedShield() { } @Composable -private fun GroupLinkButton() { - Row( - Modifier - .fillMaxSize(), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - Icons.Outlined.Link, - stringResource(R.string.group_link), - tint = HighOrLowlight - ) - Spacer(Modifier.size(8.dp)) - Text(stringResource(R.string.group_link)) - } +private fun GroupLinkButton(onClick: () -> Unit) { + SettingsActionItem( + Icons.Outlined.Link, + stringResource(R.string.group_link), + onClick, + iconColor = HighOrLowlight + ) } @Composable -private fun CreateGroupLinkButton() { - Row( - Modifier - .fillMaxSize(), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - Icons.Outlined.AddLink, - stringResource(R.string.create_group_link), - tint = HighOrLowlight - ) - Spacer(Modifier.size(8.dp)) - Text(stringResource(R.string.create_group_link)) - } +private fun CreateGroupLinkButton(onClick: () -> Unit) { + SettingsActionItem( + Icons.Outlined.AddLink, + stringResource(R.string.create_group_link), + onClick, + iconColor = HighOrLowlight + ) } @Composable -fun EditGroupProfileButton() { - Row( - Modifier - .fillMaxSize(), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - Icons.Outlined.Edit, - stringResource(R.string.button_edit_group_profile), - tint = HighOrLowlight - ) - Spacer(Modifier.size(8.dp)) - Text(stringResource(R.string.button_edit_group_profile)) - } +fun EditGroupProfileButton(onClick: () -> Unit) { + SettingsActionItem( + Icons.Outlined.Edit, + stringResource(R.string.button_edit_group_profile), + onClick, + iconColor = HighOrLowlight + ) } @Composable -private fun AddOrEditWelcomeMessage(welcomeMessage: String?) { +private fun AddOrEditWelcomeMessage(welcomeMessage: String?, onClick: () -> Unit) { val text = if (welcomeMessage == null) { stringResource(R.string.button_add_welcome_message) } else { stringResource(R.string.button_welcome_message) } - Row( - Modifier - .fillMaxSize(), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - Icons.Outlined.MapsUgc, - text, - tint = HighOrLowlight - ) - Spacer(Modifier.size(8.dp)) - Text(text) - } + SettingsActionItem( + Icons.Outlined.MapsUgc, + text, + onClick, + iconColor = HighOrLowlight + ) } @Composable -private fun LeaveGroupButton() { - Row( - Modifier.fillMaxSize(), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - Icons.Outlined.Logout, - stringResource(R.string.button_leave_group), - tint = Color.Red - ) - Spacer(Modifier.size(8.dp)) - Text(stringResource(R.string.button_leave_group), color = Color.Red) - } +private fun LeaveGroupButton(onClick: () -> Unit) { + SettingsActionItem( + Icons.Outlined.Logout, + stringResource(R.string.button_leave_group), + onClick, + iconColor = Color.Red, + textColor = Color.Red + ) } @Composable -private fun DeleteGroupButton() { - Row( - Modifier.fillMaxSize(), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - Icons.Outlined.Delete, - stringResource(R.string.button_delete_group), - tint = Color.Red - ) - Spacer(Modifier.size(8.dp)) - Text(stringResource(R.string.button_delete_group), color = Color.Red) - } +private fun DeleteGroupButton(onClick: () -> Unit) { + SettingsActionItem( + Icons.Outlined.Delete, + stringResource(R.string.button_delete_group), + onClick, + iconColor = Color.Red, + textColor = Color.Red + ) } @Preview diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupLinkView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupLinkView.kt index ab8e35a9c6..555c19af73 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupLinkView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupLinkView.kt @@ -102,14 +102,14 @@ fun GroupLinkLayout( Column( Modifier .verticalScroll(rememberScrollState()) - .padding(start = DEFAULT_PADDING, bottom = DEFAULT_BOTTOM_PADDING, end = DEFAULT_PADDING), + .padding(bottom = DEFAULT_BOTTOM_PADDING), horizontalAlignment = Alignment.Start, verticalArrangement = Arrangement.Top ) { - AppBarTitle(stringResource(R.string.group_link), false) + AppBarTitle(stringResource(R.string.group_link)) Text( stringResource(R.string.you_can_share_group_link_anybody_will_be_able_to_connect), - Modifier.padding(bottom = 12.dp), + Modifier.padding(start = DEFAULT_PADDING, end = DEFAULT_PADDING, bottom = 12.dp), lineHeight = 22.sp ) Column( @@ -120,9 +120,7 @@ fun GroupLinkLayout( if (groupLink == null) { SimpleButton(stringResource(R.string.button_create_group_link), icon = Icons.Outlined.AddLink, disabled = creatingLink, click = createLink) } else { - SectionItemView(padding = PaddingValues(bottom = DEFAULT_PADDING)) { - RoleSelectionRow(groupInfo, groupLinkMemberRole) - } + RoleSelectionRow(groupInfo, groupLinkMemberRole) var initialLaunch by remember { mutableStateOf(true) } LaunchedEffect(groupLinkMemberRole.value) { if (!initialLaunch) { @@ -130,11 +128,11 @@ fun GroupLinkLayout( } initialLaunch = false } - QRCode(groupLink, Modifier.aspectRatio(1f)) + QRCode(groupLink, Modifier.aspectRatio(1f).padding(start = DEFAULT_PADDING, end = DEFAULT_PADDING)) Row( horizontalArrangement = Arrangement.spacedBy(10.dp), verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.padding(vertical = 10.dp) + modifier = Modifier.padding(horizontal = DEFAULT_PADDING, vertical = 10.dp) ) { SimpleButton( stringResource(R.string.share_link), diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt index b6441dc8ac..4884a7ecd9 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt @@ -1,8 +1,7 @@ package chat.simplex.app.views.chat.group import InfoRow -import SectionDivider -import SectionItemView +import SectionDividerSpaced import SectionSpacer import SectionView import androidx.activity.compose.BackHandler @@ -169,9 +168,6 @@ fun GroupMemberInfoLayout( val chat = getContactChat(contactId) if ((chat != null && chat.chatInfo is ChatInfo.Direct && chat.chatInfo.contact.directOrUsed) || groupInfo.fullGroupPreferences.directMessages.on) { OpenChatButton(onClick = { openDirectChat(contactId) }) - if (connectionCode != null) { - SectionDivider() - } } if (connectionCode != null) { VerifyCodeButton(member.verified, verifyClicked) @@ -183,36 +179,30 @@ fun GroupMemberInfoLayout( SectionView(title = stringResource(R.string.member_info_section_title_member)) { InfoRow(stringResource(R.string.info_row_group), groupInfo.displayName) - SectionDivider() val roles = remember { member.canChangeRoleTo(groupInfo) } if (roles != null) { - SectionItemView { - RoleSelectionRow(roles, newRole, onRoleSelected) - } + RoleSelectionRow(roles, newRole, onRoleSelected) } else { InfoRow(stringResource(R.string.role_in_group), member.memberRole.text) } val conn = member.activeConn if (conn != null) { - SectionDivider() val connLevelDesc = if (conn.connLevel == 0) stringResource(R.string.conn_level_desc_direct) else String.format(generalGetString(R.string.conn_level_desc_indirect), conn.connLevel) InfoRow(stringResource(R.string.info_row_connection), connLevelDesc) } } - SectionSpacer() if (connStats != null) { + SectionDividerSpaced() SectionView(title = stringResource(R.string.conn_stats_section_title_servers)) { SwitchAddressButton(switchMemberAddress) - SectionDivider() val rcvServers = connStats.rcvServers val sndServers = connStats.sndServers if ((rcvServers != null && rcvServers.isNotEmpty()) || (sndServers != null && sndServers.isNotEmpty())) { if (rcvServers != null && rcvServers.isNotEmpty()) { SimplexServers(stringResource(R.string.receiving_via), rcvServers) if (sndServers != null && sndServers.isNotEmpty()) { - SectionDivider() SimplexServers(stringResource(R.string.sending_via), sndServers) } } else if (sndServers != null && sndServers.isNotEmpty()) { @@ -220,24 +210,24 @@ fun GroupMemberInfoLayout( } } } - SectionSpacer() } if (member.canBeRemoved(groupInfo)) { + SectionDividerSpaced() SectionView { RemoveMemberButton(removeMember) } - SectionSpacer() } if (developerTools) { + SectionDividerSpaced() SectionView(title = stringResource(R.string.section_title_for_console)) { InfoRow(stringResource(R.string.info_row_local_name), member.localDisplayName) - SectionDivider() InfoRow(stringResource(R.string.info_row_database_id), member.groupMemberId.toString()) } SectionSpacer() } + SectionSpacer() } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupPreferences.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupPreferences.kt index 48a5cd1117..f2428668e1 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupPreferences.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupPreferences.kt @@ -1,9 +1,8 @@ package chat.simplex.app.views.chat.group import InfoRow -import SectionDivider +import SectionDividerSpaced import SectionItemView -import SectionSpacer import SectionTextFooter import SectionView import androidx.compose.foundation.* @@ -45,7 +44,6 @@ fun GroupPreferencesView(m: ChatModel, chatId: String, close: () -> Unit,) { if (preferences == currentPreferences) close() else showUnsavedChangesAlert({ savePrefs(close) }, close) }, - background = if (isInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight ) { GroupPreferencesLayout( preferences, @@ -87,23 +85,23 @@ private fun GroupPreferencesLayout( applyPrefs(preferences.copy(timedMessages = TimedMessagesGroupPreference(enable = enable, ttl = currentPreferences.timedMessages.ttl))) } } - SectionSpacer() + SectionDividerSpaced() val allowDirectMessages = remember(preferences) { mutableStateOf(preferences.directMessages.enable) } FeatureSection(GroupFeature.DirectMessages, allowDirectMessages, groupInfo, preferences, onTTLUpdated) { applyPrefs(preferences.copy(directMessages = GroupPreference(enable = it))) } - SectionSpacer() + SectionDividerSpaced() val allowFullDeletion = remember(preferences) { mutableStateOf(preferences.fullDelete.enable) } FeatureSection(GroupFeature.FullDelete, allowFullDeletion, groupInfo, preferences, onTTLUpdated) { applyPrefs(preferences.copy(fullDelete = GroupPreference(enable = it))) } - SectionSpacer() + SectionDividerSpaced() val allowVoice = remember(preferences) { mutableStateOf(preferences.voice.enable) } FeatureSection(GroupFeature.Voice, allowVoice, groupInfo, preferences, onTTLUpdated) { applyPrefs(preferences.copy(voice = GroupPreference(enable = it))) } if (groupInfo.canEdit) { - SectionSpacer() + SectionDividerSpaced() ResetSaveButtons( reset = reset, save = savePrefs, @@ -128,18 +126,15 @@ private fun FeatureSection( val iconTint = if (on) SimplexGreen else HighOrLowlight val timedOn = feature == GroupFeature.TimedMessages && enableFeature.value == GroupFeatureEnabled.ON if (groupInfo.canEdit) { - SectionItemView { - PreferenceToggleWithIcon( - feature.text, - icon, - iconTint, - enableFeature.value == GroupFeatureEnabled.ON, - ) { checked -> - onSelected(if (checked) GroupFeatureEnabled.ON else GroupFeatureEnabled.OFF) - } + PreferenceToggleWithIcon( + feature.text, + icon, + iconTint, + enableFeature.value == GroupFeatureEnabled.ON, + ) { checked -> + onSelected(if (checked) GroupFeatureEnabled.ON else GroupFeatureEnabled.OFF) } if (timedOn) { - SectionDivider() val ttl = rememberSaveable(preferences.timedMessages) { mutableStateOf(preferences.timedMessages.ttl) } TimedMessagesTTLPicker(ttl, onTTLUpdated) } @@ -151,7 +146,6 @@ private fun FeatureSection( iconTint = iconTint, ) if (timedOn) { - SectionDivider() InfoRow(generalGetString(R.string.delete_after), TimedMessagesPreference.ttlText(preferences.timedMessages.ttl)) } } @@ -165,7 +159,6 @@ private fun ResetSaveButtons(reset: () -> Unit, save: () -> Unit, disabled: Bool SectionItemView(reset, disabled = disabled) { Text(stringResource(R.string.reset_verb), color = if (disabled) HighOrLowlight else MaterialTheme.colors.primary) } - SectionDivider() SectionItemView(save, disabled = disabled) { Text(stringResource(R.string.save_and_notify_group_members), color = if (disabled) HighOrLowlight else MaterialTheme.colors.primary) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/WelcomeMessageView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/WelcomeMessageView.kt index f20630b94c..285c794238 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/WelcomeMessageView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/WelcomeMessageView.kt @@ -44,7 +44,6 @@ fun GroupWelcomeView(m: ChatModel, groupInfo: GroupInfo, close: () -> Unit) { if (welcomeText.value == groupInfo.groupProfile.description || (welcomeText.value == "" && groupInfo.groupProfile.description == null)) close() else showUnsavedChangesAlert({ save(close) }, close) }, - background = if (isInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight ) { GroupWelcomeLayout( welcomeText, diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt index 89f0a07743..f176b11c72 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt @@ -67,8 +67,7 @@ fun ChatListView(chatModel: ChatModel, setPerformLA: (Boolean, FragmentActivity) val scaffoldState = rememberScaffoldState() val scope = rememberCoroutineScope() val switchingUsers = rememberSaveable { mutableStateOf(false) } - Scaffold( - topBar = { ChatListToolbar(chatModel, scaffoldState.drawerState, userPickerState, stopped) { searchInList = it.trim() } }, + Scaffold(topBar = { ChatListToolbar(chatModel, scaffoldState.drawerState, userPickerState, stopped) { searchInList = it.trim() } }, scaffoldState = scaffoldState, drawerContent = { SettingsView(chatModel, setPerformLA) }, floatingActionButton = { @@ -79,6 +78,7 @@ fun ChatListView(chatModel: ChatModel, setPerformLA: (Boolean, FragmentActivity) if (newChatSheetState.value.isVisible()) hideNewChatSheet(true) else showNewChatSheet() } }, + Modifier.padding(end = DEFAULT_PADDING - 16.dp, bottom = DEFAULT_PADDING - 16.dp), elevation = FloatingActionButtonDefaults.elevation( defaultElevation = 0.dp, pressedElevation = 0.dp, diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/UserPicker.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/UserPicker.kt index a2494fb81c..63492aaf51 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/UserPicker.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/UserPicker.kt @@ -115,7 +115,7 @@ fun UserPicker( ) { Column(Modifier.weight(1f).verticalScroll(rememberScrollState())) { users.forEach { u -> - UserProfilePickerItem(u.user, u.unreadCount, PaddingValues(start = DEFAULT_PADDING, end = DEFAULT_PADDING * 2), openSettings = { + UserProfilePickerItem(u.user, u.unreadCount, PaddingValues(start = DEFAULT_PADDING, end = DEFAULT_PADDING), openSettings = { settingsClicked() userPickerState.value = AnimatedViewState.GONE }) { @@ -153,7 +153,7 @@ fun UserPicker( } @Composable -fun UserProfilePickerItem(u: User, unreadCount: Int = 0, padding: PaddingValues = PaddingValues(start = 8.dp, end = DEFAULT_PADDING), onLongClick: () -> Unit = {}, openSettings: () -> Unit = {}, onClick: () -> Unit) { +fun UserProfilePickerItem(u: User, unreadCount: Int = 0, padding: PaddingValues = PaddingValues(start = DEFAULT_PADDING, end = DEFAULT_PADDING), onLongClick: () -> Unit = {}, openSettings: () -> Unit = {}, onClick: () -> Unit) { Row( Modifier .fillMaxWidth() @@ -221,10 +221,10 @@ fun UserProfileRow(u: User) { @Composable private fun SettingsPickerItem(onClick: () -> Unit) { - SectionItemView(onClick, padding = PaddingValues(start = DEFAULT_PADDING * 2.2f, end = DEFAULT_PADDING * 2), minHeight = 68.dp) { + SectionItemView(onClick, padding = PaddingValues(start = DEFAULT_PADDING + 17.dp, end = DEFAULT_PADDING), minHeight = 68.dp) { val text = generalGetString(R.string.settings_section_title_settings).lowercase().capitalize(Locale.current) Icon(Icons.Outlined.Settings, text, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground) - Spacer(Modifier.width(DEFAULT_PADDING * 1.5f)) + Spacer(Modifier.width(DEFAULT_PADDING + 8.dp)) Text( text, color = if (isInDarkTheme()) MenuTextColorDark else Color.Black, @@ -234,10 +234,10 @@ private fun SettingsPickerItem(onClick: () -> Unit) { @Composable private fun CancelPickerItem(onClick: () -> Unit) { - SectionItemViewSpaceBetween(onClick, padding = PaddingValues(start = DEFAULT_PADDING * 2.2f, end = DEFAULT_PADDING * 2), minHeight = 68.dp) { + SectionItemView(onClick, padding = PaddingValues(start = DEFAULT_PADDING + 17.dp, end = DEFAULT_PADDING), minHeight = 68.dp) { val text = generalGetString(R.string.cancel_verb) Icon(Icons.Outlined.Close, text, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground) - Spacer(Modifier.width(DEFAULT_PADDING * 1.5f)) + Spacer(Modifier.width(DEFAULT_PADDING + 8.dp)) Text( text, color = if (isInDarkTheme()) MenuTextColorDark else Color.Black, diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/database/ChatArchiveView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/database/ChatArchiveView.kt index cc92ee75ec..12861c0861 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/database/ChatArchiveView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/database/ChatArchiveView.kt @@ -1,6 +1,5 @@ package chat.simplex.app.views.database -import SectionDivider import SectionTextFooter import SectionView import android.content.Context @@ -22,7 +21,6 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp import chat.simplex.app.R import chat.simplex.app.TAG import chat.simplex.app.model.ChatModel @@ -68,7 +66,6 @@ fun ChatArchiveLayout( textColor = MaterialTheme.colors.primary, iconColor = MaterialTheme.colors.primary, ) - SectionDivider() SettingsActionItem( Icons.Outlined.Delete, stringResource(R.string.delete_archive), diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseEncryptionView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseEncryptionView.kt index ff6229e9e6..ed82b30d84 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseEncryptionView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseEncryptionView.kt @@ -1,6 +1,5 @@ package chat.simplex.app.views.database -import SectionDivider import SectionItemView import SectionItemViewSpaceBetween import SectionTextFooter @@ -162,8 +161,6 @@ fun DatabaseEncryptionLayout( } if (!initialRandomDBPassphrase.value && chatDbEncrypted == true) { - SectionDivider() - PassphraseField( currentKey, generalGetString(R.string.current_passphrase), @@ -173,8 +170,6 @@ fun DatabaseEncryptionLayout( ) } - SectionDivider() - PassphraseField( newKey, generalGetString(R.string.new_passphrase), @@ -206,8 +201,6 @@ fun DatabaseEncryptionLayout( !validKey(newKey.value) || progressIndicator.value - SectionDivider() - PassphraseField( confirmNewKey, generalGetString(R.string.confirm_new_passphrase), @@ -219,8 +212,6 @@ fun DatabaseEncryptionLayout( }), ) - SectionDivider() - SectionItemViewSpaceBetween(onClickUpdate, disabled = disabled, minHeight = TextFieldDefaults.MinHeight) { Text(generalGetString(R.string.update_database_passphrase), color = if (disabled) HighOrLowlight else MaterialTheme.colors.primary) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseErrorView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseErrorView.kt index a59e2820be..e0673f80d5 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseErrorView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseErrorView.kt @@ -61,7 +61,7 @@ fun DatabaseErrorView( fun DatabaseErrorDetails(@StringRes title: Int, content: @Composable ColumnScope.() -> Unit) { Text( generalGetString(title), - Modifier.padding(start = 16.dp, top = 16.dp, bottom = 16.dp), + Modifier.padding(start = DEFAULT_PADDING, top = DEFAULT_PADDING, bottom = DEFAULT_PADDING), style = MaterialTheme.typography.h1 ) SectionView(null, padding = PaddingValues(horizontal = DEFAULT_PADDING, vertical = DEFAULT_PADDING_HALF), content) @@ -158,7 +158,7 @@ fun DatabaseErrorView( if (restoreDbFromBackup.value) { SectionSpacer() Text(generalGetString(R.string.database_backup_can_be_restored)) - Spacer(Modifier.size(16.dp)) + Spacer(Modifier.size(DEFAULT_PADDING)) RestoreDbButton { AlertManager.shared.showAlertDialog( title = generalGetString(R.string.restore_database_alert_title), diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseView.kt index 0be861245c..f0a1ad8b3d 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/database/DatabaseView.kt @@ -1,9 +1,8 @@ package chat.simplex.app.views.database -import SectionDivider +import SectionDividerSpaced import SectionTextFooter import SectionItemView -import SectionSpacer import SectionView import android.content.Context import android.content.res.Configuration @@ -160,7 +159,7 @@ fun DatabaseLayout( AppBarTitle(stringResource(R.string.your_chat_database)) SectionView(stringResource(R.string.messages_section_title).uppercase()) { - SectionItemView { TtlOptions(chatItemTTL, enabled = rememberUpdatedState(!stopped && !progressIndicator), onChatItemTTLSelected) } + TtlOptions(chatItemTTL, enabled = rememberUpdatedState(!stopped && !progressIndicator), onChatItemTTLSelected) } SectionTextFooter( remember(currentUser?.displayName) { @@ -173,12 +172,12 @@ fun DatabaseLayout( } } ) - SectionSpacer() + SectionDividerSpaced() SectionView(stringResource(R.string.run_chat_section)) { RunChatSetting(runChat, stopped, chatDbDeleted, startChat, stopChatAlert) } - SectionSpacer() + SectionDividerSpaced() SectionView(stringResource(R.string.chat_database_section)) { val unencrypted = chatDbEncrypted == false @@ -189,9 +188,8 @@ fun DatabaseLayout( iconColor = if (unencrypted) WarningOrange else HighOrLowlight, disabled = operationsDisabled ) - SectionDivider() AppDataBackupPreference(privacyFullBackup, initialRandomDBPassphrase) - SectionDivider() + SectionDividerSpaced() SettingsActionItem( Icons.Outlined.IosShare, stringResource(R.string.export_database), @@ -206,7 +204,6 @@ fun DatabaseLayout( iconColor = MaterialTheme.colors.primary, disabled = operationsDisabled ) - SectionDivider() SettingsActionItem( Icons.Outlined.FileDownload, stringResource(R.string.import_database), @@ -215,7 +212,6 @@ fun DatabaseLayout( iconColor = Color.Red, disabled = operationsDisabled ) - SectionDivider() val chatArchiveNameVal = chatArchiveName.value val chatArchiveTimeVal = chatArchiveTime.value val chatLastStartVal = chatLastStart.value @@ -227,7 +223,6 @@ fun DatabaseLayout( click = showSettingsModal { ChatArchiveView(it, title, chatArchiveNameVal, chatArchiveTimeVal) }, disabled = operationsDisabled ) - SectionDivider() } SettingsActionItem( Icons.Outlined.DeleteForever, @@ -245,7 +240,7 @@ fun DatabaseLayout( stringResource(R.string.stop_chat_to_enable_database_actions) } ) - SectionSpacer() + SectionDividerSpaced() SectionView(stringResource(R.string.files_and_media_section).uppercase()) { val deleteFilesDisabled = operationsDisabled || appFilesCountAndSize.value.first == 0 @@ -272,32 +267,20 @@ fun DatabaseLayout( @Composable private fun AppDataBackupPreference(privacyFullBackup: SharedPreference, initialRandomDBPassphrase: SharedPreference) { - SectionItemView { - Row(verticalAlignment = Alignment.CenterVertically) { - Icon(Icons.Outlined.Backup, stringResource(R.string.full_backup), tint = HighOrLowlight) - Spacer(Modifier.padding(horizontal = 4.dp)) - val prefState = remember { mutableStateOf(privacyFullBackup.get()) } - Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { - Text(stringResource(R.string.full_backup), Modifier.padding(end = 24.dp)) - Spacer(Modifier.fillMaxWidth().weight(1f)) - Switch( - checked = prefState.value, - onCheckedChange = { - if (initialRandomDBPassphrase.get()) { - exportProhibitedAlert() - } else { - privacyFullBackup.set(it) - prefState.value = it - } - }, - colors = SwitchDefaults.colors( - checkedThumbColor = MaterialTheme.colors.primary, - uncheckedThumbColor = HighOrLowlight - ) - ) + SettingsPreferenceItem( + Icons.Outlined.Backup, + iconColor = HighOrLowlight, + pref = privacyFullBackup, + text = stringResource(R.string.full_backup), + onChange = { + if (initialRandomDBPassphrase.get()) { + exportProhibitedAlert() + privacyFullBackup.set(false) + } else { + privacyFullBackup.set(it) } } - } + ) } private fun setChatItemTTLAlert( @@ -350,36 +333,27 @@ fun RunChatSetting( startChat: () -> Unit, stopChatAlert: () -> Unit ) { - SectionItemView() { - Row(verticalAlignment = Alignment.CenterVertically) { - val chatRunningText = if (stopped) stringResource(R.string.chat_is_stopped) else stringResource(R.string.chat_is_running) - Icon( - if (stopped) Icons.Filled.Report else Icons.Filled.PlayArrow, - chatRunningText, - tint = if (stopped) Color.Red else MaterialTheme.colors.primary - ) - Spacer(Modifier.padding(horizontal = 4.dp)) - Text( - chatRunningText, - Modifier.padding(end = 24.dp) - ) - Spacer(Modifier.fillMaxWidth().weight(1f)) - Switch( - enabled = !chatDbDeleted, - checked = runChat, - onCheckedChange = { runChatSwitch -> - if (runChatSwitch) { - startChat() - } else { - stopChatAlert() - } - }, - colors = SwitchDefaults.colors( - checkedThumbColor = MaterialTheme.colors.primary, - uncheckedThumbColor = HighOrLowlight - ), - ) - } + val chatRunningText = if (stopped) stringResource(R.string.chat_is_stopped) else stringResource(R.string.chat_is_running) + SettingsActionItemWithContent( + icon = if (stopped) Icons.Filled.Report else Icons.Filled.PlayArrow, + text = chatRunningText, + iconColor = if (stopped) Color.Red else MaterialTheme.colors.primary, + ) { + Switch( + enabled = !chatDbDeleted, + checked = runChat, + onCheckedChange = { runChatSwitch -> + if (runChatSwitch) { + startChat() + } else { + stopChatAlert() + } + }, + colors = SwitchDefaults.colors( + checkedThumbColor = MaterialTheme.colors.primary, + uncheckedThumbColor = HighOrLowlight + ), + ) } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/AlertManager.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/AlertManager.kt index 7eb452a5e6..bb6f418705 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/AlertManager.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/AlertManager.kt @@ -129,7 +129,7 @@ class AlertManager { text = alertText(text), buttons = { Column( - Modifier.fillMaxWidth().padding(horizontal = 8.dp).padding(top = 16.dp, bottom = 2.dp), + Modifier.fillMaxWidth().padding(horizontal = DEFAULT_PADDING_HALF).padding(top = DEFAULT_PADDING, bottom = 2.dp), horizontalAlignment = Alignment.CenterHorizontally ) { TextButton(onClick = { diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/CloseSheetBar.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/CloseSheetBar.kt index 5a910c563a..1c9cb170d0 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/CloseSheetBar.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/CloseSheetBar.kt @@ -6,11 +6,10 @@ import androidx.compose.material.* import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import chat.simplex.app.R import chat.simplex.app.ui.theme.* @Composable @@ -42,30 +41,15 @@ fun CloseSheetBar(close: (() -> Unit)?, endButtons: @Composable RowScope.() -> U @Composable fun AppBarTitle(title: String, withPadding: Boolean = true) { - val padding = if (withPadding) - PaddingValues(start = DEFAULT_PADDING, end = DEFAULT_PADDING, bottom = DEFAULT_PADDING) - else - PaddingValues(bottom = DEFAULT_PADDING) Text( title, Modifier .fillMaxWidth() - .padding(padding), - overflow = TextOverflow.Ellipsis, - style = MaterialTheme.typography.h1 - ) -} - -@Composable -fun ColumnScope.AppBarTitleCentered(title: String, withPadding: Boolean = true) { - Text( - title, - Modifier - .padding(bottom = if (withPadding) DEFAULT_PADDING * 1.5f else 0.dp) - .align(Alignment.CenterHorizontally), + .padding(bottom = DEFAULT_PADDING * 1.5f, start = if (withPadding) DEFAULT_PADDING else 0.dp, end = if (withPadding) DEFAULT_PADDING else 0.dp,), overflow = TextOverflow.Ellipsis, style = MaterialTheme.typography.h1, - color = MaterialTheme.colors.primary + color = MaterialTheme.colors.primary, + textAlign = TextAlign.Center ) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ExposedDropDownSettingRow.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ExposedDropDownSettingRow.kt index 3ae959d463..8c081a83ce 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ExposedDropDownSettingRow.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ExposedDropDownSettingRow.kt @@ -16,6 +16,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import chat.simplex.app.R import chat.simplex.app.ui.theme.* +import chat.simplex.app.views.usersettings.SettingsActionItemWithContent @Composable fun ExposedDropDownSettingRow( @@ -28,22 +29,8 @@ fun ExposedDropDownSettingRow( enabled: State = mutableStateOf(true), onSelected: (T) -> Unit ) { - Row( - Modifier.fillMaxWidth().padding(vertical = 10.dp), - verticalAlignment = Alignment.CenterVertically, - ) { + SettingsActionItemWithContent(icon, title, iconColor = iconTint, disabled = !enabled.value) { val expanded = remember { mutableStateOf(false) } - - if (icon != null) { - Icon( - icon, - "", - Modifier.padding(end = 8.dp), - tint = iconTint - ) - } - Text(title, Modifier.weight(1f), color = if (enabled.value) Color.Unspecified else HighOrLowlight) - ExposedDropdownMenuBox( expanded = expanded.value, onExpandedChange = { @@ -55,7 +42,7 @@ fun ExposedDropDownSettingRow( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.End ) { - val maxWidth = with(LocalDensity.current){ 180.sp.toDp() } + val maxWidth = with(LocalDensity.current) { 180.sp.toDp() } Text( values.first { it.first == selection.value }.second + (if (label != null) " $label" else ""), Modifier.widthIn(max = maxWidth), diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ModalView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ModalView.kt index 5908f32a39..7e834806a1 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ModalView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ModalView.kt @@ -11,7 +11,6 @@ import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import chat.simplex.app.TAG -import chat.simplex.app.ui.theme.SettingsBackgroundLight import chat.simplex.app.ui.theme.isInDarkTheme import java.util.concurrent.atomic.AtomicBoolean @@ -40,13 +39,13 @@ class ModalManager { fun showModal(settings: Boolean = false, endButtons: @Composable RowScope.() -> Unit = {}, content: @Composable () -> Unit) { showCustomModal { close -> - ModalView(close, if (!settings || isInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight, endButtons = endButtons, content = content) + ModalView(close, endButtons = endButtons, content = content) } } fun showModalCloseable(settings: Boolean = false, content: @Composable (close: () -> Unit) -> Unit) { showCustomModal { close -> - ModalView(close, if (!settings || isInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight, content = { content(close) }) + ModalView(close, content = { content(close) }) } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Section.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Section.kt index ce8d52a316..315cbfb10b 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Section.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Section.kt @@ -18,6 +18,7 @@ import androidx.compose.ui.unit.* import chat.simplex.app.ui.theme.* import chat.simplex.app.views.helpers.ValueTitleDesc import chat.simplex.app.views.helpers.ValueTitle +import chat.simplex.app.views.usersettings.SettingsActionItemWithContent @Composable fun SectionView(title: String? = null, padding: PaddingValues = PaddingValues(), content: (@Composable ColumnScope.() -> Unit)) { @@ -28,9 +29,7 @@ fun SectionView(title: String? = null, padding: PaddingValues = PaddingValues(), modifier = Modifier.padding(start = DEFAULT_PADDING, bottom = 5.dp), fontSize = 12.sp ) } - Surface(color = if (isInDarkTheme()) GroupDark else MaterialTheme.colors.background) { - Column(Modifier.padding(padding).fillMaxWidth()) { content() } - } + Column(Modifier.padding(padding).fillMaxWidth()) { content() } } } @@ -46,13 +45,11 @@ fun SectionView( Column { val iconSize = with(LocalDensity.current) { 21.sp.toDp() } Row(Modifier.padding(start = DEFAULT_PADDING, bottom = 5.dp), verticalAlignment = Alignment.CenterVertically) { - if (leadingIcon) Icon(icon, null, Modifier.padding(end = 4.dp).size(iconSize), tint = iconTint) + if (leadingIcon) Icon(icon, null, Modifier.padding(end = DEFAULT_PADDING_HALF).size(iconSize), tint = iconTint) Text(title, color = HighOrLowlight, style = MaterialTheme.typography.body2, fontSize = 12.sp) - if (!leadingIcon) Icon(icon, null, Modifier.padding(start = 4.dp).size(iconSize), tint = iconTint) - } - Surface(color = if (isInDarkTheme()) GroupDark else MaterialTheme.colors.background) { - Column(Modifier.padding(padding).fillMaxWidth()) { content() } + if (!leadingIcon) Icon(icon, null, Modifier.padding(start = DEFAULT_PADDING_HALF).size(iconSize), tint = iconTint) } + Column(Modifier.padding(padding).fillMaxWidth()) { content() } } } @@ -85,7 +82,27 @@ fun SectionItemView( click: (() -> Unit)? = null, minHeight: Dp = 46.dp, disabled: Boolean = false, - padding: PaddingValues = PaddingValues(horizontal = DEFAULT_PADDING), + extraPadding: Boolean = false, + padding: PaddingValues = if (extraPadding) PaddingValues(start = DEFAULT_PADDING * 2, end = DEFAULT_PADDING) else PaddingValues(horizontal = DEFAULT_PADDING), + content: (@Composable RowScope.() -> Unit) +) { + val modifier = Modifier + .fillMaxWidth() + .sizeIn(minHeight = minHeight) + Row( + if (click == null || disabled) modifier.padding(padding) else modifier.clickable(onClick = click).padding(padding), + verticalAlignment = Alignment.CenterVertically + ) { + content() + } +} + +@Composable +fun SectionItemViewWithIcon( + click: (() -> Unit)? = null, + minHeight: Dp = 46.dp, + disabled: Boolean = false, + padding: PaddingValues = PaddingValues(start = DEFAULT_PADDING * 2, end = DEFAULT_PADDING), content: (@Composable RowScope.() -> Unit) ) { val modifier = Modifier @@ -131,19 +148,7 @@ fun SectionItemWithValue( enabled: State = mutableStateOf(true), onSelected: () -> Unit ) { - SectionItemView(click = if (enabled.value) onSelected else null) { - if (icon != null) { - Icon( - icon, - title, - Modifier.padding(end = 8.dp), - tint = iconTint - ) - } - Text(title, color = if (enabled.value) Color.Unspecified else HighOrLowlight) - - Spacer(Modifier.fillMaxWidth().weight(1f)) - + SettingsActionItemWithContent(icon = icon, text = title, iconColor = iconTint, click = if (enabled.value) onSelected else null, disabled = !enabled.value) { Row( Modifier.padding(start = 10.dp), verticalAlignment = Alignment.CenterVertically, @@ -189,11 +194,23 @@ fun SectionDivider() { Divider(Modifier.padding(horizontal = 8.dp)) } +@Composable +fun SectionDividerSpaced() { + SectionSpacer() + Divider(Modifier.padding(horizontal = DEFAULT_PADDING_HALF)) + SectionSpacer() +} + @Composable fun SectionSpacer() { Spacer(Modifier.height(30.dp)) } +@Composable +fun TextIconSpaced(extraPadding: Boolean = false) { + Spacer(Modifier.padding(horizontal = if (extraPadding) DEFAULT_PADDING else DEFAULT_PADDING_HALF)) +} + @Composable fun InfoRow(title: String, value: String, icon: ImageVector? = null, iconTint: Color? = null) { SectionItemViewSpaceBetween { diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactView.kt index 6fd7c26b54..091ce162cf 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactView.kt @@ -19,7 +19,6 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import chat.simplex.app.R -import chat.simplex.app.model.ChatModel import chat.simplex.app.ui.theme.* import chat.simplex.app.views.helpers.* @@ -40,7 +39,7 @@ fun AddContactLayout(connReq: String, connIncognito: Boolean, share: () -> Unit) Column( Modifier .verticalScroll(rememberScrollState()) - .padding(bottom = 16.dp), + .padding(bottom = DEFAULT_BOTTOM_PADDING), verticalArrangement = Arrangement.SpaceBetween, ) { AppBarTitle(stringResource(R.string.add_contact), false) @@ -75,7 +74,7 @@ fun AddContactLayout(connReq: String, connIncognito: Boolean, share: () -> Unit) annotatedStringResource(R.string.if_you_cannot_meet_in_person_show_QR_in_video_call_or_via_another_channel), lineHeight = 22.sp, modifier = Modifier - .padding(top = 16.dp, bottom = if (screenHeight > 600.dp) 16.dp else 0.dp) + .padding(top = DEFAULT_PADDING, bottom = if (screenHeight > 600.dp) DEFAULT_PADDING else 0.dp) ) Row( Modifier.fillMaxWidth(), diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddGroupView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddGroupView.kt index 2cf1a1d90e..c0bb4d35ae 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddGroupView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddGroupView.kt @@ -89,7 +89,7 @@ fun AddGroupLayout(createGroup: (GroupProfile) -> Unit, close: () -> Unit) { .verticalScroll(rememberScrollState()) .padding(horizontal = DEFAULT_PADDING) ) { - AppBarTitleCentered(stringResource(R.string.create_secret_group_title)) + AppBarTitle(stringResource(R.string.create_secret_group_title)) ReadableText(R.string.group_is_decentralized, TextAlign.Center) Box( Modifier diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ContactConnectionInfoView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ContactConnectionInfoView.kt index 036289cbd4..365bf7a5c0 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ContactConnectionInfoView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ContactConnectionInfoView.kt @@ -1,6 +1,5 @@ package chat.simplex.app.views.newchat -import SectionDivider import SectionView import android.content.res.Configuration import androidx.compose.foundation.layout.* @@ -101,7 +100,6 @@ private fun ContactConnectionInfoLayout( SectionView { if (!connReq.isNullOrEmpty() && contactConnection.initiated) { ShowQrButton(contactConnection.incognito, showQr) - SectionDivider() } DeleteButton(deleteConnection) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/NewChatSheet.kt b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/NewChatSheet.kt index e0e6469e6e..c4ced3efac 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/NewChatSheet.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/NewChatSheet.kt @@ -147,7 +147,7 @@ private fun NewChatSheetLayout( } FloatingActionButton( onClick = { if (!stopped) closeNewChatSheet(true) }, - Modifier.padding(end = 16.dp, bottom = 16.dp), + Modifier.padding(end = DEFAULT_PADDING, bottom = DEFAULT_PADDING), elevation = FloatingActionButtonDefaults.elevation( defaultElevation = 0.dp, pressedElevation = 0.dp, diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/PasteToConnect.kt b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/PasteToConnect.kt index f231195b0e..19f7a7ff99 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/PasteToConnect.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/PasteToConnect.kt @@ -84,7 +84,7 @@ fun PasteToConnectLayout( generalGetString(R.string.profile_will_be_sent_to_contact_sending_link) ) - Box(Modifier.padding(top = 16.dp, bottom = 6.dp)) { + Box(Modifier.padding(top = DEFAULT_PADDING, bottom = 6.dp)) { TextEditor(Modifier.height(180.dp), text = connectionLink) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/HowItWorks.kt b/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/HowItWorks.kt index 7df26e2d2d..3ee0118970 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/HowItWorks.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/HowItWorks.kt @@ -47,7 +47,7 @@ fun HowItWorks(user: User?, onboardingStage: MutableState? = n Spacer(Modifier.fillMaxHeight().weight(1f)) if (onboardingStage != null) { - Box(Modifier.fillMaxWidth().padding(bottom = 16.dp), contentAlignment = Alignment.Center) { + Box(Modifier.fillMaxWidth().padding(bottom = DEFAULT_PADDING), contentAlignment = Alignment.Center) { OnboardingActionButton(user, onboardingStage, onclick = { ModalManager.shared.closeModal() }) } Spacer(Modifier.fillMaxHeight().weight(1f)) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/SetNotificationsMode.kt b/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/SetNotificationsMode.kt index 01d4af6c23..774a962c42 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/SetNotificationsMode.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/SetNotificationsMode.kt @@ -10,10 +10,8 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import chat.simplex.app.R @@ -32,7 +30,7 @@ fun SetNotificationsMode(m: ChatModel) { .padding(vertical = 14.dp) ) { //CloseSheetBar(null) - AppBarTitleCentered(stringResource(R.string.onboarding_notifications_mode_title)) + AppBarTitle(stringResource(R.string.onboarding_notifications_mode_title)) val currentMode = rememberSaveable { mutableStateOf(NotificationsMode.default) } Column(Modifier.padding(horizontal = DEFAULT_PADDING * 1f)) { Text(stringResource(R.string.onboarding_notifications_mode_subtitle), Modifier.fillMaxWidth(), textAlign = TextAlign.Center) @@ -42,7 +40,7 @@ fun SetNotificationsMode(m: ChatModel) { NotificationButton(currentMode, NotificationsMode.SERVICE, R.string.onboarding_notifications_mode_service, R.string.onboarding_notifications_mode_service_desc) } Spacer(Modifier.fillMaxHeight().weight(1f)) - Box(Modifier.fillMaxWidth().padding(bottom = 16.dp), contentAlignment = Alignment.Center) { + Box(Modifier.fillMaxWidth().padding(bottom = DEFAULT_PADDING), contentAlignment = Alignment.Center) { OnboardingActionButton(R.string.use_chat, OnboardingStage.OnboardingComplete, m.onboardingStage, false) { changeNotificationsMode(currentMode.value, m) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/SimpleXInfo.kt b/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/SimpleXInfo.kt index a315ac2376..165092aaac 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/SimpleXInfo.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/SimpleXInfo.kt @@ -138,7 +138,7 @@ fun OnboardingActionButton( Icon( Icons.Outlined.ArrowForwardIos, "next stage", tint = MaterialTheme.colors.primary, modifier = Modifier - .padding(start = 16.dp, top = 5.dp) + .padding(start = DEFAULT_PADDING, top = 5.dp) .size(15.dp) ) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/WhatsNewView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/WhatsNewView.kt index dbd3ce5e35..dc1191e242 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/WhatsNewView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/onboarding/WhatsNewView.kt @@ -68,7 +68,7 @@ fun WhatsNewView(viaSettings: Boolean = false, close: () -> Unit) { fun pagination() { Row( Modifier - .padding(bottom = 16.dp) + .padding(bottom = DEFAULT_PADDING) ) { if (currentVersion.value > 0) { val prev = currentVersion.value - 1 @@ -113,7 +113,7 @@ fun WhatsNewView(viaSettings: Boolean = false, close: () -> Unit) { .padding(horizontal = DEFAULT_PADDING) .verticalScroll(rememberScrollState()), horizontalAlignment = Alignment.Start, - verticalArrangement = Arrangement.spacedBy(16.dp) + verticalArrangement = Arrangement.spacedBy(DEFAULT_PADDING) ) { Text( String.format(generalGetString(R.string.new_in_version), v.version), diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AcceptRequestsView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AcceptRequestsView.kt index bfcd012b90..912116cec8 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AcceptRequestsView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AcceptRequestsView.kt @@ -1,8 +1,6 @@ package chat.simplex.app.views.usersettings import SectionCustomFooter -import SectionDivider -import SectionItemView import SectionView import androidx.compose.foundation.layout.* import androidx.compose.foundation.rememberScrollState @@ -53,25 +51,20 @@ private fun AcceptRequestsLayout( val autoAcceptState = remember { mutableStateOf(AutoAcceptState(contactLink)) } val autoAcceptStateSaved = remember { mutableStateOf(autoAcceptState.value) } SectionView(stringResource(R.string.accept_requests).uppercase()) { - SectionItemView { - PreferenceToggleWithIcon(stringResource(R.string.accept_automatically), Icons.Outlined.Check, checked = autoAcceptState.value.enable) { - autoAcceptState.value = if (!it) - AutoAcceptState() - else - AutoAcceptState(it, autoAcceptState.value.incognito, autoAcceptState.value.welcomeText) - } + PreferenceToggleWithIcon(stringResource(R.string.accept_automatically), Icons.Outlined.Check, checked = autoAcceptState.value.enable) { + autoAcceptState.value = if (!it) + AutoAcceptState() + else + AutoAcceptState(it, autoAcceptState.value.incognito, autoAcceptState.value.welcomeText) } if (autoAcceptState.value.enable) { - SectionDivider() - SectionItemView { - PreferenceToggleWithIcon( - stringResource(R.string.incognito), - if (autoAcceptState.value.incognito) Icons.Filled.TheaterComedy else Icons.Outlined.TheaterComedy, - if (autoAcceptState.value.incognito) Indigo else HighOrLowlight, - autoAcceptState.value.incognito, - ) { - autoAcceptState.value = AutoAcceptState(autoAcceptState.value.enable, it, autoAcceptState.value.welcomeText) - } + PreferenceToggleWithIcon( + stringResource(R.string.incognito), + if (autoAcceptState.value.incognito) Icons.Filled.TheaterComedy else Icons.Outlined.TheaterComedy, + if (autoAcceptState.value.incognito) Indigo else HighOrLowlight, + autoAcceptState.value.incognito, + ) { + autoAcceptState.value = AutoAcceptState(autoAcceptState.value.enable, it, autoAcceptState.value.welcomeText) } } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AdvancedNetworkSettings.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AdvancedNetworkSettings.kt index e133f04a58..ae2ca28388 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AdvancedNetworkSettings.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AdvancedNetworkSettings.kt @@ -1,7 +1,6 @@ package chat.simplex.app.views.usersettings import SectionCustomFooter -import SectionDivider import SectionItemView import SectionSpacer import SectionView @@ -148,48 +147,40 @@ fun AdvancedNetworkSettingsView(chatModel: ChatModel) { SectionItemView { ResetToDefaultsButton(reset, disabled = resetDisabled) } - SectionDivider() SectionItemView { TimeoutSettingRow( stringResource(R.string.network_option_tcp_connection_timeout), networkTCPConnectTimeout, listOf(2_500000, 5_000000, 7_500000, 10_000000, 15_000000, 20_000000), secondsLabel ) } - SectionDivider() SectionItemView { TimeoutSettingRow( stringResource(R.string.network_option_protocol_timeout), networkTCPTimeout, listOf(1_500000, 3_000000, 5_000000, 7_000000, 10_000000, 15_000000), secondsLabel ) } - SectionDivider() SectionItemView { TimeoutSettingRow( stringResource(R.string.network_option_ping_interval), networkSMPPingInterval, listOf(120_000000, 300_000000, 600_000000, 1200_000000, 2400_000000, 3600_000000), secondsLabel ) } - SectionDivider() SectionItemView { IntSettingRow( stringResource(R.string.network_option_ping_count), networkSMPPingCount, listOf(1, 2, 3, 5, 8), "" ) } - SectionDivider() SectionItemView { EnableKeepAliveSwitch(networkEnableKeepAlive) } - SectionDivider() if (networkEnableKeepAlive.value) { SectionItemView { IntSettingRow("TCP_KEEPIDLE", networkTCPKeepIdle, listOf(15, 30, 60, 120, 180), secondsLabel) } - SectionDivider() SectionItemView { IntSettingRow("TCP_KEEPINTVL", networkTCPKeepIntvl, listOf(5, 10, 15, 30, 60), secondsLabel) } - SectionDivider() SectionItemView { IntSettingRow("TCP_KEEPCNT", networkTCPKeepCnt, listOf(1, 2, 4, 6, 8), "") } @@ -197,11 +188,9 @@ fun AdvancedNetworkSettingsView(chatModel: ChatModel) { SectionItemView { Text("TCP_KEEPIDLE", color = HighOrLowlight) } - SectionDivider() SectionItemView { Text("TCP_KEEPINTVL", color = HighOrLowlight) } - SectionDivider() SectionItemView { Text("TCP_KEEPCNT", color = HighOrLowlight) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Appearance.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Appearance.kt index da340dc890..4b7d9ed212 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Appearance.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Appearance.kt @@ -1,21 +1,15 @@ package chat.simplex.app.views.usersettings import SectionCustomFooter -import SectionDivider -import SectionItemView +import SectionDividerSpaced import SectionItemViewSpaceBetween -import SectionItemWithValue import SectionSpacer import SectionView import android.app.Activity import android.content.ComponentName -import android.content.Intent import android.content.pm.PackageManager import android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT import android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED -import android.net.Uri -import android.os.Build -import android.provider.Settings import androidx.compose.foundation.* import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyRow @@ -105,26 +99,24 @@ fun AppearanceView(m: ChatModel) { // onSelected = { openSystemLangPicker(context as? Activity ?: return@SectionItemWithValue) } // ) // } else { - val state = rememberSaveable { mutableStateOf(languagePref.get() ?: "system") } - SectionItemView { - LangSelector(state) { - state.value = it - withApi { - delay(200) - val activity = context as? Activity - if (activity != null) { - if (it == "system") { - saveAppLocale(languagePref, activity) - } else { - saveAppLocale(languagePref, activity, it) - } - } + val state = rememberSaveable { mutableStateOf(languagePref.get() ?: "system") } + LangSelector(state) { + state.value = it + withApi { + delay(200) + val activity = context as? Activity + if (activity != null) { + if (it == "system") { + saveAppLocale(languagePref, activity) + } else { + saveAppLocale(languagePref, activity, it) } } } + } // } } - SectionSpacer() + SectionDividerSpaced() SectionView(stringResource(R.string.settings_section_title_icon), padding = PaddingValues(horizontal = DEFAULT_PADDING_HALF)) { LazyRow { @@ -149,17 +141,14 @@ fun AppearanceView(m: ChatModel) { } } - SectionSpacer() + SectionDividerSpaced() val currentTheme by CurrentColors.collectAsState() SectionView(stringResource(R.string.settings_section_title_themes)) { - SectionItemViewSpaceBetween { - val darkTheme = isSystemInDarkTheme() - val state = remember { derivedStateOf { currentTheme.second } } - ThemeSelector(state) { - ThemeManager.applyTheme(it.name, darkTheme) - } + val darkTheme = isSystemInDarkTheme() + val state = remember { derivedStateOf { currentTheme.second } } + ThemeSelector(state) { + ThemeManager.applyTheme(it.name, darkTheme) } - SectionDivider() SectionItemViewSpaceBetween({ editPrimaryColor(currentTheme.first.primary) }) { val title = generalGetString(R.string.color_primary) Text(title) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/CallSettings.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/CallSettings.kt index c1fa4a04bc..982075c8e2 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/CallSettings.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/CallSettings.kt @@ -1,6 +1,5 @@ package chat.simplex.app.views.usersettings -import SectionDivider import SectionItemView import SectionTextFooter import SectionView @@ -45,14 +44,10 @@ fun CallSettingsLayout( val lockCallState = remember { mutableStateOf(callOnLockScreen.get()) } SectionView(stringResource(R.string.settings_section_title_settings)) { SectionItemView(editIceServers) { Text(stringResource(R.string.webrtc_ice_servers)) } - SectionDivider() val enabled = remember { mutableStateOf(true) } - SectionItemView { LockscreenOpts(lockCallState, enabled, onSelected = { callOnLockScreen.set(it); lockCallState.value = it }) } - SectionDivider() - SectionItemView() { - SharedPreferenceToggle(stringResource(R.string.always_use_relay), webrtcPolicyRelay) - } + LockscreenOpts(lockCallState, enabled, onSelected = { callOnLockScreen.set(it); lockCallState.value = it }) + SettingsPreferenceItem(null, stringResource(R.string.always_use_relay), webrtcPolicyRelay) } SectionTextFooter( if (remember { webrtcPolicyRelay.state }.value) { @@ -87,28 +82,22 @@ private fun LockscreenOpts(lockscreenOpts: State, enabled: Sta @Composable fun SharedPreferenceToggle( - text: String, preference: SharedPreference, - preferenceState: MutableState? = null, + enabled: Boolean = true, onChange: ((Boolean) -> Unit)? = null, - ) { - val prefState = preferenceState ?: remember { mutableStateOf(preference.get()) } - Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { - Text(text, Modifier.padding(end = 24.dp)) - Spacer(Modifier.fillMaxWidth().weight(1f)) - Switch( - checked = prefState.value, - onCheckedChange = { - preference.set(it) - prefState.value = it - onChange?.invoke(it) - }, - colors = SwitchDefaults.colors( - checkedThumbColor = MaterialTheme.colors.primary, - uncheckedThumbColor = HighOrLowlight - ) +) { + Switch( + enabled = enabled, + checked = remember { preference.state }.value, + onCheckedChange = { + preference.set(it) + onChange?.invoke(it) + }, + colors = SwitchDefaults.colors( + checkedThumbColor = MaterialTheme.colors.primary, + uncheckedThumbColor = HighOrLowlight ) - } + ) } @Composable diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/DeveloperView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/DeveloperView.kt index 1310288ec9..2f3311321e 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/DeveloperView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/DeveloperView.kt @@ -1,6 +1,5 @@ package chat.simplex.app.views.usersettings -import SectionDivider import SectionSpacer import SectionTextFooter import SectionView @@ -9,7 +8,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.* import androidx.compose.runtime.* -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.stringResource @@ -28,15 +26,12 @@ fun DeveloperView( val uriHandler = LocalUriHandler.current AppBarTitle(stringResource(R.string.settings_developer_tools)) val developerTools = m.controller.appPrefs.developerTools - val devTools = remember { mutableStateOf(developerTools.get()) } + val devTools = remember { developerTools.state } SectionView() { InstallTerminalAppItem(uriHandler) - SectionDivider() ChatConsoleItem { withAuth(showCustomModal { it, close -> TerminalView(it, close) }) } - SectionDivider() SettingsPreferenceItem(Icons.Outlined.DriveFolderUpload, stringResource(R.string.confirm_database_upgrades), m.controller.appPrefs.confirmDBUpgrades) - SectionDivider() - SettingsPreferenceItem(Icons.Outlined.Code, stringResource(R.string.show_developer_options), developerTools, devTools) + SettingsPreferenceItem(Icons.Outlined.Code, stringResource(R.string.show_developer_options), developerTools) } SectionTextFooter( generalGetString(if (devTools.value) R.string.show_dev_options else R.string.hide_dev_options) + " " + diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/HiddenProfileView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/HiddenProfileView.kt index 6571b8c4af..9a2862113f 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/HiddenProfileView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/HiddenProfileView.kt @@ -1,6 +1,5 @@ package chat.simplex.app.views.usersettings -import SectionDivider import SectionItemView import SectionItemViewSpaceBetween import SectionSpacer @@ -12,9 +11,7 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.material.* import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import chat.simplex.app.R @@ -76,11 +73,9 @@ private fun HiddenProfileLayout( SectionItemView { PassphraseField(hidePassword, generalGetString(R.string.password_to_show), isValid = { passwordValid }, showStrength = true) } - SectionDivider() SectionItemView { PassphraseField(confirmHidePassword, stringResource(R.string.confirm_password), isValid = { confirmValid }, dependsOn = hidePassword) } - SectionDivider() SectionItemViewSpaceBetween({ saveProfilePassword(hidePassword.value) }, disabled = saveDisabled, minHeight = TextFieldDefaults.MinHeight) { Text(generalGetString(R.string.save_profile_password), color = if (saveDisabled) HighOrLowlight else MaterialTheme.colors.primary) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NetworkAndServers.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NetworkAndServers.kt index 6af1b107e9..0723fe5000 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NetworkAndServers.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NetworkAndServers.kt @@ -1,13 +1,12 @@ package chat.simplex.app.views.usersettings import SectionCustomFooter -import SectionDivider +import SectionDividerSpaced import SectionItemView import SectionItemWithValue -import SectionSpacer -import SectionTextFooter import SectionView import SectionViewSelectable +import TextIconSpaced import androidx.compose.foundation.* import androidx.compose.foundation.layout.* import androidx.compose.foundation.text.KeyboardActions @@ -19,13 +18,17 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.TextRange +import androidx.compose.ui.text.* +import androidx.compose.ui.text.font.Font +import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.input.* import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import chat.simplex.app.R import chat.simplex.app.model.* import chat.simplex.app.ui.theme.* +import chat.simplex.app.views.chat.item.ClickableText import chat.simplex.app.views.helpers.* @Composable @@ -163,27 +166,20 @@ fun NetworkAndServersView( AppBarTitle(stringResource(R.string.network_and_servers)) SectionView(generalGetString(R.string.settings_section_title_messages)) { SettingsActionItem(Icons.Outlined.Dns, stringResource(R.string.smp_servers), showCustomModal { m, close -> ProtocolServersView(m, ServerProtocol.SMP, close) }) - SectionDivider() SettingsActionItem(Icons.Outlined.Dns, stringResource(R.string.xftp_servers), showCustomModal { m, close -> ProtocolServersView(m, ServerProtocol.XFTP, close) }) - SectionDivider() - SectionItemView { - UseSocksProxySwitch(networkUseSocksProxy, proxyPort, toggleSocksProxy, showSettingsModal) - } - SectionDivider() + UseSocksProxySwitch(networkUseSocksProxy, proxyPort, toggleSocksProxy, showSettingsModal) UseOnionHosts(onionHosts, networkUseSocksProxy, showSettingsModal, useOnion) - SectionDivider() if (developerTools) { SessionModePicker(sessionMode, showSettingsModal, updateSessionMode) - SectionDivider() } SettingsActionItem(Icons.Outlined.Cable, stringResource(R.string.network_settings), showSettingsModal { AdvancedNetworkSettingsView(it) }) } if (networkUseSocksProxy.value) { SectionCustomFooter { Text(annotatedStringResource(R.string.disable_onion_hosts_when_not_supported)) } } - Spacer(Modifier.height(16.dp)) + SectionDividerSpaced() SectionView(generalGetString(R.string.settings_section_title_calls)) { SettingsActionItem(Icons.Outlined.ElectricalServices, stringResource(R.string.webrtc_ice_servers), showModal { RTCServersView(it) }) } @@ -198,30 +194,42 @@ fun UseSocksProxySwitch( showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit) ) { Row( - Modifier.fillMaxWidth(), + Modifier.fillMaxWidth().padding(end = DEFAULT_PADDING), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { Row( - Modifier.weight(1f), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp) + Modifier.weight(1f).padding(horizontal = DEFAULT_PADDING), + verticalAlignment = Alignment.CenterVertically ) { Icon( Icons.Outlined.SettingsEthernet, stringResource(R.string.network_socks_toggle), tint = HighOrLowlight ) + TextIconSpaced(false) if (networkUseSocksProxy.value) { - Row { - Text(generalGetString(R.string.network_socks_toggle_use_socks_proxy) + " (") - Text( - generalGetString(R.string.network_proxy_port).format(proxyPort.value), - Modifier.clickable { showSettingsModal { SockProxySettings(it) }() }, - color = MaterialTheme.colors.primary + val text = buildAnnotatedString { + append(generalGetString(R.string.network_socks_toggle_use_socks_proxy) + " (") + val style = SpanStyle(color = MaterialTheme.colors.primary) + withAnnotation(tag = "PORT", annotation = generalGetString(R.string.network_proxy_port).format(proxyPort.value)) { + withStyle(style) { append(generalGetString(R.string.network_proxy_port).format(proxyPort.value)) } + } + append(")") + } + ClickableText( + text, + style = TextStyle(color = MaterialTheme.colors.onBackground, fontSize = 16.sp, fontFamily = FontFamily(Font(R.font.inter_regular))), + onClick = { offset -> + text.getStringAnnotations(tag = "PORT", start = offset, end = offset) + .firstOrNull()?.let { _ -> + showSettingsModal { SockProxySettings(it) }() + } + }, + shouldConsumeEvent = { offset -> + text.getStringAnnotations(tag = "PORT", start = offset, end = offset).any() + } ) - Text(")") - } } else { Text(stringResource(R.string.network_socks_toggle)) } @@ -273,7 +281,6 @@ fun SockProxySettings(m: ChatModel) { } }, disabled = hostPort == defaultHostPort) } - SectionDivider() SectionItemView { DefaultConfigurableTextField( hostUnsaved, @@ -284,7 +291,6 @@ fun SockProxySettings(m: ChatModel) { keyboardType = KeyboardType.Text, ) } - SectionDivider() SectionItemView { DefaultConfigurableTextField( portUnsaved, diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NotificationsSettingsView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NotificationsSettingsView.kt index 8f56be3c33..414af16444 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NotificationsSettingsView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NotificationsSettingsView.kt @@ -1,7 +1,5 @@ package chat.simplex.app.views.usersettings -import SectionDivider -import SectionItemViewSpaceBetween import SectionView import SectionViewSelectable import android.os.Build @@ -14,7 +12,6 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.capitalize import androidx.compose.ui.text.intl.Locale import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp import chat.simplex.app.* import chat.simplex.app.R import chat.simplex.app.model.ChatModel @@ -84,9 +81,7 @@ fun NotificationsSettingsLayout( ) { AppBarTitle(stringResource(R.string.notifications)) SectionView(null) { - SectionItemViewSpaceBetween({ showPage(CurrentPage.NOTIFICATIONS_MODE) }) { - Text(stringResource(R.string.settings_notifications_mode_title)) - Spacer(Modifier.padding(horizontal = 10.dp)) + SettingsActionItemWithContent(null, stringResource(R.string.settings_notifications_mode_title), { showPage(CurrentPage.NOTIFICATIONS_MODE) }) { Text( modes.first { it.value == notificationsMode.value }.title, maxLines = 1, @@ -94,10 +89,7 @@ fun NotificationsSettingsLayout( color = HighOrLowlight ) } - SectionDivider() - SectionItemViewSpaceBetween({ showPage(CurrentPage.NOTIFICATION_PREVIEW_MODE) }) { - Text(stringResource(R.string.settings_notification_preview_mode_title)) - Spacer(Modifier.padding(horizontal = 10.dp)) + SettingsActionItemWithContent(null, stringResource(R.string.settings_notification_preview_mode_title), { showPage(CurrentPage.NOTIFICATION_PREVIEW_MODE) }) { Text( previewModes.first { it.value == notificationPreviewMode.value }.title, maxLines = 1, diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Preferences.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Preferences.kt index e5de1edac0..b123b0c64d 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Preferences.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Preferences.kt @@ -1,6 +1,6 @@ package chat.simplex.app.views.usersettings -import SectionDivider +import SectionDividerSpaced import SectionItemView import SectionSpacer import SectionTextFooter @@ -40,7 +40,6 @@ fun PreferencesView(m: ChatModel, user: User, close: () -> Unit,) { if (preferences == currentPreferences) close() else showUnsavedChangesAlert({ savePrefs(close) }, close) }, - background = if (isInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight ) { PreferencesLayout( preferences, @@ -69,22 +68,22 @@ private fun PreferencesLayout( TimedMessagesFeatureSection(timedMessages) { applyPrefs(preferences.copy(timedMessages = TimedMessagesPreference(allow = if (it) FeatureAllowed.YES else FeatureAllowed.NO))) } - SectionSpacer() + SectionDividerSpaced() val allowFullDeletion = remember(preferences) { mutableStateOf(preferences.fullDelete.allow) } FeatureSection(ChatFeature.FullDelete, allowFullDeletion) { applyPrefs(preferences.copy(fullDelete = 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, @@ -96,16 +95,14 @@ private fun PreferencesLayout( @Composable private fun FeatureSection(feature: ChatFeature, allowFeature: State, onSelected: (FeatureAllowed) -> Unit) { SectionView { - SectionItemView { - ExposedDropDownSettingRow( - feature.text, - FeatureAllowed.values().map { it to it.text }, - allowFeature, - icon = feature.icon, - enabled = remember { mutableStateOf(feature != ChatFeature.Calls) }, - onSelected = onSelected, - ) - } + ExposedDropDownSettingRow( + feature.text, + FeatureAllowed.values().map { it to it.text }, + allowFeature, + icon = feature.icon, + enabled = remember { mutableStateOf(feature != ChatFeature.Calls) }, + onSelected = onSelected, + ) } SectionTextFooter(feature.allowDescription(allowFeature.value) + (if (feature == ChatFeature.Calls) generalGetString(R.string.available_in_v51) else "")) } @@ -113,15 +110,14 @@ private fun FeatureSection(feature: ChatFeature, allowFeature: State, onSelected: (Boolean) -> Unit) { SectionView { - SectionItemView { - PreferenceToggleWithIcon( - ChatFeature.TimedMessages.text, - ChatFeature.TimedMessages.icon, - HighOrLowlight, - allowFeature.value == FeatureAllowed.ALWAYS || allowFeature.value == FeatureAllowed.YES, - onSelected - ) - } + PreferenceToggleWithIcon( + ChatFeature.TimedMessages.text, + ChatFeature.TimedMessages.icon, + HighOrLowlight, + allowFeature.value == FeatureAllowed.ALWAYS || allowFeature.value == FeatureAllowed.YES, + extraPadding = false, + onSelected + ) } SectionTextFooter(ChatFeature.TimedMessages.allowDescription(allowFeature.value)) } @@ -132,7 +128,6 @@ private fun ResetSaveButtons(reset: () -> Unit, save: () -> Unit, disabled: Bool SectionItemView(reset, disabled = disabled) { Text(stringResource(R.string.reset_verb), color = if (disabled) HighOrLowlight else MaterialTheme.colors.primary) } - SectionDivider() SectionItemView(save, disabled = disabled) { Text(stringResource(R.string.save_and_notify_contacts), color = if (disabled) HighOrLowlight else MaterialTheme.colors.primary) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/PrivacySettings.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/PrivacySettings.kt index 50cffd2976..48d730a3cc 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/PrivacySettings.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/PrivacySettings.kt @@ -1,15 +1,13 @@ package chat.simplex.app.views.usersettings -import SectionDivider +import SectionDividerSpaced import SectionItemView -import SectionSpacer import SectionTextFooter import SectionView import android.view.WindowManager import androidx.compose.foundation.layout.* import androidx.compose.material.* import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Lock import androidx.compose.material.icons.outlined.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment @@ -21,7 +19,6 @@ import androidx.fragment.app.FragmentActivity import chat.simplex.app.R import chat.simplex.app.model.* import chat.simplex.app.ui.theme.HighOrLowlight -import chat.simplex.app.ui.theme.SimplexGreen import chat.simplex.app.views.helpers.* import chat.simplex.app.views.helpers.DatabaseUtils.ksAppPassword import chat.simplex.app.views.localauth.SetAppPasscodeView @@ -51,7 +48,6 @@ fun PrivacySettingsView( AppBarTitle(stringResource(R.string.your_privacy)) SectionView(stringResource(R.string.settings_section_title_device)) { ChatLockItem(chatModel, showSettingsModal, setPerformLA) - SectionDivider() val context = LocalContext.current SettingsPreferenceItem(Icons.Outlined.VisibilityOff, stringResource(R.string.protect_app_screen), chatModel.controller.appPrefs.privacyProtectScreen) { on -> if (on) { @@ -64,19 +60,15 @@ fun PrivacySettingsView( } } } - SectionSpacer() + SectionDividerSpaced() SectionView(stringResource(R.string.settings_section_title_chats)) { SettingsPreferenceItem(Icons.Outlined.Image, stringResource(R.string.auto_accept_images), chatModel.controller.appPrefs.privacyAcceptImages) - SectionDivider() SettingsPreferenceItem(Icons.Outlined.TravelExplore, stringResource(R.string.send_link_previews), chatModel.controller.appPrefs.privacyLinkPreviews) - SectionDivider() - SectionItemView { - SimpleXLinkOptions(chatModel.simplexLinkMode, onSelected = { - simplexLinkMode.set(it) - chatModel.simplexLinkMode.value = it - }) - } + SimpleXLinkOptions(chatModel.simplexLinkMode, onSelected = { + simplexLinkMode.set(it) + chatModel.simplexLinkMode.value = it + }) } if (chatModel.simplexLinkMode.value == SimplexLinkMode.BROWSER) { SectionTextFooter(stringResource(R.string.simplex_link_mode_browser_warning)) @@ -241,25 +233,18 @@ fun SimplexLockView( setPerformLA(false, activity) } } - SectionDivider() - SectionItemView { - LockModeSelector(laMode) { newLAMode -> - if (laMode.value == newLAMode) return@LockModeSelector - if (chatModel.controller.appPrefs.performLA.get()) { - toggleLAMode(newLAMode) - } else { - currentLAMode.set(newLAMode) - } + LockModeSelector(laMode) { newLAMode -> + if (laMode.value == newLAMode) return@LockModeSelector + if (chatModel.controller.appPrefs.performLA.get()) { + toggleLAMode(newLAMode) + } else { + currentLAMode.set(newLAMode) } } if (performLA.value) { - SectionDivider() - SectionItemView { - LockDelaySelector(remember { laLockDelay.state }) { laLockDelay.set(it) } - } + LockDelaySelector(remember { laLockDelay.state }) { laLockDelay.set(it) } if (showChangePasscode.value && laMode.value == LAMode.PASSCODE) { - SectionDivider() SectionItemView({ changeLAPassword() }) { Text(generalGetString(R.string.la_change_app_passcode)) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServerView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServerView.kt index 923693790b..519041c1fd 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServerView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServerView.kt @@ -1,6 +1,6 @@ package chat.simplex.app.views.usersettings -import SectionDivider +import SectionDividerSpaced import SectionItemView import SectionItemViewSpaceBetween import SectionSpacer @@ -113,7 +113,7 @@ private fun PresetServer( ) } } - SectionSpacer() + SectionDividerSpaced() UseServerSection(true, testing, server, testServer, onUpdate, onDelete) } @@ -151,15 +151,16 @@ private fun CustomServer( onUpdate(server.copy(server = it, tested = testedPreviously[serverAddress.value])) } } - SectionSpacer() + SectionDividerSpaced() UseServerSection(valid.value, testing, server, testServer, onUpdate, onDelete) - SectionSpacer() if (valid.value) { + SectionDividerSpaced() SectionView(stringResource(R.string.smp_servers_add_to_another_device).uppercase()) { QRCode(serverAddress.value, Modifier.aspectRatio(1f)) } } + SectionSpacer() } @Composable @@ -176,12 +177,8 @@ private fun UseServerSection( Text(stringResource(R.string.smp_servers_test_server), color = if (valid && !testing) MaterialTheme.colors.onBackground else HighOrLowlight) ShowTestStatus(server) } - SectionDivider() - SectionItemView { - val enabled = rememberUpdatedState(server.enabled) - PreferenceToggle(stringResource(R.string.smp_servers_use_server_for_new_conn), enabled.value) { onUpdate(server.copy(enabled = it)) } - } - SectionDivider() + val enabled = rememberUpdatedState(server.enabled) + PreferenceToggle(stringResource(R.string.smp_servers_use_server_for_new_conn), enabled.value) { onUpdate(server.copy(enabled = it)) } SectionItemView(onDelete, disabled = testing) { Text(stringResource(R.string.smp_servers_delete_server), color = if (testing) HighOrLowlight else MaterialTheme.colors.error) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServersView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServersView.kt index 2b7224f8e9..019da7ecfa 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServersView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/ProtocolServersView.kt @@ -1,8 +1,7 @@ package chat.simplex.app.views.usersettings -import SectionDivider +import SectionDividerSpaced import SectionItemView -import SectionSpacer import SectionTextFooter import SectionView import androidx.compose.foundation.* @@ -92,7 +91,6 @@ fun ProtocolServersView(m: ChatModel, serverProtocol: ServerProtocol, close: () if (saveDisabled.value) close() else showUnsavedChangesAlert({ saveServers(serverProtocol, currServers, servers, m, close) }, close) }, - background = if (isInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight ) { ProtocolServersLayout( serverProtocol, @@ -204,7 +202,6 @@ private fun ProtocolServersLayout( SectionItemView({ showServer(srv) }, disabled = testing) { ProtocolServerView(serverProtocol, srv, servers, testing) } - SectionDivider() } SettingsActionItem( Icons.Outlined.Add, @@ -226,22 +223,20 @@ private fun ProtocolServersLayout( } } ) - SectionSpacer() + SectionDividerSpaced() SectionView { SectionItemView(resetServers, disabled = serversUnchanged) { Text(stringResource(R.string.reset_verb), color = if (!serversUnchanged) MaterialTheme.colors.onBackground else HighOrLowlight) } - SectionDivider() val testServersDisabled = testing || allServersDisabled SectionItemView(testServers, disabled = testServersDisabled) { Text(stringResource(R.string.smp_servers_test_servers), color = if (!testServersDisabled) MaterialTheme.colors.onBackground else HighOrLowlight) } - SectionDivider() SectionItemView(saveSMPServers, disabled = saveDisabled) { Text(stringResource(R.string.smp_servers_save), color = if (!saveDisabled) MaterialTheme.colors.onBackground else HighOrLowlight) } } - SectionSpacer() + SectionDividerSpaced() SectionView { HowToButton() } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt index 5d84a78f75..f18bb1ca7e 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt @@ -1,12 +1,12 @@ package chat.simplex.app.views.usersettings -import SectionDivider +import SectionDividerSpaced import SectionItemView -import SectionSpacer +import SectionItemViewWithIcon import SectionView +import TextIconSpaced import android.content.Context import android.content.res.Configuration -import androidx.activity.compose.BackHandler import androidx.compose.foundation.* import androidx.compose.foundation.layout.* import androidx.compose.material.* @@ -22,9 +22,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.* import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.capitalize import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.intl.Locale import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.* @@ -33,7 +31,6 @@ import chat.simplex.app.* import chat.simplex.app.R import chat.simplex.app.model.* import chat.simplex.app.ui.theme.* -import chat.simplex.app.views.TerminalView import chat.simplex.app.views.database.DatabaseView import chat.simplex.app.views.helpers.* import chat.simplex.app.views.newchat.CreateLinkTab @@ -66,7 +63,6 @@ fun SettingsView(chatModel: ChatModel, setPerformLA: (Boolean, FragmentActivity) val search = rememberSaveable { mutableStateOf("") } ModalView( { close() }, - if (isInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight, endButtons = { SearchTextField(Modifier.fillMaxWidth(), stringResource(android.R.string.search_go), alwaysVisible = true) { search.value = it } }, @@ -135,78 +131,58 @@ fun SettingsLayout( withAuth: (block: () -> Unit) -> Unit ) { val uriHandler = LocalUriHandler.current - Surface(Modifier.fillMaxSize().verticalScroll(rememberScrollState())) { + Box(Modifier.fillMaxSize().verticalScroll(rememberScrollState()).background(MaterialTheme.colors.background)) { Column( Modifier .fillMaxSize() - .background(if (isInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight) .padding(top = DEFAULT_PADDING) ) { - Text( - stringResource(R.string.your_settings), - style = MaterialTheme.typography.h1, - modifier = Modifier.padding(horizontal = DEFAULT_PADDING), - overflow = TextOverflow.Ellipsis, - ) + AppBarTitle(stringResource(R.string.your_settings)) Spacer(Modifier.height(30.dp)) SectionView(stringResource(R.string.settings_section_title_you)) { SectionItemView(showCustomModal { chatModel, close -> UserProfileView(chatModel, close) }, 80.dp, disabled = stopped) { + Spacer(Modifier.width(2.dp)) ProfilePreview(profile, stopped = stopped) + Spacer(Modifier.width(2.dp)) } - SectionDivider() val profileHidden = rememberSaveable { mutableStateOf(false) } - SettingsActionItem(Icons.Outlined.ManageAccounts, stringResource(R.string.your_chat_profiles), { withAuth { showSettingsModalWithSearch { it, search -> UserProfilesView(it, search, profileHidden) } } }, disabled = stopped) - SectionDivider() + SettingsActionItem(Icons.Outlined.ManageAccounts, stringResource(R.string.your_chat_profiles), { withAuth { showSettingsModalWithSearch { it, search -> UserProfilesView(it, search, profileHidden) } } }, disabled = stopped, extraPadding = true) SettingsIncognitoActionItem(incognitoPref, incognito, stopped) { showModal { IncognitoView() }() } - SectionDivider() - SettingsActionItem(Icons.Outlined.QrCode, stringResource(R.string.your_simplex_contact_address), showModal { CreateLinkView(it, CreateLinkTab.LONG_TERM) }, disabled = stopped) - SectionDivider() + SettingsActionItem(Icons.Outlined.QrCode, stringResource(R.string.your_simplex_contact_address), showModal { CreateLinkView(it, CreateLinkTab.LONG_TERM) }, disabled = stopped, extraPadding = true) ChatPreferencesItem(showCustomModal, stopped = stopped) } - SectionSpacer() + SectionDividerSpaced() SectionView(stringResource(R.string.settings_section_title_settings)) { - SettingsActionItem(Icons.Outlined.Bolt, stringResource(R.string.notifications), showSettingsModal { NotificationsSettingsView(it) }, disabled = stopped) - SectionDivider() - SettingsActionItem(Icons.Outlined.WifiTethering, stringResource(R.string.network_and_servers), showSettingsModal { NetworkAndServersView(it, showModal, showSettingsModal, showCustomModal) }, disabled = stopped) - SectionDivider() - SettingsActionItem(Icons.Outlined.Videocam, stringResource(R.string.settings_audio_video_calls), showSettingsModal { CallSettingsView(it, showModal) }, disabled = stopped) - SectionDivider() - SettingsActionItem(Icons.Outlined.Lock, stringResource(R.string.privacy_and_security), showSettingsModal { PrivacySettingsView(it, showSettingsModal, setPerformLA) }, disabled = stopped) - SectionDivider() - SettingsActionItem(Icons.Outlined.LightMode, stringResource(R.string.appearance_settings), showSettingsModal { AppearanceView(it) }, disabled = stopped) - SectionDivider() + SettingsActionItem(Icons.Outlined.Bolt, stringResource(R.string.notifications), showSettingsModal { NotificationsSettingsView(it) }, disabled = stopped, extraPadding = true) + SettingsActionItem(Icons.Outlined.WifiTethering, stringResource(R.string.network_and_servers), showSettingsModal { NetworkAndServersView(it, showModal, showSettingsModal, showCustomModal) }, disabled = stopped, extraPadding = true) + SettingsActionItem(Icons.Outlined.Videocam, stringResource(R.string.settings_audio_video_calls), showSettingsModal { CallSettingsView(it, showModal) }, disabled = stopped, extraPadding = true) + SettingsActionItem(Icons.Outlined.Lock, stringResource(R.string.privacy_and_security), showSettingsModal { PrivacySettingsView(it, showSettingsModal, setPerformLA) }, disabled = stopped, extraPadding = true) + SettingsActionItem(Icons.Outlined.LightMode, stringResource(R.string.appearance_settings), showSettingsModal { AppearanceView(it) }, disabled = stopped, extraPadding = true) DatabaseItem(encrypted, showSettingsModal { DatabaseView(it, showSettingsModal) }, stopped) } - SectionSpacer() + SectionDividerSpaced() SectionView(stringResource(R.string.settings_section_title_help)) { - SettingsActionItem(Icons.Outlined.HelpOutline, stringResource(R.string.how_to_use_simplex_chat), showModal { HelpView(userDisplayName) }, disabled = stopped) - SectionDivider() - SettingsActionItem(Icons.Outlined.Add, stringResource(R.string.whats_new), showCustomModal { _, close -> WhatsNewView(viaSettings = true, close) }, disabled = stopped) - SectionDivider() - SettingsActionItem(Icons.Outlined.Info, stringResource(R.string.about_simplex_chat), showModal { SimpleXInfo(it, onboarding = false) }) - SectionDivider() - SettingsActionItem(Icons.Outlined.Tag, stringResource(R.string.chat_with_the_founder), { uriHandler.openUriCatching(simplexTeamUri) }, textColor = MaterialTheme.colors.primary, disabled = stopped) - SectionDivider() - SettingsActionItem(Icons.Outlined.Email, stringResource(R.string.send_us_an_email), { uriHandler.openUriCatching("mailto:chat@simplex.chat") }, textColor = MaterialTheme.colors.primary) + SettingsActionItem(Icons.Outlined.HelpOutline, stringResource(R.string.how_to_use_simplex_chat), showModal { HelpView(userDisplayName) }, disabled = stopped, extraPadding = true) + SettingsActionItem(Icons.Outlined.Add, stringResource(R.string.whats_new), showCustomModal { _, close -> WhatsNewView(viaSettings = true, close) }, disabled = stopped, extraPadding = true) + SettingsActionItem(Icons.Outlined.Info, stringResource(R.string.about_simplex_chat), showModal { SimpleXInfo(it, onboarding = false) }, extraPadding = true) + SettingsActionItem(Icons.Outlined.Tag, stringResource(R.string.chat_with_the_founder), { uriHandler.openUriCatching(simplexTeamUri) }, textColor = MaterialTheme.colors.primary, disabled = stopped, extraPadding = true) + SettingsActionItem(Icons.Outlined.Email, stringResource(R.string.send_us_an_email), { uriHandler.openUriCatching("mailto:chat@simplex.chat") }, textColor = MaterialTheme.colors.primary, extraPadding = true) } - SectionSpacer() + SectionDividerSpaced() SectionView(stringResource(R.string.settings_section_title_support)) { ContributeItem(uriHandler) - SectionDivider() RateAppItem(uriHandler) - SectionDivider() StarOnGithubItem(uriHandler) } - SectionSpacer() + SectionDividerSpaced() SectionView(stringResource(R.string.settings_section_title_develop)) { - SettingsActionItem(Icons.Outlined.Code, stringResource(R.string.settings_developer_tools), showSettingsModal { DeveloperView(it, showCustomModal, withAuth) }) - SectionDivider() + SettingsActionItem(Icons.Outlined.Code, stringResource(R.string.settings_developer_tools), showSettingsModal { DeveloperView(it, showCustomModal, withAuth) }, extraPadding = true) AppVersionItem(showVersion) } } @@ -251,18 +227,18 @@ fun MaintainIncognitoState(chatModel: ChatModel) { } @Composable private fun DatabaseItem(encrypted: Boolean, openDatabaseView: () -> Unit, stopped: Boolean) { - SectionItemView(openDatabaseView) { + SectionItemViewWithIcon(openDatabaseView) { Row( Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween ) { - Row { + Row(Modifier.weight(1f)) { Icon( Icons.Outlined.FolderOpen, contentDescription = stringResource(R.string.database_passphrase_and_export), tint = if (encrypted) HighOrLowlight else WarningOrange, ) - Spacer(Modifier.padding(horizontal = 4.dp)) + TextIconSpaced(true) Text(stringResource(R.string.database_passphrase_and_export)) } if (stopped) { @@ -288,7 +264,8 @@ fun MaintainIncognitoState(chatModel: ChatModel) { }() } }), - disabled = stopped + disabled = stopped, + extraPadding = true ) } @@ -300,39 +277,31 @@ fun ChatLockItem( ) { val performLA = remember { chatModel.performLA } val currentLAMode = remember { chatModel.controller.appPrefs.laMode } - SectionItemView(showSettingsModal { SimplexLockView(chatModel, currentLAMode, setPerformLA) }) { - Row(verticalAlignment = Alignment.CenterVertically) { - Icon( - if (performLA.value) Icons.Filled.Lock else Icons.Outlined.Lock, - contentDescription = stringResource(R.string.chat_lock), - tint = if (performLA.value) SimplexGreen else HighOrLowlight, - ) - Spacer(Modifier.padding(horizontal = 4.dp)) - Text( - stringResource(R.string.chat_lock), Modifier - .padding(end = 24.dp) - .fillMaxWidth() - .weight(1F) - ) - Text(if (performLA.value) remember { currentLAMode.state }.value.text else generalGetString(androidx.compose.ui.R.string.off), color = HighOrLowlight) - } + SettingsActionItemWithContent( + click = showSettingsModal { SimplexLockView(chatModel, currentLAMode, setPerformLA) }, + icon = if (performLA.value) Icons.Filled.Lock else Icons.Outlined.Lock, + text = stringResource(R.string.chat_lock), + iconColor = if (performLA.value) SimplexGreen else HighOrLowlight, + extraPadding = false, + ) { + Text(if (performLA.value) remember { currentLAMode.state }.value.text else generalGetString(androidx.compose.ui.R.string.off), color = HighOrLowlight) } } @Composable private fun ContributeItem(uriHandler: UriHandler) { - SectionItemView({ uriHandler.openUriCatching("https://github.com/simplex-chat/simplex-chat#contribute") }) { + SectionItemViewWithIcon({ uriHandler.openUriCatching("https://github.com/simplex-chat/simplex-chat#contribute") }) { Icon( Icons.Outlined.Keyboard, contentDescription = "GitHub", tint = HighOrLowlight, ) - Spacer(Modifier.padding(horizontal = 4.dp)) + TextIconSpaced(extraPadding = true) Text(generalGetString(R.string.contribute), color = MaterialTheme.colors.primary) } } @Composable private fun RateAppItem(uriHandler: UriHandler) { - SectionItemView({ + SectionItemViewWithIcon({ runCatching { uriHandler.openUriCatching("market://details?id=chat.simplex.app") } .onFailure { uriHandler.openUriCatching("https://play.google.com/store/apps/details?id=chat.simplex.app") } } @@ -342,19 +311,19 @@ fun ChatLockItem( contentDescription = "Google Play", tint = HighOrLowlight, ) - Spacer(Modifier.padding(horizontal = 4.dp)) + TextIconSpaced(extraPadding = true) Text(generalGetString(R.string.rate_the_app), color = MaterialTheme.colors.primary) } } @Composable private fun StarOnGithubItem(uriHandler: UriHandler) { - SectionItemView({ uriHandler.openUriCatching("https://github.com/simplex-chat/simplex-chat") }) { + SectionItemViewWithIcon({ uriHandler.openUriCatching("https://github.com/simplex-chat/simplex-chat") }) { Icon( painter = painterResource(id = R.drawable.ic_github), contentDescription = "GitHub", tint = HighOrLowlight, ) - Spacer(Modifier.padding(horizontal = 4.dp)) + TextIconSpaced(extraPadding = true) Text(generalGetString(R.string.star_on_github), color = MaterialTheme.colors.primary) } } @@ -366,7 +335,7 @@ fun ChatLockItem( contentDescription = stringResource(R.string.chat_console), tint = HighOrLowlight, ) - Spacer(Modifier.padding(horizontal = 4.dp)) + TextIconSpaced() Text(stringResource(R.string.chat_console)) } } @@ -378,13 +347,13 @@ fun ChatLockItem( contentDescription = "GitHub", tint = HighOrLowlight, ) - Spacer(Modifier.padding(horizontal = 4.dp)) + TextIconSpaced() Text(generalGetString(R.string.install_simplex_chat_for_terminal), color = MaterialTheme.colors.primary) } } @Composable private fun AppVersionItem(showVersion: () -> Unit) { - SectionItemView(showVersion) { AppVersionText() } + SectionItemViewWithIcon(showVersion) { AppVersionText() } } @Composable fun AppVersionText() { @@ -393,7 +362,7 @@ fun ChatLockItem( @Composable fun ProfilePreview(profileOf: NamedChat, size: Dp = 60.dp, color: Color = MaterialTheme.colors.secondary, stopped: Boolean = false) { ProfileImage(size = size, image = profileOf.image, color = color) - Spacer(Modifier.padding(horizontal = 4.dp)) + Spacer(Modifier.padding(horizontal = DEFAULT_PADDING_HALF)) Column { Text( profileOf.displayName, @@ -413,28 +382,45 @@ fun ChatLockItem( } @Composable -fun SettingsActionItem(icon: ImageVector, text: String, click: (() -> Unit)? = null, textColor: Color = Color.Unspecified, iconColor: Color = HighOrLowlight, disabled: Boolean = false) { - SectionItemView(click, disabled = disabled) { +fun SettingsActionItem(icon: ImageVector, text: String, click: (() -> Unit)? = null, textColor: Color = Color.Unspecified, iconColor: Color = HighOrLowlight, disabled: Boolean = false, extraPadding: Boolean = false) { + SectionItemView(click, disabled = disabled, extraPadding = extraPadding) { Icon(icon, text, tint = if (disabled) HighOrLowlight else iconColor) - Spacer(Modifier.padding(horizontal = 4.dp)) + TextIconSpaced(extraPadding) Text(text, color = if (disabled) HighOrLowlight else textColor) } } +@Composable +fun SettingsActionItemWithContent(icon: ImageVector?, text: String? = null, click: (() -> Unit)? = null, iconColor: Color = HighOrLowlight, disabled: Boolean = false, extraPadding: Boolean = false, content: @Composable RowScope.() -> Unit) { + SectionItemView( + click, + extraPadding = extraPadding, + padding = if (extraPadding && icon != null) PaddingValues(start = DEFAULT_PADDING * 2, end = DEFAULT_PADDING) else PaddingValues(horizontal = DEFAULT_PADDING), + disabled = disabled + ) { + if (icon != null) { + Icon(icon, text, tint = if (disabled) HighOrLowlight else iconColor) + TextIconSpaced(extraPadding) + } + if (text != null) { + Text(text, Modifier.weight(1f), color = if (disabled) HighOrLowlight else MaterialTheme.colors.onBackground) + Spacer(Modifier.width(DEFAULT_PADDING)) + } + content() + } +} + @Composable fun SettingsPreferenceItem( - icon: ImageVector, + icon: ImageVector?, text: String, pref: SharedPreference, - prefState: MutableState? = null, + iconColor: Color = HighOrLowlight, + enabled: Boolean = true, onChange: ((Boolean) -> Unit)? = null, ) { - SectionItemView { - Row(verticalAlignment = Alignment.CenterVertically) { - Icon(icon, text, tint = HighOrLowlight) - Spacer(Modifier.padding(horizontal = 4.dp)) - SharedPreferenceToggle(text, pref, prefState, onChange) - } + SettingsActionItemWithContent(icon, text, iconColor = iconColor,) { + SharedPreferenceToggle(pref, enabled, onChange) } } @@ -448,12 +434,8 @@ fun SettingsPreferenceItemWithInfo( pref: SharedPreference, prefState: MutableState? = null ) { - SectionItemView(if (stopped) null else onClickInfo) { - Row(verticalAlignment = Alignment.CenterVertically) { - Icon(icon, text, tint = if (stopped) HighOrLowlight else iconTint) - Spacer(Modifier.padding(horizontal = 4.dp)) - SharedPreferenceToggleWithIcon(text, Icons.Outlined.Info, stopped, onClickInfo, pref, prefState) - } + SettingsActionItemWithContent(icon, null, click = if (stopped) null else onClickInfo, iconColor = iconTint, extraPadding = true,) { + SharedPreferenceToggleWithIcon(text, Icons.Outlined.Info, stopped, onClickInfo, pref, prefState) } } @@ -463,9 +445,7 @@ fun PreferenceToggle( checked: Boolean, onChange: (Boolean) -> Unit = {}, ) { - Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { - Text(text) - Spacer(Modifier.fillMaxWidth().weight(1f)) + SettingsActionItemWithContent(null, text, extraPadding = true,) { Switch( checked = checked, onCheckedChange = onChange, @@ -483,19 +463,10 @@ fun PreferenceToggleWithIcon( icon: ImageVector? = null, iconColor: Color? = HighOrLowlight, checked: Boolean, + extraPadding: Boolean = false, onChange: (Boolean) -> Unit = {}, ) { - Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { - if (icon != null) { - Icon( - icon, - null, - tint = iconColor ?: HighOrLowlight - ) - Spacer(Modifier.padding(horizontal = 4.dp)) - } - Text(text) - Spacer(Modifier.fillMaxWidth().weight(1f)) + SettingsActionItemWithContent(icon, text, iconColor = iconColor ?: HighOrLowlight, extraPadding = extraPadding) { Switch( checked = checked, onCheckedChange = { diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserAddressView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserAddressView.kt index 3dd48d53de..7352fda18d 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserAddressView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserAddressView.kt @@ -90,7 +90,7 @@ fun UserAddressLayout( Row( horizontalArrangement = Arrangement.spacedBy(10.dp), verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.padding(vertical = 16.dp) + modifier = Modifier.padding(vertical = DEFAULT_PADDING) ) { SimpleButton( stringResource(R.string.share_link), diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserProfileView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserProfileView.kt index 8d9a7b4c11..b6310c3467 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserProfileView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserProfileView.kt @@ -102,7 +102,7 @@ fun UserProfileLayout( .padding(horizontal = DEFAULT_PADDING), horizontalAlignment = Alignment.Start ) { - AppBarTitleCentered(stringResource(R.string.your_current_profile)) + AppBarTitle(stringResource(R.string.your_current_profile)) ReadableText(generalGetString(R.string.your_profile_is_stored_on_device_and_shared_only_with_contacts_simplex_cannot_see_it), TextAlign.Center) Column( Modifier diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserProfilesView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserProfilesView.kt index d8f7f11c1a..5587cecb30 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserProfilesView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/UserProfilesView.kt @@ -217,7 +217,7 @@ private fun UserView( UserProfilePickerItem(user, onLongClick = { if (users.size > 1) showMenu.value = true }) { activateUser(user) } - Box(Modifier.padding(horizontal = 16.dp)) { + Box(Modifier.padding(horizontal = DEFAULT_PADDING)) { DefaultDropdownMenu(showMenu) { if (user.hidden) { ItemAction(stringResource(R.string.user_unhide), Icons.Outlined.LockOpen, onClick = {