diff --git a/README.md b/README.md
index 06c1f62a0f..c27637dd43 100644
--- a/README.md
+++ b/README.md
@@ -48,7 +48,23 @@
## Join user groups
-You can join an English-speaking users group if you want to ask any questions: [#SimpleX-Group-3](https://simplex.chat/contact#/?v=1-2&smp=smp%3A%2F%2Fhpq7_4gGJiilmz5Rf-CswuU5kZGkm_zOIooSw6yALRg%3D%40smp5.simplex.im%2FeDEgekVhh0zIBYvUupGWZ96kiBEMbXwK%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAS7Z3zQyOhZ9o1qzI9OTZRySpkFTagdLMa6Rc7opuNh4%253D%26srv%3Djjbyvoemxysm7qxap7m5d5m35jzv5qq6gnlv7s4rsn7tdwwmuqciwpid.onion&data=%7B%22type%22%3A%22group%22%2C%22groupLinkId%22%3A%22cG3W1qxZGzyrvHTugx16bg%3D%3D%22%7D)
+**Please note**: The groups below are created for the users to be able to ask questions, make suggestions and ask questions about SimpleX Chat only.
+
+You also can:
+- criticize the app, and make comparisons with other messengers.
+- share new messengers you think could be interesting for privacy, as long as you don't spam.
+- share some privacy related publications, infrequently.
+- having preliminary approved with the admin in direct message, share the link to a group you created.
+
+You must:
+- be polite to other users
+- avoid spam (too frequent messages, even if they are relevant)
+- avoid any personal attacks or hostility.
+- avoid sharing any content that is not relevant to the above (that includes, but is not limited to, discussing politics or any aspects of society other than privacy, security, technology and communications, sharing any content that may be found offensive by other users, etc.).
+
+Messages not following these rules will be deleted, the right to send messages may be revoked, and the access to the new members to the group may be temporarily restricted, to prevent re-joining under a different name - our imperfect group moderation does not have a better solution at the moment.
+
+You can join an English-speaking users group if you want to ask any questions: [#SimpleX-Group-3](https://simplex.chat/contact#/?v=1-2&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2Fp-j-D_PrY2UMDchFHEUtbSES0nmzCnvD%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEA3gBfMjB_GDEmKQwjNdqGbnX91yfuZ7nRJgQijsx5Khc%253D%26srv%3Dbylepyau3ty4czmn77q4fglvperknl4bi2eb2fdy2bh4jxtf32kf73yd.onion&data=%7B%22type%22%3A%22group%22%2C%22groupLinkId%22%3A%2262MvNZ_Ec2mmlS8V0QNtLQ%3D%3D%22%7D)
There are groups in other languages, that we have the apps interface translated into. These groups are for testing, and asking questions to other SimpleX Chat users:
@@ -181,6 +197,8 @@ You can use SimpleX with your own servers and still communicate with people usin
Recent updates:
+[Apr 22, 2023. SimpleX Chat: vision and funding, v5.0 released with videos and files up to 1gb](./blog/20230422-simplex-chat-vision-funding-v5-videos-files-passcode.md).
+
[Mar 28, 2023. v4.6 released - with Android 8+ and ARMv7a support, hidden profiles, community moderation, improved audio/video calls and reduced battery usage](./blog/20230328-simplex-chat-v4-6-hidden-profiles.md).
[Mar 1, 2023. SimpleX File Transfer Protocol – send large files efficiently, privately and securely, soon to be integrated into SimpleX Chat apps.](./blog/20230301-simplex-file-transfer-protocol.md).
@@ -295,13 +313,15 @@ If you are considering developing with SimpleX platform please get in touch for
- ✅ Improved audio & video calls.
- ✅ Support older Android OS and 32-bit CPUs.
- ✅ Hidden chat profiles.
-- 🏗 Sending and receiving large files via [XFTP protocol](./blog/20230301-simplex-file-transfer-protocol.md).
-- 🏗 Video messages.
+- ✅ Sending and receiving large files via [XFTP protocol](./blog/20230301-simplex-file-transfer-protocol.md).
+- ✅ Video messages.
+- ✅ App access passcode.
+- 🏗 Improved Android app UI design.
- 🏗 SMP queue redundancy and rotation (manual is supported).
- 🏗 Reduced battery and traffic usage in large groups.
- Include optional message into connection request sent via contact address.
- Ephemeral/disappearing/OTR conversations with the existing contacts.
-- Access password/pin (with optional alternative access password).
+- Optional alternative access password.
- Local app files encryption.
- Improved navigation and search in the conversation (expand and scroll to quoted message, scroll to search results, etc.).
- Message delivery confirmation (with sender opt-in or opt-out per contact, TBC).
diff --git a/apps/android/app/build.gradle b/apps/android/app/build.gradle
index f2d84c246c..0a256bbb99 100644
--- a/apps/android/app/build.gradle
+++ b/apps/android/app/build.gradle
@@ -119,7 +119,7 @@ dependencies {
implementation 'androidx.fragment:fragment:1.4.1'
implementation 'org.jetbrains.kotlinx:kotlinx-datetime:0.3.2'
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2'
- implementation "androidx.compose.material:material-icons-extended:$compose_version"
+ //implementation "androidx.compose.material:material-icons-extended:$compose_version"
implementation "androidx.compose.ui:ui-util:$compose_version"
implementation "androidx.navigation:navigation-compose:2.4.1"
implementation "com.google.accompanist:accompanist-insets:0.23.0"
diff --git a/apps/android/app/src/main/java/chat/simplex/app/MainActivity.kt b/apps/android/app/src/main/java/chat/simplex/app/MainActivity.kt
index 1e7641df3c..953b598630 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/MainActivity.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/MainActivity.kt
@@ -13,13 +13,12 @@ import androidx.compose.animation.core.*
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.Lock
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.fragment.app.FragmentActivity
@@ -426,7 +425,7 @@ fun MainPage(
) {
SimpleButton(
stringResource(R.string.auth_unlock),
- icon = Icons.Outlined.Lock,
+ icon = painterResource(R.drawable.ic_lock),
click = {
laFailed.value = false
runAuthenticate()
diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt b/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt
index adda558d29..0f54b42d8c 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt
@@ -2,11 +2,10 @@ package chat.simplex.app.model
import android.net.Uri
import androidx.compose.material.MaterialTheme
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.*
import androidx.compose.runtime.*
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.painter.Painter
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.font.*
import androidx.compose.ui.text.style.TextDecoration
@@ -1517,12 +1516,12 @@ data class CIMeta (
val isRcvNew: Boolean get() = itemStatus is CIStatus.RcvNew
- fun statusIcon(primaryColor: Color, metaColor: Color = HighOrLowlight): Pair? =
+ fun statusIcon(primaryColor: Color, metaColor: Color = HighOrLowlight): Pair? =
when (itemStatus) {
- is CIStatus.SndSent -> Icons.Filled.Check to metaColor
- is CIStatus.SndErrorAuth -> Icons.Filled.Close to Color.Red
- is CIStatus.SndError -> Icons.Filled.WarningAmber to WarningYellow
- is CIStatus.RcvNew -> Icons.Filled.Circle to primaryColor
+ is CIStatus.SndSent -> R.drawable.ic_check_filled to metaColor
+ is CIStatus.SndErrorAuth -> R.drawable.ic_close to Color.Red
+ is CIStatus.SndError -> R.drawable.ic_warning_filled to WarningYellow
+ is CIStatus.RcvNew -> R.drawable.ic_circle_filled to primaryColor
else -> null
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt b/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt
index 6937cc7f1e..1fe7e1aa1a 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt
@@ -9,14 +9,13 @@ import android.provider.Settings
import android.util.Log
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.*
-import androidx.compose.material.icons.outlined.*
+import chat.simplex.app.views.helpers.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.toArgb
-import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
@@ -24,7 +23,6 @@ import chat.simplex.app.*
import chat.simplex.app.R
import chat.simplex.app.ui.theme.*
import chat.simplex.app.views.call.*
-import chat.simplex.app.views.helpers.*
import chat.simplex.app.views.newchat.ConnectViaLinkTab
import chat.simplex.app.views.onboarding.OnboardingStage
import chat.simplex.app.views.usersettings.*
@@ -1633,7 +1631,7 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a
title = {
Row {
Icon(
- Icons.Outlined.Bolt,
+ painterResource(R.drawable.ic_bolt),
contentDescription =
if (mode == NotificationsMode.SERVICE) stringResource(R.string.icon_descr_instant_notifications) else stringResource(R.string.periodic_notifications),
)
@@ -1670,7 +1668,7 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a
title = {
Row {
Icon(
- Icons.Outlined.Bolt,
+ painterResource(R.drawable.ic_bolt),
contentDescription =
if (mode == NotificationsMode.SERVICE) stringResource(R.string.icon_descr_instant_notifications) else stringResource(R.string.periodic_notifications),
)
@@ -1701,7 +1699,7 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a
title = {
Row {
Icon(
- Icons.Outlined.Bolt,
+ painterResource(R.drawable.ic_bolt),
contentDescription =
if (mode == NotificationsMode.SERVICE) stringResource(R.string.icon_descr_instant_notifications) else stringResource(R.string.periodic_notifications),
)
@@ -2628,7 +2626,8 @@ sealed class ContactUserPrefTimed {
interface Feature {
// val icon: ImageVector
val text: String
- val iconFilled: ImageVector
+ @Composable
+ fun iconFilled(): Painter
val hasParam: Boolean
}
@@ -2657,21 +2656,21 @@ enum class ChatFeature: Feature {
Calls -> generalGetString(R.string.audio_video_calls)
}
- val icon: ImageVector
- get() = when(this) {
- TimedMessages -> Icons.Outlined.Timer
- FullDelete -> Icons.Outlined.DeleteForever
- Voice -> Icons.Outlined.KeyboardVoice
- Calls -> Icons.Outlined.Phone
+ val icon: Painter
+ @Composable get() = when(this) {
+ TimedMessages -> painterResource(R.drawable.ic_timer)
+ FullDelete -> painterResource(R.drawable.ic_delete_forever)
+ Voice -> painterResource(R.drawable.ic_keyboard_voice)
+ Calls -> painterResource(R.drawable.ic_call)
}
- override val iconFilled: ImageVector
- get() = when(this) {
- TimedMessages -> Icons.Filled.Timer
- FullDelete -> Icons.Filled.DeleteForever
- Voice -> Icons.Filled.KeyboardVoice
- Calls -> Icons.Filled.Phone
- }
+ @Composable
+ override fun iconFilled(): Painter = when(this) {
+ TimedMessages -> painterResource(R.drawable.ic_timer_filled)
+ FullDelete -> painterResource(R.drawable.ic_delete_forever_filled)
+ Voice -> painterResource(R.drawable.ic_keyboard_voice_filled)
+ Calls -> painterResource(R.drawable.ic_call_filled)
+ }
fun allowDescription(allowed: FeatureAllowed): String =
when (this) {
@@ -2746,21 +2745,21 @@ enum class GroupFeature: Feature {
Voice -> generalGetString(R.string.voice_messages)
}
- val icon: ImageVector
- get() = when(this) {
- TimedMessages -> Icons.Outlined.Timer
- DirectMessages -> Icons.Outlined.SwapHorizontalCircle
- FullDelete -> Icons.Outlined.DeleteForever
- Voice -> Icons.Outlined.KeyboardVoice
+ val icon: Painter
+ @Composable get() = when(this) {
+ TimedMessages -> painterResource(R.drawable.ic_timer)
+ DirectMessages -> painterResource(R.drawable.ic_swap_horizontal_circle)
+ FullDelete -> painterResource(R.drawable.ic_delete_forever)
+ Voice -> painterResource(R.drawable.ic_keyboard_voice)
}
- override val iconFilled: ImageVector
- get() = when(this) {
- TimedMessages -> Icons.Filled.Timer
- DirectMessages -> Icons.Filled.SwapHorizontalCircle
- FullDelete -> Icons.Filled.DeleteForever
- Voice -> Icons.Filled.KeyboardVoice
- }
+ @Composable
+ override fun iconFilled(): Painter = when(this) {
+ TimedMessages -> painterResource(R.drawable.ic_timer_filled)
+ DirectMessages -> painterResource(R.drawable.ic_swap_horizontal_circle_filled)
+ FullDelete -> painterResource(R.drawable.ic_delete_forever_filled)
+ Voice -> painterResource(R.drawable.ic_keyboard_voice_filled)
+ }
fun enableDescription(enabled: GroupFeatureEnabled, canEdit: Boolean): String =
if (canEdit) {
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..e0187c60e4 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
@@ -13,12 +13,12 @@ val SimplexGreen = Color(77, 218, 103, 255)
val SecretColor = Color(0x40808080)
val LightGray = Color(241, 242, 246, 255)
val DarkGray = Color(43, 44, 46, 255)
+val DarkGrayBackground = Color(38, 38, 38, 255)
val HighOrLowlight = Color(139, 135, 134, 255)
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..cf9084ea1b 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
@@ -7,9 +7,6 @@ import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.*
import androidx.compose.material.MaterialTheme.colors
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.ArrowBackIosNew
-import androidx.compose.material.icons.outlined.ArrowForwardIos
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
@@ -17,6 +14,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.*
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
@@ -58,7 +56,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))
@@ -89,7 +87,7 @@ fun CreateProfilePanel(chatModel: ChatModel, close: () -> Unit) {
if (chatModel.users.isEmpty()) {
SimpleButtonDecorated(
text = stringResource(R.string.about_simplex),
- icon = Icons.Outlined.ArrowBackIosNew,
+ icon = painterResource(R.drawable.ic_arrow_back_ios_new),
textDecoration = TextDecoration.None,
fontWeight = FontWeight.Medium
) { chatModel.onboardingStage.value = OnboardingStage.Step1_SimpleXInfo }
@@ -108,7 +106,7 @@ fun CreateProfilePanel(chatModel: ChatModel, close: () -> Unit) {
Surface(shape = RoundedCornerShape(20.dp)) {
Row(verticalAlignment = Alignment.CenterVertically, modifier = createModifier) {
Text(stringResource(R.string.create_profile_button), style = MaterialTheme.typography.caption, color = createColor, fontWeight = FontWeight.Medium)
- Icon(Icons.Outlined.ArrowForwardIos, stringResource(R.string.create_profile_button), tint = createColor)
+ Icon(painterResource(R.drawable.ic_arrow_forward_ios), stringResource(R.string.create_profile_button), tint = createColor)
}
}
}
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..9025ba32db 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
@@ -16,17 +16,15 @@ import androidx.activity.compose.BackHandler
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.*
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.tooling.preview.Preview
@@ -263,7 +261,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)
@@ -272,14 +270,14 @@ private fun ActiveCallOverlayLayout(
ToggleAudioButton(call, toggleAudio)
Spacer(Modifier.size(40.dp))
IconButton(onClick = dismiss) {
- Icon(Icons.Filled.CallEnd, stringResource(R.string.icon_descr_hang_up), tint = Color.Red, modifier = Modifier.size(64.dp))
+ Icon(painterResource(R.drawable.ic_call_end_filled), stringResource(R.string.icon_descr_hang_up), tint = Color.Red, modifier = Modifier.size(64.dp))
}
if (call.videoEnabled) {
- ControlButton(call, Icons.Filled.FlipCameraAndroid, R.string.icon_descr_flip_camera, flipCamera)
- ControlButton(call, Icons.Filled.Videocam, R.string.icon_descr_video_off, toggleVideo)
+ ControlButton(call, painterResource(R.drawable.ic_flip_camera_android_filled), R.string.icon_descr_flip_camera, flipCamera)
+ ControlButton(call, painterResource(R.drawable.ic_videocam_filled), R.string.icon_descr_video_off, toggleVideo)
} else {
Spacer(Modifier.size(48.dp))
- ControlButton(call, Icons.Outlined.VideocamOff, R.string.icon_descr_video_on, toggleVideo)
+ ControlButton(call, painterResource(R.drawable.ic_videocam_off), R.string.icon_descr_video_on, toggleVideo)
}
}
}
@@ -297,7 +295,7 @@ private fun ActiveCallOverlayLayout(
Box(Modifier.fillMaxWidth().padding(bottom = DEFAULT_BOTTOM_PADDING), contentAlignment = Alignment.CenterStart) {
Box(Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
IconButton(onClick = dismiss) {
- Icon(Icons.Filled.CallEnd, stringResource(R.string.icon_descr_hang_up), tint = Color.Red, modifier = Modifier.size(64.dp))
+ Icon(painterResource(R.drawable.ic_call_end_filled), stringResource(R.string.icon_descr_hang_up), tint = Color.Red, modifier = Modifier.size(64.dp))
}
}
Box(Modifier.padding(start = 32.dp)) {
@@ -315,7 +313,7 @@ private fun ActiveCallOverlayLayout(
}
@Composable
-private fun ControlButton(call: Call, icon: ImageVector, @StringRes iconText: Int, action: () -> Unit, enabled: Boolean = true) {
+private fun ControlButton(call: Call, icon: Painter, @StringRes iconText: Int, action: () -> Unit, enabled: Boolean = true) {
if (call.hasMedia) {
IconButton(onClick = action, enabled = enabled) {
Icon(icon, stringResource(iconText), tint = if (enabled) Color(0xFFFFFFD8) else HighOrLowlight, modifier = Modifier.size(40.dp))
@@ -328,18 +326,18 @@ private fun ControlButton(call: Call, icon: ImageVector, @StringRes iconText: In
@Composable
private fun ToggleAudioButton(call: Call, toggleAudio: () -> Unit) {
if (call.audioEnabled) {
- ControlButton(call, Icons.Outlined.Mic, R.string.icon_descr_audio_off, toggleAudio)
+ ControlButton(call, painterResource(R.drawable.ic_mic), R.string.icon_descr_audio_off, toggleAudio)
} else {
- ControlButton(call, Icons.Outlined.MicOff, R.string.icon_descr_audio_on, toggleAudio)
+ ControlButton(call, painterResource(R.drawable.ic_mic_off), R.string.icon_descr_audio_on, toggleAudio)
}
}
@Composable
private fun ToggleSoundButton(call: Call, enabled: Boolean, toggleSound: () -> Unit) {
if (call.soundSpeaker) {
- ControlButton(call, Icons.Outlined.VolumeUp, R.string.icon_descr_speaker_off, toggleSound, enabled)
+ ControlButton(call, painterResource(R.drawable.ic_volume_up), R.string.icon_descr_speaker_off, toggleSound, enabled)
} else {
- ControlButton(call, Icons.Outlined.VolumeDown, R.string.icon_descr_speaker_on, toggleSound, enabled)
+ ControlButton(call, painterResource(R.drawable.ic_volume_down), R.string.icon_descr_speaker_on, toggleSound, enabled)
}
}
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..55abc1a941 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
@@ -17,14 +17,12 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
@@ -171,18 +169,18 @@ fun IncomingCallLockScreenAlertLayout(
Text(invitation.contact.chatViewName, style = MaterialTheme.typography.h2)
Spacer(Modifier.fillMaxHeight().weight(1f))
Row {
- LockScreenCallButton(stringResource(R.string.reject), Icons.Filled.CallEnd, Color.Red, rejectCall)
+ LockScreenCallButton(stringResource(R.string.reject), painterResource(R.drawable.ic_call_end_filled), Color.Red, rejectCall)
Spacer(Modifier.size(48.dp))
- LockScreenCallButton(stringResource(R.string.ignore), Icons.Filled.Close, MaterialTheme.colors.primary, ignoreCall)
+ LockScreenCallButton(stringResource(R.string.ignore), painterResource(R.drawable.ic_close), MaterialTheme.colors.primary, ignoreCall)
Spacer(Modifier.size(48.dp))
- LockScreenCallButton(stringResource(R.string.accept), Icons.Filled.Check, SimplexGreen, acceptCall)
+ LockScreenCallButton(stringResource(R.string.accept), painterResource(R.drawable.ic_check_filled), SimplexGreen, acceptCall)
}
} else if (callOnLockScreen == CallOnLockScreen.SHOW) {
SimpleXLogo()
Text(stringResource(R.string.open_simplex_chat_to_accept_call), textAlign = TextAlign.Center, lineHeight = 22.sp)
Text(stringResource(R.string.allow_accepting_calls_from_lock_screen), textAlign = TextAlign.Center, style = MaterialTheme.typography.body2, lineHeight = 22.sp)
Spacer(Modifier.fillMaxHeight().weight(1f))
- SimpleButton(text = stringResource(R.string.open_verb), icon = Icons.Filled.Check, click = openApp)
+ SimpleButton(text = stringResource(R.string.open_verb), icon = painterResource(R.drawable.ic_check_filled), click = openApp)
}
}
}
@@ -199,7 +197,7 @@ private fun SimpleXLogo() {
}
@Composable
-private fun LockScreenCallButton(text: String, icon: ImageVector, color: Color, action: () -> Unit) {
+private fun LockScreenCallButton(text: String, icon: Painter, color: Color, action: () -> Unit) {
Surface(
shape = RoundedCornerShape(10.dp),
color = Color.Transparent
@@ -213,7 +211,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..56d57e1443 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
@@ -4,15 +4,14 @@ import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@@ -52,7 +51,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) {
@@ -60,9 +59,9 @@ fun IncomingCallAlertLayout(
ProfilePreview(profileOf = invitation.contact, size = 64.dp, color = Color.White)
}
Row(verticalAlignment = Alignment.CenterVertically) {
- CallButton(stringResource(R.string.reject), Icons.Filled.CallEnd, Color.Red, rejectCall)
- CallButton(stringResource(R.string.ignore), Icons.Filled.Close, MaterialTheme.colors.primary, ignoreCall)
- CallButton(stringResource(R.string.accept), Icons.Filled.Check, SimplexGreen, acceptCall)
+ CallButton(stringResource(R.string.reject), painterResource(R.drawable.ic_call_end_filled), Color.Red, rejectCall)
+ CallButton(stringResource(R.string.ignore), painterResource(R.drawable.ic_close), MaterialTheme.colors.primary, ignoreCall)
+ CallButton(stringResource(R.string.accept), painterResource(R.drawable.ic_check_filled), SimplexGreen, acceptCall)
}
}
}
@@ -70,21 +69,21 @@ fun IncomingCallAlertLayout(
@Composable
fun IncomingCallInfo(invitation: RcvCallInvitation, chatModel: ChatModel) {
- @Composable fun CallIcon(icon: ImageVector, descr: String) = Icon(icon, descr, tint = SimplexGreen)
+ @Composable fun CallIcon(icon: Painter, descr: String) = Icon(icon, descr, tint = SimplexGreen)
Row(verticalAlignment = Alignment.CenterVertically) {
if (chatModel.users.size > 1) {
ProfileImage(size = 32.dp, image = invitation.user.profile.image, color = MaterialTheme.colors.secondary)
Spacer(Modifier.width(4.dp))
}
- if (invitation.callType.media == CallMediaType.Video) CallIcon(Icons.Filled.Videocam, stringResource(R.string.icon_descr_video_call))
- else CallIcon(Icons.Filled.Phone, stringResource(R.string.icon_descr_audio_call))
+ if (invitation.callType.media == CallMediaType.Video) CallIcon(painterResource(R.drawable.ic_videocam_filled), stringResource(R.string.icon_descr_video_call))
+ else CallIcon(painterResource(R.drawable.ic_call_filled), stringResource(R.string.icon_descr_audio_call))
Spacer(Modifier.width(4.dp))
Text(invitation.callTypeText)
}
}
@Composable
-private fun CallButton(text: String, icon: ImageVector, color: Color, action: () -> Unit) {
+private fun CallButton(text: String, icon: Painter, color: Color, action: () -> Unit) {
Surface(
shape = RoundedCornerShape(10.dp),
color = Color.Transparent
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..c74b579f08 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,8 @@ package chat.simplex.app.views.chat
import InfoRow
import InfoRowEllipsis
-import SectionDivider
+import SectionBottomSpacer
+import SectionDividerSpaced
import SectionItemView
import SectionSpacer
import SectionView
@@ -12,9 +13,6 @@ import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.*
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
@@ -22,6 +20,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.ClipboardManager
import androidx.compose.ui.platform.LocalClipboardManager
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.TextStyle
@@ -168,8 +167,7 @@ fun ChatInfoLayout(
Column(
Modifier
.fillMaxWidth()
- .verticalScroll(rememberScrollState()),
- horizontalAlignment = Alignment.Start
+ .verticalScroll(rememberScrollState())
) {
Row(
Modifier.fillMaxWidth(),
@@ -179,28 +177,25 @@ fun ChatInfoLayout(
}
LocalAliasEditor(localAlias, updateValue = onLocalAliasChanged)
-
+ SectionSpacer()
if (customUserProfile != null) {
- SectionSpacer()
SectionView(generalGetString(R.string.incognito).uppercase()) {
InfoRow(generalGetString(R.string.incognito_random_profile), customUserProfile.chatViewName)
}
+ SectionDividerSpaced()
}
- SectionSpacer()
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 +206,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()
}
+ SectionBottomSpacer()
}
}
@@ -249,7 +240,7 @@ fun ChatInfoHeader(cInfo: ChatInfo, contact: Contact) {
ChatInfoImage(cInfo, size = 192.dp, iconColor = if (isInDarkTheme()) GroupDark else SettingsSecondaryLight)
Row(Modifier.padding(bottom = 8.dp), verticalAlignment = Alignment.CenterVertically) {
if (contact.verified) {
- Icon(Icons.Outlined.VerifiedUser, null, Modifier.padding(end = 6.dp, top = 4.dp).size(24.dp), tint = HighOrLowlight)
+ Icon(painterResource(R.drawable.ic_verified_user), null, Modifier.padding(end = 6.dp, top = 4.dp).size(24.dp), tint = HighOrLowlight)
}
Text(
contact.profile.displayName, style = MaterialTheme.typography.h1.copy(fontWeight = FontWeight.Normal),
@@ -294,7 +285,7 @@ fun LocalAliasEditor(
)
},
leadingIcon = if (leadingIcon) {
- { Icon(Icons.Default.Edit, null, Modifier.padding(start = 7.dp)) }
+ { Icon(painterResource(R.drawable.ic_edit_filled), null, Modifier.padding(start = 7.dp)) }
} else null,
color = HighOrLowlight,
focus = focus,
@@ -331,7 +322,7 @@ private fun NetworkStatusRow(networkStatus: NetworkStatus) {
) {
Text(stringResource(R.string.network_status))
Icon(
- Icons.Outlined.Info,
+ painterResource(R.drawable.ic_info),
stringResource(R.string.network_status),
tint = MaterialTheme.colors.primary
)
@@ -355,12 +346,12 @@ private fun ServerImage(networkStatus: NetworkStatus) {
Box(Modifier.size(18.dp)) {
when (networkStatus) {
is NetworkStatus.Connected ->
- Icon(Icons.Filled.Circle, stringResource(R.string.icon_descr_server_status_connected), tint = MaterialTheme.colors.primaryVariant)
+ Icon(painterResource(R.drawable.ic_circle_filled), stringResource(R.string.icon_descr_server_status_connected), tint = MaterialTheme.colors.primaryVariant)
is NetworkStatus.Disconnected ->
- Icon(Icons.Filled.Pending, stringResource(R.string.icon_descr_server_status_disconnected), tint = HighOrLowlight)
+ Icon(painterResource(R.drawable.ic_pending_filled), stringResource(R.string.icon_descr_server_status_disconnected), tint = HighOrLowlight)
is NetworkStatus.Error ->
- Icon(Icons.Filled.Error, stringResource(R.string.icon_descr_server_status_error), tint = HighOrLowlight)
- else -> Icon(Icons.Outlined.Circle, stringResource(R.string.icon_descr_server_status_pending), tint = HighOrLowlight)
+ Icon(painterResource(R.drawable.ic_error_filled), stringResource(R.string.icon_descr_server_status_error), tint = HighOrLowlight)
+ else -> Icon(painterResource(R.drawable.ic_circle), stringResource(R.string.icon_descr_server_status_pending), tint = HighOrLowlight)
}
}
}
@@ -385,7 +376,7 @@ fun SwitchAddressButton(onClick: () -> Unit) {
@Composable
fun VerifyCodeButton(contactVerified: Boolean, onClick: () -> Unit) {
SettingsActionItem(
- if (contactVerified) Icons.Outlined.VerifiedUser else Icons.Outlined.Shield,
+ if (contactVerified) painterResource(R.drawable.ic_verified_user) else painterResource(R.drawable.ic_shield),
stringResource(if (contactVerified) R.string.view_security_code else R.string.verify_security_code),
click = onClick,
iconColor = HighOrLowlight,
@@ -395,7 +386,7 @@ fun VerifyCodeButton(contactVerified: Boolean, onClick: () -> Unit) {
@Composable
private fun ContactPreferencesButton(onClick: () -> Unit) {
SettingsActionItem(
- Icons.Outlined.ToggleOn,
+ painterResource(R.drawable.ic_toggle_on),
stringResource(R.string.contact_preferences),
click = onClick
)
@@ -404,7 +395,7 @@ private fun ContactPreferencesButton(onClick: () -> Unit) {
@Composable
fun ClearChatButton(onClick: () -> Unit) {
SettingsActionItem(
- Icons.Outlined.Restore,
+ painterResource(R.drawable.ic_settings_backup_restore),
stringResource(R.string.clear_chat_button),
click = onClick,
textColor = WarningOrange,
@@ -415,7 +406,7 @@ fun ClearChatButton(onClick: () -> Unit) {
@Composable
private fun DeleteContactButton(onClick: () -> Unit) {
SettingsActionItem(
- Icons.Outlined.Delete,
+ painterResource(R.drawable.ic_delete),
stringResource(R.string.button_delete_contact),
click = onClick,
textColor = Color.Red,
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..1731ba49a6 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
@@ -12,9 +12,6 @@ import androidx.compose.foundation.lazy.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.*
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.mapSaver
import androidx.compose.runtime.saveable.rememberSaveable
@@ -23,6 +20,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
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
@@ -392,7 +390,7 @@ fun ChatInfoToolbar(
val barButtons = arrayListOf<@Composable RowScope.() -> Unit>()
val menuItems = arrayListOf<@Composable () -> Unit>()
menuItems.add {
- ItemAction(stringResource(android.R.string.search_go).capitalize(Locale.current), Icons.Outlined.Search, onClick = {
+ ItemAction(stringResource(android.R.string.search_go).capitalize(Locale.current), painterResource(R.drawable.ic_search), onClick = {
showMenu.value = false
showSearch = true
})
@@ -404,11 +402,11 @@ fun ChatInfoToolbar(
showMenu.value = false
startCall(CallMediaType.Audio)
}) {
- Icon(Icons.Outlined.Phone, stringResource(R.string.icon_descr_more_button), tint = MaterialTheme.colors.primary)
+ Icon(painterResource(R.drawable.ic_call_500), stringResource(R.string.icon_descr_more_button), tint = MaterialTheme.colors.primary)
}
}
menuItems.add {
- ItemAction(stringResource(R.string.icon_descr_video_call).capitalize(Locale.current), Icons.Outlined.Videocam, onClick = {
+ ItemAction(stringResource(R.string.icon_descr_video_call).capitalize(Locale.current), painterResource(R.drawable.ic_videocam), onClick = {
showMenu.value = false
startCall(CallMediaType.Video)
})
@@ -419,7 +417,7 @@ fun ChatInfoToolbar(
showMenu.value = false
addMembers(chat.chatInfo.groupInfo)
}) {
- Icon(Icons.Outlined.PersonAdd, stringResource(R.string.icon_descr_add_members), tint = MaterialTheme.colors.primary)
+ Icon(painterResource(R.drawable.ic_person_add_500), stringResource(R.string.icon_descr_add_members), tint = MaterialTheme.colors.primary)
}
}
}
@@ -427,7 +425,7 @@ fun ChatInfoToolbar(
menuItems.add {
ItemAction(
if (ntfsEnabled.value) stringResource(R.string.mute_chat) else stringResource(R.string.unmute_chat),
- if (ntfsEnabled.value) Icons.Outlined.NotificationsOff else Icons.Outlined.Notifications,
+ if (ntfsEnabled.value) painterResource(R.drawable.ic_notifications_off) else painterResource(R.drawable.ic_notifications),
onClick = {
showMenu.value = false
// Just to make a delay before changing state of ntfsEnabled, otherwise it will redraw menu item with new value before closing the menu
@@ -441,7 +439,7 @@ fun ChatInfoToolbar(
barButtons.add {
IconButton({ showMenu.value = true }) {
- Icon(Icons.Default.MoreVert, stringResource(R.string.icon_descr_more_button), tint = MaterialTheme.colors.primary)
+ Icon(MoreVertFilled, stringResource(R.string.icon_descr_more_button), tint = MaterialTheme.colors.primary)
}
}
@@ -498,7 +496,7 @@ fun ChatInfoToolbarTitle(cInfo: ChatInfo, imageSize: Dp = 40.dp, iconColor: Colo
@Composable
private fun ContactVerifiedShield() {
- Icon(Icons.Outlined.VerifiedUser, null, Modifier.size(18.dp).padding(end = 3.dp, top = 1.dp), tint = HighOrLowlight)
+ Icon(painterResource(R.drawable.ic_verified_user), null, Modifier.size(18.dp).padding(end = 3.dp, top = 1.dp), tint = HighOrLowlight)
}
data class CIListState(val scrolled: Boolean, val itemCount: Int, val keyboardState: KeyboardState)
@@ -787,17 +785,17 @@ 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,
+ painterResource(R.drawable.ic_check),
onClick = {
markRead(
CC.ItemRange(minUnreadItemId, chatItems[chatItems.size - listState.layoutInfo.visibleItemsInfo.lastIndex - 1].id - 1),
@@ -901,7 +899,7 @@ private fun bottomEndFloatingButton(
modifier = Modifier.size(48.dp)
) {
Icon(
- imageVector = Icons.Default.KeyboardArrowDown,
+ painter = painterResource(R.drawable.ic_keyboard_arrow_down),
contentDescription = null,
tint = MaterialTheme.colors.primary
)
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeFileView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeFileView.kt
index dd7b628e1e..a36b09a169 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeFileView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeFileView.kt
@@ -1,12 +1,10 @@
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.InsertDriveFile
-import androidx.compose.material.icons.outlined.Close
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@@ -25,7 +23,7 @@ fun ComposeFileView(fileName: String, cancelFile: () -> Unit, cancelEnabled: Boo
verticalAlignment = Alignment.CenterVertically
) {
Icon(
- Icons.Filled.InsertDriveFile,
+ painterResource(R.drawable.ic_draft_filled),
stringResource(R.string.icon_descr_file),
Modifier
.padding(start = 4.dp, end = 2.dp)
@@ -37,7 +35,7 @@ fun ComposeFileView(fileName: String, cancelFile: () -> Unit, cancelEnabled: Boo
if (cancelEnabled) {
IconButton(onClick = cancelFile, modifier = Modifier.padding(0.dp)) {
Icon(
- Icons.Outlined.Close,
+ painterResource(R.drawable.ic_close),
contentDescription = stringResource(R.string.icon_descr_cancel_file_preview),
tint = MaterialTheme.colors.primary,
modifier = Modifier.padding(10.dp)
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeImageView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeImageView.kt
index f22c04bd98..6823f29ce8 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeImageView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeImageView.kt
@@ -6,14 +6,12 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Videocam
-import androidx.compose.material.icons.outlined.Close
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@@ -49,7 +47,7 @@ fun ComposeImageView(media: ComposePreview.MediaPreview, cancelImages: () -> Uni
modifier = Modifier.widthIn(max = 80.dp).height(60.dp)
)
Icon(
- Icons.Default.Videocam,
+ painterResource(R.drawable.ic_videocam_filled),
"preview video",
Modifier
.size(20.dp),
@@ -69,7 +67,7 @@ fun ComposeImageView(media: ComposePreview.MediaPreview, cancelImages: () -> Uni
if (cancelEnabled) {
IconButton(onClick = cancelImages) {
Icon(
- Icons.Outlined.Close,
+ painterResource(R.drawable.ic_close),
contentDescription = stringResource(R.string.icon_descr_cancel_image_preview),
tint = MaterialTheme.colors.primary,
)
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeView.kt
index 19b8042a99..1840600666 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeView.kt
@@ -19,10 +19,6 @@ import androidx.activity.result.contract.ActivityResultContract
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.AttachFile
-import androidx.compose.material.icons.filled.Edit
-import androidx.compose.material.icons.outlined.Reply
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.Saver
import androidx.compose.runtime.saveable.rememberSaveable
@@ -30,6 +26,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat
@@ -652,10 +649,10 @@ fun ComposeView(
fun contextItemView() {
when (val contextItem = composeState.value.contextItem) {
ComposeContextItem.NoContextItem -> {}
- is ComposeContextItem.QuotedItem -> ContextItemView(contextItem.chatItem, Icons.Outlined.Reply) {
+ is ComposeContextItem.QuotedItem -> ContextItemView(contextItem.chatItem, painterResource(R.drawable.ic_reply)) {
composeState.value = composeState.value.copy(contextItem = ComposeContextItem.NoContextItem)
}
- is ComposeContextItem.EditingItem -> ContextItemView(contextItem.chatItem, Icons.Filled.Edit) {
+ is ComposeContextItem.EditingItem -> ContextItemView(contextItem.chatItem, painterResource(R.drawable.ic_edit_filled)) {
clearState()
}
}
@@ -690,7 +687,7 @@ fun ComposeView(
) {
IconButton(showChooseAttachment, enabled = !composeState.value.attachmentDisabled && rememberUpdatedState(chat.userCanSend).value) {
Icon(
- Icons.Filled.AttachFile,
+ painterResource(R.drawable.ic_attach_file_filled_500),
contentDescription = stringResource(R.string.attach),
tint = if (!composeState.value.attachmentDisabled && userCanSend.value) MaterialTheme.colors.primary else HighOrLowlight,
modifier = Modifier
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeVoiceView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeVoiceView.kt
index 64bd3f43bb..f0994b870e 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeVoiceView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ComposeVoiceView.kt
@@ -2,13 +2,11 @@ import androidx.compose.animation.core.Animatable
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.*
-import androidx.compose.material.icons.outlined.Close
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@@ -77,7 +75,7 @@ fun ComposeVoiceView(
},
enabled = finishedRecording) {
Icon(
- if (audioPlaying.value) Icons.Filled.Pause else Icons.Filled.PlayArrow,
+ if (audioPlaying.value) painterResource(R.drawable.ic_pause_filled) else painterResource(R.drawable.ic_play_arrow_filled),
stringResource(R.string.icon_descr_file),
Modifier
.padding(start = 4.dp, end = 2.dp)
@@ -109,7 +107,7 @@ fun ComposeVoiceView(
modifier = Modifier.padding(0.dp)
) {
Icon(
- Icons.Outlined.Close,
+ painterResource(R.drawable.ic_close),
contentDescription = stringResource(R.string.icon_descr_cancel_file_preview),
tint = MaterialTheme.colors.primary,
modifier = Modifier.padding(10.dp)
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..46c96e47af 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,9 @@
package chat.simplex.app.views.chat
import InfoRow
-import SectionDivider
+import SectionBottomSpacer
+import SectionDividerSpaced
import SectionItemView
-import SectionSpacer
import SectionTextFooter
import SectionView
import androidx.compose.foundation.*
@@ -12,7 +12,6 @@ import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
-import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
@@ -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,
@@ -81,9 +79,7 @@ private fun ContactPreferencesLayout(
Column(
Modifier
.fillMaxWidth()
- .verticalScroll(rememberScrollState())
- .padding(bottom = DEFAULT_PADDING),
- horizontalAlignment = Alignment.Start,
+ .verticalScroll(rememberScrollState()),
) {
AppBarTitle(stringResource(R.string.contact_preferences))
val timedMessages: MutableState = remember(featuresAllowed) { mutableStateOf(featuresAllowed.timedMessagesAllowed) }
@@ -93,27 +89,28 @@ private fun ContactPreferencesLayout(
TimedMessagesFeatureSection(featuresAllowed, contact.mergedPreferences.timedMessages, timedMessages, onTTLUpdated) { allowed, ttl ->
applyPrefs(featuresAllowed.copy(timedMessagesAllowed = allowed, timedMessagesTTL = ttl ?: currentFeaturesAllowed.timedMessagesTTL))
}
- SectionSpacer()
+ SectionDividerSpaced(true, maxBottomPadding = false)
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(true, maxBottomPadding = false)
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(true, maxBottomPadding = false)
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(maxTopPadding = true, maxBottomPadding = false)
ResetSaveButtons(
reset = reset,
save = savePrefs,
disabled = featuresAllowed == currentFeaturesAllowed
)
+ SectionBottomSpacer()
}
}
@@ -133,21 +130,18 @@ private fun FeatureSection(
SectionView(
feature.text.uppercase(),
- icon = feature.iconFilled,
+ icon = feature.iconFilled(),
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
@@ -172,24 +166,20 @@ private fun TimedMessagesFeatureSection(
SectionView(
ChatFeature.TimedMessages.text.uppercase(),
- icon = ChatFeature.TimedMessages.iconFilled,
+ icon = ChatFeature.TimedMessages.iconFilled(),
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 +196,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 +206,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/ContextItemView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ContextItemView.kt
index c07ff70aa1..c030fb86d2 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ContextItemView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ContextItemView.kt
@@ -3,13 +3,11 @@ package chat.simplex.app.views.chat
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Edit
-import androidx.compose.material.icons.outlined.Close
+import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@@ -23,7 +21,7 @@ import kotlinx.datetime.Clock
@Composable
fun ContextItemView(
contextItem: ChatItem,
- contextIcon: ImageVector,
+ contextIcon: Painter,
cancelContextItem: () -> Unit
) {
val sent = contextItem.chatDir.sent
@@ -58,7 +56,7 @@ fun ContextItemView(
}
IconButton(onClick = cancelContextItem) {
Icon(
- Icons.Outlined.Close,
+ painterResource(R.drawable.ic_close),
contentDescription = stringResource(R.string.cancel_verb),
tint = MaterialTheme.colors.primary,
modifier = Modifier.padding(10.dp)
@@ -73,8 +71,7 @@ fun PreviewContextItemView() {
SimpleXTheme {
ContextItemView(
contextItem = ChatItem.getSampleData(1, CIDirection.DirectRcv(), Clock.System.now(), "hello"),
- contextIcon = Icons.Filled.Edit,
- cancelContextItem = {}
- )
+ contextIcon = painterResource(R.drawable.ic_edit_filled)
+ ) {}
}
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/SendMsgView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/SendMsgView.kt
index 9df27148f0..7b9b323cb6 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/SendMsgView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/SendMsgView.kt
@@ -20,9 +20,6 @@ import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.*
-import androidx.compose.material.icons.outlined.*
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
@@ -30,8 +27,9 @@ import androidx.compose.ui.*
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.*
-import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.platform.*
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.TextStyle
@@ -146,7 +144,7 @@ fun SendMsgView(
}
else -> {
val cs = composeState.value
- val icon = if (cs.editing || cs.liveMessage != null) Icons.Filled.Check else Icons.Outlined.ArrowUpward
+ val icon = if (cs.editing || cs.liveMessage != null) painterResource(R.drawable.ic_check_filled) else painterResource(R.drawable.ic_arrow_upward)
val disabled = !cs.sendEnabled() ||
(!allowedVoiceByPrefs && cs.preview is ComposePreview.VoicePreview) ||
cs.endLiveDisabled
@@ -163,7 +161,7 @@ fun SendMsgView(
) {
ItemAction(
generalGetString(R.string.send_live_message),
- Icons.Filled.Bolt,
+ BoltFilled,
onClick = {
startLiveMessage(scope, sendLiveMessage, updateLiveMessage, sendButtonSize, sendButtonAlpha, composeState, liveMessageAlertShown)
showDropdown.value = false
@@ -297,7 +295,7 @@ private fun BoxScope.DeleteTextButton(composeState: MutableState)
{ composeState.value = composeState.value.copy(message = "") },
Modifier.align(Alignment.TopEnd).size(36.dp)
) {
- Icon(Icons.Filled.Close, null, Modifier.padding(7.dp).size(36.dp), tint = HighOrLowlight)
+ Icon(painterResource(R.drawable.ic_close), null, Modifier.padding(7.dp).size(36.dp), tint = HighOrLowlight)
}
}
@@ -354,7 +352,7 @@ private fun RecordVoiceView(recState: MutableState, stopRecOnNex
private fun DisallowedVoiceButton(enabled: Boolean, onClick: () -> Unit) {
IconButton(onClick, Modifier.size(36.dp), enabled = enabled) {
Icon(
- Icons.Outlined.KeyboardVoice,
+ painterResource(R.drawable.ic_keyboard_voice),
stringResource(R.string.icon_descr_record_voice_message),
tint = HighOrLowlight,
modifier = Modifier
@@ -368,7 +366,7 @@ private fun DisallowedVoiceButton(enabled: Boolean, onClick: () -> Unit) {
private fun VoiceButtonWithoutPermission(onClick: () -> Unit) {
IconButton(onClick, Modifier.size(36.dp)) {
Icon(
- Icons.Filled.KeyboardVoice,
+ painterResource(R.drawable.ic_keyboard_voice_filled),
stringResource(R.string.icon_descr_record_voice_message),
tint = MaterialTheme.colors.primary,
modifier = Modifier
@@ -400,7 +398,7 @@ private fun LockToCurrentOrientationUntilDispose() {
private fun StopRecordButton(onClick: () -> Unit) {
IconButton(onClick, Modifier.size(36.dp)) {
Icon(
- Icons.Filled.Stop,
+ painterResource(R.drawable.ic_stop_filled),
stringResource(R.string.icon_descr_record_voice_message),
tint = MaterialTheme.colors.primary,
modifier = Modifier
@@ -414,7 +412,7 @@ private fun StopRecordButton(onClick: () -> Unit) {
private fun RecordVoiceButton(interactionSource: MutableInteractionSource) {
IconButton({}, Modifier.size(36.dp), interactionSource = interactionSource) {
Icon(
- Icons.Filled.KeyboardVoice,
+ painterResource(R.drawable.ic_keyboard_voice_filled),
stringResource(R.string.icon_descr_record_voice_message),
tint = MaterialTheme.colors.primary,
modifier = Modifier
@@ -435,7 +433,7 @@ private fun CancelLiveMessageButton(
) {
IconButton(onClick, Modifier.size(36.dp)) {
Icon(
- Icons.Filled.Close,
+ painterResource(R.drawable.ic_close),
stringResource(R.string.icon_descr_cancel_live_message),
tint = MaterialTheme.colors.primary,
modifier = Modifier
@@ -447,7 +445,7 @@ private fun CancelLiveMessageButton(
@Composable
private fun SendMsgButton(
- icon: ImageVector,
+ icon: Painter,
sizeDp: Animatable,
alpha: Animatable,
enabled: Boolean,
@@ -497,7 +495,7 @@ private fun StartLiveMessageButton(enabled: Boolean, onClick: () -> Unit) {
contentAlignment = Alignment.Center
) {
Icon(
- Icons.Filled.Bolt,
+ BoltFilled,
stringResource(R.string.icon_descr_send_message),
tint = if (enabled) MaterialTheme.colors.primary else HighOrLowlight,
modifier = Modifier
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/VerifyCodeView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/VerifyCodeView.kt
index 58c13e8bb5..81d20e8444 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/VerifyCodeView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/VerifyCodeView.kt
@@ -1,18 +1,17 @@
package chat.simplex.app.views.chat
+import SectionBottomSpacer
import SectionView
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Share
-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.LocalContext
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp
@@ -66,7 +65,7 @@ private fun VerifyCodeLayout(
val splitCode = splitToParts(connectionCode, 24)
Row(Modifier.fillMaxWidth().padding(bottom = DEFAULT_PADDING_HALF), horizontalArrangement = Arrangement.Center) {
if (connectionVerified) {
- Icon(Icons.Outlined.VerifiedUser, null, Modifier.padding(end = 4.dp).size(22.dp), tint = HighOrLowlight)
+ Icon(painterResource(R.drawable.ic_verified_user), null, Modifier.padding(end = 4.dp).size(22.dp), tint = HighOrLowlight)
Text(String.format(stringResource(R.string.is_verified), displayName))
} else {
Text(String.format(stringResource(R.string.is_not_verified), displayName))
@@ -90,7 +89,7 @@ private fun VerifyCodeLayout(
val context = LocalContext.current
Box(Modifier.weight(1f)) {
IconButton({ shareText(context, connectionCode) }, Modifier.size(20.dp).align(Alignment.CenterStart)) {
- Icon(Icons.Filled.Share, null, tint = MaterialTheme.colors.primary)
+ Icon(painterResource(R.drawable.ic_share_filled), null, tint = MaterialTheme.colors.primary)
}
}
Spacer(Modifier.weight(1f))
@@ -106,16 +105,16 @@ private fun VerifyCodeLayout(
horizontalArrangement = Arrangement.spacedBy(10.dp)
) {
if (connectionVerified) {
- SimpleButton(generalGetString(R.string.clear_verification), Icons.Outlined.Shield) {
+ SimpleButton(generalGetString(R.string.clear_verification), painterResource(R.drawable.ic_shield)) {
verifyCode(null) {}
}
} else {
- SimpleButton(generalGetString(R.string.scan_code), Icons.Outlined.QrCode) {
+ SimpleButton(generalGetString(R.string.scan_code), painterResource(R.drawable.ic_qr_code)) {
ModalManager.shared.showModal {
ScanCodeView(verifyCode) { }
}
}
- SimpleButton(generalGetString(R.string.mark_code_verified), Icons.Outlined.VerifiedUser) {
+ SimpleButton(generalGetString(R.string.mark_code_verified), painterResource(R.drawable.ic_verified_user)) {
verifyCode(connectionCode) { verified ->
if (!verified) {
AlertManager.shared.showAlertMsg(
@@ -126,6 +125,7 @@ private fun VerifyCodeLayout(
}
}
}
+ SectionBottomSpacer()
}
}
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..a57f563250 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,8 @@
package chat.simplex.app.views.chat.group
+import SectionBottomSpacer
import SectionCustomFooter
-import SectionDivider
+import SectionDividerSpaced
import SectionItemView
import SectionSpacer
import SectionView
@@ -9,15 +10,12 @@ import androidx.activity.compose.BackHandler
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.CheckCircle
-import androidx.compose.material.icons.filled.TheaterComedy
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.painter.Painter
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
@@ -105,7 +103,6 @@ fun AddGroupMembersLayout(
Modifier
.fillMaxWidth()
.verticalScroll(rememberScrollState()),
- horizontalAlignment = Alignment.Start,
) {
AppBarTitle(stringResource(R.string.button_add_members))
InfoAboutIncognito(
@@ -145,12 +142,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,13 +153,13 @@ fun AddGroupMembersLayout(
SectionCustomFooter {
InviteSectionFooter(selectedContactsCount = selectedContacts.size, allowModifyMembers, clearSelection)
}
- SectionSpacer()
+ SectionDividerSpaced(maxTopPadding = true)
SectionView(stringResource(R.string.select_contacts)) {
ContactList(contacts = contactsToAdd, selectedContacts, groupInfo, allowModifyMembers, addContact, removeContact)
}
- SectionSpacer()
}
+ SectionBottomSpacer()
}
}
@@ -183,16 +176,15 @@ private fun RoleSelectionRow(groupInfo: GroupInfo, selectedRole: MutableState Unit, disabled: Boolean) {
SettingsActionItem(
- Icons.Outlined.Check,
+ painterResource(R.drawable.ic_check),
stringResource(R.string.invite_to_group_button),
click = onClick,
textColor = MaterialTheme.colors.primary,
@@ -204,7 +196,7 @@ fun InviteMembersButton(onClick: () -> Unit, disabled: Boolean) {
@Composable
fun SkipInvitingButton(onClick: () -> Unit) {
SettingsActionItem(
- Icons.Outlined.Check,
+ painterResource(R.drawable.ic_check),
stringResource(R.string.skip_inviting_button),
click = onClick,
textColor = MaterialTheme.colors.primary,
@@ -260,9 +252,6 @@ fun ContactList(
checked = selectedContacts.contains(contact.apiId),
enabled = enabled,
)
- if (index < contacts.lastIndex) {
- SectionDivider()
- }
}
}
}
@@ -277,16 +266,16 @@ fun ContactCheckRow(
enabled: Boolean,
) {
val prohibitedToInviteIncognito = !groupInfo.membership.memberIncognito && contact.contactConnIncognito
- val icon: ImageVector
+ val icon: Painter
val iconColor: Color
if (prohibitedToInviteIncognito) {
- icon = Icons.Filled.TheaterComedy
+ icon = painterResource(R.drawable.ic_theater_comedy_filled)
iconColor = HighOrLowlight
} else if (checked) {
- icon = Icons.Filled.CheckCircle
+ icon = painterResource(R.drawable.ic_check_circle_filled)
iconColor = if (enabled) MaterialTheme.colors.primary else HighOrLowlight
} else {
- icon = Icons.Outlined.Circle
+ icon = painterResource(R.drawable.ic_circle)
iconColor = HighOrLowlight
}
SectionItemView(
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..89c9d1b1dc 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,8 @@
package chat.simplex.app.views.chat.group
import InfoRow
-import SectionDivider
+import SectionBottomSpacer
+import SectionDividerSpaced
import SectionItemView
import SectionSpacer
import SectionTextFooter
@@ -11,12 +12,11 @@ import androidx.activity.compose.BackHandler
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
-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.graphics.Color
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
@@ -160,8 +160,7 @@ fun GroupChatInfoLayout(
Column(
Modifier
.fillMaxWidth()
- .verticalScroll(rememberScrollState()),
- horizontalAlignment = Alignment.Start
+ .verticalScroll(rememberScrollState())
) {
Row(
Modifier.fillMaxWidth(),
@@ -173,63 +172,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(maxTopPadding = true)
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) {
+ SectionItemView(minHeight = 54.dp) {
MemberRow(groupInfo.membership, user = true)
}
- if (members.isNotEmpty()) {
- SectionDivider()
- }
MembersList(members, showMemberInfo)
}
- SectionSpacer()
+ SectionDividerSpaced(maxTopPadding = true, maxBottomPadding = false)
SectionView {
ClearChatButton(clearChat)
if (groupInfo.canDelete) {
- SectionDivider()
- SectionItemView(deleteGroup) { DeleteGroupButton() }
+ DeleteGroupButton(deleteGroup)
}
if (groupInfo.membership.memberCurrent) {
- SectionDivider()
- SectionItemView(leaveGroup) { LeaveGroupButton() }
+ LeaveGroupButton(leaveGroup)
}
}
- SectionSpacer()
if (developerTools) {
+ SectionDividerSpaced()
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()
}
+ SectionBottomSpacer()
}
}
@@ -260,38 +246,31 @@ private fun GroupChatInfoHeader(cInfo: ChatInfo) {
@Composable
private fun GroupPreferencesButton(onClick: () -> Unit) {
SettingsActionItem(
- Icons.Outlined.ToggleOn,
+ painterResource(R.drawable.ic_toggle_on),
stringResource(R.string.group_preferences),
click = onClick
)
}
@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(
+ painterResource(R.drawable.ic_add),
+ stringResource(R.string.button_add_members),
+ onClick,
+ iconColor = tint,
+ textColor = tint
+ )
}
@Composable
private fun MembersList(members: List, showMemberInfo: (GroupMember) -> Unit) {
Column {
members.forEachIndexed { index, member ->
- SectionItemView({ showMemberInfo(member) }, minHeight = 50.dp) {
+ Divider()
+ SectionItemView({ showMemberInfo(member) }, minHeight = 54.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) {
@@ -339,112 +319,74 @@ private fun MemberRow(member: GroupMember, user: Boolean = false) {
@Composable
private fun MemberVerifiedShield() {
- Icon(Icons.Outlined.VerifiedUser, null, Modifier.padding(end = 3.dp).size(16.dp), tint = HighOrLowlight)
+ Icon(painterResource(R.drawable.ic_verified_user), null, Modifier.padding(end = 3.dp).size(16.dp), tint = HighOrLowlight)
}
@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(
+ painterResource(R.drawable.ic_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(
+ painterResource(R.drawable.ic_add_link),
+ 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(
+ painterResource(R.drawable.ic_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(
+ painterResource(R.drawable.ic_maps_ugc),
+ 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(
+ painterResource(R.drawable.ic_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(
+ painterResource(R.drawable.ic_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..a044e9cc1b 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
@@ -1,19 +1,18 @@
package chat.simplex.app.views.chat.group
-import SectionItemView
+import SectionBottomSpacer
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Text
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@@ -101,15 +100,12 @@ fun GroupLinkLayout(
) {
Column(
Modifier
- .verticalScroll(rememberScrollState())
- .padding(start = DEFAULT_PADDING, bottom = DEFAULT_BOTTOM_PADDING, end = DEFAULT_PADDING),
- horizontalAlignment = Alignment.Start,
- verticalArrangement = Arrangement.Top
+ .verticalScroll(rememberScrollState()),
) {
- 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(
@@ -118,11 +114,9 @@ fun GroupLinkLayout(
verticalArrangement = Arrangement.SpaceEvenly
) {
if (groupLink == null) {
- SimpleButton(stringResource(R.string.button_create_group_link), icon = Icons.Outlined.AddLink, disabled = creatingLink, click = createLink)
+ SimpleButton(stringResource(R.string.button_create_group_link), icon = painterResource(R.drawable.ic_add_link), 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,26 +124,27 @@ fun GroupLinkLayout(
}
initialLaunch = false
}
- QRCode(groupLink, Modifier.aspectRatio(1f))
+ QRCode(groupLink, Modifier.aspectRatio(1f).padding(horizontal = 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),
- icon = Icons.Outlined.Share,
+ icon = painterResource(R.drawable.ic_share),
click = share
)
SimpleButton(
stringResource(R.string.delete_link),
- icon = Icons.Outlined.Delete,
+ icon = painterResource(R.drawable.ic_delete),
color = Color.Red,
click = deleteLink
)
}
}
}
+ SectionBottomSpacer()
}
}
@@ -166,9 +161,8 @@ private fun RoleSelectionRow(groupInfo: GroupInfo, selectedRole: MutableState Unit) {
SettingsActionItem(
- Icons.Outlined.Delete,
+ painterResource(R.drawable.ic_delete),
stringResource(R.string.button_remove_member),
click = onClick,
textColor = Color.Red,
@@ -284,7 +272,7 @@ fun RemoveMemberButton(onClick: () -> Unit) {
@Composable
fun OpenChatButton(onClick: () -> Unit) {
SettingsActionItem(
- Icons.Outlined.Message,
+ painterResource(R.drawable.ic_chat),
stringResource(R.string.button_send_direct_message),
click = onClick,
textColor = MaterialTheme.colors.primary,
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..aa9715cf1a 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,9 @@
package chat.simplex.app.views.chat.group
import InfoRow
-import SectionDivider
+import SectionBottomSpacer
+import SectionDividerSpaced
import SectionItemView
-import SectionSpacer
import SectionTextFooter
import SectionView
import androidx.compose.foundation.*
@@ -12,7 +12,6 @@ import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
-import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import chat.simplex.app.R
@@ -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,
@@ -73,7 +71,6 @@ private fun GroupPreferencesLayout(
) {
Column(
Modifier.fillMaxWidth().verticalScroll(rememberScrollState()),
- horizontalAlignment = Alignment.Start,
) {
AppBarTitle(stringResource(R.string.group_preferences))
val timedMessages = remember(preferences) { mutableStateOf(preferences.timedMessages.enable) }
@@ -87,29 +84,30 @@ private fun GroupPreferencesLayout(
applyPrefs(preferences.copy(timedMessages = TimedMessagesGroupPreference(enable = enable, ttl = currentPreferences.timedMessages.ttl)))
}
}
- SectionSpacer()
+ SectionDividerSpaced(true, maxBottomPadding = false)
val allowDirectMessages = remember(preferences) { mutableStateOf(preferences.directMessages.enable) }
FeatureSection(GroupFeature.DirectMessages, allowDirectMessages, groupInfo, preferences, onTTLUpdated) {
applyPrefs(preferences.copy(directMessages = GroupPreference(enable = it)))
}
- SectionSpacer()
+ SectionDividerSpaced(true, maxBottomPadding = false)
val allowFullDeletion = remember(preferences) { mutableStateOf(preferences.fullDelete.enable) }
FeatureSection(GroupFeature.FullDelete, allowFullDeletion, groupInfo, preferences, onTTLUpdated) {
applyPrefs(preferences.copy(fullDelete = GroupPreference(enable = it)))
}
- SectionSpacer()
+ SectionDividerSpaced(true, maxBottomPadding = false)
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(maxTopPadding = true, maxBottomPadding = false)
ResetSaveButtons(
reset = reset,
save = savePrefs,
disabled = preferences == currentPreferences
)
}
+ SectionBottomSpacer()
}
}
@@ -124,22 +122,19 @@ private fun FeatureSection(
) {
SectionView {
val on = enableFeature.value == GroupFeatureEnabled.ON
- val icon = if (on) feature.iconFilled else feature.icon
+ val icon = if (on) feature.iconFilled() else feature.icon
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/GroupProfileView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupProfileView.kt
index 3ad913d431..844c0f149e 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupProfileView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupProfileView.kt
@@ -1,5 +1,6 @@
package chat.simplex.app.views.chat.group
+import SectionBottomSpacer
import android.content.res.Configuration
import android.net.Uri
import androidx.compose.foundation.*
@@ -64,7 +65,7 @@ fun GroupProfileLayout(
val dataUnchanged =
displayName.value == groupProfile.displayName &&
fullName.value == groupProfile.fullName &&
- chosenImage.value == null
+ groupProfile.image == profileImage.value
val closeWithAlert = {
if (dataUnchanged || !(displayName.value.isNotEmpty() && isValidDisplayName(displayName.value))) {
close()
@@ -167,7 +168,7 @@ fun GroupProfileLayout(
}
}
- Spacer(Modifier.height(DEFAULT_BOTTOM_BUTTON_PADDING))
+ SectionBottomSpacer()
LaunchedEffect(Unit) {
delay(300)
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..906a8815e9 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
@@ -1,5 +1,6 @@
package chat.simplex.app.views.chat.group
+import SectionBottomSpacer
import SectionItemView
import SectionSpacer
import SectionView
@@ -44,7 +45,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,
@@ -71,6 +71,7 @@ private fun GroupWelcomeLayout(
save = save,
disabled = welcomeText.value == groupInfo.groupProfile.description || (welcomeText.value == "" && groupInfo.groupProfile.description == null)
)
+ SectionBottomSpacer()
}
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CICallItemView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CICallItemView.kt
index 4c9bbae077..06224d1cc0 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CICallItemView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CICallItemView.kt
@@ -3,13 +3,11 @@ package chat.simplex.app.views.chat.item
import androidx.compose.foundation.layout.*
import androidx.compose.material.Icon
import androidx.compose.material.Text
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.PhoneInTalk
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@@ -24,20 +22,20 @@ fun CICallItemView(cInfo: ChatInfo, cItem: ChatItem, status: CICallStatus, durat
Modifier
.padding(horizontal = 4.dp)
.padding(bottom = 8.dp), horizontalAlignment = Alignment.CenterHorizontally) {
- @Composable fun ConnectingCallIcon() = Icon(Icons.Outlined.SettingsPhone, stringResource(R.string.icon_descr_call_connecting), tint = SimplexGreen)
+ @Composable fun ConnectingCallIcon() = Icon(painterResource(R.drawable.ic_settings_phone), stringResource(R.string.icon_descr_call_connecting), tint = SimplexGreen)
when (status) {
CICallStatus.Pending -> if (sent) {
- Icon(Icons.Outlined.Call, stringResource(R.string.icon_descr_call_pending_sent))
+ Icon(painterResource(R.drawable.ic_call), stringResource(R.string.icon_descr_call_pending_sent))
} else {
AcceptCallButton(cInfo, acceptCall)
}
- CICallStatus.Missed -> Icon(Icons.Outlined.Call, stringResource(R.string.icon_descr_call_missed), tint = Color.Red)
- CICallStatus.Rejected -> Icon(Icons.Outlined.CallEnd, stringResource(R.string.icon_descr_call_rejected), tint = Color.Red)
+ CICallStatus.Missed -> Icon(painterResource(R.drawable.ic_call), stringResource(R.string.icon_descr_call_missed), tint = Color.Red)
+ CICallStatus.Rejected -> Icon(painterResource(R.drawable.ic_call_end), stringResource(R.string.icon_descr_call_rejected), tint = Color.Red)
CICallStatus.Accepted -> ConnectingCallIcon()
CICallStatus.Negotiated -> ConnectingCallIcon()
- CICallStatus.Progress -> Icon(Icons.Filled.PhoneInTalk, stringResource(R.string.icon_descr_call_progress), tint = SimplexGreen)
+ CICallStatus.Progress -> Icon(painterResource(R.drawable.ic_phone_in_talk_filled), stringResource(R.string.icon_descr_call_progress), tint = SimplexGreen)
CICallStatus.Ended -> Row {
- Icon(Icons.Outlined.CallEnd, stringResource(R.string.icon_descr_call_ended), tint = HighOrLowlight, modifier = Modifier.padding(end = 4.dp))
+ Icon(painterResource(R.drawable.ic_call_end), stringResource(R.string.icon_descr_call_ended), tint = HighOrLowlight, modifier = Modifier.padding(end = 4.dp))
Text(durationText(duration), color = HighOrLowlight)
}
CICallStatus.Error -> {}
@@ -55,9 +53,9 @@ fun CICallItemView(cInfo: ChatInfo, cItem: ChatItem, status: CICallStatus, durat
@Composable
fun AcceptCallButton(cInfo: ChatInfo, acceptCall: (Contact) -> Unit) {
if (cInfo is ChatInfo.Direct) {
- SimpleButton(stringResource(R.string.answer_call), Icons.Outlined.RingVolume) { acceptCall(cInfo.contact) }
+ SimpleButton(stringResource(R.string.answer_call), painterResource(R.drawable.ic_ring_volume)) { acceptCall(cInfo.contact) }
} else {
- Icon(Icons.Outlined.RingVolume, stringResource(R.string.answer_call), tint = HighOrLowlight)
+ Icon(painterResource(R.drawable.ic_ring_volume), stringResource(R.string.answer_call), tint = HighOrLowlight)
}
// if case let .direct(contact) = chatInfo {
// Button {
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIChatFeatureView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIChatFeatureView.kt
index 347dde80fc..752cf8681b 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIChatFeatureView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIChatFeatureView.kt
@@ -6,7 +6,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import chat.simplex.app.model.*
@@ -16,14 +16,14 @@ fun CIChatFeatureView(
chatItem: ChatItem,
feature: Feature,
iconColor: Color,
- icon: ImageVector? = null
+ icon: Painter? = null
) {
Row(
Modifier.padding(horizontal = 6.dp, vertical = 6.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(4.dp)
) {
- Icon(icon ?: feature.iconFilled, feature.text, Modifier.size(18.dp), tint = iconColor)
+ Icon(icon ?: feature.iconFilled(), feature.text, Modifier.size(18.dp), tint = iconColor)
Text(
chatEventText(chatItem),
Modifier,
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIFileView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIFileView.kt
index 01694f6c41..0194da14d8 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIFileView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIFileView.kt
@@ -6,18 +6,15 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Check
-import androidx.compose.material.icons.filled.InsertDriveFile
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.*
import androidx.compose.ui.unit.dp
@@ -39,14 +36,14 @@ fun CIFileView(
@Composable
fun fileIcon(
- innerIcon: ImageVector? = null,
+ innerIcon: Painter? = null,
color: Color = if (isInDarkTheme()) FileDark else FileLight
) {
Box(
contentAlignment = Alignment.Center
) {
Icon(
- Icons.Filled.InsertDriveFile,
+ painterResource(R.drawable.ic_draft_filled),
stringResource(R.string.icon_descr_file),
Modifier.fillMaxSize(),
tint = color
@@ -154,15 +151,15 @@ fun CIFileView(
FileProtocol.XFTP -> progressCircle(file.fileStatus.sndProgress, file.fileStatus.sndTotal)
FileProtocol.SMP -> progressIndicator()
}
- is CIFileStatus.SndComplete -> fileIcon(innerIcon = Icons.Filled.Check)
- is CIFileStatus.SndCancelled -> fileIcon(innerIcon = Icons.Outlined.Close)
- is CIFileStatus.SndError -> fileIcon(innerIcon = Icons.Outlined.Close)
+ is CIFileStatus.SndComplete -> fileIcon(innerIcon = painterResource(R.drawable.ic_check_filled))
+ is CIFileStatus.SndCancelled -> fileIcon(innerIcon = painterResource(R.drawable.ic_close))
+ is CIFileStatus.SndError -> fileIcon(innerIcon = painterResource(R.drawable.ic_close))
is CIFileStatus.RcvInvitation ->
if (fileSizeValid())
- fileIcon(innerIcon = Icons.Outlined.ArrowDownward, color = MaterialTheme.colors.primary)
+ fileIcon(innerIcon = painterResource(R.drawable.ic_arrow_downward), color = MaterialTheme.colors.primary)
else
- fileIcon(innerIcon = Icons.Outlined.PriorityHigh, color = WarningOrange)
- is CIFileStatus.RcvAccepted -> fileIcon(innerIcon = Icons.Outlined.MoreHoriz)
+ fileIcon(innerIcon = painterResource(R.drawable.ic_priority_high), color = WarningOrange)
+ is CIFileStatus.RcvAccepted -> fileIcon(innerIcon = painterResource(R.drawable.ic_more_horiz))
is CIFileStatus.RcvTransfer ->
if (file.fileProtocol == FileProtocol.XFTP && file.fileStatus.rcvProgress < file.fileStatus.rcvTotal) {
progressCircle(file.fileStatus.rcvProgress, file.fileStatus.rcvTotal)
@@ -170,8 +167,8 @@ fun CIFileView(
progressIndicator()
}
is CIFileStatus.RcvComplete -> fileIcon()
- is CIFileStatus.RcvCancelled -> fileIcon(innerIcon = Icons.Outlined.Close)
- is CIFileStatus.RcvError -> fileIcon(innerIcon = Icons.Outlined.Close)
+ is CIFileStatus.RcvCancelled -> fileIcon(innerIcon = painterResource(R.drawable.ic_close))
+ is CIFileStatus.RcvError -> fileIcon(innerIcon = painterResource(R.drawable.ic_close))
}
} else {
fileIcon()
@@ -190,9 +187,7 @@ fun CIFileView(
else
" "
if (file != null) {
- Column(
- horizontalAlignment = Alignment.Start
- ) {
+ Column {
Text(
file.fileName,
maxLines = 1
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIGroupInvitationView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIGroupInvitationView.kt
index 3bdd453b41..d55c4ee8ba 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIGroupInvitationView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIGroupInvitationView.kt
@@ -1,16 +1,14 @@
package chat.simplex.app.views.chat.item
import android.content.res.Configuration
-import android.util.Log
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.SupervisedUserCircle
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
@@ -46,7 +44,7 @@ fun CIGroupInvitationView(
.padding(vertical = 4.dp)
.padding(end = 2.dp)
) {
- ProfileImage(size = 60.dp, image = groupInvitation.groupProfile.image, icon = Icons.Filled.SupervisedUserCircle, color = iconColor)
+ ProfileImage(size = 60.dp, image = groupInvitation.groupProfile.image, icon = R.drawable.ic_supervised_user_circle_filled, color = iconColor)
Spacer(Modifier.padding(horizontal = 3.dp))
Column(
Modifier.defaultMinSize(minHeight = 60.dp),
@@ -89,7 +87,6 @@ fun CIGroupInvitationView(
Modifier
.defaultMinSize(minWidth = 220.dp)
.padding(bottom = 4.dp),
- horizontalAlignment = Alignment.Start
) {
groupInfoView()
Column(Modifier.padding(top = 2.dp, start = 5.dp)) {
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIImageView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIImageView.kt
index 70cc608d61..c4368e1b7a 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIImageView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIImageView.kt
@@ -8,9 +8,6 @@ import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.*
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Icon
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Check
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -18,10 +15,10 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.graphics.painter.Painter
-import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.layoutId
import androidx.compose.ui.platform.*
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
@@ -55,7 +52,7 @@ fun CIImageView(
}
@Composable
- fun fileIcon(icon: ImageVector, @StringRes stringId: Int) {
+ fun fileIcon(icon: Painter, @StringRes stringId: Int) {
Icon(
icon,
stringResource(stringId),
@@ -80,14 +77,14 @@ fun CIImageView(
FileProtocol.SMP -> {}
}
is CIFileStatus.SndTransfer -> progressIndicator()
- is CIFileStatus.SndComplete -> fileIcon(Icons.Filled.Check, R.string.icon_descr_image_snd_complete)
- is CIFileStatus.SndCancelled -> fileIcon(Icons.Outlined.Close, R.string.icon_descr_file)
- is CIFileStatus.SndError -> fileIcon(Icons.Outlined.Close, R.string.icon_descr_file)
- is CIFileStatus.RcvInvitation -> fileIcon(Icons.Outlined.ArrowDownward, R.string.icon_descr_asked_to_receive)
- is CIFileStatus.RcvAccepted -> fileIcon(Icons.Outlined.MoreHoriz, R.string.icon_descr_waiting_for_image)
+ is CIFileStatus.SndComplete -> fileIcon(painterResource(R.drawable.ic_check_filled), R.string.icon_descr_image_snd_complete)
+ is CIFileStatus.SndCancelled -> fileIcon(painterResource(R.drawable.ic_close), R.string.icon_descr_file)
+ is CIFileStatus.SndError -> fileIcon(painterResource(R.drawable.ic_close), R.string.icon_descr_file)
+ is CIFileStatus.RcvInvitation -> fileIcon(painterResource(R.drawable.ic_arrow_downward), R.string.icon_descr_asked_to_receive)
+ is CIFileStatus.RcvAccepted -> fileIcon(painterResource(R.drawable.ic_more_horiz), R.string.icon_descr_waiting_for_image)
is CIFileStatus.RcvTransfer -> progressIndicator()
- is CIFileStatus.RcvCancelled -> fileIcon(Icons.Outlined.Close, R.string.icon_descr_file)
- is CIFileStatus.RcvError -> fileIcon(Icons.Outlined.Close, R.string.icon_descr_file)
+ is CIFileStatus.RcvCancelled -> fileIcon(painterResource(R.drawable.ic_close), R.string.icon_descr_file)
+ is CIFileStatus.RcvError -> fileIcon(painterResource(R.drawable.ic_close), R.string.icon_descr_file)
else -> {}
}
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIInvalidJSONView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIInvalidJSONView.kt
index 51a6d92bce..f22fcf46a2 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIInvalidJSONView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIInvalidJSONView.kt
@@ -5,12 +5,11 @@ import SectionView
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.Share
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.unit.dp
@@ -35,7 +34,7 @@ fun InvalidJSONView(json: String) {
Spacer(Modifier.height(DEFAULT_PADDING))
SectionView {
val context = LocalContext.current
- SettingsActionItem(Icons.Outlined.Share, generalGetString(R.string.share_verb), click = {
+ SettingsActionItem(painterResource(R.drawable.ic_share), generalGetString(R.string.share_verb), click = {
shareText(context, json)
})
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIMetaView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIMetaView.kt
index 67b4f54a4d..81afbc10e4 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIMetaView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIMetaView.kt
@@ -2,15 +2,13 @@ package chat.simplex.app.views.chat.item
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Circle
-import androidx.compose.material.icons.outlined.Edit
-import androidx.compose.material.icons.outlined.Timer
+import androidx.compose.ui.graphics.painter.Painter
+import androidx.compose.ui.res.painterResource
+import chat.simplex.app.R
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@@ -39,11 +37,11 @@ fun CIMetaView(chatItem: ChatItem, timedMessagesTTL: Int?, metaColor: Color = Hi
// changing this function requires updating reserveSpaceForMeta
private fun CIMetaText(meta: CIMeta, chatTTL: Int?, color: Color) {
if (meta.itemEdited) {
- StatusIconText(Icons.Outlined.Edit, color)
+ StatusIconText(painterResource(R.drawable.ic_edit), color)
Spacer(Modifier.width(3.dp))
}
if (meta.disappearing) {
- StatusIconText(Icons.Outlined.Timer, color)
+ StatusIconText(painterResource(R.drawable.ic_timer), color)
val ttl = meta.itemTimed?.ttl
if (ttl != chatTTL) {
Text(TimedMessagesPreference.shortTtlText(ttl), color = color, fontSize = 13.sp)
@@ -53,10 +51,10 @@ private fun CIMetaText(meta: CIMeta, chatTTL: Int?, color: Color) {
val statusIcon = meta.statusIcon(MaterialTheme.colors.primary, color)
if (statusIcon != null) {
val (icon, statusColor) = statusIcon
- StatusIconText(icon, statusColor)
+ StatusIconText(painterResource(icon), statusColor)
Spacer(Modifier.width(4.dp))
} else if (!meta.disappearing) {
- StatusIconText(Icons.Filled.Circle, Color.Transparent)
+ StatusIconText(painterResource(R.drawable.ic_circle_filled), Color.Transparent)
Spacer(Modifier.width(4.dp))
}
Text(meta.timestampText, color = color, fontSize = 13.sp, maxLines = 1, overflow = TextOverflow.Ellipsis)
@@ -81,7 +79,7 @@ fun reserveSpaceForMeta(meta: CIMeta, chatTTL: Int?): String {
}
@Composable
-private fun StatusIconText(icon: ImageVector, color: Color) {
+private fun StatusIconText(icon: Painter, color: Color) {
Icon(icon, null, Modifier.height(12.dp), tint = color)
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIVideoView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIVideoView.kt
index cc976e242e..63d554b9bb 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIVideoView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIVideoView.kt
@@ -9,17 +9,15 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.*
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.*
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
-import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.layout.*
import androidx.compose.ui.platform.*
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.*
import androidx.compose.ui.viewinterop.AndroidView
@@ -163,9 +161,8 @@ private fun BoxScope.PlayButton(error: Boolean = false, onLongClick: () -> Unit,
contentAlignment = Alignment.Center
) {
Icon(
- imageVector = Icons.Filled.PlayArrow,
+ painterResource(R.drawable.ic_play_arrow_filled),
contentDescription = null,
- Modifier.size(25.dp),
tint = if (error) WarningOrange else Color.White
)
}
@@ -192,7 +189,7 @@ private fun DurationProgress(file: CIFile, playing: MutableState, durat
color = Color.White
)
/*if (!soundEnabled.value) {
- Icon(Icons.Outlined.VolumeOff, null,
+ Icon(painterResource(R.drawable.ic_volume_off_filled), null,
Modifier.padding(start = 5.dp).size(10.dp),
tint = Color.White
)
@@ -255,7 +252,7 @@ private fun progressIndicator() {
}
@Composable
-private fun fileIcon(icon: ImageVector, @StringRes stringId: Int) {
+private fun fileIcon(icon: Painter, @StringRes stringId: Int) {
Icon(
icon,
stringResource(stringId),
@@ -298,19 +295,19 @@ private fun loadingIndicator(file: CIFile?) {
FileProtocol.XFTP -> progressCircle(file.fileStatus.sndProgress, file.fileStatus.sndTotal)
FileProtocol.SMP -> progressIndicator()
}
- is CIFileStatus.SndComplete -> fileIcon(Icons.Filled.Check, R.string.icon_descr_video_snd_complete)
- is CIFileStatus.SndCancelled -> fileIcon(Icons.Outlined.Close, R.string.icon_descr_file)
- is CIFileStatus.SndError -> fileIcon(Icons.Outlined.Close, R.string.icon_descr_file)
- is CIFileStatus.RcvInvitation -> fileIcon(Icons.Outlined.ArrowDownward, R.string.icon_descr_video_asked_to_receive)
- is CIFileStatus.RcvAccepted -> fileIcon(Icons.Outlined.MoreHoriz, R.string.icon_descr_waiting_for_video)
+ is CIFileStatus.SndComplete -> fileIcon(painterResource(R.drawable.ic_check_filled), R.string.icon_descr_video_snd_complete)
+ is CIFileStatus.SndCancelled -> fileIcon(painterResource(R.drawable.ic_close), R.string.icon_descr_file)
+ is CIFileStatus.SndError -> fileIcon(painterResource(R.drawable.ic_close), R.string.icon_descr_file)
+ is CIFileStatus.RcvInvitation -> fileIcon(painterResource(R.drawable.ic_arrow_downward), R.string.icon_descr_video_asked_to_receive)
+ is CIFileStatus.RcvAccepted -> fileIcon(painterResource(R.drawable.ic_more_horiz), R.string.icon_descr_waiting_for_video)
is CIFileStatus.RcvTransfer ->
if (file.fileProtocol == FileProtocol.XFTP && file.fileStatus.rcvProgress < file.fileStatus.rcvTotal) {
progressCircle(file.fileStatus.rcvProgress, file.fileStatus.rcvTotal)
} else {
progressIndicator()
}
- is CIFileStatus.RcvCancelled -> fileIcon(Icons.Outlined.Close, R.string.icon_descr_file)
- is CIFileStatus.RcvError -> fileIcon(Icons.Outlined.Close, R.string.icon_descr_file)
+ is CIFileStatus.RcvCancelled -> fileIcon(painterResource(R.drawable.ic_close), R.string.icon_descr_file)
+ is CIFileStatus.RcvError -> fileIcon(painterResource(R.drawable.ic_close), R.string.icon_descr_file)
else -> {}
}
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIVoiceView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIVoiceView.kt
index cc873ac6ec..8d6bd2c8cc 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIVoiceView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/CIVoiceView.kt
@@ -5,8 +5,6 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
@@ -19,7 +17,9 @@ import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.*
+import chat.simplex.app.R
import chat.simplex.app.model.*
import chat.simplex.app.ui.theme.*
import chat.simplex.app.views.helpers.*
@@ -171,7 +171,7 @@ private fun PlayPauseButton(
contentAlignment = Alignment.Center
) {
Icon(
- imageVector = if (audioPlaying) Icons.Filled.Pause else Icons.Filled.PlayArrow,
+ if (audioPlaying) painterResource(R.drawable.ic_pause_filled) else painterResource(R.drawable.ic_play_arrow_filled),
contentDescription = null,
Modifier.size(36.dp),
tint = if (error) WarningOrange else if (!enabled) HighOrLowlight else MaterialTheme.colors.primary
@@ -200,7 +200,7 @@ private fun VoiceMsgIndicator(
if (hasText) {
IconButton({ if (!audioPlaying) play() else pause() }, Modifier.size(56.dp).drawRingModifier(angle, strokeColor, strokeWidth)) {
Icon(
- imageVector = if (audioPlaying) Icons.Filled.Pause else Icons.Filled.PlayArrow,
+ if (audioPlaying) painterResource(R.drawable.ic_pause_filled) else painterResource(R.drawable.ic_play_arrow_filled),
contentDescription = null,
Modifier.size(36.dp),
tint = MaterialTheme.colors.primary
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/ChatItemView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/ChatItemView.kt
index d1b87aae6b..5e64d13e8d 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/ChatItemView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/ChatItemView.kt
@@ -6,16 +6,15 @@ import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Edit
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.painter.Painter
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.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@@ -106,7 +105,7 @@ fun ChatItemView(
fun MsgContentItemDropdownMenu() {
DefaultDropdownMenu(showMenu) {
if (cItem.meta.itemDeleted == null && !live) {
- ItemAction(stringResource(R.string.reply_verb), Icons.Outlined.Reply, onClick = {
+ ItemAction(stringResource(R.string.reply_verb), painterResource(R.drawable.ic_reply), onClick = {
if (composeState.value.editing) {
composeState.value = ComposeState(contextItem = ComposeContextItem.QuotedItem(cItem), useLinkPreviews = useLinkPreviews)
} else {
@@ -115,7 +114,7 @@ fun ChatItemView(
showMenu.value = false
})
}
- ItemAction(stringResource(R.string.share_verb), Icons.Outlined.Share, onClick = {
+ ItemAction(stringResource(R.string.share_verb), painterResource(R.drawable.ic_share), onClick = {
val filePath = getLoadedFilePath(SimplexApp.context, cItem.file)
when {
filePath != null -> shareFile(context, cItem.text, filePath)
@@ -123,7 +122,7 @@ fun ChatItemView(
}
showMenu.value = false
})
- ItemAction(stringResource(R.string.copy_verb), Icons.Outlined.ContentCopy, onClick = {
+ ItemAction(stringResource(R.string.copy_verb), painterResource(R.drawable.ic_content_copy), onClick = {
copyText(context, cItem.content.text)
showMenu.value = false
})
@@ -131,7 +130,7 @@ fun ChatItemView(
val filePath = getLoadedFilePath(context, cItem.file)
if (filePath != null) {
val writePermissionState = rememberPermissionState(permission = Manifest.permission.WRITE_EXTERNAL_STORAGE)
- ItemAction(stringResource(R.string.save_verb), Icons.Outlined.SaveAlt, onClick = {
+ ItemAction(stringResource(R.string.save_verb), painterResource(R.drawable.ic_download), onClick = {
when (cItem.content.msgContent) {
is MsgContent.MCImage -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R || writePermissionState.hasPermission) {
@@ -148,7 +147,7 @@ fun ChatItemView(
}
}
if (cItem.meta.editable && cItem.content.msgContent !is MsgContent.MCVoice && !live) {
- ItemAction(stringResource(R.string.edit_verb), Icons.Filled.Edit, onClick = {
+ ItemAction(stringResource(R.string.edit_verb), painterResource(R.drawable.ic_edit_filled), onClick = {
composeState.value = ComposeState(editingItem = cItem, useLinkPreviews = useLinkPreviews)
showMenu.value = false
})
@@ -156,7 +155,7 @@ fun ChatItemView(
if (cItem.meta.itemDeleted != null && revealed.value) {
ItemAction(
stringResource(R.string.hide_verb),
- Icons.Outlined.VisibilityOff,
+ painterResource(R.drawable.ic_visibility_off),
onClick = {
revealed.value = false
showMenu.value = false
@@ -182,7 +181,7 @@ fun ChatItemView(
if (!cItem.isDeletedContent) {
ItemAction(
stringResource(R.string.reveal_verb),
- Icons.Outlined.Visibility,
+ painterResource(R.drawable.ic_visibility),
onClick = {
revealed.value = true
showMenu.value = false
@@ -270,7 +269,7 @@ fun CancelFileItemAction(
) {
ItemAction(
stringResource(cancelAction.uiActionId),
- Icons.Outlined.Close,
+ painterResource(R.drawable.ic_close),
onClick = {
showMenu.value = false
cancelFileAlertDialog(fileId, cancelFile = cancelFile, cancelAction = cancelAction)
@@ -288,7 +287,7 @@ fun DeleteItemAction(
) {
ItemAction(
stringResource(R.string.delete_verb),
- Icons.Outlined.Delete,
+ painterResource(R.drawable.ic_delete),
onClick = {
showMenu.value = false
deleteMessageAlertDialog(cItem, questionText, deleteMessage = deleteMessage)
@@ -306,7 +305,7 @@ fun ModerateItemAction(
) {
ItemAction(
stringResource(R.string.moderate_verb),
- Icons.Outlined.Flag,
+ painterResource(R.drawable.ic_flag),
onClick = {
showMenu.value = false
moderateMessageAlertDialog(cItem, questionText, deleteMessage = deleteMessage)
@@ -315,6 +314,26 @@ fun ModerateItemAction(
)
}
+@Composable
+fun ItemAction(text: String, icon: Painter, onClick: () -> Unit, color: Color = Color.Unspecified) {
+ val finalColor = if (color == Color.Unspecified) {
+ if (isInDarkTheme()) MenuTextColorDark else Color.Black
+ } else color
+ DropdownMenuItem(onClick, contentPadding = PaddingValues(horizontal = DEFAULT_PADDING * 1.5f)) {
+ Row(verticalAlignment = Alignment.CenterVertically) {
+ Text(
+ text,
+ modifier = Modifier
+ .fillMaxWidth()
+ .weight(1F)
+ .padding(end = 15.dp),
+ color = finalColor
+ )
+ Icon(icon, text, tint = finalColor)
+ }
+ }
+}
+
@Composable
fun ItemAction(text: String, icon: ImageVector, onClick: () -> Unit, color: Color = Color.Unspecified) {
val finalColor = if (color == Color.Unspecified) {
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/FramedItemView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/FramedItemView.kt
index 4717ae2c4d..fe80af7bc5 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/FramedItemView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/FramedItemView.kt
@@ -4,10 +4,6 @@ import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.*
-import androidx.compose.material.icons.outlined.Delete
-import androidx.compose.material.icons.outlined.Flag
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -15,9 +11,10 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
-import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.layout.*
import androidx.compose.ui.platform.UriHandler
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.*
import androidx.compose.ui.text.font.FontStyle
@@ -72,7 +69,7 @@ fun FramedItemView(
}
@Composable
- fun FramedItemHeader(caption: String, italic: Boolean, icon: ImageVector? = null) {
+ fun FramedItemHeader(caption: String, italic: Boolean, icon: Painter? = null) {
Row(
Modifier
.background(if (sent) SentQuoteColorLight else ReceivedQuoteColorLight)
@@ -142,7 +139,7 @@ fun FramedItemView(
ciQuotedMsgView(qi)
}
Icon(
- if (qi.content is MsgContent.MCFile) Icons.Filled.InsertDriveFile else Icons.Filled.Mic,
+ if (qi.content is MsgContent.MCFile) painterResource(R.drawable.ic_draft_filled) else painterResource(R.drawable.ic_mic_filled),
if (qi.content is MsgContent.MCFile) stringResource(R.string.icon_descr_file) else stringResource(R.string.voice_message),
Modifier
.padding(top = 6.dp, end = 4.dp)
@@ -181,9 +178,9 @@ fun FramedItemView(
PriorityLayout(Modifier, CHAT_IMAGE_LAYOUT_ID) {
if (ci.meta.itemDeleted != null) {
if (ci.meta.itemDeleted is CIDeleted.Moderated) {
- FramedItemHeader(String.format(stringResource(R.string.moderated_item_description), ci.meta.itemDeleted.byGroupMember.chatViewName), true, Icons.Outlined.Flag)
+ FramedItemHeader(String.format(stringResource(R.string.moderated_item_description), ci.meta.itemDeleted.byGroupMember.chatViewName), true, painterResource(R.drawable.ic_flag))
} else {
- FramedItemHeader(stringResource(R.string.marked_deleted_description), true, Icons.Outlined.Delete)
+ FramedItemHeader(stringResource(R.string.marked_deleted_description), true, painterResource(R.drawable.ic_delete))
}
} else if (ci.meta.isLive) {
FramedItemHeader(stringResource(R.string.live), false)
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatHelpView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatHelpView.kt
index 4807241cdd..6fd7212b8e 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatHelpView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatHelpView.kt
@@ -4,8 +4,7 @@ import android.content.res.Configuration
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.PersonAdd
+import androidx.compose.ui.res.painterResource
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -28,7 +27,6 @@ val bold = SpanStyle(fontWeight = FontWeight.Bold)
@Composable
fun ChatHelpView(addContact: (() -> Unit)? = null) {
Column(
- horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.spacedBy(10.dp)
) {
val uriHandler = LocalUriHandler.current
@@ -44,7 +42,6 @@ fun ChatHelpView(addContact: (() -> Unit)? = null) {
Column(
Modifier.padding(top = 24.dp),
- horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.spacedBy(10.dp)
) {
Text(
@@ -58,7 +55,7 @@ fun ChatHelpView(addContact: (() -> Unit)? = null) {
) {
Text(stringResource(R.string.chat_help_tap_button))
Icon(
- Icons.Outlined.PersonAdd,
+ painterResource(R.drawable.ic_person_add),
stringResource(R.string.add_contact),
modifier = if (addContact != null) Modifier.clickable(onClick = addContact) else Modifier,
)
@@ -70,7 +67,6 @@ fun ChatHelpView(addContact: (() -> Unit)? = null) {
Column(
Modifier.padding(top = 24.dp),
- horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.spacedBy(10.dp)
) {
Text(stringResource(R.string.to_connect_via_link_title), style = MaterialTheme.typography.h2)
@@ -81,7 +77,6 @@ fun ChatHelpView(addContact: (() -> Unit)? = null) {
Column(
Modifier.padding(vertical = 24.dp),
- horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.spacedBy(10.dp)
) {
Text(stringResource(R.string.markdown_in_messages), style = MaterialTheme.typography.h2)
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListNavLinkView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListNavLinkView.kt
index 1e8ed4a62f..921197a6f7 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListNavLinkView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListNavLinkView.kt
@@ -4,14 +4,12 @@ import android.content.res.Configuration
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.*
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
@@ -183,7 +181,7 @@ fun GroupMenuItems(chat: Chat, groupInfo: GroupInfo, chatModel: ChatModel, showM
fun MarkReadChatAction(chat: Chat, chatModel: ChatModel, showMenu: MutableState) {
ItemAction(
stringResource(R.string.mark_read),
- Icons.Outlined.Check,
+ painterResource(R.drawable.ic_check),
onClick = {
markChatRead(chat, chatModel)
chatModel.controller.ntfManager.cancelNotificationsForChat(chat.id)
@@ -196,7 +194,7 @@ fun MarkReadChatAction(chat: Chat, chatModel: ChatModel, showMenu: MutableState<
fun MarkUnreadChatAction(chat: Chat, chatModel: ChatModel, showMenu: MutableState) {
ItemAction(
stringResource(R.string.mark_unread),
- Icons.Outlined.MarkChatUnread,
+ painterResource(R.drawable.ic_mark_chat_unread),
onClick = {
markChatUnread(chat, chatModel)
showMenu.value = false
@@ -208,7 +206,7 @@ fun MarkUnreadChatAction(chat: Chat, chatModel: ChatModel, showMenu: MutableStat
fun ToggleNotificationsChatAction(chat: Chat, chatModel: ChatModel, ntfsEnabled: Boolean, showMenu: MutableState) {
ItemAction(
if (ntfsEnabled) stringResource(R.string.mute_chat) else stringResource(R.string.unmute_chat),
- if (ntfsEnabled) Icons.Outlined.NotificationsOff else Icons.Outlined.Notifications,
+ if (ntfsEnabled) painterResource(R.drawable.ic_notifications_off) else painterResource(R.drawable.ic_notifications),
onClick = {
changeNtfsStatePerChat(!ntfsEnabled, mutableStateOf(ntfsEnabled), chat, chatModel)
showMenu.value = false
@@ -220,7 +218,7 @@ fun ToggleNotificationsChatAction(chat: Chat, chatModel: ChatModel, ntfsEnabled:
fun ClearChatAction(chat: Chat, chatModel: ChatModel, showMenu: MutableState) {
ItemAction(
stringResource(R.string.clear_chat_menu_action),
- Icons.Outlined.Restore,
+ painterResource(R.drawable.ic_settings_backup_restore),
onClick = {
clearChatDialog(chat.chatInfo, chatModel)
showMenu.value = false
@@ -233,7 +231,7 @@ fun ClearChatAction(chat: Chat, chatModel: ChatModel, showMenu: MutableState) {
ItemAction(
stringResource(R.string.delete_contact_menu_action),
- Icons.Outlined.Delete,
+ painterResource(R.drawable.ic_delete),
onClick = {
deleteContactDialog(chat.chatInfo, chatModel)
showMenu.value = false
@@ -246,7 +244,7 @@ fun DeleteContactAction(chat: Chat, chatModel: ChatModel, showMenu: MutableState
fun DeleteGroupAction(chat: Chat, groupInfo: GroupInfo, chatModel: ChatModel, showMenu: MutableState) {
ItemAction(
stringResource(R.string.delete_group_menu_action),
- Icons.Outlined.Delete,
+ painterResource(R.drawable.ic_delete),
onClick = {
deleteGroupDialog(chat.chatInfo, groupInfo, chatModel)
showMenu.value = false
@@ -260,7 +258,7 @@ fun JoinGroupAction(chat: Chat, groupInfo: GroupInfo, chatModel: ChatModel, show
val joinGroup: () -> Unit = { withApi { chatModel.controller.apiJoinGroup(groupInfo.groupId) } }
ItemAction(
if (chat.chatInfo.incognito) stringResource(R.string.join_group_incognito_button) else stringResource(R.string.join_group_button),
- if (chat.chatInfo.incognito) Icons.Filled.TheaterComedy else Icons.Outlined.Login,
+ if (chat.chatInfo.incognito) painterResource(R.drawable.ic_theater_comedy_filled) else painterResource(R.drawable.ic_login),
color = if (chat.chatInfo.incognito) Indigo else MaterialTheme.colors.onBackground,
onClick = {
joinGroup()
@@ -273,7 +271,7 @@ fun JoinGroupAction(chat: Chat, groupInfo: GroupInfo, chatModel: ChatModel, show
fun LeaveGroupAction(groupInfo: GroupInfo, chatModel: ChatModel, showMenu: MutableState) {
ItemAction(
stringResource(R.string.leave_group_button),
- Icons.Outlined.Logout,
+ painterResource(R.drawable.ic_logout),
onClick = {
leaveGroupDialog(groupInfo, chatModel)
showMenu.value = false
@@ -286,7 +284,7 @@ fun LeaveGroupAction(groupInfo: GroupInfo, chatModel: ChatModel, showMenu: Mutab
fun ContactRequestMenuItems(chatInfo: ChatInfo.ContactRequest, chatModel: ChatModel, showMenu: MutableState) {
ItemAction(
if (chatModel.incognito.value) stringResource(R.string.accept_contact_incognito_button) else stringResource(R.string.accept_contact_button),
- if (chatModel.incognito.value) Icons.Filled.TheaterComedy else Icons.Outlined.Check,
+ if (chatModel.incognito.value) painterResource(R.drawable.ic_theater_comedy_filled) else painterResource(R.drawable.ic_check),
color = if (chatModel.incognito.value) Indigo else MaterialTheme.colors.onBackground,
onClick = {
acceptContactRequest(chatInfo.apiId, chatInfo, true, chatModel)
@@ -295,7 +293,7 @@ fun ContactRequestMenuItems(chatInfo: ChatInfo.ContactRequest, chatModel: ChatMo
)
ItemAction(
stringResource(R.string.reject_contact_button),
- Icons.Outlined.Close,
+ painterResource(R.drawable.ic_close),
onClick = {
rejectContactRequest(chatInfo, chatModel)
showMenu.value = false
@@ -308,7 +306,7 @@ fun ContactRequestMenuItems(chatInfo: ChatInfo.ContactRequest, chatModel: ChatMo
fun ContactConnectionMenuItems(chatInfo: ChatInfo.ContactConnection, chatModel: ChatModel, showMenu: MutableState) {
ItemAction(
stringResource(R.string.set_contact_name),
- Icons.Outlined.Edit,
+ painterResource(R.drawable.ic_edit),
onClick = {
ModalManager.shared.showModalCloseable(true) { close ->
ContactConnectionInfoView(chatModel, chatInfo.contactConnection.connReqInv, chatInfo.contactConnection, true, close)
@@ -318,7 +316,7 @@ fun ContactConnectionMenuItems(chatInfo: ChatInfo.ContactConnection, chatModel:
)
ItemAction(
stringResource(R.string.delete_verb),
- Icons.Outlined.Delete,
+ painterResource(R.drawable.ic_delete),
onClick = {
deleteContactConnectionAlert(chatInfo.contactConnection, chatModel) {}
showMenu.value = false
@@ -330,7 +328,7 @@ fun ContactConnectionMenuItems(chatInfo: ChatInfo.ContactConnection, chatModel:
@Composable
private fun InvalidDataView() {
Row {
- ProfileImage(72.dp, null, Icons.Filled.AccountCircle, HighOrLowlight)
+ ProfileImage(72.dp, null, R.drawable.ic_account_circle_filled, HighOrLowlight)
Column(
modifier = Modifier
.padding(horizontal = 8.dp)
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..1580a265d2 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
@@ -7,15 +7,13 @@ import androidx.compose.foundation.lazy.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.*
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.*
import androidx.compose.ui.platform.LocalUriHandler
+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
@@ -67,10 +65,10 @@ 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) },
+ drawerScrimColor = MaterialTheme.colors.onSurface.copy(alpha = if (isInDarkTheme()) 0.16f else 0.32f),
floatingActionButton = {
if (searchInList.isEmpty()) {
FloatingActionButton(
@@ -79,6 +77,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,
@@ -88,7 +87,7 @@ fun ChatListView(chatModel: ChatModel, setPerformLA: (Boolean, FragmentActivity)
backgroundColor = if (!stopped) MaterialTheme.colors.primary else HighOrLowlight,
contentColor = Color.White
) {
- Icon(if (!newChatSheetState.collectAsState().value.isVisible()) Icons.Default.Edit else Icons.Default.Close, stringResource(R.string.add_contact_or_create_group))
+ Icon(if (!newChatSheetState.collectAsState().value.isVisible()) painterResource(R.drawable.ic_edit_filled) else painterResource(R.drawable.ic_close), stringResource(R.string.add_contact_or_create_group))
}
}
}
@@ -181,7 +180,7 @@ private fun ChatListToolbar(chatModel: ChatModel, drawerState: DrawerState, user
if (chatModel.chats.size >= 8) {
barButtons.add {
IconButton({ showSearch = true }) {
- Icon(Icons.Outlined.Search, stringResource(android.R.string.search_go).capitalize(Locale.current), tint = MaterialTheme.colors.primary)
+ Icon(painterResource(R.drawable.ic_search_500), stringResource(android.R.string.search_go).capitalize(Locale.current), tint = MaterialTheme.colors.primary)
}
}
}
@@ -194,7 +193,7 @@ private fun ChatListToolbar(chatModel: ChatModel, drawerState: DrawerState, user
)
}) {
Icon(
- Icons.Filled.Report,
+ painterResource(R.drawable.ic_report_filled),
generalGetString(R.string.chat_is_stopped_indication),
tint = Color.Red,
)
@@ -231,7 +230,7 @@ private fun ChatListToolbar(chatModel: ChatModel, drawerState: DrawerState, user
)
if (chatModel.incognito.value) {
Icon(
- Icons.Filled.TheaterComedy,
+ painterResource(R.drawable.ic_theater_comedy_filled),
stringResource(R.string.incognito),
tint = Indigo,
modifier = Modifier.padding(10.dp).size(26.dp)
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatPreviewView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatPreviewView.kt
index 30c4a360c3..1c641f696a 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatPreviewView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatPreviewView.kt
@@ -7,15 +7,12 @@ import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.text.InlineTextContent
import androidx.compose.foundation.text.appendInlineContent
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.*
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.*
import androidx.compose.ui.text.font.FontWeight
@@ -46,7 +43,7 @@ fun ChatPreviewView(
@Composable
fun groupInactiveIcon() {
Icon(
- Icons.Filled.Cancel,
+ painterResource(R.drawable.ic_cancel_filled),
stringResource(R.string.icon_descr_group_inactive),
Modifier.size(18.dp).background(MaterialTheme.colors.background, CircleShape),
tint = HighOrLowlight
@@ -79,15 +76,15 @@ fun ChatPreviewView(
@Composable
fun VerifiedIcon() {
- Icon(Icons.Outlined.VerifiedUser, null, Modifier.size(19.dp).padding(end = 3.dp, top = 1.dp), tint = HighOrLowlight)
+ Icon(painterResource(R.drawable.ic_verified_user), null, Modifier.size(19.dp).padding(end = 3.dp, top = 1.dp), tint = HighOrLowlight)
}
fun messageDraft(draft: ComposeState): Pair> {
- fun attachment(): Pair? =
+ fun attachment(): Pair? =
when (draft.preview) {
- is ComposePreview.FilePreview -> Icons.Filled.InsertDriveFile to draft.preview.fileName
- is ComposePreview.MediaPreview -> Icons.Outlined.Image to null
- is ComposePreview.VoicePreview -> Icons.Filled.PlayArrow to durationText(draft.preview.durationMs / 1000)
+ is ComposePreview.FilePreview -> R.drawable.ic_draft_filled to draft.preview.fileName
+ is ComposePreview.MediaPreview -> R.drawable.ic_image to null
+ is ComposePreview.VoicePreview -> R.drawable.ic_play_arrow_filled to durationText(draft.preview.durationMs / 1000)
else -> null
}
@@ -108,12 +105,12 @@ fun ChatPreviewView(
"editIcon" to InlineTextContent(
Placeholder(20.sp, 20.sp, PlaceholderVerticalAlign.TextCenter)
) {
- Icon(Icons.Outlined.EditNote, null, tint = MaterialTheme.colors.primary)
+ Icon(painterResource(R.drawable.ic_edit_note), null, tint = MaterialTheme.colors.primary)
},
"attachmentIcon" to InlineTextContent(
Placeholder(20.sp, 20.sp, PlaceholderVerticalAlign.TextCenter)
) {
- Icon(attachment?.first ?: Icons.Outlined.EditNote, null, tint = HighOrLowlight)
+ Icon(if (attachment?.first != null) painterResource(attachment.first) else painterResource(R.drawable.ic_edit_note), null, tint = HighOrLowlight)
}
)
return text to inlineContent
@@ -239,7 +236,7 @@ fun ChatPreviewView(
contentAlignment = Alignment.Center
) {
Icon(
- Icons.Filled.NotificationsOff,
+ painterResource(R.drawable.ic_notifications_off_filled),
contentDescription = generalGetString(R.string.notifications),
tint = HighOrLowlight,
modifier = Modifier
@@ -281,7 +278,7 @@ fun ChatStatusImage(s: NetworkStatus?) {
val descr = s?.statusString
if (s is NetworkStatus.Error) {
Icon(
- Icons.Outlined.ErrorOutline,
+ painterResource(R.drawable.ic_error),
contentDescription = descr,
tint = HighOrLowlight,
modifier = Modifier
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ContactConnectionView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ContactConnectionView.kt
index 31c43ead06..9e4cd20cad 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ContactConnectionView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ContactConnectionView.kt
@@ -3,16 +3,16 @@ package chat.simplex.app.views.chatlist
import androidx.compose.foundation.layout.*
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
-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.LocalDensity
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
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.helpers.ProfileImage
@@ -21,7 +21,7 @@ import chat.simplex.app.views.helpers.ProfileImage
fun ContactConnectionView(contactConnection: PendingContactConnection) {
Row {
Box(Modifier.size(72.dp), contentAlignment = Alignment.Center) {
- ProfileImage(size = 54.dp, null, if (contactConnection.initiated) Icons.Outlined.AddLink else Icons.Outlined.Link)
+ ProfileImage(size = 54.dp, null, if (contactConnection.initiated) R.drawable.ic_add_link else R.drawable.ic_link)
}
Column(
modifier = Modifier
@@ -42,7 +42,6 @@ fun ContactConnectionView(contactConnection: PendingContactConnection) {
val ts = getTimestampText(contactConnection.updatedAt)
Column(
Modifier.fillMaxHeight(),
- verticalArrangement = Arrangement.Top
) {
Text(
ts,
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ContactRequestView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ContactRequestView.kt
index f1d6acd20b..064cb4a66a 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ContactRequestView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ContactRequestView.kt
@@ -39,7 +39,6 @@ fun ContactRequestView(chatModelIncognito: Boolean, contactRequest: ChatInfo.Con
val ts = getTimestampText(contactRequest.contactRequest.updatedAt)
Column(
Modifier.fillMaxHeight(),
- verticalArrangement = Arrangement.Top
) {
Text(
ts,
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ShareListView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ShareListView.kt
index c99c4c4055..f601e65378 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ShareListView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ShareListView.kt
@@ -6,14 +6,12 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.*
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
+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
@@ -86,7 +84,7 @@ private fun ShareListToolbar(chatModel: ChatModel, userPickerState: MutableState
if (chatModel.chats.size >= 8) {
barButtons.add {
IconButton({ showSearch = true }) {
- Icon(Icons.Outlined.Search, stringResource(android.R.string.search_go).capitalize(Locale.current), tint = MaterialTheme.colors.primary)
+ Icon(painterResource(R.drawable.ic_search_500), stringResource(android.R.string.search_go).capitalize(Locale.current), tint = MaterialTheme.colors.primary)
}
}
}
@@ -99,7 +97,7 @@ private fun ShareListToolbar(chatModel: ChatModel, userPickerState: MutableState
)
}) {
Icon(
- Icons.Filled.Report,
+ painterResource(R.drawable.ic_report_filled),
generalGetString(R.string.chat_is_stopped_indication),
tint = Color.Red,
)
@@ -123,7 +121,7 @@ private fun ShareListToolbar(chatModel: ChatModel, userPickerState: MutableState
)
if (chatModel.incognito.value) {
Icon(
- Icons.Filled.TheaterComedy,
+ painterResource(R.drawable.ic_theater_comedy_filled),
stringResource(R.string.incognito),
tint = Indigo,
modifier = Modifier.padding(10.dp).size(26.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..d073d2d2de 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
@@ -1,7 +1,6 @@
package chat.simplex.app.views.chatlist
import SectionItemView
-import SectionItemViewSpaceBetween
import android.util.Log
import androidx.compose.animation.core.*
import androidx.compose.foundation.*
@@ -9,9 +8,6 @@ import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.*
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.*
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.ui.*
import androidx.compose.ui.draw.*
@@ -19,6 +15,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.capitalize
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.intl.Locale
@@ -110,12 +107,12 @@ fun UserPicker(
.width(IntrinsicSize.Min)
.height(IntrinsicSize.Min)
.shadow(8.dp, RoundedCornerShape(corner = CornerSize(25.dp)), clip = true)
- .background(if (isInDarkTheme()) Color(0xff222222) else MaterialTheme.colors.background, RoundedCornerShape(corner = CornerSize(25.dp)))
+ .background(if (isInDarkTheme()) DarkGrayBackground else MaterialTheme.colors.background, RoundedCornerShape(corner = CornerSize(25.dp)))
.clip(RoundedCornerShape(corner = CornerSize(25.dp)))
) {
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_HALF, end = DEFAULT_PADDING), openSettings = {
settingsClicked()
userPickerState.value = AnimatedViewState.GONE
}) {
@@ -153,7 +150,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_HALF, end = DEFAULT_PADDING), onLongClick: () -> Unit = {}, openSettings: () -> Unit = {}, onClick: () -> Unit) {
Row(
Modifier
.fillMaxWidth()
@@ -170,27 +167,25 @@ fun UserProfilePickerItem(u: User, unreadCount: Int = 0, padding: PaddingValues
) {
UserProfileRow(u)
if (u.activeUser) {
- Icon(Icons.Filled.Done, null, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground)
+ Icon(painterResource(R.drawable.ic_done_filled), null, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground)
} else if (u.hidden) {
- Icon(Icons.Outlined.Lock, null, Modifier.size(20.dp), tint = HighOrLowlight)
+ Icon(painterResource(R.drawable.ic_lock), null, Modifier.size(20.dp), tint = HighOrLowlight)
} else if (unreadCount > 0) {
- Row {
+ Box(
+ contentAlignment = Alignment.Center
+ ) {
Text(
unreadCountStr(unreadCount),
color = Color.White,
fontSize = 11.sp,
modifier = Modifier
.background(if (u.showNtfs) MaterialTheme.colors.primary else HighOrLowlight, shape = CircleShape)
- .sizeIn(minWidth = 20.dp, minHeight = 20.dp)
- .padding(horizontal = 3.dp)
- .padding(vertical = 1.dp),
- textAlign = TextAlign.Center,
- maxLines = 1
+ .padding(2.dp)
+ .badgeLayout()
)
- Spacer(Modifier.width(2.dp))
}
} else if (!u.showNtfs) {
- Icon(Icons.Outlined.NotificationsOff, null, Modifier.size(20.dp), tint = HighOrLowlight)
+ Icon(painterResource(R.drawable.ic_notifications_off), null, Modifier.size(20.dp), tint = HighOrLowlight)
} else {
Box(Modifier.size(20.dp))
}
@@ -212,7 +207,7 @@ fun UserProfileRow(u: User) {
Text(
u.displayName,
modifier = Modifier
- .padding(start = 8.dp, end = 8.dp),
+ .padding(start = 10.dp, end = 8.dp),
color = if (isInDarkTheme()) MenuTextColorDark else Color.Black,
fontWeight = if (u.activeUser) FontWeight.Medium else FontWeight.Normal
)
@@ -221,10 +216,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 + 7.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))
+ Icon(painterResource(R.drawable.ic_settings), text, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground)
+ Spacer(Modifier.width(DEFAULT_PADDING + 6.dp))
Text(
text,
color = if (isInDarkTheme()) MenuTextColorDark else Color.Black,
@@ -234,10 +229,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 + 7.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))
+ Icon(painterResource(R.drawable.ic_close), text, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground)
+ Spacer(Modifier.width(DEFAULT_PADDING + 6.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..5dc5b55faf 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,6 @@
package chat.simplex.app.views.database
-import SectionDivider
+import SectionBottomSpacer
import SectionTextFooter
import SectionView
import android.content.Context
@@ -13,16 +13,14 @@ import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
-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.graphics.Color
import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.painterResource
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
@@ -57,20 +55,18 @@ fun ChatArchiveLayout(
) {
Column(
Modifier.fillMaxWidth(),
- horizontalAlignment = Alignment.Start,
) {
AppBarTitle(title)
SectionView(stringResource(R.string.chat_archive_section)) {
SettingsActionItem(
- Icons.Outlined.IosShare,
+ painterResource(R.drawable.ic_ios_share),
stringResource(R.string.save_archive),
saveArchive,
textColor = MaterialTheme.colors.primary,
iconColor = MaterialTheme.colors.primary,
)
- SectionDivider()
SettingsActionItem(
- Icons.Outlined.Delete,
+ painterResource(R.drawable.ic_delete),
stringResource(R.string.delete_archive),
deleteArchiveAlert,
textColor = Color.Red,
@@ -81,6 +77,7 @@ fun ChatArchiveLayout(
SectionTextFooter(
String.format(generalGetString(R.string.archive_created_on_ts), archiveTs)
)
+ SectionBottomSpacer()
}
}
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..a2e5993e07 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,6 @@
package chat.simplex.app.views.database
-import SectionDivider
+import SectionBottomSpacer
import SectionItemView
import SectionItemViewSpaceBetween
import SectionTextFooter
@@ -12,15 +12,13 @@ import androidx.compose.foundation.shape.ZeroCornerSize
import androidx.compose.foundation.text.*
import androidx.compose.material.*
import androidx.compose.material.TextFieldDefaults.indicatorLine
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.*
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.*
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.*
import androidx.compose.ui.text.font.FontWeight
@@ -137,7 +135,6 @@ fun DatabaseEncryptionLayout(
) {
Column(
Modifier.fillMaxWidth().verticalScroll(rememberScrollState()),
- horizontalAlignment = Alignment.Start,
) {
AppBarTitle(stringResource(R.string.database_passphrase))
SectionView(null) {
@@ -162,8 +159,6 @@ fun DatabaseEncryptionLayout(
}
if (!initialRandomDBPassphrase.value && chatDbEncrypted == true) {
- SectionDivider()
-
PassphraseField(
currentKey,
generalGetString(R.string.current_passphrase),
@@ -173,8 +168,6 @@ fun DatabaseEncryptionLayout(
)
}
- SectionDivider()
-
PassphraseField(
newKey,
generalGetString(R.string.new_passphrase),
@@ -206,8 +199,6 @@ fun DatabaseEncryptionLayout(
!validKey(newKey.value) ||
progressIndicator.value
- SectionDivider()
-
PassphraseField(
confirmNewKey,
generalGetString(R.string.confirm_new_passphrase),
@@ -219,8 +210,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)
}
@@ -245,6 +234,7 @@ fun DatabaseEncryptionLayout(
SectionTextFooter(generalGetString(R.string.impossible_to_recover_passphrase))
}
}
+ SectionBottomSpacer()
}
}
@@ -300,7 +290,7 @@ fun SavePassphraseSetting(
SectionItemView(minHeight = minHeight) {
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(
- if (storedKey) Icons.Filled.VpnKey else Icons.Filled.VpnKeyOff,
+ if (storedKey) painterResource(R.drawable.ic_vpn_key_filled) else painterResource(R.drawable.ic_vpn_key_off_filled),
stringResource(R.string.save_passphrase_in_keychain),
tint = if (storedKey) SimplexGreen else HighOrLowlight
)
@@ -311,13 +301,9 @@ fun SavePassphraseSetting(
color = Color.Unspecified
)
Spacer(Modifier.fillMaxWidth().weight(1f))
- Switch(
+ DefaultSwitch(
checked = useKeychain,
onCheckedChange = onCheckedChange,
- colors = SwitchDefaults.colors(
- checkedThumbColor = MaterialTheme.colors.primary,
- uncheckedThumbColor = HighOrLowlight
- ),
enabled = !initialRandomDBPassphrase && !progressIndicator
)
}
@@ -371,8 +357,8 @@ fun PassphraseField(
var valid by remember { mutableStateOf(validKey(key.value)) }
var showKey by remember { mutableStateOf(false) }
val icon = if (valid) {
- if (showKey) Icons.Filled.VisibilityOff else Icons.Filled.Visibility
- } else Icons.Outlined.Error
+ if (showKey) painterResource(R.drawable.ic_visibility_off_filled) else painterResource(R.drawable.ic_visibility_filled)
+ } else painterResource(R.drawable.ic_error)
val iconColor = if (valid) {
if (showStrength && key.value.isNotEmpty()) PassphraseStrength.check(key.value).color else HighOrLowlight
} else Color.Red
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..410bdea630 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
@@ -1,5 +1,6 @@
package chat.simplex.app.views.database
+import SectionBottomSpacer
import SectionSpacer
import SectionView
import android.content.Context
@@ -61,7 +62,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)
@@ -79,7 +80,6 @@ fun DatabaseErrorView(
Column(
Modifier.fillMaxSize().verticalScroll(rememberScrollState()),
- horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.Center,
) {
val buttonEnabled = validKey(dbKey.value) && !progressIndicator.value
@@ -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),
@@ -169,6 +169,7 @@ fun DatabaseErrorView(
)
}
}
+ SectionBottomSpacer()
}
if (progressIndicator.value) {
Box(
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..8ac6f8cb40 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,9 @@
package chat.simplex.app.views.database
-import SectionDivider
+import SectionBottomSpacer
+import SectionDividerSpaced
import SectionTextFooter
import SectionItemView
-import SectionSpacer
import SectionView
import android.content.Context
import android.content.res.Configuration
@@ -17,14 +17,12 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.*
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.*
import androidx.compose.ui.text.font.FontWeight
@@ -154,13 +152,12 @@ fun DatabaseLayout(
val operationsDisabled = !stopped || progressIndicator
Column(
- Modifier.fillMaxWidth().verticalScroll(rememberScrollState()).padding(bottom = DEFAULT_BOTTOM_PADDING),
- horizontalAlignment = Alignment.Start,
+ Modifier.fillMaxWidth().verticalScroll(rememberScrollState()),
) {
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,27 +170,28 @@ fun DatabaseLayout(
}
}
)
- SectionSpacer()
+ SectionDividerSpaced(maxTopPadding = true)
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
SettingsActionItem(
- if (unencrypted) Icons.Outlined.LockOpen else if (useKeyChain) Icons.Filled.VpnKey else Icons.Outlined.Lock,
+ if (unencrypted) painterResource(R.drawable.ic_lock_open) else if (useKeyChain) painterResource(R.drawable.ic_vpn_key_filled)
+ else painterResource(R
+ .drawable.ic_lock),
stringResource(R.string.database_passphrase),
click = showSettingsModal() { DatabaseEncryptionView(it) },
iconColor = if (unencrypted) WarningOrange else HighOrLowlight,
disabled = operationsDisabled
)
- SectionDivider()
AppDataBackupPreference(privacyFullBackup, initialRandomDBPassphrase)
- SectionDivider()
+ SectionDividerSpaced(maxBottomPadding = false)
SettingsActionItem(
- Icons.Outlined.IosShare,
+ painterResource(R.drawable.ic_ios_share),
stringResource(R.string.export_database),
click = {
if (initialRandomDBPassphrase.get()) {
@@ -206,31 +204,28 @@ fun DatabaseLayout(
iconColor = MaterialTheme.colors.primary,
disabled = operationsDisabled
)
- SectionDivider()
SettingsActionItem(
- Icons.Outlined.FileDownload,
+ painterResource(R.drawable.ic_download),
stringResource(R.string.import_database),
{ importArchiveLauncher.launch("application/zip") },
textColor = Color.Red,
iconColor = Color.Red,
disabled = operationsDisabled
)
- SectionDivider()
val chatArchiveNameVal = chatArchiveName.value
val chatArchiveTimeVal = chatArchiveTime.value
val chatLastStartVal = chatLastStart.value
if (chatArchiveNameVal != null && chatArchiveTimeVal != null && chatLastStartVal != null) {
val title = chatArchiveTitle(chatArchiveTimeVal, chatLastStartVal)
SettingsActionItem(
- Icons.Outlined.Inventory2,
+ painterResource(R.drawable.ic_inventory_2),
title,
click = showSettingsModal { ChatArchiveView(it, title, chatArchiveNameVal, chatArchiveTimeVal) },
disabled = operationsDisabled
)
- SectionDivider()
}
SettingsActionItem(
- Icons.Outlined.DeleteForever,
+ painterResource(R.drawable.ic_delete_forever),
stringResource(R.string.delete_database),
deleteChatAlert,
textColor = Color.Red,
@@ -245,7 +240,7 @@ fun DatabaseLayout(
stringResource(R.string.stop_chat_to_enable_database_actions)
}
)
- SectionSpacer()
+ SectionDividerSpaced(maxTopPadding = true)
SectionView(stringResource(R.string.files_and_media_section).uppercase()) {
val deleteFilesDisabled = operationsDisabled || appFilesCountAndSize.value.first == 0
@@ -267,35 +262,23 @@ fun DatabaseLayout(
String.format(stringResource(R.string.total_files_count_and_size), count, formatBytes(size))
}
)
+ SectionBottomSpacer()
}
}
@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(
+ painterResource(R.drawable.ic_backup),
+ iconColor = HighOrLowlight,
+ pref = privacyFullBackup,
+ text = stringResource(R.string.full_backup)
+ ) {
+ if (initialRandomDBPassphrase.get()) {
+ exportProhibitedAlert()
+ privacyFullBackup.set(false)
+ } else {
+ privacyFullBackup.set(it)
}
}
}
@@ -350,36 +333,23 @@ 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) painterResource(R.drawable.ic_report_filled) else painterResource(R.drawable.ic_play_arrow_filled),
+ text = chatRunningText,
+ iconColor = if (stopped) Color.Red else MaterialTheme.colors.primary,
+ ) {
+ DefaultSwitch(
+ enabled = !chatDbDeleted,
+ checked = runChat,
+ onCheckedChange = { runChatSwitch ->
+ if (runChatSwitch) {
+ startChat()
+ } else {
+ stopChatAlert()
+ }
+ },
+ )
}
}
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..7f07bbe38f 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
@@ -37,7 +37,7 @@ class AlertManager {
) {
showAlert {
AlertDialog(
- backgroundColor = if (isInDarkTheme()) Color(0xff222222) else MaterialTheme.colors.background,
+ backgroundColor = if (isInDarkTheme()) DarkGrayBackground else MaterialTheme.colors.background,
onDismissRequest = this::hideAlert,
title = alertTitle(title),
text = alertText(text),
@@ -56,7 +56,7 @@ class AlertManager {
Dialog(onDismissRequest = this::hideAlert) {
Column(
Modifier
- .background(if (isInDarkTheme()) Color(0xff222222) else MaterialTheme.colors.background, RoundedCornerShape(corner = CornerSize(25.dp)))
+ .background(if (isInDarkTheme()) DarkGrayBackground else MaterialTheme.colors.background, RoundedCornerShape(corner = CornerSize(25.dp)))
.padding(bottom = DEFAULT_PADDING)
) {
Text(
@@ -106,7 +106,7 @@ class AlertManager {
}) { Text(confirmText, color = if (destructive) MaterialTheme.colors.error else Color.Unspecified) }
}
},
- backgroundColor = if (isInDarkTheme()) Color(0xff222222) else MaterialTheme.colors.background,
+ backgroundColor = if (isInDarkTheme()) DarkGrayBackground else MaterialTheme.colors.background,
shape = RoundedCornerShape(corner = CornerSize(25.dp))
)
}
@@ -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 = {
@@ -142,7 +142,7 @@ class AlertManager {
}) { Text(confirmText, color = if (destructive) Color.Red else Color.Unspecified, textAlign = TextAlign.End) }
}
},
- backgroundColor = if (isInDarkTheme()) Color(0xff222222) else MaterialTheme.colors.background,
+ backgroundColor = if (isInDarkTheme()) DarkGrayBackground else MaterialTheme.colors.background,
shape = RoundedCornerShape(corner = CornerSize(25.dp))
)
}
@@ -168,7 +168,7 @@ class AlertManager {
}) { Text(confirmText, color = Color.Unspecified) }
}
},
- backgroundColor = if (isInDarkTheme()) Color(0xff222222) else MaterialTheme.colors.background,
+ backgroundColor = if (isInDarkTheme()) DarkGrayBackground else MaterialTheme.colors.background,
shape = RoundedCornerShape(corner = CornerSize(25.dp))
)
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ChatInfoImage.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ChatInfoImage.kt
index f1d6fa9caa..04d2744484 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ChatInfoImage.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ChatInfoImage.kt
@@ -5,15 +5,12 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.asImageBitmap
-import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.*
import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
@@ -25,8 +22,8 @@ import chat.simplex.app.ui.theme.SimpleXTheme
@Composable
fun ChatInfoImage(chatInfo: ChatInfo, size: Dp, iconColor: Color = MaterialTheme.colors.secondary) {
val icon =
- if (chatInfo is ChatInfo.Group) Icons.Filled.SupervisedUserCircle
- else Icons.Filled.AccountCircle
+ if (chatInfo is ChatInfo.Group) R.drawable.ic_supervised_user_circle_filled
+ else R.drawable.ic_account_circle_filled
ProfileImage(size, chatInfo.image, icon, iconColor)
}
@@ -34,7 +31,7 @@ fun ChatInfoImage(chatInfo: ChatInfo, size: Dp, iconColor: Color = MaterialTheme
fun IncognitoImage(size: Dp, iconColor: Color = MaterialTheme.colors.secondary) {
Box(Modifier.size(size)) {
Icon(
- Icons.Filled.TheaterComedy, stringResource(R.string.incognito),
+ painterResource(R.drawable.ic_theater_comedy_filled), stringResource(R.string.incognito),
modifier = Modifier.size(size).padding(size / 12),
iconColor
)
@@ -45,17 +42,31 @@ fun IncognitoImage(size: Dp, iconColor: Color = MaterialTheme.colors.secondary)
fun ProfileImage(
size: Dp,
image: String? = null,
- icon: ImageVector = Icons.Filled.AccountCircle,
+ icon: Int = R.drawable.ic_account_circle_filled,
color: Color = MaterialTheme.colors.secondary
) {
Box(Modifier.size(size)) {
if (image == null) {
- Icon(
- icon,
- contentDescription = stringResource(R.string.icon_descr_profile_image_placeholder),
- tint = color,
- modifier = Modifier.fillMaxSize()
- )
+ val iconToReplace = when (icon) {
+ R.drawable.ic_account_circle_filled -> AccountCircleFilled
+ R.drawable.ic_supervised_user_circle_filled -> SupervisedUserCircleFilled
+ else -> null
+ }
+ if (iconToReplace != null) {
+ Icon(
+ iconToReplace,
+ contentDescription = stringResource(R.string.icon_descr_profile_image_placeholder),
+ tint = color,
+ modifier = Modifier.fillMaxSize()
+ )
+ } else {
+ Icon(
+ painterResource(icon),
+ contentDescription = stringResource(R.string.icon_descr_profile_image_placeholder),
+ tint = color,
+ modifier = Modifier.fillMaxSize()
+ )
+ }
} else {
val imageBitmap = base64ToBitmap(image).asImageBitmap()
Image(
@@ -68,6 +79,7 @@ fun ProfileImage(
}
}
+
@Preview
@Composable
fun PreviewChatInfoImage() {
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ChooseAttachmentView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ChooseAttachmentView.kt
index 9c4e6ad5d6..5ca600a0b3 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ChooseAttachmentView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ChooseAttachmentView.kt
@@ -2,8 +2,6 @@ package chat.simplex.app.views.helpers
import androidx.compose.foundation.layout.*
import androidx.compose.material.MaterialTheme
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.ui.Alignment
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/CustomIcons.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/CustomIcons.kt
new file mode 100644
index 0000000000..1ed7d3a954
--- /dev/null
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/CustomIcons.kt
@@ -0,0 +1,143 @@
+package chat.simplex.app.views.helpers
+
+import androidx.compose.material.icons.materialIcon
+import androidx.compose.material.icons.materialPath
+import androidx.compose.ui.graphics.vector.*
+
+val AccountCircleFilled: ImageVector
+ get() {
+ if (_accountCircleFilled != null) {
+ return _accountCircleFilled!!
+ }
+ _accountCircleFilled = materialIcon(name = "Filled.AccountCircle") {
+ materialPath {
+ moveTo(12.0f, 2.0f)
+ curveTo(6.48f, 2.0f, 2.0f, 6.48f, 2.0f, 12.0f)
+ reflectiveCurveToRelative(4.48f, 10.0f, 10.0f, 10.0f)
+ reflectiveCurveToRelative(10.0f, -4.48f, 10.0f, -10.0f)
+ reflectiveCurveTo(17.52f, 2.0f, 12.0f, 2.0f)
+ close()
+ moveTo(12.0f, 5.0f)
+ curveToRelative(1.66f, 0.0f, 3.0f, 1.34f, 3.0f, 3.0f)
+ reflectiveCurveToRelative(-1.34f, 3.0f, -3.0f, 3.0f)
+ reflectiveCurveToRelative(-3.0f, -1.34f, -3.0f, -3.0f)
+ reflectiveCurveToRelative(1.34f, -3.0f, 3.0f, -3.0f)
+ close()
+ moveTo(12.0f, 19.2f)
+ curveToRelative(-2.5f, 0.0f, -4.71f, -1.28f, -6.0f, -3.22f)
+ curveToRelative(0.03f, -1.99f, 4.0f, -3.08f, 6.0f, -3.08f)
+ curveToRelative(1.99f, 0.0f, 5.97f, 1.09f, 6.0f, 3.08f)
+ curveToRelative(-1.29f, 1.94f, -3.5f, 3.22f, -6.0f, 3.22f)
+ close()
+ }
+ }
+ return _accountCircleFilled!!
+ }
+
+private var _accountCircleFilled: ImageVector? = null
+
+val SupervisedUserCircleFilled: ImageVector
+ get() {
+ if (_supervisedUserCircleFilled != null) {
+ return _supervisedUserCircleFilled!!
+ }
+ _supervisedUserCircleFilled = materialIcon(name = "Filled.SupervisedUserCircle") {
+ materialPath {
+ moveTo(11.99f, 2.0f)
+ curveToRelative(-5.52f, 0.0f, -10.0f, 4.48f, -10.0f, 10.0f)
+ reflectiveCurveToRelative(4.48f, 10.0f, 10.0f, 10.0f)
+ reflectiveCurveToRelative(10.0f, -4.48f, 10.0f, -10.0f)
+ reflectiveCurveToRelative(-4.48f, -10.0f, -10.0f, -10.0f)
+ close()
+ moveTo(15.6f, 8.34f)
+ curveToRelative(1.07f, 0.0f, 1.93f, 0.86f, 1.93f, 1.93f)
+ curveToRelative(0.0f, 1.07f, -0.86f, 1.93f, -1.93f, 1.93f)
+ curveToRelative(-1.07f, 0.0f, -1.93f, -0.86f, -1.93f, -1.93f)
+ curveToRelative(-0.01f, -1.07f, 0.86f, -1.93f, 1.93f, -1.93f)
+ close()
+ moveTo(9.6f, 6.76f)
+ curveToRelative(1.3f, 0.0f, 2.36f, 1.06f, 2.36f, 2.36f)
+ curveToRelative(0.0f, 1.3f, -1.06f, 2.36f, -2.36f, 2.36f)
+ reflectiveCurveToRelative(-2.36f, -1.06f, -2.36f, -2.36f)
+ curveToRelative(0.0f, -1.31f, 1.05f, -2.36f, 2.36f, -2.36f)
+ close()
+ moveTo(9.6f, 15.89f)
+ verticalLineToRelative(3.75f)
+ curveToRelative(-2.4f, -0.75f, -4.3f, -2.6f, -5.14f, -4.96f)
+ curveToRelative(1.05f, -1.12f, 3.67f, -1.69f, 5.14f, -1.69f)
+ curveToRelative(0.53f, 0.0f, 1.2f, 0.08f, 1.9f, 0.22f)
+ curveToRelative(-1.64f, 0.87f, -1.9f, 2.02f, -1.9f, 2.68f)
+ close()
+ moveTo(11.99f, 20.0f)
+ curveToRelative(-0.27f, 0.0f, -0.53f, -0.01f, -0.79f, -0.04f)
+ verticalLineToRelative(-4.07f)
+ curveToRelative(0.0f, -1.42f, 2.94f, -2.13f, 4.4f, -2.13f)
+ curveToRelative(1.07f, 0.0f, 2.92f, 0.39f, 3.84f, 1.15f)
+ curveToRelative(-1.17f, 2.97f, -4.06f, 5.09f, -7.45f, 5.09f)
+ close()
+ }
+ }
+ return _supervisedUserCircleFilled!!
+ }
+
+private var _supervisedUserCircleFilled: ImageVector? = null
+
+val BoltFilled: ImageVector
+ get() {
+ if (_boltFilled != null) {
+ return _boltFilled!!
+ }
+ _boltFilled = materialIcon(name = "Filled.Bolt") {
+ materialPath {
+ moveTo(11.0f, 21.0f)
+ horizontalLineToRelative(-1.0f)
+ lineToRelative(1.0f, -7.0f)
+ horizontalLineTo(7.5f)
+ curveToRelative(-0.58f, 0.0f, -0.57f, -0.32f, -0.38f, -0.66f)
+ curveToRelative(0.19f, -0.34f, 0.05f, -0.08f, 0.07f, -0.12f)
+ curveTo(8.48f, 10.94f, 10.42f, 7.54f, 13.0f, 3.0f)
+ horizontalLineToRelative(1.0f)
+ lineToRelative(-1.0f, 7.0f)
+ horizontalLineToRelative(3.5f)
+ curveToRelative(0.49f, 0.0f, 0.56f, 0.33f, 0.47f, 0.51f)
+ lineToRelative(-0.07f, 0.15f)
+ curveTo(12.96f, 17.55f, 11.0f, 21.0f, 11.0f, 21.0f)
+ close()
+ }
+ }
+ return _boltFilled!!
+ }
+
+private var _boltFilled: ImageVector? = null
+
+val MoreVertFilled: ImageVector
+ get() {
+ if (_moreVertFilled != null) {
+ return _moreVertFilled!!
+ }
+ _moreVertFilled = materialIcon(name = "Filled.MoreVert") {
+ materialPath {
+ moveTo(12.0f, 8.0f)
+ curveToRelative(1.1f, 0.0f, 2.0f, -0.9f, 2.0f, -2.0f)
+ reflectiveCurveToRelative(-0.9f, -2.0f, -2.0f, -2.0f)
+ reflectiveCurveToRelative(-2.0f, 0.9f, -2.0f, 2.0f)
+ reflectiveCurveToRelative(0.9f, 2.0f, 2.0f, 2.0f)
+ close()
+ moveTo(12.0f, 10.0f)
+ curveToRelative(-1.1f, 0.0f, -2.0f, 0.9f, -2.0f, 2.0f)
+ reflectiveCurveToRelative(0.9f, 2.0f, 2.0f, 2.0f)
+ reflectiveCurveToRelative(2.0f, -0.9f, 2.0f, -2.0f)
+ reflectiveCurveToRelative(-0.9f, -2.0f, -2.0f, -2.0f)
+ close()
+ moveTo(12.0f, 16.0f)
+ curveToRelative(-1.1f, 0.0f, -2.0f, 0.9f, -2.0f, 2.0f)
+ reflectiveCurveToRelative(0.9f, 2.0f, 2.0f, 2.0f)
+ reflectiveCurveToRelative(2.0f, -0.9f, 2.0f, -2.0f)
+ reflectiveCurveToRelative(-0.9f, -2.0f, -2.0f, -2.0f)
+ close()
+ }
+ }
+ return _moreVertFilled!!
+ }
+
+private var _moreVertFilled: ImageVector? = null
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultBasicTextField.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultBasicTextField.kt
index 18253a3a69..e3d4048cfa 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultBasicTextField.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultBasicTextField.kt
@@ -8,10 +8,6 @@ import androidx.compose.foundation.shape.ZeroCornerSize
import androidx.compose.foundation.text.*
import androidx.compose.material.*
import androidx.compose.material.TextFieldDefaults.indicatorLine
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Visibility
-import androidx.compose.material.icons.filled.VisibilityOff
-import androidx.compose.material.icons.outlined.Error
import androidx.compose.runtime.*
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
@@ -19,11 +15,13 @@ import androidx.compose.ui.focus.*
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.*
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.*
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
+import chat.simplex.app.R
import chat.simplex.app.ui.theme.HighOrLowlight
import chat.simplex.app.views.database.PassphraseStrength
import chat.simplex.app.views.database.validKey
@@ -136,8 +134,8 @@ fun DefaultConfigurableTextField(
var valid by remember { mutableStateOf(validKey(state.value.text)) }
var showKey by remember { mutableStateOf(false) }
val icon = if (valid) {
- if (showKey) Icons.Filled.VisibilityOff else Icons.Filled.Visibility
- } else Icons.Outlined.Error
+ if (showKey) painterResource(R.drawable.ic_visibility_off_filled) else painterResource(R.drawable.ic_visibility_filled)
+ } else painterResource(R.drawable.ic_error)
val iconColor = if (valid) {
if (showPasswordStrength && state.value.text.isNotEmpty()) PassphraseStrength.check(state.value.text).color else HighOrLowlight
} else Color.Red
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultDropdownMenu.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultDropdownMenu.kt
index 0cb501e7f4..e6ec87e14d 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultDropdownMenu.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultDropdownMenu.kt
@@ -19,7 +19,7 @@ fun DefaultDropdownMenu(
dropdownMenuItems: (@Composable () -> Unit)?
) {
MaterialTheme(
- colors = MaterialTheme.colors.copy(surface = if (isInDarkTheme()) Color(0xFF080808) else MaterialTheme.colors.background),
+ colors = MaterialTheme.colors.copy(surface = if (isInDarkTheme()) Color(0xFF0B0B0B) else MaterialTheme.colors.background),
shapes = MaterialTheme.shapes.copy(medium = RoundedCornerShape(corner = CornerSize(25.dp)))
) {
DropdownMenu(
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultSwitch.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultSwitch.kt
new file mode 100644
index 0000000000..251cb8df30
--- /dev/null
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultSwitch.kt
@@ -0,0 +1,40 @@
+package chat.simplex.app.views.helpers
+
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.material.*
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.drawBehind
+import androidx.compose.ui.geometry.*
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.unit.dp
+import chat.simplex.app.ui.theme.HighOrLowlight
+
+@Composable
+fun DefaultSwitch(
+ checked: Boolean,
+ onCheckedChange: ((Boolean) -> Unit)?,
+ modifier: Modifier = Modifier,
+ enabled: Boolean = true,
+ interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
+ colors: SwitchColors = SwitchDefaults.colors(
+ checkedThumbColor = MaterialTheme.colors.primary,
+ uncheckedThumbColor = HighOrLowlight,
+ checkedTrackAlpha = 0.0f,
+ uncheckedTrackAlpha = 0.0f,
+ )
+) {
+ val color = if (checked) MaterialTheme.colors.primary.copy(alpha = 0.3f) else HighOrLowlight.copy(alpha = 0.3f)
+ val size = with(LocalDensity.current) { Size(46.dp.toPx(), 28.dp.toPx()) }
+ val offset = with(LocalDensity.current) { Offset(1.dp.toPx(), 10.dp.toPx()) }
+ val radius = with(LocalDensity.current) { 28.dp.toPx() }
+ Switch(
+ checked = checked,
+ onCheckedChange = onCheckedChange,
+ modifier.drawBehind { drawRoundRect(color, size = size, topLeft = offset, cornerRadius = CornerRadius(radius, radius)) },
+ colors = colors,
+ enabled = enabled,
+ interactionSource = interactionSource,
+ )
+}
\ No newline at end of file
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultTopAppBar.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultTopAppBar.kt
index 6dfe6f3408..225dd393ba 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultTopAppBar.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultTopAppBar.kt
@@ -4,12 +4,11 @@ import chat.simplex.app.R
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.*
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import chat.simplex.app.ui.theme.*
@@ -48,7 +47,7 @@ fun DefaultTopAppBar(
fun NavigationButtonBack(onButtonClicked: (() -> Unit)?) {
IconButton(onButtonClicked ?: {}, enabled = onButtonClicked != null) {
Icon(
- Icons.Outlined.ArrowBackIos, stringResource(R.string.back), tint = if (onButtonClicked != null) MaterialTheme.colors.primary else HighOrLowlight
+ painterResource(R.drawable.ic_arrow_back_ios_new), stringResource(R.string.back), tint = if (onButtonClicked != null) MaterialTheme.colors.primary else HighOrLowlight
)
}
}
@@ -57,7 +56,7 @@ fun NavigationButtonBack(onButtonClicked: (() -> Unit)?) {
fun ShareButton(onButtonClicked: () -> Unit) {
IconButton(onButtonClicked) {
Icon(
- Icons.Outlined.Share, stringResource(R.string.share_verb), tint = MaterialTheme.colors.primary
+ painterResource(R.drawable.ic_share), stringResource(R.string.share_verb), tint = MaterialTheme.colors.primary
)
}
}
@@ -66,7 +65,7 @@ fun ShareButton(onButtonClicked: () -> Unit) {
fun NavigationButtonMenu(onButtonClicked: () -> Unit) {
IconButton(onClick = onButtonClicked) {
Icon(
- Icons.Outlined.Menu,
+ painterResource(R.drawable.ic_menu),
stringResource(R.string.icon_descr_settings),
tint = MaterialTheme.colors.primary,
)
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..7fa87a482c 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
@@ -2,20 +2,19 @@ package chat.simplex.app.views.helpers
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.ExpandLess
-import androidx.compose.material.icons.outlined.ExpandMore
+import androidx.compose.ui.res.painterResource
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.style.TextOverflow
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(
@@ -23,27 +22,13 @@ fun ExposedDropDownSettingRow(
values: List>,
selection: State,
label: String? = null,
- icon: ImageVector? = null,
+ icon: Painter? = null,
iconTint: Color = HighOrLowlight,
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 +40,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),
@@ -65,7 +50,7 @@ fun ExposedDropDownSettingRow(
)
Spacer(Modifier.size(12.dp))
Icon(
- if (!expanded.value) Icons.Outlined.ExpandMore else Icons.Outlined.ExpandLess,
+ if (!expanded.value) painterResource(R.drawable.ic_expand_more) else painterResource(R.drawable.ic_expand_less),
generalGetString(R.string.icon_descr_more_button),
tint = HighOrLowlight
)
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/GetImageView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/GetImageView.kt
index c50d434178..9ad3180ae5 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/GetImageView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/GetImageView.kt
@@ -17,14 +17,13 @@ import androidx.activity.result.contract.ActivityResultContract
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.CallSuper
import androidx.compose.foundation.layout.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.Saver
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat
@@ -247,7 +246,7 @@ fun GetImageBottomSheet(
.padding(horizontal = 8.dp, vertical = 30.dp),
horizontalArrangement = Arrangement.SpaceEvenly
) {
- ActionButton(null, stringResource(R.string.use_camera_button), icon = Icons.Outlined.PhotoCamera) {
+ ActionButton(null, stringResource(R.string.use_camera_button), icon = painterResource(R.drawable.ic_photo_camera)) {
when (PackageManager.PERMISSION_GRANTED) {
ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) -> {
cameraLauncher.launchWithFallback()
@@ -258,7 +257,7 @@ fun GetImageBottomSheet(
}
}
}
- ActionButton(null, stringResource(R.string.from_gallery_button), icon = Icons.Outlined.Image) {
+ ActionButton(null, stringResource(R.string.from_gallery_button), icon = painterResource(R.drawable.ic_image)) {
try {
galleryLauncher.launch(0)
} catch (e: ActivityNotFoundException) {
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/LinkPreviews.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/LinkPreviews.kt
index 47b06b42d1..7624665036 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/LinkPreviews.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/LinkPreviews.kt
@@ -6,13 +6,12 @@ import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.Close
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
@@ -112,7 +111,7 @@ fun ComposeLinkView(linkPreview: LinkPreview?, cancelPreview: () -> Unit) {
}
IconButton(onClick = cancelPreview, modifier = Modifier.padding(0.dp)) {
Icon(
- Icons.Outlined.Close,
+ painterResource(R.drawable.ic_close),
contentDescription = stringResource(R.string.icon_descr_cancel_link_preview),
tint = MaterialTheme.colors.primary,
modifier = Modifier.padding(10.dp)
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/LocalAuthentication.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/LocalAuthentication.kt
index 818f6b247b..403b21899c 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/LocalAuthentication.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/LocalAuthentication.kt
@@ -1,6 +1,7 @@
package chat.simplex.app.views.helpers
import android.os.Build.VERSION.SDK_INT
+import androidx.activity.compose.BackHandler
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricManager.Authenticators.*
import androidx.biometric.BiometricPrompt
@@ -53,6 +54,10 @@ fun authenticate(
LAMode.PASSCODE -> {
val password = ksAppPassword.get() ?: return completed(LAResult.Unavailable(generalGetString(R.string.la_no_app_password)))
ModalManager.shared.showCustomModal(animated = false) { close ->
+ BackHandler {
+ close()
+ completed(LAResult.Error(generalGetString(R.string.authentication_cancelled)))
+ }
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
LocalAuthView(SimplexApp.context.chatModel, LocalAuthRequest(promptTitle, promptSubtitle, password) {
close()
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/SearchTextField.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/SearchTextField.kt
index 38c6a2647b..2655f75e31 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/SearchTextField.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/SearchTextField.kt
@@ -8,8 +8,6 @@ import androidx.compose.foundation.text.*
import androidx.compose.material.*
import androidx.compose.material.TextFieldDefaults.indicatorLine
import androidx.compose.material.TextFieldDefaults.textFieldWithLabelPadding
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Close
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.ExperimentalComposeUiApi
@@ -19,6 +17,7 @@ import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.*
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
@@ -99,7 +98,7 @@ fun SearchTextField(modifier: Modifier, placeholder: String, alwaysVisible: Bool
searchText = TextFieldValue("");
onValueChange("")
}) {
- Icon(Icons.Default.Close, stringResource(R.string.icon_descr_close_button), tint = MaterialTheme.colors.primary,)
+ Icon(painterResource(R.drawable.ic_close), stringResource(R.string.icon_descr_close_button), tint = MaterialTheme.colors.primary,)
}
}} else null,
singleLine = true,
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..2a50888e8e 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
@@ -3,21 +3,22 @@ import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.Check
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.*
+import chat.simplex.app.R
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,16 +29,14 @@ 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() }
}
}
@Composable
fun SectionView(
title: String,
- icon: ImageVector,
+ icon: Painter,
iconTint: Color = HighOrLowlight,
leadingIcon: Boolean = false,
padding: PaddingValues = PaddingValues(),
@@ -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() }
}
}
@@ -70,7 +67,7 @@ fun SectionViewSelectable(
SectionItemViewSpaceBetween({ onSelected(item.value) }) {
Text(item.title)
if (currentValue.value == item.value) {
- Icon(Icons.Outlined.Check, item.title, tint = MaterialTheme.colors.primary)
+ Icon(painterResource(R.drawable.ic_check), item.title, tint = MaterialTheme.colors.primary)
}
}
Spacer(Modifier.padding(horizontal = 4.dp))
@@ -85,7 +82,30 @@ 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 * 1.7f, 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 * 1.7f, end = DEFAULT_PADDING),
content: (@Composable RowScope.() -> Unit)
) {
val modifier = Modifier
@@ -126,24 +146,12 @@ fun SectionItemWithValue(
currentValue: State,
values: List>,
label: String? = null,
- icon: ImageVector? = null,
+ icon: Painter? = null,
iconTint: Color = HighOrLowlight,
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,13 +197,34 @@ fun SectionDivider() {
Divider(Modifier.padding(horizontal = 8.dp))
}
+@Composable
+fun SectionDividerSpaced(maxTopPadding: Boolean = false, maxBottomPadding: Boolean = true) {
+ Divider(
+ Modifier.padding(
+ start = DEFAULT_PADDING_HALF,
+ top = if (maxTopPadding) 40.dp else 30.dp,
+ end = DEFAULT_PADDING_HALF,
+ bottom = if (maxBottomPadding) 40.dp else 30.dp)
+ )
+}
+
@Composable
fun SectionSpacer() {
Spacer(Modifier.height(30.dp))
}
@Composable
-fun InfoRow(title: String, value: String, icon: ImageVector? = null, iconTint: Color? = null) {
+fun SectionBottomSpacer() {
+ Spacer(Modifier.height(DEFAULT_BOTTOM_PADDING))
+}
+
+@Composable
+fun TextIconSpaced(extraPadding: Boolean = false) {
+ Spacer(Modifier.padding(horizontal = if (extraPadding) 17.dp else DEFAULT_PADDING_HALF))
+}
+
+@Composable
+fun InfoRow(title: String, value: String, icon: Painter? = null, iconTint: Color? = null) {
SectionItemViewSpaceBetween {
Row {
val iconSize = with(LocalDensity.current) { 21.sp.toDp() }
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/SimpleButton.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/SimpleButton.kt
index ba8176edda..9f32850e95 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/SimpleButton.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/SimpleButton.kt
@@ -5,20 +5,20 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.Share
+import androidx.compose.ui.res.painterResource
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
+import chat.simplex.app.R
@Composable
-fun SimpleButton(text: String, icon: ImageVector,
+fun SimpleButton(text: String, icon: Painter,
color: Color = MaterialTheme.colors.primary,
click: () -> Unit) {
SimpleButtonFrame(click) {
@@ -31,7 +31,7 @@ fun SimpleButton(text: String, icon: ImageVector,
}
@Composable
-fun SimpleButtonDecorated(text: String, icon: ImageVector,
+fun SimpleButtonDecorated(text: String, icon: Painter,
color: Color = MaterialTheme.colors.primary,
textDecoration: TextDecoration = TextDecoration.Underline,
fontWeight: FontWeight = FontWeight.Normal,
@@ -47,7 +47,7 @@ fun SimpleButtonDecorated(text: String, icon: ImageVector,
@Composable
fun SimpleButton(
- text: String, icon: ImageVector,
+ text: String, icon: Painter,
color: Color = MaterialTheme.colors.primary,
disabled: Boolean,
click: () -> Unit
@@ -64,7 +64,7 @@ fun SimpleButton(
@Composable
fun SimpleButtonIconEnded(
text: String,
- icon: ImageVector,
+ icon: Painter,
color: Color = MaterialTheme.colors.primary,
click: () -> Unit
) {
@@ -92,6 +92,6 @@ fun SimpleButtonFrame(click: () -> Unit, modifier: Modifier = Modifier, disabled
@Composable
fun PreviewCloseSheetBar() {
SimpleXTheme {
- SimpleButton(text = "Share", icon = Icons.Outlined.Share, click = {})
+ SimpleButton(text = "Share", icon = painterResource(R.drawable.ic_share), click = {})
}
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Util.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Util.kt
index ccb00f4613..0a274d20b9 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Util.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Util.kt
@@ -557,7 +557,7 @@ fun getBitmapFromVideo(uri: Uri, timestamp: Long? = null, random: Boolean = true
val image = when {
timestamp != null -> mmr.getFrameAtTime(timestamp * 1000, MediaMetadataRetriever.OPTION_CLOSEST)
random -> mmr.frameAtTime
- else -> mmr.getFrameAtIndex(0)
+ else -> mmr.getFrameAtTime(0)
}
mmr.release()
return VideoPlayer.PreviewAndDuration(image, durationMs, timestamp ?: 0)
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/VideoPlayer.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/VideoPlayer.kt
index db8f8ccc32..dc0744a752 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/VideoPlayer.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/VideoPlayer.kt
@@ -86,7 +86,7 @@ class VideoPlayer private constructor(
.build()
.apply {
// Repeat the same track endlessly
- repeatMode = 1
+ repeatMode = Player.REPEAT_MODE_ONE
currentVolume = volume
if (!soundEnabled) {
volume = 0f
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/localauth/PasscodeView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/localauth/PasscodeView.kt
index e6ef8de892..0aec5dc344 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/localauth/PasscodeView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/localauth/PasscodeView.kt
@@ -4,13 +4,11 @@ import android.content.res.Configuration
import androidx.compose.foundation.layout.*
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Close
-import androidx.compose.material.icons.filled.Done
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import chat.simplex.app.R
import chat.simplex.app.ui.theme.DEFAULT_PADDING
@@ -41,9 +39,9 @@ fun PasscodeView(
}
PasscodeEntry(passcode, true)
Row {
- SimpleButton(generalGetString(R.string.cancel_verb), icon = Icons.Default.Close, click = cancel)
+ SimpleButton(generalGetString(R.string.cancel_verb), icon = painterResource(R.drawable.ic_close), click = cancel)
Spacer(Modifier.size(20.dp))
- SimpleButton(submitLabel, icon = Icons.Default.Done, disabled = submitEnabled?.invoke(passcode.value) == false || passcode.value.length < 4, click = submit)
+ SimpleButton(submitLabel, icon = painterResource(R.drawable.ic_done_filled), disabled = submitEnabled?.invoke(passcode.value) == false || passcode.value.length < 4, click = submit)
}
}
}
@@ -84,8 +82,8 @@ fun PasscodeView(
Modifier.padding(start = 30.dp).height(s * 3),
verticalArrangement = Arrangement.SpaceEvenly
) {
- SimpleButton(generalGetString(R.string.cancel_verb), icon = Icons.Default.Close, click = cancel)
- SimpleButton(submitLabel, icon = Icons.Default.Done, disabled = submitEnabled?.invoke(passcode.value) == false || passcode.value.length < 4, click = submit)
+ SimpleButton(generalGetString(R.string.cancel_verb), icon = painterResource(R.drawable.ic_close), click = cancel)
+ SimpleButton(submitLabel, icon = painterResource(R.drawable.ic_done_filled), disabled = submitEnabled?.invoke(passcode.value) == false || passcode.value.length < 4, click = submit)
}
}
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/localauth/PasswordEntry.kt b/apps/android/app/src/main/java/chat/simplex/app/views/localauth/PasswordEntry.kt
index d42264e301..20ee2fbcde 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/localauth/PasswordEntry.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/localauth/PasswordEntry.kt
@@ -5,20 +5,18 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Close
-import androidx.compose.material.icons.outlined.Backspace
+import androidx.compose.ui.graphics.painter.Painter
+import androidx.compose.ui.res.painterResource
+import chat.simplex.app.R
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.*
-import chat.simplex.app.model.ChatModel
import chat.simplex.app.ui.theme.HighOrLowlight
@Composable
@@ -59,13 +57,13 @@ private fun BoxWithConstraintsScope.VerticalPasswordGrid(password: MutableState<
DigitsRow(s, 7, 8, 9, password)
Divider()
Row(Modifier.requiredHeight(s)) {
- PasswordEdit(s, Icons.Default.Close) {
+ PasswordEdit(s, painterResource(R.drawable.ic_close)) {
password.value = ""
}
VerticalDivider()
PasswordDigit(s, 0, password)
VerticalDivider()
- PasswordEdit(s, Icons.Outlined.Backspace) {
+ PasswordEdit(s, painterResource(R.drawable.ic_backspace)) {
password.value = password.value.dropLast(1)
}
}
@@ -79,7 +77,7 @@ private fun BoxWithConstraintsScope.HorizontalPasswordGrid(password: MutableStat
Row(Modifier.height(IntrinsicSize.Min)) {
DigitsRow(s, 1, 2, 3, password);
VerticalDivider()
- PasswordEdit(s, Icons.Default.Close) {
+ PasswordEdit(s, painterResource(R.drawable.ic_close)) {
password.value = ""
}
}
@@ -93,7 +91,7 @@ private fun BoxWithConstraintsScope.HorizontalPasswordGrid(password: MutableStat
Row(Modifier.height(IntrinsicSize.Min)) {
DigitsRow(s, 7, 8, 9, password)
VerticalDivider()
- PasswordEdit(s, Icons.Outlined.Backspace) {
+ PasswordEdit(s, painterResource(R.drawable.ic_backspace)) {
password.value = password.value.dropLast(1)
}
}
@@ -137,7 +135,7 @@ private fun PasswordDigit(size: Dp, d: Int, password: MutableState) {
}
@Composable
-private fun PasswordEdit(size: Dp, image: ImageVector, action: () -> Unit) {
+private fun PasswordEdit(size: Dp, image: Painter, action: () -> Unit) {
PasswordButton(size, action) {
Icon(image, null, tint = HighOrLowlight)
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/localauth/SetAppPasscodeView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/localauth/SetAppPasscodeView.kt
index 0506c592dd..cb6c6368d0 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/localauth/SetAppPasscodeView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/localauth/SetAppPasscodeView.kt
@@ -1,5 +1,6 @@
package chat.simplex.app.views.localauth
+import androidx.activity.compose.BackHandler
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import chat.simplex.app.R
@@ -18,6 +19,10 @@ fun SetAppPasscodeView(
@Composable
fun SetPasswordView(title: String, submitLabel: String, submitEnabled: (((String) -> Boolean))? = null, submit: () -> Unit) {
+ BackHandler {
+ close()
+ cancel()
+ }
PasscodeView(passcode, title = title, submitLabel = submitLabel, submitEnabled = submitEnabled, submit = submit) {
close()
cancel()
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..b307ea62d9 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
@@ -1,14 +1,12 @@
package chat.simplex.app.views.newchat
+import SectionBottomSpacer
import android.content.res.Configuration
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.TheaterComedy
-import androidx.compose.material.icons.outlined.Info
-import androidx.compose.material.icons.outlined.Share
+import androidx.compose.ui.res.painterResource
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -19,7 +17,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.*
@@ -39,8 +36,7 @@ fun AddContactLayout(connReq: String, connIncognito: Boolean, share: () -> Unit)
val screenHeight = maxHeight
Column(
Modifier
- .verticalScroll(rememberScrollState())
- .padding(bottom = 16.dp),
+ .verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.SpaceBetween,
) {
AppBarTitle(stringResource(R.string.add_contact), false)
@@ -75,14 +71,15 @@ 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(),
horizontalArrangement = Arrangement.Center
) {
- SimpleButton(stringResource(R.string.share_invitation_link), icon = Icons.Outlined.Share, click = share)
+ SimpleButton(stringResource(R.string.share_invitation_link), icon = painterResource(R.drawable.ic_share), click = share)
}
+ SectionBottomSpacer()
}
}
}
@@ -98,7 +95,7 @@ fun InfoAboutIncognito(chatModelIncognito: Boolean, supportedIncognito: Boolean
horizontalArrangement = if (centered) Arrangement.Center else Arrangement.Start
) {
Icon(
- if (supportedIncognito) Icons.Filled.TheaterComedy else Icons.Outlined.Info,
+ if (supportedIncognito) painterResource(R.drawable.ic_theater_comedy_filled) else painterResource(R.drawable.ic_info),
stringResource(R.string.incognito),
tint = if (supportedIncognito) Indigo else WarningOrange,
modifier = Modifier.padding(end = 10.dp).size(20.dp)
@@ -114,7 +111,7 @@ fun InfoAboutIncognito(chatModelIncognito: Boolean, supportedIncognito: Boolean
horizontalArrangement = if (centered) Arrangement.Center else Arrangement.Start
) {
Icon(
- Icons.Outlined.Info,
+ painterResource(R.drawable.ic_info),
stringResource(R.string.incognito),
tint = HighOrLowlight,
modifier = Modifier.padding(end = 10.dp).size(20.dp)
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..d8acc440bf 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
@@ -5,14 +5,13 @@ import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.ArrowForwardIos
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
@@ -89,7 +88,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
@@ -163,7 +162,7 @@ fun CreateGroupButton(color: Color, modifier: Modifier) {
Surface(shape = RoundedCornerShape(20.dp)) {
Row(modifier, verticalAlignment = Alignment.CenterVertically) {
Text(stringResource(R.string.create_profile_button), style = MaterialTheme.typography.caption, color = color, fontWeight = FontWeight.Bold)
- Icon(Icons.Outlined.ArrowForwardIos, stringResource(R.string.create_profile_button), tint = color)
+ Icon(painterResource(R.drawable.ic_arrow_forward_ios), stringResource(R.string.create_profile_button), tint = color)
}
}
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ConnectViaLinkView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ConnectViaLinkView.kt
index 0919d234f4..ba9c8fc25d 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ConnectViaLinkView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ConnectViaLinkView.kt
@@ -2,10 +2,9 @@ package chat.simplex.app.views.newchat
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.sp
import chat.simplex.app.R
@@ -58,7 +57,7 @@ fun ConnectViaLinkView(m: ChatModel, close: () -> Unit) {
text = { Text(it, fontSize = 13.sp) },
icon = {
Icon(
- if (ConnectViaLinkTab.SCAN.ordinal == index) Icons.Outlined.QrCode else Icons.Outlined.Article,
+ if (ConnectViaLinkTab.SCAN.ordinal == index) painterResource(R.drawable.ic_qr_code) else painterResource(R.drawable.ic_article),
it
)
},
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..12aa97cc12 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,17 +1,16 @@
package chat.simplex.app.views.newchat
-import SectionDivider
+import SectionBottomSpacer
import SectionView
import android.content.res.Configuration
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import chat.simplex.app.R
@@ -101,17 +100,17 @@ private fun ContactConnectionInfoLayout(
SectionView {
if (!connReq.isNullOrEmpty() && contactConnection.initiated) {
ShowQrButton(contactConnection.incognito, showQr)
- SectionDivider()
}
DeleteButton(deleteConnection)
}
+ SectionBottomSpacer()
}
}
@Composable
fun ShowQrButton(incognito: Boolean, onClick: () -> Unit) {
SettingsActionItem(
- Icons.Outlined.QrCode,
+ painterResource(R.drawable.ic_qr_code),
stringResource(R.string.show_QR_code),
click = onClick,
textColor = if (incognito) Indigo else MaterialTheme.colors.primary,
@@ -122,7 +121,7 @@ fun ShowQrButton(incognito: Boolean, onClick: () -> Unit) {
@Composable
fun DeleteButton(onClick: () -> Unit) {
SettingsActionItem(
- Icons.Outlined.Delete,
+ painterResource(R.drawable.ic_delete),
stringResource(R.string.delete_verb),
click = onClick,
textColor = Color.Red,
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/CreateLinkView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/CreateLinkView.kt
index 5326e38bd5..6e4c6849d4 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/CreateLinkView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/CreateLinkView.kt
@@ -2,11 +2,10 @@ package chat.simplex.app.views.newchat
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.sp
import chat.simplex.app.R
@@ -80,7 +79,7 @@ fun CreateLinkView(m: ChatModel, initialSelection: CreateLinkTab) {
text = { Text(it, fontSize = 13.sp) },
icon = {
Icon(
- if (CreateLinkTab.ONE_TIME.ordinal == index) Icons.Outlined.RepeatOne else Icons.Outlined.AllInclusive,
+ if (CreateLinkTab.ONE_TIME.ordinal == index) painterResource(R.drawable.ic_repeat_one) else painterResource(R.drawable.ic_all_inclusive),
it
)
},
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..c0214eb3cb 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
@@ -9,18 +9,14 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Close
-import androidx.compose.material.icons.filled.Edit
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.painter.Painter
-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.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
@@ -60,7 +56,7 @@ fun NewChatSheet(chatModel: ChatModel, newChatSheetState: StateFlow Unit = {}
) {
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..c69f9c18fb 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
@@ -1,5 +1,6 @@
package chat.simplex.app.views.newchat
+import SectionBottomSpacer
import android.content.ClipboardManager
import android.content.res.Configuration
import android.net.Uri
@@ -8,11 +9,10 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Text
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@@ -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)
}
@@ -93,21 +93,22 @@ fun PasteToConnectLayout(
horizontalArrangement = Arrangement.Start,
) {
if (connectionLink.value == "") {
- SimpleButton(text = stringResource(R.string.paste_button), icon = Icons.Outlined.ContentPaste) {
+ SimpleButton(text = stringResource(R.string.paste_button), icon = painterResource(R.drawable.ic_content_paste)) {
pasteFromClipboard()
}
} else {
- SimpleButton(text = stringResource(R.string.clear_verb), icon = Icons.Outlined.Clear) {
+ SimpleButton(text = stringResource(R.string.clear_verb), icon = painterResource(R.drawable.ic_close)) {
connectionLink.value = ""
}
}
Spacer(Modifier.weight(1f).fillMaxWidth())
- SimpleButton(text = stringResource(R.string.connect_button), icon = Icons.Outlined.Link) {
+ SimpleButton(text = stringResource(R.string.connect_button), icon = painterResource(R.drawable.ic_link)) {
connectViaLink(connectionLink.value)
}
}
Text(annotatedStringResource(R.string.you_can_also_connect_by_clicking_the_link))
+ SectionBottomSpacer()
}
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ScanToConnectView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ScanToConnectView.kt
index eb7558dbf5..4f6e4c41d0 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ScanToConnectView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ScanToConnectView.kt
@@ -1,5 +1,6 @@
package chat.simplex.app.views.newchat
+import SectionBottomSpacer
import android.Manifest
import android.content.res.Configuration
import android.net.Uri
@@ -141,6 +142,7 @@ fun ConnectContactLayout(chatModelIncognito: Boolean, qrCodeScanner: @Composable
annotatedStringResource(R.string.if_you_cannot_meet_in_person_scan_QR_in_video_call_or_ask_for_invitation_link),
lineHeight = 22.sp
)
+ SectionBottomSpacer()
}
}
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..5e76c8b095 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
@@ -26,7 +26,6 @@ fun HowItWorks(user: User?, onboardingStage: MutableState? = n
Column(Modifier
.fillMaxWidth()
.padding(horizontal = DEFAULT_PADDING),
- horizontalAlignment = Alignment.Start
) {
AppBarTitle(stringResource(R.string.how_simplex_works), false)
ReadableText(R.string.many_people_asked_how_can_it_deliver)
@@ -47,7 +46,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..0efcdcdc90 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
@@ -6,9 +6,6 @@ import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.ArrowForwardIos
-import androidx.compose.material.icons.outlined.Info
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.ui.Alignment
@@ -71,7 +68,7 @@ fun SimpleXInfoLayout(
.fillMaxWidth()
.padding(bottom = DEFAULT_PADDING, top = DEFAULT_PADDING), contentAlignment = Alignment.Center
) {
- SimpleButtonDecorated(text = stringResource(R.string.how_it_works), icon = Icons.Outlined.Info,
+ SimpleButtonDecorated(text = stringResource(R.string.how_it_works), icon = painterResource(R.drawable.ic_info),
click = showModal { HowItWorks(user, onboardingStage) })
}
Spacer(Modifier.weight(1f))
@@ -95,7 +92,7 @@ private fun InfoRow(icon: Painter, @StringRes titleId: Int, @StringRes textId: I
Image(icon, contentDescription = null, modifier = Modifier
.width(width)
.padding(top = 8.dp, start = 8.dp, end = 24.dp))
- Column(horizontalAlignment = Alignment.Start) {
+ Column {
Text(stringResource(titleId), fontWeight = FontWeight.Bold, style = MaterialTheme.typography.h3, lineHeight = 24.sp)
Text(stringResource(textId), lineHeight = 24.sp, style = MaterialTheme.typography.body1)
}
@@ -136,9 +133,9 @@ fun OnboardingActionButton(
}, modifier) {
Text(stringResource(labelId), style = MaterialTheme.typography.h2, color = MaterialTheme.colors.primary, fontSize = 20.sp)
Icon(
- Icons.Outlined.ArrowForwardIos, "next stage", tint = MaterialTheme.colors.primary,
+ painterResource(R.drawable.ic_arrow_forward_ios), "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..a3acb2e34b 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
@@ -1,17 +1,17 @@
package chat.simplex.app.views.onboarding
import android.content.res.Configuration
+import androidx.annotation.IntegerRes
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
-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.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.platform.LocalUriHandler
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
@@ -28,19 +28,18 @@ fun WhatsNewView(viaSettings: Boolean = false, close: () -> Unit) {
val currentVersion = remember { mutableStateOf(versionDescriptions.lastIndex) }
@Composable
- fun featureDescription(icon: ImageVector, titleId: Int, descrId: Int, link: String?) {
+ fun featureDescription(icon: Painter, titleId: Int, descrId: Int, link: String?) {
@Composable
fun linkButton(link: String) {
val uriHandler = LocalUriHandler.current
Icon(
- Icons.Outlined.OpenInNew, stringResource(titleId), tint = MaterialTheme.colors.primary,
+ painterResource(R.drawable.ic_open_in_new), stringResource(titleId), tint = MaterialTheme.colors.primary,
modifier = Modifier
.clickable { uriHandler.openUriCatching(link) }
)
}
Column(
- horizontalAlignment = Alignment.Start,
modifier = Modifier.padding(bottom = 12.dp)
) {
Row(
@@ -68,7 +67,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
@@ -80,7 +79,7 @@ fun WhatsNewView(viaSettings: Boolean = false, close: () -> Unit) {
.clickable { currentVersion.value = prev }
.padding(8.dp)
) {
- Icon(Icons.Outlined.ArrowBackIosNew, "previous", tint = MaterialTheme.colors.primary)
+ Icon(painterResource(R.drawable.ic_arrow_back_ios_new), "previous", tint = MaterialTheme.colors.primary)
Text(versionDescriptions[prev].version, color = MaterialTheme.colors.primary)
}
}
@@ -97,7 +96,7 @@ fun WhatsNewView(viaSettings: Boolean = false, close: () -> Unit) {
.padding(8.dp)
) {
Text(versionDescriptions[next].version, color = MaterialTheme.colors.primary)
- Icon(Icons.Outlined.ArrowForwardIos, "next", tint = MaterialTheme.colors.primary)
+ Icon(painterResource(R.drawable.ic_arrow_forward_ios), "next", tint = MaterialTheme.colors.primary)
}
}
}
@@ -112,8 +111,7 @@ fun WhatsNewView(viaSettings: Boolean = false, close: () -> Unit) {
.fillMaxSize()
.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),
@@ -128,7 +126,7 @@ fun WhatsNewView(viaSettings: Boolean = false, close: () -> Unit) {
)
v.features.forEach { feature ->
- featureDescription(feature.icon, feature.titleId, feature.descrId, feature.link)
+ featureDescription(painterResource(feature.icon), feature.titleId, feature.descrId, feature.link)
}
if (!viaSettings) {
@@ -154,7 +152,7 @@ fun WhatsNewView(viaSettings: Boolean = false, close: () -> Unit) {
}
private data class FeatureDescription(
- val icon: ImageVector,
+ val icon: Int,
val titleId: Int,
val descrId: Int,
val link: String? = null
@@ -170,18 +168,18 @@ private val versionDescriptions: List = listOf(
version = "v4.2",
features = listOf(
FeatureDescription(
- icon = Icons.Outlined.VerifiedUser,
+ icon = R.drawable.ic_verified_user,
titleId = R.string.v4_2_security_assessment,
descrId = R.string.v4_2_security_assessment_desc,
link = "https://simplex.chat/blog/20221108-simplex-chat-v4.2-security-audit-new-website.html"
),
FeatureDescription(
- icon = Icons.Outlined.Group,
+ icon = R.drawable.ic_group,
titleId = R.string.v4_2_group_links,
descrId = R.string.v4_2_group_links_desc
),
FeatureDescription(
- icon = Icons.Outlined.Check,
+ icon = R.drawable.ic_check,
titleId = R.string.v4_2_auto_accept_contact_requests,
descrId = R.string.v4_2_auto_accept_contact_requests_desc
),
@@ -191,22 +189,22 @@ private val versionDescriptions: List = listOf(
version = "v4.3",
features = listOf(
FeatureDescription(
- icon = Icons.Outlined.Mic,
+ icon = R.drawable.ic_mic,
titleId = R.string.v4_3_voice_messages,
descrId = R.string.v4_3_voice_messages_desc
),
FeatureDescription(
- icon = Icons.Outlined.DeleteForever,
+ icon = R.drawable.ic_delete_forever,
titleId = R.string.v4_3_irreversible_message_deletion,
descrId = R.string.v4_3_irreversible_message_deletion_desc
),
FeatureDescription(
- icon = Icons.Outlined.WifiTethering,
+ icon = R.drawable.ic_wifi_tethering,
titleId = R.string.v4_3_improved_server_configuration,
descrId = R.string.v4_3_improved_server_configuration_desc
),
FeatureDescription(
- icon = Icons.Outlined.VisibilityOff,
+ icon = R.drawable.ic_visibility_off,
titleId = R.string.v4_3_improved_privacy_and_security,
descrId = R.string.v4_3_improved_privacy_and_security_desc
),
@@ -216,22 +214,22 @@ private val versionDescriptions: List = listOf(
version = "v4.4",
features = listOf(
FeatureDescription(
- icon = Icons.Outlined.Timer,
+ icon = R.drawable.ic_timer,
titleId = R.string.v4_4_disappearing_messages,
descrId = R.string.v4_4_disappearing_messages_desc
),
FeatureDescription(
- icon = Icons.Outlined.Pending,
+ icon = R.drawable.ic_pending,
titleId = R.string.v4_4_live_messages,
descrId = R.string.v4_4_live_messages_desc
),
FeatureDescription(
- icon = Icons.Outlined.VerifiedUser,
+ icon = R.drawable.ic_verified_user,
titleId = R.string.v4_4_verify_connection_security,
descrId = R.string.v4_4_verify_connection_security_desc
),
FeatureDescription(
- icon = Icons.Outlined.Translate,
+ icon = R.drawable.ic_translate,
titleId = R.string.v4_4_french_interface,
descrId = R.string.v4_4_french_interface_descr
)
@@ -241,33 +239,33 @@ private val versionDescriptions: List = listOf(
version = "v4.5",
features = listOf(
FeatureDescription(
- icon = Icons.Outlined.ManageAccounts,
+ icon = R.drawable.ic_manage_accounts,
titleId = R.string.v4_5_multiple_chat_profiles,
descrId = R.string.v4_5_multiple_chat_profiles_descr
),
FeatureDescription(
- icon = Icons.Outlined.EditNote,
+ icon = R.drawable.ic_edit_note,
titleId = R.string.v4_5_message_draft,
descrId = R.string.v4_5_message_draft_descr
),
FeatureDescription(
- icon = Icons.Outlined.SafetyDivider,
+ icon = R.drawable.ic_safety_divider,
titleId = R.string.v4_5_transport_isolation,
descrId = R.string.v4_5_transport_isolation_descr,
link = "https://simplex.chat/blog/20230204-simplex-chat-v4-5-user-chat-profiles.html#transport-isolation"
),
FeatureDescription(
- icon = Icons.Outlined.Task,
+ icon = R.drawable.ic_task,
titleId = R.string.v4_5_private_filenames,
descrId = R.string.v4_5_private_filenames_descr
),
FeatureDescription(
- icon = Icons.Outlined.Battery2Bar,
+ icon = R.drawable.ic_battery_2_bar,
titleId = R.string.v4_5_reduced_battery_usage,
descrId = R.string.v4_5_reduced_battery_usage_descr
),
FeatureDescription(
- icon = Icons.Outlined.Translate,
+ icon = R.drawable.ic_translate,
titleId = R.string.v4_5_italian_interface,
descrId = R.string.v4_5_italian_interface_descr,
link = "https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps"
@@ -278,32 +276,32 @@ private val versionDescriptions: List = listOf(
version = "v4.6",
features = listOf(
FeatureDescription(
- icon = Icons.Outlined.Lock,
+ icon = R.drawable.ic_lock,
titleId = R.string.v4_6_hidden_chat_profiles,
descrId = R.string.v4_6_hidden_chat_profiles_descr
),
FeatureDescription(
- icon = Icons.Outlined.Flag,
+ icon = R.drawable.ic_flag,
titleId = R.string.v4_6_group_moderation,
descrId = R.string.v4_6_group_moderation_descr
),
FeatureDescription(
- icon = Icons.Outlined.MapsUgc,
+ icon = R.drawable.ic_maps_ugc,
titleId = R.string.v4_6_group_welcome_message,
descrId = R.string.v4_6_group_welcome_message_descr
),
FeatureDescription(
- icon = Icons.Outlined.Call,
+ icon = R.drawable.ic_call,
titleId = R.string.v4_6_audio_video_calls,
descrId = R.string.v4_6_audio_video_calls_descr
),
FeatureDescription(
- icon = Icons.Outlined.Battery3Bar,
+ icon = R.drawable.ic_battery_3_bar,
titleId = R.string.v4_6_reduced_battery_usage,
descrId = R.string.v4_6_reduced_battery_usage_descr
),
FeatureDescription(
- icon = Icons.Outlined.Translate,
+ icon = R.drawable.ic_translate,
titleId = R.string.v4_6_chinese_spanish_interface,
descrId = R.string.v4_6_chinese_spanish_interface_descr,
link = "https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps"
@@ -314,17 +312,17 @@ private val versionDescriptions: List = listOf(
version = "v5.0",
features = listOf(
FeatureDescription(
- icon = Icons.Outlined.UploadFile,
+ icon = R.drawable.ic_upload_file,
titleId = R.string.v5_0_large_files_support,
descrId = R.string.v5_0_large_files_support_descr
),
FeatureDescription(
- icon = Icons.Outlined.Lock,
+ icon = R.drawable.ic_lock,
titleId = R.string.v5_0_app_passcode,
descrId = R.string.v5_0_app_passcode_descr
),
FeatureDescription(
- icon = Icons.Outlined.Translate,
+ icon = R.drawable.ic_translate,
titleId = R.string.v5_0_polish_interface,
descrId = R.string.v5_0_polish_interface_descr,
link = "https://github.com/simplex-chat/simplex-chat/tree/stable#translate-the-apps"
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..4c5ff2fd85 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,17 +1,14 @@
package chat.simplex.app.views.usersettings
+import SectionBottomSpacer
import SectionCustomFooter
-import SectionDivider
-import SectionItemView
import SectionView
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.TheaterComedy
-import androidx.compose.material.icons.outlined.*
+import androidx.compose.ui.res.painterResource
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -53,25 +50,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), painterResource(R.drawable.ic_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) painterResource(R.drawable.ic_theater_comedy_filled) else painterResource(R.drawable.ic_theater_comedy),
+ if (autoAcceptState.value.incognito) Indigo else HighOrLowlight,
+ autoAcceptState.value.incognito,
+ ) {
+ autoAcceptState.value = AutoAcceptState(autoAcceptState.value.enable, it, autoAcceptState.value.welcomeText)
}
}
}
@@ -99,6 +91,7 @@ private fun AcceptRequestsLayout(
}
}
}
+ SectionBottomSpacer()
}
}
@@ -109,8 +102,8 @@ private fun ButtonsFooter(cancel: () -> Unit, save: () -> Unit, disabled: Boolea
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
- FooterButton(Icons.Outlined.Replay, stringResource(R.string.cancel_verb), cancel, disabled)
- FooterButton(Icons.Outlined.Check, stringResource(R.string.save_verb), save, disabled)
+ FooterButton(painterResource(R.drawable.ic_replay), stringResource(R.string.cancel_verb), cancel, disabled)
+ FooterButton(painterResource(R.drawable.ic_check), stringResource(R.string.save_verb), save, disabled)
}
}
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..a8841e824c 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,22 +1,20 @@
package chat.simplex.app.views.usersettings
+import SectionBottomSpacer
import SectionCustomFooter
-import SectionDivider
import SectionItemView
-import SectionSpacer
import SectionView
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.painter.Painter
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
@@ -141,55 +139,46 @@ fun AdvancedNetworkSettingsView(chatModel: ChatModel) {
Modifier
.fillMaxWidth()
.verticalScroll(rememberScrollState()),
- horizontalAlignment = Alignment.Start,
) {
AppBarTitle(stringResource(R.string.network_settings_title))
SectionView {
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 +186,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)
}
@@ -210,7 +197,7 @@ fun AdvancedNetworkSettingsView(chatModel: ChatModel) {
SectionCustomFooter {
SettingsSectionFooter(revert, save, footerDisabled)
}
- SectionSpacer()
+ SectionBottomSpacer()
}
}
@@ -236,13 +223,9 @@ fun EnableKeepAliveSwitch(
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(stringResource(R.string.network_option_enable_tcp_keep_alive))
- Switch(
+ DefaultSwitch(
checked = networkEnableKeepAlive.value,
onCheckedChange = { networkEnableKeepAlive.value = it },
- colors = SwitchDefaults.colors(
- checkedThumbColor = MaterialTheme.colors.primary,
- uncheckedThumbColor = HighOrLowlight
- ),
)
}
}
@@ -277,7 +260,7 @@ fun IntSettingRow(title: String, selection: MutableState, values: List
)
Spacer(Modifier.size(4.dp))
Icon(
- if (!expanded.value) Icons.Outlined.ExpandMore else Icons.Outlined.ExpandLess,
+ if (!expanded.value) painterResource(R.drawable.ic_expand_more) else painterResource(R.drawable.ic_expand_less),
generalGetString(R.string.invite_to_group_button),
modifier = Modifier.padding(start = 8.dp),
tint = HighOrLowlight
@@ -338,7 +321,7 @@ fun TimeoutSettingRow(title: String, selection: MutableState, values: List
)
Spacer(Modifier.size(4.dp))
Icon(
- if (!expanded.value) Icons.Outlined.ExpandMore else Icons.Outlined.ExpandLess,
+ if (!expanded.value) painterResource(R.drawable.ic_expand_more) else painterResource(R.drawable.ic_expand_less),
generalGetString(R.string.invite_to_group_button),
modifier = Modifier.padding(start = 8.dp),
tint = HighOrLowlight
@@ -374,13 +357,13 @@ fun SettingsSectionFooter(revert: () -> Unit, save: () -> Unit, disabled: Boolea
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
- FooterButton(Icons.Outlined.Replay, stringResource(R.string.network_options_revert), revert, disabled)
- FooterButton(Icons.Outlined.Check, stringResource(R.string.network_options_save), save, disabled)
+ FooterButton(painterResource(R.drawable.ic_replay), stringResource(R.string.network_options_revert), revert, disabled)
+ FooterButton(painterResource(R.drawable.ic_check), stringResource(R.string.network_options_save), save, disabled)
}
}
@Composable
-fun FooterButton(icon: ImageVector, title: String, action: () -> Unit, disabled: Boolean) {
+fun FooterButton(icon: Painter, title: String, action: () -> Unit, disabled: Boolean) {
Surface(
shape = RoundedCornerShape(20.dp),
color = Color.Black.copy(alpha = 0f)
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..ae84518bfd 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,28 +1,21 @@
package chat.simplex.app.views.usersettings
+import SectionBottomSpacer
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
import androidx.compose.material.*
import androidx.compose.material.MaterialTheme.colors
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Circle
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
@@ -31,6 +24,7 @@ import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.*
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@@ -91,8 +85,7 @@ fun AppearanceView(m: ChatModel) {
editPrimaryColor: (Color) -> Unit,
) {
Column(
- Modifier.fillMaxWidth(),
- horizontalAlignment = Alignment.Start,
+ Modifier.fillMaxWidth().verticalScroll(rememberScrollState()),
) {
AppBarTitle(stringResource(R.string.appearance_settings))
SectionView(stringResource(R.string.settings_section_title_language), padding = PaddingValues()) {
@@ -105,26 +98,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,21 +140,18 @@ fun AppearanceView(m: ChatModel) {
}
}
- SectionSpacer()
+ SectionDividerSpaced(maxTopPadding = true)
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)
- Icon(Icons.Filled.Circle, title, tint = colors.primary)
+ Icon(painterResource(R.drawable.ic_circle_filled), title, tint = colors.primary)
}
}
if (currentTheme.first.primary != LightColorPalette.primary) {
@@ -177,6 +165,7 @@ fun AppearanceView(m: ChatModel) {
}
}
}
+ SectionBottomSpacer()
}
}
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..e487276231 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,17 +1,17 @@
package chat.simplex.app.views.usersettings
-import SectionDivider
+import SectionBottomSpacer
import SectionItemView
import SectionTextFooter
import SectionView
-import androidx.compose.foundation.clickable
+import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import chat.simplex.app.R
@@ -37,22 +37,17 @@ fun CallSettingsLayout(
editIceServers: () -> Unit,
) {
Column(
- Modifier.fillMaxWidth(),
- horizontalAlignment = Alignment.Start,
+ Modifier.fillMaxWidth().verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
AppBarTitle(stringResource(R.string.your_calls))
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) {
@@ -61,6 +56,7 @@ fun CallSettingsLayout(
generalGetString(R.string.relay_server_if_necessary)
}
)
+ SectionBottomSpacer()
}
}
@@ -87,34 +83,24 @@ 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
- )
- )
- }
+) {
+ DefaultSwitch(
+ enabled = enabled,
+ checked = remember { preference.state }.value,
+ onCheckedChange = {
+ preference.set(it)
+ onChange?.invoke(it)
+ },
+ )
}
@Composable
fun SharedPreferenceToggleWithIcon(
text: String,
- icon: ImageVector,
+ icon: Painter,
stopped: Boolean = false,
onClickInfo: () -> Unit,
preference: SharedPreference,
@@ -130,16 +116,12 @@ fun SharedPreferenceToggleWithIcon(
tint = MaterialTheme.colors.primary
)
Spacer(Modifier.fillMaxWidth().weight(1f))
- Switch(
+ DefaultSwitch(
checked = prefState.value,
onCheckedChange = {
preference.set(it)
prefState.value = it
},
- colors = SwitchDefaults.colors(
- checkedThumbColor = MaterialTheme.colors.primary,
- uncheckedThumbColor = HighOrLowlight
- ),
enabled = !stopped
)
}
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..6a79b807de 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,17 +1,16 @@
package chat.simplex.app.views.usersettings
-import SectionDivider
-import SectionSpacer
+import SectionBottomSpacer
import SectionTextFooter
import SectionView
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.*
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
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.painterResource
import androidx.compose.ui.res.stringResource
import chat.simplex.app.R
import chat.simplex.app.model.ChatModel
@@ -22,26 +21,23 @@ import chat.simplex.app.views.helpers.*
fun DeveloperView(
m: ChatModel,
showCustomModal: (@Composable (ChatModel, () -> Unit) -> Unit) -> (() -> Unit),
- withAuth: (block: () -> Unit) -> Unit
+ withAuth: (title: String, desc: String, block: () -> Unit) -> Unit
) {
- Column(Modifier.fillMaxWidth()) {
+ Column(Modifier.fillMaxWidth().verticalScroll(rememberScrollState())) {
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)
+ ChatConsoleItem { withAuth(generalGetString(R.string.auth_open_chat_console), generalGetString(R.string.auth_log_in_using_credential), showCustomModal { it, close -> TerminalView(it, close) })}
+ SettingsPreferenceItem(painterResource(R.drawable.ic_drive_folder_upload), stringResource(R.string.confirm_database_upgrades), m.controller.appPrefs.confirmDBUpgrades)
+ SettingsPreferenceItem(painterResource(R.drawable.ic_code), stringResource(R.string.show_developer_options), developerTools)
}
SectionTextFooter(
generalGetString(if (devTools.value) R.string.show_dev_options else R.string.hide_dev_options) + " " +
generalGetString(R.string.developer_options)
)
- SectionSpacer()
+ SectionBottomSpacer()
}
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/HelpView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/HelpView.kt
index 062735a144..79f0ed3348 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/HelpView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/HelpView.kt
@@ -27,7 +27,6 @@ fun HelpLayout(userDisplayName: String) {
.fillMaxWidth()
.verticalScroll(rememberScrollState())
.padding(horizontal = DEFAULT_PADDING),
- horizontalAlignment = Alignment.Start
){
AppBarTitle(String.format(stringResource(R.string.personal_welcome), userDisplayName), false)
ChatHelpView()
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..75017d8478 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,6 @@
package chat.simplex.app.views.usersettings
-import SectionDivider
+import SectionBottomSpacer
import SectionItemView
import SectionItemViewSpaceBetween
import SectionSpacer
@@ -12,9 +12,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
@@ -58,8 +56,7 @@ private fun HiddenProfileLayout(
Column(
Modifier
.fillMaxWidth()
- .verticalScroll(rememberScrollState())
- .padding(bottom = DEFAULT_BOTTOM_PADDING),
+ .verticalScroll(rememberScrollState()),
) {
AppBarTitle(stringResource(R.string.hide_profile))
SectionView(padding = PaddingValues(start = 8.dp, end = DEFAULT_PADDING)) {
@@ -76,15 +73,14 @@ 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)
}
}
SectionTextFooter(stringResource(R.string.to_reveal_profile_enter_password))
+ SectionBottomSpacer()
}
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/IncognitoView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/IncognitoView.kt
index 5f49b15091..e138805270 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/IncognitoView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/IncognitoView.kt
@@ -1,5 +1,6 @@
package chat.simplex.app.views.usersettings
+import SectionBottomSpacer
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
@@ -31,6 +32,7 @@ fun IncognitoLayout() {
Text(generalGetString(R.string.incognito_info_allows))
Text(generalGetString(R.string.incognito_info_share))
Text(generalGetString(R.string.incognito_info_find))
+ SectionBottomSpacer()
}
}
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/MarkdownHelpView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/MarkdownHelpView.kt
index 6a09ba2447..eb9ab5a0ea 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/MarkdownHelpView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/MarkdownHelpView.kt
@@ -1,5 +1,6 @@
package chat.simplex.app.views.usersettings
+import SectionBottomSpacer
import android.content.res.Configuration
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
@@ -58,6 +59,7 @@ fun MarkdownHelpView() {
})
}
}
+ SectionBottomSpacer()
}
}
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..fce9aa3894 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,31 +1,33 @@
package chat.simplex.app.views.usersettings
+import SectionBottomSpacer
import SectionCustomFooter
-import SectionDivider
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
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
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
@@ -156,37 +158,33 @@ fun NetworkAndServersView(
updateSessionMode: (TransportSessionMode) -> Unit,
) {
Column(
- Modifier.fillMaxWidth(),
- horizontalAlignment = Alignment.Start,
+ Modifier.fillMaxWidth().verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
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(painterResource(R.drawable.ic_dns), stringResource(R.string.smp_servers), showCustomModal { m, close -> ProtocolServersView(m, ServerProtocol.SMP, close) })
- SettingsActionItem(Icons.Outlined.Dns, stringResource(R.string.xftp_servers), showCustomModal { m, close -> ProtocolServersView(m, ServerProtocol.XFTP, close) })
- SectionDivider()
+ SettingsActionItem(painterResource(R.drawable.ic_dns), stringResource(R.string.xftp_servers), showCustomModal { m, close -> ProtocolServersView(m, ServerProtocol.XFTP, close) })
- 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) })
+ SettingsActionItem(painterResource(R.drawable.ic_cable), stringResource(R.string.network_settings), showSettingsModal { AdvancedNetworkSettingsView(it) })
}
if (networkUseSocksProxy.value) {
SectionCustomFooter { Text(annotatedStringResource(R.string.disable_onion_hosts_when_not_supported)) }
+ Divider(Modifier.padding(start = DEFAULT_PADDING_HALF, top = 32.dp, end = DEFAULT_PADDING_HALF, bottom = 30.dp))
+ } else {
+ Divider(Modifier.padding(start = DEFAULT_PADDING_HALF, top = 24.dp, end = DEFAULT_PADDING_HALF, bottom = 30.dp))
}
- Spacer(Modifier.height(16.dp))
+
SectionView(generalGetString(R.string.settings_section_title_calls)) {
- SettingsActionItem(Icons.Outlined.ElectricalServices, stringResource(R.string.webrtc_ice_servers), showModal { RTCServersView(it) })
+ SettingsActionItem(painterResource(R.drawable.ic_electrical_services), stringResource(R.string.webrtc_ice_servers), showModal { RTCServersView(it) })
}
+ SectionBottomSpacer()
}
}
@@ -198,41 +196,49 @@ 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,
+ painterResource(R.drawable.ic_settings_ethernet),
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))
}
}
- Switch(
+ DefaultSwitch(
checked = networkUseSocksProxy.value,
onCheckedChange = toggleSocksProxy,
- colors = SwitchDefaults.colors(
- checkedThumbColor = MaterialTheme.colors.primary,
- uncheckedThumbColor = HighOrLowlight
- ),
)
}
}
@@ -243,7 +249,6 @@ fun SockProxySettings(m: ChatModel) {
Modifier
.fillMaxWidth()
.verticalScroll(rememberScrollState())
- .padding(bottom = DEFAULT_BOTTOM_PADDING),
) {
val defaultHostPort = remember { "localhost:9050" }
AppBarTitle(generalGetString(R.string.network_socks_proxy_settings))
@@ -273,7 +278,6 @@ fun SockProxySettings(m: ChatModel) {
}
}, disabled = hostPort == defaultHostPort)
}
- SectionDivider()
SectionItemView {
DefaultConfigurableTextField(
hostUnsaved,
@@ -284,7 +288,6 @@ fun SockProxySettings(m: ChatModel) {
keyboardType = KeyboardType.Text,
)
}
- SectionDivider()
SectionItemView {
DefaultConfigurableTextField(
portUnsaved,
@@ -311,6 +314,7 @@ fun SockProxySettings(m: ChatModel) {
remember { derivedStateOf { !validPort(portUnsaved.value.text) } }.value
)
}
+ SectionBottomSpacer()
}
}
@@ -333,7 +337,6 @@ private fun UseOnionHosts(
val onSelected = showModal {
Column(
Modifier.fillMaxWidth(),
- horizontalAlignment = Alignment.Start,
) {
AppBarTitle(stringResource(R.string.network_use_onion_hosts))
SectionViewSelectable(null, onionHosts, values, useOnion)
@@ -344,7 +347,7 @@ private fun UseOnionHosts(
generalGetString(R.string.network_use_onion_hosts),
onionHosts,
values,
- icon = Icons.Outlined.Security,
+ icon = painterResource(R.drawable.ic_security),
enabled = enabled,
onSelected = onSelected
)
@@ -369,11 +372,10 @@ private fun SessionModePicker(
generalGetString(R.string.network_session_mode_transport_isolation),
sessionMode,
values,
- icon = Icons.Outlined.SafetyDivider,
+ icon = painterResource(R.drawable.ic_safety_divider),
onSelected = showModal {
Column(
Modifier.fillMaxWidth(),
- horizontalAlignment = Alignment.Start,
) {
AppBarTitle(stringResource(R.string.network_session_mode_transport_isolation))
SectionViewSelectable(null, sessionMode, values, updateSessionMode)
@@ -389,8 +391,8 @@ private fun NetworkSectionFooter(revert: () -> Unit, save: () -> Unit, revertDis
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
- FooterButton(Icons.Outlined.Replay, stringResource(R.string.network_options_revert), revert, revertDisabled)
- FooterButton(Icons.Outlined.Check, stringResource(R.string.network_options_save), save, saveDisabled)
+ FooterButton(painterResource(R.drawable.ic_replay), stringResource(R.string.network_options_revert), revert, revertDisabled)
+ FooterButton(painterResource(R.drawable.ic_check), stringResource(R.string.network_options_save), save, saveDisabled)
}
}
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..6d3190ab53 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,11 +1,12 @@
package chat.simplex.app.views.usersettings
-import SectionDivider
-import SectionItemViewSpaceBetween
+import SectionBottomSpacer
import SectionView
import SectionViewSelectable
import android.os.Build
import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
@@ -14,7 +15,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
@@ -79,14 +79,11 @@ fun NotificationsSettingsLayout(
val previewModes = remember { notificationPreviewModes() }
Column(
- Modifier.fillMaxWidth(),
- horizontalAlignment = Alignment.Start,
+ Modifier.fillMaxWidth().verticalScroll(rememberScrollState()),
) {
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 +91,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,
@@ -106,6 +100,7 @@ fun NotificationsSettingsLayout(
)
}
}
+ SectionBottomSpacer()
}
}
@@ -117,7 +112,6 @@ fun NotificationsModeView(
val modes = remember { notificationModes() }
Column(
Modifier.fillMaxWidth(),
- horizontalAlignment = Alignment.Start,
) {
AppBarTitle(stringResource(R.string.settings_notifications_mode_title).lowercase().capitalize(Locale.current))
SectionViewSelectable(null, notificationsMode, modes, onNotificationsModeSelected)
@@ -132,7 +126,6 @@ fun NotificationPreviewView(
val previewModes = remember { notificationPreviewModes() }
Column(
Modifier.fillMaxWidth(),
- horizontalAlignment = Alignment.Start,
) {
AppBarTitle(stringResource(R.string.settings_notification_preview_title))
SectionViewSelectable(null, notificationPreviewMode, previewModes, onNotificationPreviewModeSelected)
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..a8fe451c5e 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,8 +1,8 @@
package chat.simplex.app.views.usersettings
-import SectionDivider
+import SectionBottomSpacer
+import SectionDividerSpaced
import SectionItemView
-import SectionSpacer
import SectionTextFooter
import SectionView
import androidx.compose.foundation.*
@@ -11,7 +11,6 @@ import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
-import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import chat.simplex.app.R
@@ -40,7 +39,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,
@@ -62,50 +60,48 @@ private fun PreferencesLayout(
) {
Column(
Modifier.fillMaxWidth().verticalScroll(rememberScrollState()),
- horizontalAlignment = Alignment.Start,
) {
AppBarTitle(stringResource(R.string.your_preferences))
val timedMessages = remember(preferences) { mutableStateOf(preferences.timedMessages.allow) }
TimedMessagesFeatureSection(timedMessages) {
applyPrefs(preferences.copy(timedMessages = TimedMessagesPreference(allow = if (it) FeatureAllowed.YES else FeatureAllowed.NO)))
}
- SectionSpacer()
+ SectionDividerSpaced(true, maxBottomPadding = false)
val allowFullDeletion = remember(preferences) { mutableStateOf(preferences.fullDelete.allow) }
FeatureSection(ChatFeature.FullDelete, allowFullDeletion) {
applyPrefs(preferences.copy(fullDelete = SimpleChatPreference(allow = it)))
}
- SectionSpacer()
+ SectionDividerSpaced(true, maxBottomPadding = false)
val allowVoice = remember(preferences) { mutableStateOf(preferences.voice.allow) }
FeatureSection(ChatFeature.Voice, allowVoice) {
applyPrefs(preferences.copy(voice = SimpleChatPreference(allow = it)))
}
- SectionSpacer()
+ SectionDividerSpaced(true, maxBottomPadding = false)
val allowCalls = remember(preferences) { mutableStateOf(preferences.calls.allow) }
FeatureSection(ChatFeature.Calls, allowCalls) {
applyPrefs(preferences.copy(calls = SimpleChatPreference(allow = it)))
}
- SectionSpacer()
+ SectionDividerSpaced(maxTopPadding = true, maxBottomPadding = false)
ResetSaveButtons(
reset = reset,
save = savePrefs,
disabled = preferences == currentPreferences
)
+ SectionBottomSpacer()
}
}
@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 +109,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 +127,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..d2efb8416e 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,27 +1,25 @@
package chat.simplex.app.views.usersettings
-import SectionDivider
+import SectionBottomSpacer
+import SectionDividerSpaced
import SectionItemView
-import SectionSpacer
import SectionTextFooter
import SectionView
import android.view.WindowManager
import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
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
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
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
@@ -44,16 +42,14 @@ fun PrivacySettingsView(
setPerformLA: (Boolean, FragmentActivity) -> Unit
) {
Column(
- Modifier.fillMaxWidth(),
- horizontalAlignment = Alignment.Start
+ Modifier.fillMaxWidth().verticalScroll(rememberScrollState()),
) {
val simplexLinkMode = chatModel.controller.appPrefs.simplexLinkMode
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 ->
+ SettingsPreferenceItem(painterResource(R.drawable.ic_visibility_off), stringResource(R.string.protect_app_screen), chatModel.controller.appPrefs.privacyProtectScreen) { on ->
if (on) {
(context as? FragmentActivity)?.window?.setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
@@ -64,23 +60,20 @@ 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
- })
- }
+ SettingsPreferenceItem(painterResource(R.drawable.ic_image), stringResource(R.string.auto_accept_images), chatModel.controller.appPrefs.privacyAcceptImages)
+ SettingsPreferenceItem(painterResource(R.drawable.ic_travel_explore), stringResource(R.string.send_link_previews), chatModel.controller.appPrefs.privacyLinkPreviews)
+ 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))
}
+ SectionBottomSpacer()
}
}
@@ -207,8 +200,7 @@ fun SimplexLockView(
}
Column(
- Modifier.fillMaxWidth(),
- horizontalAlignment = Alignment.Start
+ Modifier.fillMaxWidth().verticalScroll(rememberScrollState()),
) {
AppBarTitle(stringResource(R.string.chat_lock))
SectionView {
@@ -241,31 +233,25 @@ 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))
}
}
}
}
+ SectionBottomSpacer()
}
}
@@ -279,13 +265,9 @@ private fun EnableLock(performLA: MutableState, onCheckedChange: (Boole
.fillMaxWidth()
.weight(1F)
)
- Switch(
+ DefaultSwitch(
checked = performLA.value,
onCheckedChange = onCheckedChange,
- colors = SwitchDefaults.colors(
- checkedThumbColor = MaterialTheme.colors.primary,
- uncheckedThumbColor = HighOrLowlight
- )
)
}
}
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..9611e6d900 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,21 +1,20 @@
package chat.simplex.app.views.usersettings
-import SectionDivider
+import SectionBottomSpacer
+import SectionDividerSpaced
import SectionItemView
import SectionItemViewSpaceBetween
-import SectionSpacer
import SectionView
import android.util.Log
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.*
-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.graphics.Color
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
@@ -81,7 +80,6 @@ private fun ProtocolServerLayout(
Modifier
.fillMaxWidth()
.verticalScroll(rememberScrollState())
- .padding(bottom = DEFAULT_PADDING)
) {
AppBarTitle(stringResource(if (server.preset) R.string.smp_servers_preset_server else R.string.smp_servers_your_server))
@@ -90,6 +88,7 @@ private fun ProtocolServerLayout(
} else {
CustomServer(testing, server, serverProtocol, testServer, onUpdate, onDelete)
}
+ SectionBottomSpacer()
}
}
@@ -113,7 +112,7 @@ private fun PresetServer(
)
}
}
- SectionSpacer()
+ SectionDividerSpaced(maxTopPadding = true)
UseServerSection(true, testing, server, testServer, onUpdate, onDelete)
}
@@ -136,7 +135,7 @@ private fun CustomServer(
}
SectionView(
stringResource(R.string.smp_servers_your_server_address).uppercase(),
- icon = Icons.Outlined.ErrorOutline,
+ icon = painterResource(R.drawable.ic_error),
iconTint = if (!valid.value) MaterialTheme.colors.error else Color.Transparent,
) {
val testedPreviously = remember { mutableMapOf() }
@@ -151,13 +150,13 @@ 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))
+ QRCode(serverAddress.value, Modifier.aspectRatio(1f).padding(horizontal = DEFAULT_PADDING))
}
}
}
@@ -176,12 +175,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)
}
@@ -191,9 +186,9 @@ private fun UseServerSection(
@Composable
fun ShowTestStatus(server: ServerCfg, modifier: Modifier = Modifier) =
when (server.tested) {
- true -> Icon(Icons.Outlined.Check, null, modifier, tint = SimplexGreen)
- false -> Icon(Icons.Outlined.Clear, null, modifier, tint = MaterialTheme.colors.error)
- else -> Icon(Icons.Outlined.Check, null, modifier, tint = Color.Transparent)
+ true -> Icon(painterResource(R.drawable.ic_check), null, modifier, tint = SimplexGreen)
+ false -> Icon(painterResource(R.drawable.ic_close), null, modifier, tint = MaterialTheme.colors.error)
+ else -> Icon(painterResource(R.drawable.ic_check), null, modifier, tint = Color.Transparent)
}
suspend fun testServerConnection(server: ServerCfg, m: ChatModel): Pair =
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..173f25c5c0 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,20 +1,19 @@
package chat.simplex.app.views.usersettings
-import SectionDivider
+import SectionBottomSpacer
+import SectionDividerSpaced
import SectionItemView
-import SectionSpacer
import SectionTextFooter
import SectionView
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.*
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.LocalUriHandler
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.*
import androidx.compose.ui.text.font.FontWeight
@@ -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,
@@ -195,7 +193,6 @@ private fun ProtocolServersLayout(
Modifier
.fillMaxWidth()
.verticalScroll(rememberScrollState())
- .padding(bottom = DEFAULT_PADDING),
) {
AppBarTitle(stringResource(if (serverProtocol == ServerProtocol.SMP) R.string.your_SMP_servers else R.string.your_XFTP_servers))
@@ -204,10 +201,9 @@ private fun ProtocolServersLayout(
SectionItemView({ showServer(srv) }, disabled = testing) {
ProtocolServerView(serverProtocol, srv, servers, testing)
}
- SectionDivider()
}
SettingsActionItem(
- Icons.Outlined.Add,
+ painterResource(R.drawable.ic_add),
stringResource(R.string.smp_servers_add),
addServer,
disabled = testing,
@@ -226,25 +222,24 @@ private fun ProtocolServersLayout(
}
}
)
- SectionSpacer()
+ SectionDividerSpaced(maxTopPadding = true, maxBottomPadding = false)
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(maxBottomPadding = false)
SectionView {
HowToButton()
}
+ SectionBottomSpacer()
}
}
@@ -253,7 +248,7 @@ private fun ProtocolServerView(serverProtocol: ServerProtocol, srv: ServerCfg, s
val address = parseServerAddress(srv.server)
when {
address == null || !address.valid || address.serverProtocol != serverProtocol || !uniqueAddress(srv, address, servers) -> InvalidServer()
- !srv.enabled -> Icon(Icons.Outlined.DoNotDisturb, null, tint = HighOrLowlight)
+ !srv.enabled -> Icon(painterResource(R.drawable.ic_do_not_disturb_on), null, tint = HighOrLowlight)
else -> ShowTestStatus(srv)
}
Spacer(Modifier.padding(horizontal = 4.dp))
@@ -269,7 +264,7 @@ private fun ProtocolServerView(serverProtocol: ServerProtocol, srv: ServerCfg, s
private fun HowToButton() {
val uriHandler = LocalUriHandler.current
SettingsActionItem(
- Icons.Outlined.OpenInNew,
+ painterResource(R.drawable.ic_open_in_new),
stringResource(R.string.how_to_use_your_servers),
{ uriHandler.openUriCatching("https://github.com/simplex-chat/simplex-chat/blob/stable/docs/SERVER.md") },
textColor = MaterialTheme.colors.primary,
@@ -279,7 +274,7 @@ private fun HowToButton() {
@Composable
fun InvalidServer() {
- Icon(Icons.Outlined.ErrorOutline, null, tint = MaterialTheme.colors.error)
+ Icon(painterResource(R.drawable.ic_error), null, tint = MaterialTheme.colors.error)
}
private fun uniqueAddress(s: ServerCfg, address: ServerAddress, servers: List): Boolean = servers.all { srv ->
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/RTCServers.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/RTCServers.kt
index 31a3dd58e8..c37d2a95bb 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/RTCServers.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/RTCServers.kt
@@ -1,5 +1,6 @@
package chat.simplex.app.views.usersettings
+import SectionBottomSpacer
import SectionItemViewSpaceBetween
import androidx.compose.runtime.Composable
import androidx.compose.foundation.*
@@ -7,12 +8,11 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.OpenInNew
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.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
@@ -102,18 +102,15 @@ fun RTCServersLayout(
Column(
Modifier
.fillMaxWidth()
+ .verticalScroll(rememberScrollState())
.padding(horizontal = DEFAULT_PADDING),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
SectionItemViewSpaceBetween(padding = PaddingValues()) {
Text(stringResource(R.string.configure_ICE_servers), Modifier.padding(end = 24.dp))
- Switch(
+ DefaultSwitch(
checked = isUserRTCServers,
onCheckedChange = isUserRTCServersOnOff,
- colors = SwitchDefaults.colors(
- checkedThumbColor = MaterialTheme.colors.primary,
- uncheckedThumbColor = HighOrLowlight
- ),
)
}
@@ -129,7 +126,7 @@ fun RTCServersLayout(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
- Column(horizontalAlignment = Alignment.Start) {
+ Column {
Row {
Text(
stringResource(R.string.cancel_verb),
@@ -175,7 +172,7 @@ fun RTCServersLayout(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
- Column(horizontalAlignment = Alignment.Start) {
+ Column {
Text(
stringResource(R.string.edit_verb),
color = MaterialTheme.colors.primary,
@@ -189,6 +186,7 @@ fun RTCServersLayout(
}
}
}
+ SectionBottomSpacer()
}
}
}
@@ -202,7 +200,7 @@ private fun howToButton() {
) {
Text(stringResource(R.string.how_to), color = MaterialTheme.colors.primary)
Icon(
- Icons.Outlined.OpenInNew, stringResource(R.string.how_to), tint = MaterialTheme.colors.primary,
+ painterResource(R.drawable.ic_open_in_new), stringResource(R.string.how_to), tint = MaterialTheme.colors.primary,
modifier = Modifier.padding(horizontal = 5.dp)
)
}
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..c28aa38f5a 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,30 +1,27 @@
package chat.simplex.app.views.usersettings
-import SectionDivider
+import SectionBottomSpacer
+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.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.*
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.painter.Painter
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 +30,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 +62,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 }
},
@@ -82,10 +77,11 @@ fun SettingsView(chatModel: ChatModel, setPerformLA: (Boolean, FragmentActivity)
}
}
},
- withAuth = { block ->
+ withAuth = { title, desc, block ->
if (!requireAuth.value) {
block()
} else {
+ var autoShow = true
ModalManager.shared.showModalCloseable { close ->
val onFinishAuth = { success: Boolean ->
if (success) {
@@ -93,8 +89,12 @@ fun SettingsView(chatModel: ChatModel, setPerformLA: (Boolean, FragmentActivity)
block()
}
}
+
LaunchedEffect(Unit) {
- runAuth(context, onFinishAuth)
+ if (autoShow) {
+ autoShow = false
+ runAuth(title, desc, context, onFinishAuth)
+ }
}
Box(
Modifier.fillMaxSize(),
@@ -102,9 +102,9 @@ fun SettingsView(chatModel: ChatModel, setPerformLA: (Boolean, FragmentActivity)
) {
SimpleButton(
stringResource(R.string.auth_unlock),
- icon = Icons.Outlined.Lock,
+ icon = painterResource(R.drawable.ic_lock),
click = {
- runAuth(context, onFinishAuth)
+ runAuth(title, desc, context, onFinishAuth)
}
)
}
@@ -132,83 +132,60 @@ fun SettingsLayout(
showSettingsModalWithSearch: (@Composable (ChatModel, MutableState) -> Unit) -> Unit,
showCustomModal: (@Composable (ChatModel, () -> Unit) -> Unit) -> (() -> Unit),
showVersion: () -> Unit,
- withAuth: (block: () -> Unit) -> Unit
+ withAuth: (title: String, desc: String, 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,
- )
-
- Spacer(Modifier.height(30.dp))
+ AppBarTitle(stringResource(R.string.your_settings))
SectionView(stringResource(R.string.settings_section_title_you)) {
- SectionItemView(showCustomModal { chatModel, close -> UserProfileView(chatModel, close) }, 80.dp, disabled = stopped) {
+ SectionItemView(showCustomModal { chatModel, close -> UserProfileView(chatModel, close) }, 80.dp, padding = PaddingValues(start = 16.dp, end = DEFAULT_PADDING), disabled = stopped) {
ProfilePreview(profile, stopped = stopped)
}
- 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(painterResource(R.drawable.ic_manage_accounts), stringResource(R.string.your_chat_profiles), { withAuth(generalGetString(R.string.auth_open_chat_profiles), generalGetString(R.string.auth_log_in_using_credential)) { 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(painterResource(R.drawable.ic_qr_code), 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(painterResource(R.drawable.ic_bolt), stringResource(R.string.notifications), showSettingsModal { NotificationsSettingsView(it) }, disabled = stopped, extraPadding = true)
+ SettingsActionItem(painterResource(R.drawable.ic_wifi_tethering), stringResource(R.string.network_and_servers), showSettingsModal { NetworkAndServersView(it, showModal, showSettingsModal, showCustomModal) }, disabled = stopped, extraPadding = true)
+ SettingsActionItem(painterResource(R.drawable.ic_videocam), stringResource(R.string.settings_audio_video_calls), showSettingsModal { CallSettingsView(it, showModal) }, disabled = stopped, extraPadding = true)
+ SettingsActionItem(painterResource(R.drawable.ic_lock), stringResource(R.string.privacy_and_security), showSettingsModal { PrivacySettingsView(it, showSettingsModal, setPerformLA) }, disabled = stopped, extraPadding = true)
+ SettingsActionItem(painterResource(R.drawable.ic_light_mode), 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(painterResource(R.drawable.ic_help), stringResource(R.string.how_to_use_simplex_chat), showModal { HelpView(userDisplayName) }, disabled = stopped, extraPadding = true)
+ SettingsActionItem(painterResource(R.drawable.ic_add), stringResource(R.string.whats_new), showCustomModal { _, close -> WhatsNewView(viaSettings = true, close) }, disabled = stopped, extraPadding = true)
+ SettingsActionItem(painterResource(R.drawable.ic_info), stringResource(R.string.about_simplex_chat), showModal { SimpleXInfo(it, onboarding = false) }, extraPadding = true)
+ SettingsActionItem(painterResource(R.drawable.ic_tag), stringResource(R.string.chat_with_the_founder), { uriHandler.openUriCatching(simplexTeamUri) }, textColor = MaterialTheme.colors.primary, disabled = stopped, extraPadding = true)
+ SettingsActionItem(painterResource(R.drawable.ic_mail), 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(painterResource(R.drawable.ic_code), stringResource(R.string.settings_developer_tools), showSettingsModal { DeveloperView(it, showCustomModal, withAuth) }, extraPadding = true)
AppVersionItem(showVersion)
}
+ SectionBottomSpacer()
}
}
}
@@ -221,7 +198,7 @@ fun SettingsIncognitoActionItem(
onClickInfo: () -> Unit,
) {
SettingsPreferenceItemWithInfo(
- if (incognito.value) Icons.Filled.TheaterComedy else Icons.Outlined.TheaterComedy,
+ if (incognito.value) painterResource(R.drawable.ic_theater_comedy_filled) else painterResource(R.drawable.ic_theater_comedy),
if (incognito.value) Indigo else HighOrLowlight,
stringResource(R.string.incognito),
stopped,
@@ -251,23 +228,23 @@ 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,
+ painterResource(R.drawable.ic_database),
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) {
Icon(
- Icons.Filled.Report,
+ painterResource(R.drawable.ic_report_filled),
contentDescription = stringResource(R.string.chat_is_stopped),
tint = Color.Red,
modifier = Modifier.padding(end = 6.dp)
@@ -279,7 +256,7 @@ fun MaintainIncognitoState(chatModel: ChatModel) {
@Composable fun ChatPreferencesItem(showCustomModal: ((@Composable (ChatModel, () -> Unit) -> Unit) -> (() -> Unit)), stopped: Boolean) {
SettingsActionItem(
- Icons.Outlined.ToggleOn,
+ painterResource(R.drawable.ic_toggle_on),
stringResource(R.string.chat_preferences),
click = if (stopped) null else ({
withApi {
@@ -288,7 +265,8 @@ fun MaintainIncognitoState(chatModel: ChatModel) {
}()
}
}),
- disabled = stopped
+ disabled = stopped,
+ extraPadding = true
)
}
@@ -300,61 +278,53 @@ 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) painterResource(R.drawable.ic_lock_filled) else painterResource(R.drawable.ic_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,
+ painterResource(R.drawable.ic_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") }
}
) {
Icon(
- Icons.Outlined.StarOutline,
+ painterResource(R.drawable.ic_star),
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 +336,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 +348,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,8 +363,8 @@ 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))
- Column {
+ Spacer(Modifier.padding(horizontal = 8.dp))
+ Column(Modifier.height(size), verticalArrangement = Arrangement.Center) {
Text(
profileOf.displayName,
style = MaterialTheme.typography.caption,
@@ -403,44 +373,67 @@ fun ChatLockItem(
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
- Text(
- profileOf.fullName,
- color = if (stopped) HighOrLowlight else Color.Unspecified,
- maxLines = 1,
- overflow = TextOverflow.Ellipsis
- )
- }
-}
-
-@Composable
-fun SettingsActionItem(icon: ImageVector, text: String, click: (() -> Unit)? = null, textColor: Color = Color.Unspecified, iconColor: Color = HighOrLowlight, disabled: Boolean = false) {
- SectionItemView(click, disabled = disabled) {
- Icon(icon, text, tint = if (disabled) HighOrLowlight else iconColor)
- Spacer(Modifier.padding(horizontal = 4.dp))
- Text(text, color = if (disabled) HighOrLowlight else textColor)
- }
-}
-
-@Composable
-fun SettingsPreferenceItem(
- icon: ImageVector,
- text: String,
- pref: SharedPreference,
- prefState: MutableState? = null,
- 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)
+ if (profileOf.fullName.isNotEmpty()) {
+ Text(
+ profileOf.fullName,
+ Modifier.padding(vertical = 5.dp),
+ color = if (stopped) HighOrLowlight else Color.Unspecified,
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis
+ )
}
}
}
+@Composable
+fun SettingsActionItem(icon: Painter, 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)
+ TextIconSpaced(extraPadding)
+ Text(text, color = if (disabled) HighOrLowlight else textColor)
+ }
+}
+
+@Composable
+fun SettingsActionItemWithContent(icon: Painter?, 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 * 1.7f, end = DEFAULT_PADDING)
+ else
+ PaddingValues(horizontal = DEFAULT_PADDING),
+ disabled = disabled
+ ) {
+ if (icon != null) {
+ Icon(icon, text, Modifier, 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: Painter?,
+ text: String,
+ pref: SharedPreference,
+ iconColor: Color = HighOrLowlight,
+ enabled: Boolean = true,
+ onChange: ((Boolean) -> Unit)? = null,
+) {
+ SettingsActionItemWithContent(icon, text, iconColor = iconColor,) {
+ SharedPreferenceToggle(pref, enabled, onChange)
+ }
+}
+
@Composable
fun SettingsPreferenceItemWithInfo(
- icon: ImageVector,
+ icon: Painter,
iconTint: Color,
text: String,
stopped: Boolean,
@@ -448,12 +441,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, painterResource(R.drawable.ic_info), stopped, onClickInfo, pref, prefState)
}
}
@@ -463,16 +452,10 @@ fun PreferenceToggle(
checked: Boolean,
onChange: (Boolean) -> Unit = {},
) {
- Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
- Text(text)
- Spacer(Modifier.fillMaxWidth().weight(1f))
- Switch(
+ SettingsActionItemWithContent(null, text, extraPadding = true,) {
+ DefaultSwitch(
checked = checked,
onCheckedChange = onChange,
- colors = SwitchDefaults.colors(
- checkedThumbColor = MaterialTheme.colors.primary,
- uncheckedThumbColor = HighOrLowlight
- )
)
}
}
@@ -480,39 +463,26 @@ fun PreferenceToggle(
@Composable
fun PreferenceToggleWithIcon(
text: String,
- icon: ImageVector? = null,
+ icon: Painter? = 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))
- Switch(
+ SettingsActionItemWithContent(icon, text, iconColor = iconColor ?: HighOrLowlight, extraPadding = extraPadding) {
+ DefaultSwitch(
checked = checked,
onCheckedChange = {
onChange(it)
},
- colors = SwitchDefaults.colors(
- checkedThumbColor = MaterialTheme.colors.primary,
- uncheckedThumbColor = HighOrLowlight
- )
)
}
}
-private fun runAuth(context: Context, onFinish: (success: Boolean) -> Unit) {
+private fun runAuth(title: String, desc: String, context: Context, onFinish: (success: Boolean) -> Unit) {
authenticate(
- generalGetString(R.string.auth_open_chat_console),
- generalGetString(R.string.auth_log_in_using_credential),
+ title,
+ desc,
context as FragmentActivity,
completed = { laResult ->
onFinish(laResult == LAResult.Success || laResult is LAResult.Unavailable)
@@ -542,7 +512,7 @@ fun PreviewSettingsLayout() {
showSettingsModalWithSearch = { },
showCustomModal = { {} },
showVersion = {},
- withAuth = {},
+ withAuth = { _, _, _ -> },
)
}
}
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..574cc158a3 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
@@ -1,18 +1,18 @@
package chat.simplex.app.views.usersettings
+import SectionBottomSpacer
import android.content.res.Configuration
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Text
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@@ -69,8 +69,6 @@ fun UserAddressLayout(
) {
Column(
Modifier.verticalScroll(rememberScrollState()),
- horizontalAlignment = Alignment.Start,
- verticalArrangement = Arrangement.Top
) {
AppBarTitle(stringResource(R.string.your_contact_address), false)
Text(
@@ -84,32 +82,33 @@ fun UserAddressLayout(
verticalArrangement = Arrangement.SpaceEvenly
) {
if (userAddress == null) {
- SimpleButton(stringResource(R.string.create_address), icon = Icons.Outlined.QrCode, click = createAddress)
+ SimpleButton(stringResource(R.string.create_address), icon = painterResource(R.drawable.ic_qr_code), click = createAddress)
} else {
QRCode(userAddress.connReqContact, Modifier.aspectRatio(1f))
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),
- icon = Icons.Outlined.Share,
+ icon = painterResource(R.drawable.ic_share),
click = { share(userAddress.connReqContact) })
SimpleButtonIconEnded(
stringResource(R.string.contact_requests),
- icon = Icons.Outlined.ChevronRight,
+ icon = painterResource(R.drawable.ic_chevron_right),
click = acceptRequests
)
}
SimpleButton(
stringResource(R.string.delete_address),
- icon = Icons.Outlined.Delete,
+ icon = painterResource(R.drawable.ic_delete),
color = Color.Red,
click = deleteAddress
)
}
}
+ SectionBottomSpacer()
}
}
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..5e70e268db 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
@@ -1,19 +1,19 @@
package chat.simplex.app.views.usersettings
+import SectionBottomSpacer
import android.content.res.Configuration
import android.net.Uri
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
@@ -86,7 +86,7 @@ fun UserProfileLayout(
val dataUnchanged =
displayName.value == profile.displayName &&
fullName.value == profile.fullName &&
- chosenImage.value == null
+ profile.image == profileImage.value
val closeWithAlert = {
if (dataUnchanged || !(displayName.value.isNotEmpty() && isValidDisplayName(displayName.value))) {
@@ -100,9 +100,8 @@ fun UserProfileLayout(
Modifier
.verticalScroll(scrollState)
.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
@@ -174,6 +173,7 @@ fun UserProfileLayout(
}
}
}
+ SectionBottomSpacer()
}
}
}
@@ -187,7 +187,7 @@ fun EditImageButton(click: () -> Unit) {
modifier = Modifier.size(30.dp)
) {
Icon(
- Icons.Outlined.PhotoCamera,
+ painterResource(R.drawable.ic_photo_camera),
contentDescription = stringResource(R.string.edit_image),
tint = MaterialTheme.colors.primary,
modifier = Modifier.size(30.dp)
@@ -199,7 +199,7 @@ fun EditImageButton(click: () -> Unit) {
fun DeleteImageButton(click: () -> Unit) {
IconButton(onClick = click) {
Icon(
- Icons.Outlined.Close,
+ painterResource(R.drawable.ic_close),
contentDescription = stringResource(R.string.delete_image),
tint = MaterialTheme.colors.primary,
)
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..780d9292f9 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
@@ -1,5 +1,6 @@
package chat.simplex.app.views.usersettings
+import SectionBottomSpacer
import SectionDivider
import SectionItemView
import SectionItemViewSpaceBetween
@@ -10,12 +11,11 @@ import androidx.annotation.StringRes
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.*
import androidx.compose.ui.text.font.FontWeight
@@ -157,11 +157,10 @@ private fun UserProfilesView(
Modifier
.fillMaxWidth()
.verticalScroll(rememberScrollState())
- .padding(bottom = DEFAULT_PADDING),
) {
if (profileHidden.value) {
SectionView {
- SettingsActionItem(Icons.Outlined.LockOpen, stringResource(R.string.enter_password_to_show), click = {
+ SettingsActionItem(painterResource(R.drawable.ic_lock_open), stringResource(R.string.enter_password_to_show), click = {
profileHidden.value = false
}
)
@@ -177,7 +176,7 @@ private fun UserProfilesView(
}
if (searchTextOrPassword.value.trim().isEmpty()) {
SectionItemView(addUser, minHeight = 68.dp) {
- Icon(Icons.Outlined.Add, stringResource(R.string.users_add), tint = MaterialTheme.colors.primary)
+ Icon(painterResource(R.drawable.ic_add), stringResource(R.string.users_add), tint = MaterialTheme.colors.primary)
Spacer(Modifier.padding(horizontal = 4.dp))
Text(stringResource(R.string.users_add), color = MaterialTheme.colors.primary)
}
@@ -197,6 +196,7 @@ private fun UserProfilesView(
)
}
}
+ SectionBottomSpacer()
}
}
@@ -217,33 +217,33 @@ 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 = {
+ ItemAction(stringResource(R.string.user_unhide), painterResource(R.drawable.ic_lock_open), onClick = {
showMenu.value = false
unhideUser(user)
})
} else {
if (visibleUsersCount > 1 && prefPerformLA) {
- ItemAction(stringResource(R.string.user_hide), Icons.Outlined.Lock, onClick = {
+ ItemAction(stringResource(R.string.user_hide), painterResource(R.drawable.ic_lock), onClick = {
showMenu.value = false
showHiddenProfile(user)
})
}
if (user.showNtfs) {
- ItemAction(stringResource(R.string.user_mute), Icons.Outlined.NotificationsOff, onClick = {
+ ItemAction(stringResource(R.string.user_mute), painterResource(R.drawable.ic_notifications_off), onClick = {
showMenu.value = false
muteUser(user)
})
} else {
- ItemAction(stringResource(R.string.user_unmute), Icons.Outlined.Notifications, onClick = {
+ ItemAction(stringResource(R.string.user_unmute), painterResource(R.drawable.ic_notifications), onClick = {
showMenu.value = false
unmuteUser(user)
})
}
}
- ItemAction(stringResource(R.string.delete_verb), Icons.Outlined.Delete, color = Color.Red, onClick = {
+ ItemAction(stringResource(R.string.delete_verb), painterResource(R.drawable.ic_delete), color = Color.Red, onClick = {
removeUser(user)
showMenu.value = false
})
@@ -262,7 +262,6 @@ private fun ProfileActionView(action: UserProfileAction, user: User, doAction: (
Modifier
.fillMaxWidth()
.verticalScroll(rememberScrollState())
- .padding(bottom = DEFAULT_BOTTOM_PADDING),
) {
val actionPassword = rememberSaveable { mutableStateOf("") }
val passwordValid by remember { derivedStateOf { actionPassword.value == actionPassword.value.trim() } }
@@ -300,6 +299,7 @@ private fun ProfileActionView(action: UserProfileAction, user: User, doAction: (
PasswordAndAction(R.string.unhide_chat_profile)
}
}
+ SectionBottomSpacer()
}
}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/VersionInfoView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/VersionInfoView.kt
index 64a541a3a8..eb3f061667 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/VersionInfoView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/VersionInfoView.kt
@@ -17,7 +17,6 @@ import chat.simplex.app.views.helpers.AppBarTitle
fun VersionInfoView(info: CoreVersionInfo) {
Column(
Modifier.padding(horizontal = DEFAULT_PADDING),
- horizontalAlignment = Alignment.Start
) {
AppBarTitle(stringResource(R.string.app_version_title), false)
Text(String.format(stringResource(R.string.app_version_name), BuildConfig.VERSION_NAME))
diff --git a/apps/android/app/src/main/res/drawable/ic_account_circle_filled.xml b/apps/android/app/src/main/res/drawable/ic_account_circle_filled.xml
new file mode 100644
index 0000000000..3af5db1b74
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_account_circle_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_add.xml b/apps/android/app/src/main/res/drawable/ic_add.xml
new file mode 100644
index 0000000000..4f306c05ae
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_add.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_add_link.xml b/apps/android/app/src/main/res/drawable/ic_add_link.xml
new file mode 100644
index 0000000000..0da3e849c2
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_add_link.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_add_photo.xml b/apps/android/app/src/main/res/drawable/ic_add_photo.xml
index 2a81fda0af..acbab9da1c 100644
--- a/apps/android/app/src/main/res/drawable/ic_add_photo.xml
+++ b/apps/android/app/src/main/res/drawable/ic_add_photo.xml
@@ -1,6 +1,6 @@
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_arrow_back_ios_new.xml b/apps/android/app/src/main/res/drawable/ic_arrow_back_ios_new.xml
new file mode 100644
index 0000000000..8d3135bf15
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_arrow_back_ios_new.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_arrow_downward.xml b/apps/android/app/src/main/res/drawable/ic_arrow_downward.xml
new file mode 100644
index 0000000000..d2cef9fe2d
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_arrow_downward.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_arrow_forward_ios.xml b/apps/android/app/src/main/res/drawable/ic_arrow_forward_ios.xml
new file mode 100644
index 0000000000..1eb5f7a9fb
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_arrow_forward_ios.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_arrow_upward.xml b/apps/android/app/src/main/res/drawable/ic_arrow_upward.xml
new file mode 100644
index 0000000000..3a52b50248
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_arrow_upward.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_article.xml b/apps/android/app/src/main/res/drawable/ic_article.xml
new file mode 100644
index 0000000000..607c3d78ec
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_article.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_attach_file_filled_500.xml b/apps/android/app/src/main/res/drawable/ic_attach_file_filled_500.xml
new file mode 100644
index 0000000000..f2f923b6d6
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_attach_file_filled_500.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_backspace.xml b/apps/android/app/src/main/res/drawable/ic_backspace.xml
new file mode 100644
index 0000000000..b9837296dd
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_backspace.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_backup.xml b/apps/android/app/src/main/res/drawable/ic_backup.xml
new file mode 100644
index 0000000000..248404d464
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_backup.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_battery_2_bar.xml b/apps/android/app/src/main/res/drawable/ic_battery_2_bar.xml
new file mode 100644
index 0000000000..cbbe134adf
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_battery_2_bar.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_battery_3_bar.xml b/apps/android/app/src/main/res/drawable/ic_battery_3_bar.xml
new file mode 100644
index 0000000000..1e60f37eb1
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_battery_3_bar.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_bolt.xml b/apps/android/app/src/main/res/drawable/ic_bolt.xml
new file mode 100644
index 0000000000..4ced77dc1d
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_bolt.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_bolt_filled.xml b/apps/android/app/src/main/res/drawable/ic_bolt_filled.xml
new file mode 100644
index 0000000000..64fa349468
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_bolt_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_cable.xml b/apps/android/app/src/main/res/drawable/ic_cable.xml
new file mode 100644
index 0000000000..b801b36d83
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_cable.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_call.xml b/apps/android/app/src/main/res/drawable/ic_call.xml
new file mode 100644
index 0000000000..c38c3fe70a
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_call.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_call_500.xml b/apps/android/app/src/main/res/drawable/ic_call_500.xml
new file mode 100644
index 0000000000..c53c2e6594
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_call_500.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_call_end.xml b/apps/android/app/src/main/res/drawable/ic_call_end.xml
new file mode 100644
index 0000000000..f71577fa09
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_call_end.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_call_end_filled.xml b/apps/android/app/src/main/res/drawable/ic_call_end_filled.xml
new file mode 100644
index 0000000000..c8def6117e
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_call_end_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_call_filled.xml b/apps/android/app/src/main/res/drawable/ic_call_filled.xml
new file mode 100644
index 0000000000..873cc021e5
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_call_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_camera_enhance.xml b/apps/android/app/src/main/res/drawable/ic_camera_enhance.xml
index d3812657c4..126527f211 100644
--- a/apps/android/app/src/main/res/drawable/ic_camera_enhance.xml
+++ b/apps/android/app/src/main/res/drawable/ic_camera_enhance.xml
@@ -1,6 +1,6 @@
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_chat.xml b/apps/android/app/src/main/res/drawable/ic_chat.xml
new file mode 100644
index 0000000000..726b53ab7b
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_chat.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_check.xml b/apps/android/app/src/main/res/drawable/ic_check.xml
new file mode 100644
index 0000000000..cb47d7db19
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_check.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_check_circle_filled.xml b/apps/android/app/src/main/res/drawable/ic_check_circle_filled.xml
new file mode 100644
index 0000000000..a1f32800fe
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_check_circle_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_check_fill.xml b/apps/android/app/src/main/res/drawable/ic_check_fill.xml
new file mode 100644
index 0000000000..da2028b14a
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_check_fill.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_check_filled.xml b/apps/android/app/src/main/res/drawable/ic_check_filled.xml
new file mode 100644
index 0000000000..da2028b14a
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_check_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_chevron_right.xml b/apps/android/app/src/main/res/drawable/ic_chevron_right.xml
new file mode 100644
index 0000000000..622e1984ac
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_chevron_right.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_circle.xml b/apps/android/app/src/main/res/drawable/ic_circle.xml
new file mode 100644
index 0000000000..129ad17b01
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_circle.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_circle_filled.xml b/apps/android/app/src/main/res/drawable/ic_circle_filled.xml
new file mode 100644
index 0000000000..fa62888802
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_circle_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_close.xml b/apps/android/app/src/main/res/drawable/ic_close.xml
new file mode 100644
index 0000000000..fc0f4d3fd6
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_close.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_code.xml b/apps/android/app/src/main/res/drawable/ic_code.xml
new file mode 100644
index 0000000000..a20431beb1
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_code.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_content_copy.xml b/apps/android/app/src/main/res/drawable/ic_content_copy.xml
new file mode 100644
index 0000000000..b8952b0299
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_content_copy.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_content_paste.xml b/apps/android/app/src/main/res/drawable/ic_content_paste.xml
new file mode 100644
index 0000000000..4e586dab46
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_content_paste.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_database.xml b/apps/android/app/src/main/res/drawable/ic_database.xml
new file mode 100644
index 0000000000..f56547850a
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_database.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_delete.xml b/apps/android/app/src/main/res/drawable/ic_delete.xml
new file mode 100644
index 0000000000..5be76620e4
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_delete.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_delete_forever.xml b/apps/android/app/src/main/res/drawable/ic_delete_forever.xml
new file mode 100644
index 0000000000..a82d8de833
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_delete_forever.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_delete_forever_filled.xml b/apps/android/app/src/main/res/drawable/ic_delete_forever_filled.xml
new file mode 100644
index 0000000000..476b04c7bd
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_delete_forever_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_dns.xml b/apps/android/app/src/main/res/drawable/ic_dns.xml
new file mode 100644
index 0000000000..60a762908c
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_dns.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_do_not_disturb_on.xml b/apps/android/app/src/main/res/drawable/ic_do_not_disturb_on.xml
new file mode 100644
index 0000000000..6ffd006109
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_do_not_disturb_on.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_done_filled.xml b/apps/android/app/src/main/res/drawable/ic_done_filled.xml
new file mode 100644
index 0000000000..da2028b14a
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_done_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_download.xml b/apps/android/app/src/main/res/drawable/ic_download.xml
new file mode 100644
index 0000000000..92d2447b67
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_download.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_draft.xml b/apps/android/app/src/main/res/drawable/ic_draft.xml
index f0a09b5e62..7ec25c71a9 100644
--- a/apps/android/app/src/main/res/drawable/ic_draft.xml
+++ b/apps/android/app/src/main/res/drawable/ic_draft.xml
@@ -1,6 +1,6 @@
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_drive_folder_upload.xml b/apps/android/app/src/main/res/drawable/ic_drive_folder_upload.xml
new file mode 100644
index 0000000000..e2f302cbc9
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_drive_folder_upload.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_edit.xml b/apps/android/app/src/main/res/drawable/ic_edit.xml
new file mode 100644
index 0000000000..4584f093bf
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_edit.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_edit_filled.xml b/apps/android/app/src/main/res/drawable/ic_edit_filled.xml
new file mode 100644
index 0000000000..7041946226
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_edit_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_edit_note.xml b/apps/android/app/src/main/res/drawable/ic_edit_note.xml
new file mode 100644
index 0000000000..4c45579a89
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_edit_note.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_electrical_services.xml b/apps/android/app/src/main/res/drawable/ic_electrical_services.xml
new file mode 100644
index 0000000000..0c9da67ae6
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_electrical_services.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_error.xml b/apps/android/app/src/main/res/drawable/ic_error.xml
new file mode 100644
index 0000000000..78bb603a3b
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_error.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_error_filled.xml b/apps/android/app/src/main/res/drawable/ic_error_filled.xml
new file mode 100644
index 0000000000..377c6e25e4
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_error_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_expand_less.xml b/apps/android/app/src/main/res/drawable/ic_expand_less.xml
new file mode 100644
index 0000000000..cd7865710f
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_expand_less.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_expand_more.xml b/apps/android/app/src/main/res/drawable/ic_expand_more.xml
new file mode 100644
index 0000000000..2033d51bfe
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_expand_more.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_flag.xml b/apps/android/app/src/main/res/drawable/ic_flag.xml
new file mode 100644
index 0000000000..794d8944a1
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_flag.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_flip_camera_android_filled.xml b/apps/android/app/src/main/res/drawable/ic_flip_camera_android_filled.xml
new file mode 100644
index 0000000000..7325087c95
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_flip_camera_android_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_group.xml b/apps/android/app/src/main/res/drawable/ic_group.xml
new file mode 100644
index 0000000000..3023eaac7d
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_group.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_help.xml b/apps/android/app/src/main/res/drawable/ic_help.xml
new file mode 100644
index 0000000000..7811daed24
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_help.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_image.xml b/apps/android/app/src/main/res/drawable/ic_image.xml
new file mode 100644
index 0000000000..0319f37153
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_image.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_info.xml b/apps/android/app/src/main/res/drawable/ic_info.xml
new file mode 100644
index 0000000000..49d73a35ef
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_info.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_inventory_2.xml b/apps/android/app/src/main/res/drawable/ic_inventory_2.xml
new file mode 100644
index 0000000000..c76a375f2e
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_inventory_2.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_ios_share.xml b/apps/android/app/src/main/res/drawable/ic_ios_share.xml
new file mode 100644
index 0000000000..e7658452c0
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_ios_share.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_keyboard.xml b/apps/android/app/src/main/res/drawable/ic_keyboard.xml
new file mode 100644
index 0000000000..1b181cd9b3
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_keyboard.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_keyboard_arrow_down.xml b/apps/android/app/src/main/res/drawable/ic_keyboard_arrow_down.xml
new file mode 100644
index 0000000000..64d16805e8
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_keyboard_arrow_down.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_keyboard_voice.xml b/apps/android/app/src/main/res/drawable/ic_keyboard_voice.xml
new file mode 100644
index 0000000000..6abc105438
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_keyboard_voice.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_keyboard_voice_filled.xml b/apps/android/app/src/main/res/drawable/ic_keyboard_voice_filled.xml
new file mode 100644
index 0000000000..7b68c1c490
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_keyboard_voice_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_light_mode.xml b/apps/android/app/src/main/res/drawable/ic_light_mode.xml
new file mode 100644
index 0000000000..3ec23acc6e
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_light_mode.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_link.xml b/apps/android/app/src/main/res/drawable/ic_link.xml
new file mode 100644
index 0000000000..0654256956
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_link.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_lock.xml b/apps/android/app/src/main/res/drawable/ic_lock.xml
new file mode 100644
index 0000000000..f0db0e4f43
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_lock.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_lock_filled.xml b/apps/android/app/src/main/res/drawable/ic_lock_filled.xml
new file mode 100644
index 0000000000..426350d6be
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_lock_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_lock_open.xml b/apps/android/app/src/main/res/drawable/ic_lock_open.xml
new file mode 100644
index 0000000000..2188d06927
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_lock_open.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_login.xml b/apps/android/app/src/main/res/drawable/ic_login.xml
new file mode 100644
index 0000000000..6cd2179c08
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_login.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_logout.xml b/apps/android/app/src/main/res/drawable/ic_logout.xml
new file mode 100644
index 0000000000..39eb443215
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_logout.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_mail.xml b/apps/android/app/src/main/res/drawable/ic_mail.xml
new file mode 100644
index 0000000000..3a063bd429
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_mail.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_manage_accounts.xml b/apps/android/app/src/main/res/drawable/ic_manage_accounts.xml
new file mode 100644
index 0000000000..0d1cc9bf77
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_manage_accounts.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_maps_ugc.xml b/apps/android/app/src/main/res/drawable/ic_maps_ugc.xml
new file mode 100644
index 0000000000..6450dd487b
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_maps_ugc.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_mark_chat_unread.xml b/apps/android/app/src/main/res/drawable/ic_mark_chat_unread.xml
new file mode 100644
index 0000000000..7d41d7ef1d
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_mark_chat_unread.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_menu.xml b/apps/android/app/src/main/res/drawable/ic_menu.xml
new file mode 100644
index 0000000000..81e2bfba4a
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_menu.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_mic.xml b/apps/android/app/src/main/res/drawable/ic_mic.xml
new file mode 100644
index 0000000000..6abc105438
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_mic.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_mic_filled.xml b/apps/android/app/src/main/res/drawable/ic_mic_filled.xml
new file mode 100644
index 0000000000..7b68c1c490
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_mic_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_mic_off.xml b/apps/android/app/src/main/res/drawable/ic_mic_off.xml
new file mode 100644
index 0000000000..1c4870f5fe
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_mic_off.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_more_horiz.xml b/apps/android/app/src/main/res/drawable/ic_more_horiz.xml
new file mode 100644
index 0000000000..db2892846d
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_more_horiz.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_note_add.xml b/apps/android/app/src/main/res/drawable/ic_note_add.xml
index 9cc342453d..38cc20d3df 100644
--- a/apps/android/app/src/main/res/drawable/ic_note_add.xml
+++ b/apps/android/app/src/main/res/drawable/ic_note_add.xml
@@ -1,6 +1,6 @@
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_notifications_off.xml b/apps/android/app/src/main/res/drawable/ic_notifications_off.xml
new file mode 100644
index 0000000000..da9106bff0
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_notifications_off.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_notifications_off_filled.xml b/apps/android/app/src/main/res/drawable/ic_notifications_off_filled.xml
new file mode 100644
index 0000000000..6f0b0b768b
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_notifications_off_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_open_in_new.xml b/apps/android/app/src/main/res/drawable/ic_open_in_new.xml
new file mode 100644
index 0000000000..a9a964d5cc
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_open_in_new.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_pause_filled.xml b/apps/android/app/src/main/res/drawable/ic_pause_filled.xml
new file mode 100644
index 0000000000..3e985d21f4
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_pause_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_pending.xml b/apps/android/app/src/main/res/drawable/ic_pending.xml
new file mode 100644
index 0000000000..9cb97c8b19
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_pending.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_pending_filled.xml b/apps/android/app/src/main/res/drawable/ic_pending_filled.xml
new file mode 100644
index 0000000000..bf17063321
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_pending_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_person_add.xml b/apps/android/app/src/main/res/drawable/ic_person_add.xml
new file mode 100644
index 0000000000..f16ef30b2d
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_person_add.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_person_add_500.xml b/apps/android/app/src/main/res/drawable/ic_person_add_500.xml
new file mode 100644
index 0000000000..9406a99761
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_person_add_500.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_phone_in_talk_filled.xml b/apps/android/app/src/main/res/drawable/ic_phone_in_talk_filled.xml
new file mode 100644
index 0000000000..624d6e04a3
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_phone_in_talk_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_photo_camera.xml b/apps/android/app/src/main/res/drawable/ic_photo_camera.xml
new file mode 100644
index 0000000000..e6c55dbba7
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_photo_camera.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_play_arrow_filled.xml b/apps/android/app/src/main/res/drawable/ic_play_arrow_filled.xml
new file mode 100644
index 0000000000..bcd917b7da
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_play_arrow_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_priority_high.xml b/apps/android/app/src/main/res/drawable/ic_priority_high.xml
new file mode 100644
index 0000000000..b7ddf72318
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_priority_high.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_qr_code.xml b/apps/android/app/src/main/res/drawable/ic_qr_code.xml
new file mode 100644
index 0000000000..1eb7cfb059
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_qr_code.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_repeat_one.xml b/apps/android/app/src/main/res/drawable/ic_repeat_one.xml
new file mode 100644
index 0000000000..0987aadbf6
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_repeat_one.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_replay.xml b/apps/android/app/src/main/res/drawable/ic_replay.xml
new file mode 100644
index 0000000000..7a9c7d7589
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_replay.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_reply.xml b/apps/android/app/src/main/res/drawable/ic_reply.xml
new file mode 100644
index 0000000000..4a2dec582d
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_reply.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_report_filled.xml b/apps/android/app/src/main/res/drawable/ic_report_filled.xml
new file mode 100644
index 0000000000..f1be1d2e41
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_report_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_ring_volume.xml b/apps/android/app/src/main/res/drawable/ic_ring_volume.xml
new file mode 100644
index 0000000000..a60020f3ea
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_ring_volume.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_safety_divider.xml b/apps/android/app/src/main/res/drawable/ic_safety_divider.xml
new file mode 100644
index 0000000000..8b49b2ac03
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_safety_divider.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_search.xml b/apps/android/app/src/main/res/drawable/ic_search.xml
new file mode 100644
index 0000000000..a1c7c1f894
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_search.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_search_500.xml b/apps/android/app/src/main/res/drawable/ic_search_500.xml
new file mode 100644
index 0000000000..2a1d817b85
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_search_500.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_security.xml b/apps/android/app/src/main/res/drawable/ic_security.xml
new file mode 100644
index 0000000000..cfe471b2ea
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_security.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_settings.xml b/apps/android/app/src/main/res/drawable/ic_settings.xml
new file mode 100644
index 0000000000..a59cecf3d5
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_settings.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_settings_backup_restore.xml b/apps/android/app/src/main/res/drawable/ic_settings_backup_restore.xml
new file mode 100644
index 0000000000..42e11a064d
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_settings_backup_restore.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_settings_ethernet.xml b/apps/android/app/src/main/res/drawable/ic_settings_ethernet.xml
new file mode 100644
index 0000000000..0d049ce4d8
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_settings_ethernet.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_settings_phone.xml b/apps/android/app/src/main/res/drawable/ic_settings_phone.xml
new file mode 100644
index 0000000000..d26a6b4e4c
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_settings_phone.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_share.xml b/apps/android/app/src/main/res/drawable/ic_share.xml
new file mode 100644
index 0000000000..dd674cd84b
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_share.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_share_filled.xml b/apps/android/app/src/main/res/drawable/ic_share_filled.xml
new file mode 100644
index 0000000000..475cef6c18
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_share_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_shield.xml b/apps/android/app/src/main/res/drawable/ic_shield.xml
new file mode 100644
index 0000000000..27e75aab71
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_shield.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_smart_display.xml b/apps/android/app/src/main/res/drawable/ic_smart_display.xml
index 6453cd6ea0..b7c815b66d 100644
--- a/apps/android/app/src/main/res/drawable/ic_smart_display.xml
+++ b/apps/android/app/src/main/res/drawable/ic_smart_display.xml
@@ -1,6 +1,6 @@
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_stop_filled.xml b/apps/android/app/src/main/res/drawable/ic_stop_filled.xml
new file mode 100644
index 0000000000..412bcd6429
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_stop_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_supervised_user_circle_filled.xml b/apps/android/app/src/main/res/drawable/ic_supervised_user_circle_filled.xml
new file mode 100644
index 0000000000..68545edc1d
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_supervised_user_circle_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_swap_horizontal_circle.xml b/apps/android/app/src/main/res/drawable/ic_swap_horizontal_circle.xml
new file mode 100644
index 0000000000..9e8b59d8a2
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_swap_horizontal_circle.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_swap_horizontal_circle_filled.xml b/apps/android/app/src/main/res/drawable/ic_swap_horizontal_circle_filled.xml
new file mode 100644
index 0000000000..554f616d6e
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_swap_horizontal_circle_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_tag.xml b/apps/android/app/src/main/res/drawable/ic_tag.xml
new file mode 100644
index 0000000000..a3c686ec3c
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_tag.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_task.xml b/apps/android/app/src/main/res/drawable/ic_task.xml
new file mode 100644
index 0000000000..8fe57f2ee7
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_task.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_theater_comedy.xml b/apps/android/app/src/main/res/drawable/ic_theater_comedy.xml
new file mode 100644
index 0000000000..d139cc2cef
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_theater_comedy.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_theater_comedy_filled.xml b/apps/android/app/src/main/res/drawable/ic_theater_comedy_filled.xml
new file mode 100644
index 0000000000..bff47ca72c
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_theater_comedy_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_timer.xml b/apps/android/app/src/main/res/drawable/ic_timer.xml
new file mode 100644
index 0000000000..b29ec1a006
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_timer.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_timer_filled.xml b/apps/android/app/src/main/res/drawable/ic_timer_filled.xml
new file mode 100644
index 0000000000..d608045bbf
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_timer_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_toggle_on.xml b/apps/android/app/src/main/res/drawable/ic_toggle_on.xml
new file mode 100644
index 0000000000..d5cd169318
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_toggle_on.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_translate.xml b/apps/android/app/src/main/res/drawable/ic_translate.xml
new file mode 100644
index 0000000000..7bd88bd420
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_translate.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_travel_explore.xml b/apps/android/app/src/main/res/drawable/ic_travel_explore.xml
new file mode 100644
index 0000000000..71c264d4be
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_travel_explore.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_upload_file.xml b/apps/android/app/src/main/res/drawable/ic_upload_file.xml
new file mode 100644
index 0000000000..bc80a6e1db
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_upload_file.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_verified_user.xml b/apps/android/app/src/main/res/drawable/ic_verified_user.xml
new file mode 100644
index 0000000000..02951ba057
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_verified_user.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_videocam.xml b/apps/android/app/src/main/res/drawable/ic_videocam.xml
new file mode 100644
index 0000000000..964c287276
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_videocam.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_videocam_filled.xml b/apps/android/app/src/main/res/drawable/ic_videocam_filled.xml
new file mode 100644
index 0000000000..e67552c004
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_videocam_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_videocam_off.xml b/apps/android/app/src/main/res/drawable/ic_videocam_off.xml
new file mode 100644
index 0000000000..d508eb273f
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_videocam_off.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_visibility.xml b/apps/android/app/src/main/res/drawable/ic_visibility.xml
new file mode 100644
index 0000000000..e9f1762303
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_visibility.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_visibility_filled.xml b/apps/android/app/src/main/res/drawable/ic_visibility_filled.xml
new file mode 100644
index 0000000000..35958c3a27
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_visibility_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_visibility_off.xml b/apps/android/app/src/main/res/drawable/ic_visibility_off.xml
new file mode 100644
index 0000000000..202fd6db1f
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_visibility_off.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_visibility_off_filled.xml b/apps/android/app/src/main/res/drawable/ic_visibility_off_filled.xml
new file mode 100644
index 0000000000..9656100328
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_visibility_off_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_volume_down.xml b/apps/android/app/src/main/res/drawable/ic_volume_down.xml
new file mode 100644
index 0000000000..6e19f180d4
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_volume_down.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_volume_up.xml b/apps/android/app/src/main/res/drawable/ic_volume_up.xml
new file mode 100644
index 0000000000..2e301273bb
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_volume_up.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_vpn_key_filled.xml b/apps/android/app/src/main/res/drawable/ic_vpn_key_filled.xml
new file mode 100644
index 0000000000..f13099ed6f
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_vpn_key_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_vpn_key_off_filled.xml b/apps/android/app/src/main/res/drawable/ic_vpn_key_off_filled.xml
new file mode 100644
index 0000000000..c07f49f274
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_vpn_key_off_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_warning_filled.xml b/apps/android/app/src/main/res/drawable/ic_warning_filled.xml
new file mode 100644
index 0000000000..e7f71762ef
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_warning_filled.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/drawable/ic_wifi_tethering.xml b/apps/android/app/src/main/res/drawable/ic_wifi_tethering.xml
new file mode 100644
index 0000000000..065c461542
--- /dev/null
+++ b/apps/android/app/src/main/res/drawable/ic_wifi_tethering.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/apps/android/app/src/main/res/values-cs/strings.xml b/apps/android/app/src/main/res/values-cs/strings.xml
index fc9a29c6fd..6a4f0eed48 100644
--- a/apps/android/app/src/main/res/values-cs/strings.xml
+++ b/apps/android/app/src/main/res/values-cs/strings.xml
@@ -1037,13 +1037,11 @@
Zobrazit:
ID databáze a možnost Izolace přenosu.
Soubor bude přijat, jakmile váš kontakt dokončí nahrávání.
- Přenos souboru bude zrušen. Pokud probíhá, bude zastaven.
Smazat chat profil
Smazat profil
Heslo profilu
Odkrýt chat profil
Odkrýt profil
- Zrušit přenos souboru\?
Žádost o přijetí videa
Současně lze odeslat pouze 10 videí
Příliš mnoho videí!
diff --git a/apps/android/app/src/main/res/values-de/strings.xml b/apps/android/app/src/main/res/values-de/strings.xml
index 355ffe3729..34db0193f0 100644
--- a/apps/android/app/src/main/res/values-de/strings.xml
+++ b/apps/android/app/src/main/res/values-de/strings.xml
@@ -1118,8 +1118,6 @@
Migrationen: %s
Das Bild wird empfangen, sobald das Hochladen durch ihren Kontakt abgeschlossen ist.
Die Datei wird empfangen, sobald das Hochladen durch ihren Kontakt abgeschlossen ist.
- Dateitransfer abbrechen\?
- Der Dateitransfer wird abgebrochen. Falls er gerade abläuft, wird er angehalten.
Chat-Profil löschen
Profil löschen
Verbergen des Profils aufheben
@@ -1155,7 +1153,6 @@
Sperr-Modus ändern
Passwort wurde nicht geändert!
Entschlüsselungsfehler
- Dauerhafter Entschlüsselungsfehler
Fehler beim Laden der XFTP-Server
Passworteingabe
Passwort eingeben
diff --git a/apps/android/app/src/main/res/values-es/strings.xml b/apps/android/app/src/main/res/values-es/strings.xml
index 976b03d0eb..a2d32f0ff1 100644
--- a/apps/android/app/src/main/res/values-es/strings.xml
+++ b/apps/android/app/src/main/res/values-es/strings.xml
@@ -1038,8 +1038,6 @@
Mostrar opciones de desarrollador
Ocultar:
Mostrar:
- ¿Cancelar el envío de archivos\?
- El envío de archivos será cancelado. Si está en progreso se detendrá.
Eliminar perfil de chat
Contraseña del perfil
Mostrar perfil de chat
diff --git a/apps/android/app/src/main/res/values-fr/strings.xml b/apps/android/app/src/main/res/values-fr/strings.xml
index c46858dff4..3ccb23d11d 100644
--- a/apps/android/app/src/main/res/values-fr/strings.xml
+++ b/apps/android/app/src/main/res/values-fr/strings.xml
@@ -1041,8 +1041,6 @@
Dévoiler le profil
Supprimer le profil de chat
Supprimer le profil
- Annuler le transfert de fichiers \?
- Le transfert de fichiers sera annulé. S\'il est en cours, il sera interrompu.
Mot de passe de profil
Trop de vidéos !
Vidéo
diff --git a/apps/android/app/src/main/res/values-hi/strings.xml b/apps/android/app/src/main/res/values-hi/strings.xml
index 862ab03496..f75ce402b7 100644
--- a/apps/android/app/src/main/res/values-hi/strings.xml
+++ b/apps/android/app/src/main/res/values-hi/strings.xml
@@ -278,7 +278,6 @@
विकास करना
आवाज़ बंद करना
अपने संपर्कों को गायब होने वाले संदेश भेजने की अनुमति दें।
- फ़ाइल स्थानांतरण रद्द करें\?
ऑडियो और वीडियो कॉल
अधिक सुधार जल्द ही आ रहे हैं!
वीडियो प्राप्त करने के लिए कहा
diff --git a/apps/android/app/src/main/res/values-it/strings.xml b/apps/android/app/src/main/res/values-it/strings.xml
index 0e0df206e8..3c1c8728c5 100644
--- a/apps/android/app/src/main/res/values-it/strings.xml
+++ b/apps/android/app/src/main/res/values-it/strings.xml
@@ -1037,8 +1037,6 @@
L\'immagine verrà ricevuta quando il tuo contatto completerà l\'invio.
la versione del database è più recente di quella dell\'app, ma nessuna migrazione downgrade per: %s
Il file verrà ricevuto quando il tuo contatto completerà l\'invio.
- Annullare il trasferimento di file\?
- Il trasferimento di file verrà annullato. Se è in corso, verrà interrotto.
Svela il profilo chat
Svela profilo
Elimina il profilo di chat
diff --git a/apps/android/app/src/main/res/values-ko/strings.xml b/apps/android/app/src/main/res/values-ko/strings.xml
index 603bb40575..62e3ca0fe2 100644
--- a/apps/android/app/src/main/res/values-ko/strings.xml
+++ b/apps/android/app/src/main/res/values-ko/strings.xml
@@ -294,7 +294,7 @@
중복된 메시지
1일로 설정
자동 삭제되는 메시지
- 전체 크기가 %s인 %d개의 파일
+ %d 개의 파일 총 크기 %s
다이렉트
이 채팅에서는 자동 삭제되는 메시지를 사용할 수 없어요.
이 그룹에서는 자동 삭제되는 메시지를 사용할 수 없어요.
@@ -530,8 +530,6 @@
이름 (선택 사항)
작동 방식
숨기기 :
- 파일 전송을 취소할까요\?
- 파일 전송이 취소될 거예요. 이미 전송이 시작되었다면 중지될 거예요.
보냄
%s(으)로 참여
그룹에 초대되었어요.
diff --git a/apps/android/app/src/main/res/values-nl/strings.xml b/apps/android/app/src/main/res/values-nl/strings.xml
index aba28a6fe8..1439d7ae68 100644
--- a/apps/android/app/src/main/res/values-nl/strings.xml
+++ b/apps/android/app/src/main/res/values-nl/strings.xml
@@ -1036,8 +1036,6 @@
Verbergen:
Ontwikkelaars opties tonen
EXPERIMENTEEL
- Bestand overdracht annuleren\?
- Bestand overdracht wordt geannuleerd. Als het bezig is, wordt het gestopt.
Verwijder profiel
Profiel wachtwoord
Chat profiel zichtbaar maken
diff --git a/apps/android/app/src/main/res/values-pl/strings.xml b/apps/android/app/src/main/res/values-pl/strings.xml
index 0af6bb4b43..6924ef1724 100644
--- a/apps/android/app/src/main/res/values-pl/strings.xml
+++ b/apps/android/app/src/main/res/values-pl/strings.xml
@@ -140,7 +140,6 @@
Usuń dla mnie
Usunąć wiadomość członka\?
edytowana
- Transfer plików zostanie anulowany. Jeśli jest w toku, zostanie zatrzymany.
Dla wszystkich
dołącz jako %s
wysyłanie nie powiodło się
@@ -937,7 +936,6 @@
Dobre dla baterii. Usługa w tle sprawdza nowe wiadomości co 10 minut. Możesz przegapić połączenia i pilne wiadomości.
Zarówno Ty, jak i Twój kontakt możecie wysyłać wiadomości głosowe.
Według profilu czatu (domyślnie) lub połączenia (BETA).
- Anulować transfer plików\?
Nie można zaprosić kontaktów!
Wyczyść weryfikację
Potwierdź swoje poświadczenia
@@ -1102,14 +1100,12 @@
Natychmiast
Prosimy o jego zapamiętanie lub bezpieczne przechowywanie - nie ma możliwości odzyskania utraconego pinu!
Błąd odszyfrowania
- Trwały błąd odszyfrowywania
Zły hash wiadomości
Zły identyfikator wiadomości
Hash poprzedniej wiadomości jest inny.
Identyfikator następnej wiadomości jest nieprawidłowy (mniejszy lub równy poprzedniej).
\nMoże się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skompromitowane.
Nie udało się odszyfrować %1$d wiadomości.
- Nie udało się odszyfrować %1$d wiadomości i nie będą one pokazane.
Ten błąd jest trwały dla tego połączenia, proszę o ponowne połączenie.
%1$d pominiętych wiadomości.
Może się to zdarzyć, gdy Ty lub Twoje połączenie użyło starej kopii zapasowej bazy danych.
diff --git a/apps/android/app/src/main/res/values-pt-rBR/strings.xml b/apps/android/app/src/main/res/values-pt-rBR/strings.xml
index ed4dde2302..4adb03c202 100644
--- a/apps/android/app/src/main/res/values-pt-rBR/strings.xml
+++ b/apps/android/app/src/main/res/values-pt-rBR/strings.xml
@@ -779,8 +779,6 @@
Novidades
Chamadas de áudio e vídeo
Proteja seus perfis de chat com uma senha!
- Cancelar transferência de arquivo\?
- A transferência do arquivo será cancelada. Se estiver em andamento, será interrompida.
Este texto está disponível nas configurações
Escanear código
Hosts Onion não serão usados.
diff --git a/apps/android/app/src/main/res/values-ru/strings.xml b/apps/android/app/src/main/res/values-ru/strings.xml
index f674b75e7c..a4df902c8a 100644
--- a/apps/android/app/src/main/res/values-ru/strings.xml
+++ b/apps/android/app/src/main/res/values-ru/strings.xml
@@ -1116,8 +1116,6 @@
разная миграция в приложении/базе данных: %s / %s
Откатить версию и открыть чат
Предупреждение: Вы можете потерять какие то данные!
- Прекратить передачу файла\?
- Передача файла будет прекращена. Если она в процессе, она будет остановлена.
ID базы данных и опция Отдельные транспортные сессии.
Показать опции для девелоперов
Удалить профиль чата
diff --git a/apps/android/app/src/main/res/values-zh-rCN/strings.xml b/apps/android/app/src/main/res/values-zh-rCN/strings.xml
index 18bca161b8..2ebcaddde6 100644
--- a/apps/android/app/src/main/res/values-zh-rCN/strings.xml
+++ b/apps/android/app/src/main/res/values-zh-rCN/strings.xml
@@ -1040,10 +1040,8 @@
删除个人资料
个人资料密码
取消隐藏聊天资料
- 取消文件传输?
删除聊天资料
取消隐藏个人资料
- 文件传输将被取消。文件传输将被终止如果它正在进行中。
同一时间只能发送10个视频
过多视频!
视频
@@ -1108,12 +1106,10 @@
此错误对于此连接是永久性的,请重新连接。
当您或您的连接使用旧数据库备份时,可能会发生这种情况。
解密错误
- 永久解密错误
请向开发者报告。
上一条消息的散列不同。
下一条消息的 ID 不正确(小于或等于上一条)。
\n它可能是由于某些错误或连接被破坏才发生。
- %1$d 消息解密失败并且不会显示。
没有空格!
停止文件
停止发送文件?
diff --git a/apps/android/app/src/main/res/values-zh-rTW/strings.xml b/apps/android/app/src/main/res/values-zh-rTW/strings.xml
index 86e43d4be9..c4e8727a53 100644
--- a/apps/android/app/src/main/res/values-zh-rTW/strings.xml
+++ b/apps/android/app/src/main/res/values-zh-rTW/strings.xml
@@ -1037,8 +1037,6 @@
檔案將會在你的聯絡人完成上傳後接收。
實驗性
升級和開始對話
- 取消傳輸檔案?
- 檔案傳遞將會取消。若是在傳遞檔案中,亦會暫停。
顯示開發者選項
刪除資料
取消隱藏聊天資料
diff --git a/apps/android/app/src/main/res/values/strings.xml b/apps/android/app/src/main/res/values/strings.xml
index 15621e0e5f..578c14a298 100644
--- a/apps/android/app/src/main/res/values/strings.xml
+++ b/apps/android/app/src/main/res/values/strings.xml
@@ -194,6 +194,7 @@
Device authentication is disabled. Turning off SimpleX Lock.
Stop chat
Open chat console
+ Open chat profiles
SimpleX Lock not enabled!
You can turn on SimpleX Lock via Settings.
diff --git a/blog/20230422-simplex-chat-vision-funding-v5-videos-files-passcode.md b/blog/20230422-simplex-chat-vision-funding-v5-videos-files-passcode.md
index 28dc96837a..93572dba33 100644
--- a/blog/20230422-simplex-chat-vision-funding-v5-videos-files-passcode.md
+++ b/blog/20230422-simplex-chat-vision-funding-v5-videos-files-passcode.md
@@ -2,8 +2,9 @@
layout: layouts/article.html
title: "SimpleX Chat: vision and funding, v5.0 released with videos and files up to 1gb"
date: 2023-04-22
-preview: This version integrates the support of XFTP protocol, allowing to receive up to 1gb files, even when the sender is offline.
-# image: images/20230301-xftp.jpg
+image: images/20230422-video.png
+imageBottom: true
+previewBody: blog_previews/20230422.html
permalink: "/blog/20230422-simplex-chat-vision-funding-v5-videos-files-passcode.html"
---
@@ -11,13 +12,13 @@ permalink: "/blog/20230422-simplex-chat-vision-funding-v5-videos-files-passcode.
**Published:** Apr 22, 2023
-This is a placeholder for v5.0 release announcement.
+SimpleX Chat vision and funding:
+- [why is it a commercial company?](#why-is-it-a-commercial-company)
+- [how is it funded and what is the business model?](#how-is-it-funded-and-what-is-the-business-model)
+- [what is next?](#what-is-next)
-## SimpleX Chat vision and funding
-
-## What's new in v5.0
-
-- [send videos and files up to 1gb](#send-files-up-to-1gb)
+What's new in v5.0:
+- [send videos and files up to 1gb](#send-videos-and-files-up-to-1gb)
- [app passcode independent from system authentication](#app-passcode)
- [networking improvements](#networking-improvements)
@@ -25,8 +26,106 @@ Also, we added Polish interface language, thanks to [the users' community and We
SimpleX Chat apps are now available in 10 languages!
+## SimpleX Chat vision and funding
+
+### Why is it a commercial company?
+
+It was a big decision: whether SimpleX Chat should be a non-profit project or an open-source project led by a commercial company.
+
+During the last 25 years of the Internet, commercial companies have shown a much higher ability to innovate than non-profit organizations. One of the most inspiring examples is NetScape that created the Web as we know it - not only as the destination to access information, but also as an application platform, inventing cookies, SSL and JavaScript, that to this day remain the main building blocks for all web applications.
+
+While SimpleX Chat Ltd is a commercial company, SimpleX Chat software is and will remain open-source. We believe that this way we will create much more value both for the end users, and also for the shareholders and the employees of the company.
+
+Many large tech companies prioritizing value extraction over value creation earned a bad reputation for all businesses, particularly in the communities that value decentralization and privacy. But commercial objectives do not have to result in exploitation. Our goal is to build a new kind of communication network, and also an application platform, that is private by design, fully decentralized and not owned by any single entity, where SimpleX Chat Ltd is one of many organizations that operate the network. I shared my thoughts about how the Internet and privacy might evolve in the interview in [Opt Out Podcast](https://optoutpod.com/episodes/s3e02-simplexchat/).
+
+### How is it funded and what is the business model?
+
+We started working full-time on the project in 2021 when [Portman Wills](https://www.linkedin.com/in/portmanwills/) and [Peter Briffett](https://www.linkedin.com/in/peterbriffett/) (the founders of [Wagestream](https://wagestream.com/en/) where I led the engineering team) supported the company very early on, and several other angel investors joined later. In July 2022 SimpleX Chat raised a pre-seed funding from the VC fund [Village Global](https://www.villageglobal.vc) - its co-founder [Ben Casnocha](https://casnocha.com) was very excited about our vision of privacy-first fully decentralized messaging and community platform, both for the individual users and for the companies, independent of any crypto-currencies, that might grow to replace large centralized platforms, such as WhatsApp, Telegram and Signal.
+
+Overall we raised from our investors approximately $370,000 for a small share of the company to allow the project team working full time for almost two years, funding product design and development, infrastructure, and also [the security assessment by Trail of Bits](https://simplex.chat/blog/20221108-simplex-chat-v4.2-security-audit-new-website.html). A large part of this money is not spent yet.
+
+The project was hugely supported by the users as well - collectively, [you donated](https://github.com/simplex-chat/simplex-chat#help-us-with-donations) over $25,000. Without these donations the investment we raised would not be possible, because we believe that voluntary user donations can sustain the project in the long term – it already covers all infrastructure costs. There are only two ways an Internet service can exist - either users are paying for it, or the users data becomes the product for the real customers, as happened with many large Internet companies. In the latter case the users are losing much more money than they are saving by giving away their privacy and the rights to the content they create on the centralized platforms.
+
+Going forward we plan to keep the basic usage of the platform free, and at the same time we will be providing the benefits to the project sponsors. For example, there will be additional app icons and user profile badges. There also will be higher file transfer limits – currently we don't limit it at all, only limiting the file size, but it's unlikely to be sustainable. In any case, the app will remain highly usable for everyone for free, and fully open-source. Several other apps are already being developed based on our app core, leading to a fully decentralized network.
+
+### What is next?
+
+Our goals for the next 1-2 years are to make the messaging network:
+- more reliable and resilient, by adding redundancy into the message delivery and delivery receipts,
+- more private, by automating rotation of the servers used to deliver messages and by adding delivery relays to better protect IP addresses of the users,
+- more usable by adding and improving the functions users are expecting in messengers, and also adding some unique functions, like we did with [incognito mode](./20220901-simplex-chat-v3.2-incognito-mode.md#incognito-mode), [live messages](./20230103-simplex-chat-v4.4-disappearing-messages.md#live-messages) and [hidden profiles](./20230328-simplex-chat-v4-6-hidden-profiles.md#hidden-chat-profiles).
+
+One major initiative we will kick-off this year is the support for large, fully decentralized and private communities and groups not hosted on any servers – something that no Internet platform achieved so far in as private and efficient way as we plan to build it.
+
+To accelerate product development and growth we will be raising a seed funding this year, both from the VCs and angel investors, and we also might offer our users an opportunity to participate in the crowd funding round on the same terms as other investors, allowing to both support the project and to benefit from its future growth. [Subscribe to our updates](https://simplex.chat#join-simplex) not to miss it, connect to the team in SimpleX Chat and [join users' groups](https://github.com/simplex-chat/simplex-chat#join-user-groups).
+
+## What's new in v5.0
+
### Send videos and files up to 1gb!
+
+
+In the beginning of March [we released servers and command-line utility to send and receive files via XFTP protocol](./20230301-simplex-file-transfer-protocol.md) - a very private and secure protocol that sends end-to-end encrypted files in chunks, protecting meta-data better than any alternatives we know of.
+
+Now this protocol is fully integrated in SimpleX Chat, and all files except small voice messages are sent using this protocol (small voice messages are sent as usual messages). Not only it is much faster than before - with the fast Internet connection I can send 25Mb file in 3 seconds and 1gb file in 2 minutes (for most users it's capped at the available Internet bandwidth), it has two other major advantages making it more usable:
+
+- the file sent to a group has to be uploaded only once, regardless of the group size.
+- once the file is uploaded (it will have the tick), you no longer need to be online for your contact (or group members) to be able to receive it.
+
+As for the metadata privacy, it has similar guarantee to SimpleX Messaging Protocol. The files are sent via TLS 1.2/1.3, with the same server identity verification, TLS channel binding and upload authorization as used with SMP servers. But the file metadata is protected even if TLS is compromised, as there are no identifiers and ciphertext in common in server received and sent traffic, allowing to correlate only by sending and receiving time. Correlating by time becomes less efficient as the server traffic grows.
+
+We also added the ability to send videos in the chat, so they can be played right in the conversation or on full screen without leaving the app – thanks to the efficient and fast file transfer they are very usable.
+
+We also plan to add support for longer and higher quality voice messages, and also for sending full resolution images in the next versions.
+
### App passcode
+
+
+While we do think that app passcode does not increase security too much, compared with device passcode or biometric protection, there are cases when it may be preferable, and also many users really wanted that it is added.
+
+Now you can choose whether to use faster and more convenient system biometric authentication or to use a separate app passcode. You can choose which one to use when it is first offered, or switch later in the settings.
+
### Networking improvements
+
+
+
+Two small improvements to the app networking capabilities were added in this version.
+
+Firstly, you can now make your self-hosted servers available on IPv6 addresses, and the app supports them as well. Please bear in mind that older clients won't be able to connect to you if you use IPv6 address, and also that some ISPs do not provide IPv6 addresses to their users, in which case they would also not be able to connect if IPv6 address is used. To allow connections in these cases you should make your servers available on some domain name that resolves to both IPv4 and IPv6 addresses, and use this domain name in the server address.
+
+Secondly, Android client now supports configuring host and port of the SOCKS proxy, allowing to use apps other than Orbot and also to run SOCKS proxy in the local network, to save mobile device battery.
+
+## SimpleX platform
+
+Some links to answer the most common questions:
+
+[SimpleX Chat security assessment](./20221108-simplex-chat-v4.2-security-audit-new-website.md).
+
+[How can SimpleX deliver messages without user identifiers](https://simplex.chat/#how-simplex-works).
+
+[What are the risks to have identifiers assigned to the users](https://simplex.chat/#why-ids-bad-for-privacy).
+
+[Technical details and limitations](https://github.com/simplex-chat/simplex-chat#privacy-technical-details-and-limitations).
+
+[How SimpleX is different from Session, Matrix, Signal, etc.](https://github.com/simplex-chat/simplex-chat/blob/stable/README.md#frequently-asked-questions).
+
+Visit our [website](https://simplex.chat) to learn more.
+
+## Help us with donations
+
+Huge thank you to everybody who donated to SimpleX Chat!
+
+We are prioritizing users privacy and security - it would be impossible without your support.
+
+Our pledge to our users is that SimpleX protocols are and will remain open, and in public domain, - so anybody can build the future implementations of the clients and the servers. We are building SimpleX platform based on the same principles as email and web, but much more private and secure.
+
+Your donations help us raise more funds – any amount, even the price of the cup of coffee, makes a big difference for us.
+
+See [this section](https://github.com/simplex-chat/simplex-chat/tree/master#help-us-with-donations) for the ways to donate.
+
+Thank you,
+
+Evgeny
+
+SimpleX Chat founder
diff --git a/blog/README.md b/blog/README.md
index 01134bd1a6..d59d6708bf 100644
--- a/blog/README.md
+++ b/blog/README.md
@@ -1,5 +1,19 @@
# Blog
+Apr 22, 2023 [SimpleX Chat: vision and funding, v5.0 released](./20230422-simplex-chat-vision-funding-v5-videos-files-passcode.md)
+
+SimpleX Chat vision and funding:
+- why is it a commercial company?
+- how is it funded and what is the business model?
+- what is next?
+
+What's new in v5.0:
+- send videos and files up to 1gb
+- app passcode independent from system authentication
+- networking improvements
+
+Also, we added Polish language interface, thanks to our users and Weblate!
+
Mar 28, 2023 [SimpleX Chat v4.6 released](./20230328-simplex-chat-v4-6-hidden-profiles.md)
- ARMv7a and Android 8+ support!
diff --git a/blog/images/20230422-passcode1.png b/blog/images/20230422-passcode1.png
new file mode 100644
index 0000000000..73760959e8
Binary files /dev/null and b/blog/images/20230422-passcode1.png differ
diff --git a/blog/images/20230422-passcode2.png b/blog/images/20230422-passcode2.png
new file mode 100644
index 0000000000..b427cee444
Binary files /dev/null and b/blog/images/20230422-passcode2.png differ
diff --git a/blog/images/20230422-socks.png b/blog/images/20230422-socks.png
new file mode 100644
index 0000000000..2115c8b042
Binary files /dev/null and b/blog/images/20230422-socks.png differ
diff --git a/blog/images/20230422-video.png b/blog/images/20230422-video.png
new file mode 100644
index 0000000000..3327613ca0
Binary files /dev/null and b/blog/images/20230422-video.png differ
diff --git a/cabal.project b/cabal.project
index 440f98089f..7daa323861 100644
--- a/cabal.project
+++ b/cabal.project
@@ -7,7 +7,7 @@ constraints: zip +disable-bzip2 +disable-zstd
source-repository-package
type: git
location: https://github.com/simplex-chat/simplexmq.git
- tag: 4da637a565bb8eff3e4e0fd940f9fdd34ce981e7
+ tag: af3f70829dca2483425eb8702cd9aeac2c026e14
source-repository-package
type: git
diff --git a/docs/XFTP-SERVER.md b/docs/XFTP-SERVER.md
new file mode 100644
index 0000000000..1359616ed1
--- /dev/null
+++ b/docs/XFTP-SERVER.md
@@ -0,0 +1,319 @@
+# Hosting your own XFTP Server
+
+## Overview
+
+XFTP is a new file transfer protocol focussed on meta-data protection - it is based on the same principles as SimpleX Messaging Protocol used in SimpleX Chat messenger:
+
+ - asynchronous file delivery - the sender does not need to be online for file to be received, it is stored on XFTP relays for a limited time (currently, it is 48 hours) or until deleted by the sender.
+ - padded e2e encryption of file content.
+ - content padding and fixed size chunks sent via different XFTP relays, assembled back into the original file by the receiving client.
+ - efficient sending to multiple recipients (the file needs to be uploaded only once).
+ - no identifiers or ciphertext in common between sent and received relay traffic, same as for messages delivered by SMP relays.
+ - protection of sender IP address from the recipients.
+
+## Installation
+
+1. Download `xftp-server` binary:
+
+ ```sh
+ sudo curl -L https://github.com/simplex-chat/simplexmq/releases/latest/download/xftp-server-ubuntu-20_04-x86-64 -o /usr/local/bin/xftp-server && sudo chmod +x /usr/local/bin/xftp-server
+ ```
+
+2. Create user and group for `xftp-server`:
+
+ ```sh
+ sudo useradd -m xftp
+ ```
+
+3. Create necessary directories and assign permissions:
+
+ ```sh
+ sudo mkdir -p /var/opt/simplex-xftp /etc/opt/simplex-xftp /srv/xftp
+ sudo chown xftp:xftp /var/opt/simplex-xftp /etc/opt/simplex-xftp /srv/xftp
+ ```
+
+4. Allow xftp-server port in firewall:
+
+ ```sh
+ # For Ubuntu
+ sudo ufw allow 443
+ ```
+
+5. **Optional** — If you're using distribution with `systemd`, create `/etc/systemd/system/xftp-server.service` file with the following content:
+
+ ```sh
+ [Unit]
+ Description=XFTP server systemd service
+
+ [Service]
+ User=xftp
+ Group=xftp
+ Type=simple
+ ExecStart=/usr/local/bin/xftp-server start +RTS -N -RTS
+ ExecStopPost=/usr/bin/env sh -c '[ -e "/var/opt/simplex-xftp/file-server-store.log" ] && cp "/var/opt/simplex-xftp/file-server-store.log" "/var/opt/simplex-xftp/file-server-store.log.$(date +'%FT%T')"'
+ LimitNOFILE=65535
+ KillSignal=SIGINT
+ TimeoutStopSec=infinity
+ AmbientCapabilities=CAP_NET_BIND_SERVICE
+
+ [Install]
+ WantedBy=multi-user.target
+ ```
+
+ And execute `sudo systemctl daemon-reload`.
+
+## Configuration
+
+To see which options are available, execute `xftp-server` without flags:
+
+```sh
+sudo su xftp -c xftp-server
+
+...
+Available commands:
+ init Initialize server - creates /etc/opt/simplex-xftp and
+ /var/opt/simplex-xftp directories and configuration
+ files
+ start Start server (configuration:
+ /etc/opt/simplex-xftp/file-server.ini)
+ delete Delete configuration and log files
+
+```
+
+You can get further help by executing `su xftp -c "xftp-server -h"`
+
+After that, we need to configure `xftp-server`:
+
+```sh
+sudo su xftp -c "xftp-server init -h"
+
+...
+Available options:
+ -l,--store-log Enable store log for persistence
+ -a,--sign-algorithm ALG Signature algorithm used for TLS certificates:
+ ED25519, ED448 (default: ED448)
+ --ip IP Server IP address, used as Common Name for TLS online
+ certificate if FQDN is not supplied
+ (default: "127.0.0.1")
+ -n,--fqdn FQDN Server FQDN used as Common Name for TLS online
+ certificate
+ -p,--path PATH Path to the directory to store files
+ -q,--quota QUOTA File storage quota (e.g. 100gb)
+ -h,--help Show this help text
+```
+
+You should determine which flags are needed for your use-case and then execute `xftp-server init`:
+
+```sh
+sudo su xftp -c "xftp-server init - "
+```
+
+For example, run:
+
+```sh
+sudo su xftp -c "xftp-server init -l --ip 192.168.1.5 -q '20gb' -p /srv/xftp/"
+```
+
+to initialize your `xftp-server` configuration with:
+
+- restoring connections when the server is restarted (`-l` flag),
+- IP address `192.168.1.5` (`--ip` flag),
+- set overall storage quota to 10Gb (`-q` flag),
+- store files in `/srv/xftp` directory (`-p` flag).
+
+To password-protect your `xftp-server`, change it in the configuration:
+
+ 1. Open configuration with:
+
+ ```sh
+ sudo su xftp -c "vim /etc/opt/simplex-xftp/file-server.ini"
+ ```
+ 2. Under `[AUTH]` section uncomment `create_password` and change it:
+
+ ```sh
+ ...
+ [AUTH]
+ # Set new_files option to off to completely prohibit uploading new files.
+ # This can be useful when you want to decommission the server, but still allow downloading the existing files.
+ new_files: on
+
+ # Use create_password option to enable basic auth to upload new files.
+ # The password should be used as part of server address in client configuration:
+ # xftp://fingerprint:password@host1,host2
+ # The password will not be shared with file recipients, you must share it only
+ # with the users who you want to allow uploading files to your server.
+ create_password: your_very_secure_password
+ ...
+ ```
+---
+
+After that, your installation is complete and you should see in your teminal output something like this:
+
+```sh
+Certificate request self-signature ok
+subject=CN = 192.168.1.5
+Server initialized, you can modify configuration in /etc/opt/simplex-xftp/file-server.ini.
+Run `file-server start` to start server.
+----------
+You should store CA private key securely and delete it from the server.
+If server TLS credential is compromised this key can be used to sign a new one, keeping the same server identity and established connections.
+CA private key location:
+/etc/opt/simplex-xftp/ca.key
+----------
+SimpleX XFTP server v0.1.0
+Fingerprint: ioyYeRyy4SqJkNvb_7nM04MuLasOM4c-acVyVnqw248=
+Server address: xftp://ioyYeRyy4SqJkNvb_7nM04MuLasOM4c-acVyVnqw248=@
+```
+
+The server address above should be used in your client configuration and if you added server password it should only be shared with the other people when you want to allow them to use your server to upload files. If you passed IP address or hostnames during the initialisation, they will be printed as part of server address, otherwise replace `` with the actual server addresses.
+
+## Documentation
+
+All necessary files for `xftp-server` are located in `/etc/opt/simplex-xftp/` folder.
+
+Stored messages, connections, statistics and server log are located in `/var/opt/simplex-xftp/` folder.
+
+Location of uploaded files is configured by the user. In our guide we're using `/srv/xftp/`
+
+### XFTP server address
+
+XFTP server address has the following format:
+
+```
+xftp://[:]@[,]
+```
+
+- ``
+
+ Your `xftp-server` fingerprint of certificate. You can check your certificate fingerprint in `/etc/opt/simplex-xftp/fingerprint`.
+
+- **optional** ``
+
+ Your configured password of `xftp-server`. You can check your configured pasword in `/etc/opt/simplex-xftp/file-server.ini`, under `[AUTH]` section in `create_password:` field.
+
+- ``, **optional** ``
+
+ Your configured hostname(s) of `xftp-server`. You can check your configured hosts in `/etc/opt/simplex-xftp/file-server.ini`, under `[TRANSPORT]` section in `host:` field.
+
+### Systemd commands
+
+To start `xftp-server` on host boot, run:
+
+```sh
+sudo systemctl enable xftp-server.service
+
+Created symlink /etc/systemd/system/multi-user.target.wants/xftp-server.service → /etc/systemd/system/xftp-server.service.
+```
+
+To start `xftp-server`, run:
+
+```sh
+sudo systemctl start xftp-server.service
+```
+
+To check status of `xftp-server`, run:
+
+```sh
+sudo systemctl status xftp-server.service
+
+● xftp-server.service - XFTP server systemd service
+ Loaded: loaded (/etc/systemd/system/xftp-server.service; enabled; vendor preset: enabled)
+ Active: active (running) since Sat 2023-03-11 13:11:55 UTC; 1 months 10 days ago
+ Main PID: 110770 (xftp-server)
+ Tasks: 14 (limit: 4611)
+ Memory: 2.4G
+ CGroup: /system.slice/xftp-server.service
+ └─110770 /usr/local/bin/xftp-server start +RTS -N -RTS
+
+Feb 27 19:21:11 localhost systemd[1]: Started XFTP server systemd service.
+Feb 27 19:21:11 localhost xftp-server[2350]: SimpleX XFTP server v0.1.0
+Feb 27 19:21:11 localhost xftp-server[2350]: Fingerprint: ioyYeRyy4SqJkNvb_7nM04MuLasOM4c-acVyVnqw248=
+Feb 27 19:21:11 localhost xftp-server[2350]: Server address: xftp://ioyYeRyy4SqJkNvb_7nM04MuLasOM4c-acVyVnqw248=@
+Feb 27 19:21:11 localhost xftp-server[2350]: Store log: /var/opt/simplex-xftp/file-server-store.log
+Feb 27 19:21:11 localhost xftp-server[2350]: Uploading new files allowed.
+Feb 27 19:21:11 localhost xftp-server[2350]: Listening on port 443...
+Feb 27 19:21:11 localhost xftp-server[2350]: [INFO 2023-02-27 19:21:11 +0000 src/Simplex/FileTransfer/Server/Env.hs:85] Total / available storage: 64424509440 / 64424509440
+```
+
+To stop `xftp-server`, run:
+
+```sh
+sudo systemctl stop xftp-server.service
+```
+
+To check tail of `xftp-server` log, run:
+
+```sh
+sudo journalctl -fu xftp-server.service
+
+Feb 27 19:21:11 localhost systemd[1]: Started XFTP server systemd service.
+Feb 27 19:21:11 localhost xftp-server[2350]: SimpleX XFTP server v0.1.0
+Feb 27 19:21:11 localhost xftp-server[2350]: Fingerprint: ioyYeRyy4SqJkNvb_7nM04MuLasOM4c-acVyVnqw248=
+Feb 27 19:21:11 localhost xftp-server[2350]: Server address: xftp://ioyYeRyy4SqJkNvb_7nM04MuLasOM4c-acVyVnqw248=@
+Feb 27 19:21:11 localhost xftp-server[2350]: Store log: /var/opt/simplex-xftp/file-server-store.log
+Feb 27 19:21:11 localhost xftp-server[2350]: Uploading new files allowed.
+Feb 27 19:21:11 localhost xftp-server[2350]: Listening on port 443...
+Feb 27 19:21:11 localhost xftp-server[2350]: [INFO 2023-02-27 19:21:11 +0000 src/Simplex/FileTransfer/Server/Env.hs:85] Total / available storage: 64424509440 / 64424509440
+````
+
+### Monitoring
+
+You can enable `xftp-server` statistics for `Grafana` dashboard by setting value `on` in `/etc/opt/simplex-xftp/file-server.ini`, under `[STORE_LOG]` section in `log_stats:` field.
+
+Logs will be stored as `csv` file in `/var/opt/simplex-xftp/file-server-stats.daily.log`. Fields for the `csv` file are:
+
+```sh
+fromTime,filesCreated,fileRecipients,filesUploaded,filesDeleted,dayCount,weekCount,monthCount,fileDownloads,fileDownloadAcks,filesCount,filesSize
+```
+
+- `fromTime` - timestamp; date and time of event
+
+- `filesCreated` - int; chunks created
+
+- `fileRecipients` - int; number of file chunks recipients
+
+- `filesUploaded` - int; chunks uploaded
+
+- `filesDeleted` - int; chunks deleted
+
+- `dayCount` - int; uploaded chunks in a day
+
+- `weekCount` - int; uploaded chunks in a week
+
+- `monthCount` - int; uploaded chunks in a month
+
+- `fileDownloads` - int; chunks downloaded
+
+- `filesCount` - int; count of stored file chunks
+
+- `filesSize` - int; total size of uploaded file chunks
+
+
+To import `csv` to `Grafana` one should:
+
+1. Install Grafana plugin: [Grafana - CSV datasource](https://grafana.com/grafana/plugins/marcusolsson-csv-datasource/)
+
+2. Allow local mode by appending following:
+
+ ```sh
+ [plugin.marcusolsson-csv-datasource]
+ allow_local_mode = true
+ ```
+
+ ... to `/etc/grafana/grafana.ini`
+
+3. Add a CSV data source:
+
+ - In the side menu, click the Configuration tab (cog icon)
+ - Click Add data source in the top-right corner of the Data Sources tab
+ - Enter "CSV" in the search box to find the CSV data source
+ - Click the search result that says "CSV"
+ - In URL, enter a file that points to CSV content
+
+4. You're done! You should be able to create your own dashboard with statistics.
+
+For further documentation, see: [CSV Data Source for Grafana - Documentation](https://grafana.github.io/grafana-csv-datasource/)
+
+### Configuring the app to use the server
+
+Please see: [SMP Server: Configuring the app to use the server](./SERVER.md#configuring-the-app-to-use-the-server).
diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix
index b6e6fe9a5b..c213269f51 100644
--- a/scripts/nix/sha256map.nix
+++ b/scripts/nix/sha256map.nix
@@ -1,5 +1,5 @@
{
- "https://github.com/simplex-chat/simplexmq.git"."4da637a565bb8eff3e4e0fd940f9fdd34ce981e7" = "1z8vrd91mm9p6hswvihn16xkn45ph6ndmbpq787hzld8kqicaddx";
+ "https://github.com/simplex-chat/simplexmq.git"."af3f70829dca2483425eb8702cd9aeac2c026e14" = "1ngngzqz6fjr11dk2v3d1wrfkyyac954a0fswhq27pfhapqdhlw0";
"https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38";
"https://github.com/kazu-yamamoto/http2.git"."b5a1b7200cf5bc7044af34ba325284271f6dff25" = "0dqb50j57an64nf4qcf5vcz4xkd1vzvghvf8bk529c1k30r9nfzb";
"https://github.com/simplex-chat/direct-sqlcipher.git"."34309410eb2069b029b8fc1872deb1e0db123294" = "0kwkmhyfsn2lixdlgl15smgr1h5gjk7fky6abzh8rng2h5ymnffd";
diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs
index 240b09adad..12e7c63455 100644
--- a/src/Simplex/Chat.hs
+++ b/src/Simplex/Chat.hs
@@ -1446,7 +1446,7 @@ processChatCommand = \case
fsFilePath <- toFSFilePath filePath
removeFile fsFilePath `E.catch` \(_ :: E.SomeException) -> pure ()
forM_ agentRcvFileId $ \(AgentRcvFileId aFileId) ->
- withAgent $ \a -> xftpDeleteRcvFile a (aUserId user) aFileId
+ withAgent (`xftpDeleteRcvFile` aFileId)
ci <- withStore $ \db -> do
liftIO $ do
updateCIFileStatus db user fileId CIFSRcvInvitation
@@ -2362,7 +2362,9 @@ processAgentMsgSndFile :: forall m. ChatMonad m => ACorrId -> SndFileId -> AComm
processAgentMsgSndFile _corrId aFileId msg =
withStore' (`getUserByASndFileId` AgentSndFileId aFileId) >>= \case
Just user -> process user `catchError` (toView . CRChatError (Just user))
- _ -> throwChatError $ CENoSndFileUser $ AgentSndFileId aFileId
+ _ -> do
+ withAgent (`xftpDeleteSndFileInternal` aFileId)
+ throwChatError $ CENoSndFileUser $ AgentSndFileId aFileId
where
process :: User -> m ()
process user = do
@@ -2390,7 +2392,7 @@ processAgentMsgSndFile _corrId aFileId msg =
withStore' $ \db -> createExtraSndFTDescrs db user fileId (map fileDescrText extraRFDs)
msgDeliveryId <- sendFileDescription sft rfd sharedMsgId $ sendDirectContactMessage ct
withStore' $ \db -> updateSndFTDeliveryXFTP db sft msgDeliveryId
- agentXFTPDeleteSndFileInternal user aFileId
+ withAgent (`xftpDeleteSndFileInternal` aFileId)
(_, _, SMDSnd, GroupChat g@GroupInfo {groupId}) -> do
ms <- withStore' $ \db -> getGroupMembers db user g
let rfdsMemberFTs = zip rfds $ memberFTs ms
@@ -2400,7 +2402,7 @@ processAgentMsgSndFile _corrId aFileId msg =
ci' <- withStore $ \db -> do
liftIO $ updateCIFileStatus db user fileId CIFSSndComplete
getChatItemByFileId db user fileId
- agentXFTPDeleteSndFileInternal user aFileId
+ withAgent (`xftpDeleteSndFileInternal` aFileId)
toView $ CRSndFileCompleteXFTP user ci' ft
where
memberFTs :: [GroupMember] -> [(Connection, SndFileTransfer)]
@@ -2424,7 +2426,7 @@ processAgentMsgSndFile _corrId aFileId msg =
ci <- withStore $ \db -> do
liftIO $ updateFileCancelled db user fileId CIFSSndError
getChatItemByFileId db user fileId
- agentXFTPDeleteSndFileInternal user aFileId
+ withAgent (`xftpDeleteSndFileInternal` aFileId)
toView $ CRSndFileError user ci
where
fileDescrText :: FilePartyI p => ValidFileDescription p -> T.Text
@@ -2449,7 +2451,9 @@ processAgentMsgRcvFile :: forall m. ChatMonad m => ACorrId -> RcvFileId -> AComm
processAgentMsgRcvFile _corrId aFileId msg =
withStore' (`getUserByARcvFileId` AgentRcvFileId aFileId) >>= \case
Just user -> process user `catchError` (toView . CRChatError (Just user))
- _ -> throwChatError $ CENoRcvFileUser $ AgentRcvFileId aFileId
+ _ -> do
+ withAgent (`xftpDeleteRcvFile` aFileId)
+ throwChatError $ CENoRcvFileUser $ AgentRcvFileId aFileId
where
process :: User -> m ()
process user = do
@@ -2474,7 +2478,7 @@ processAgentMsgRcvFile _corrId aFileId msg =
updateRcvFileStatus db fileId FSComplete
updateCIFileStatus db user fileId CIFSRcvComplete
getChatItemByFileId db user fileId
- agentXFTPDeleteRcvFile user aFileId fileId
+ agentXFTPDeleteRcvFile aFileId fileId
toView $ CRRcvFileComplete user ci
RFERR e
| temporaryAgentError e ->
@@ -2483,7 +2487,7 @@ processAgentMsgRcvFile _corrId aFileId msg =
ci <- withStore $ \db -> do
liftIO $ updateFileCancelled db user fileId CIFSRcvError
getChatItemByFileId db user fileId
- agentXFTPDeleteRcvFile user aFileId fileId
+ agentXFTPDeleteRcvFile aFileId fileId
toView $ CRRcvFileError user ci
processAgentMessageConn :: forall m. ChatMonad m => User -> ACorrId -> ConnId -> ACommand 'Agent 'AEConn -> m ()
@@ -4039,7 +4043,7 @@ cancelRcvFileTransfer user ft@RcvFileTransfer {fileId, xftpRcvFile, rcvFileInlin
deleteRcvFileChunks db ft
case xftpRcvFile of
Just XFTPRcvFile {agentRcvFileId = Just (AgentRcvFileId aFileId), agentRcvFileDeleted} ->
- unless agentRcvFileDeleted $ agentXFTPDeleteRcvFile user aFileId fileId
+ unless agentRcvFileDeleted $ agentXFTPDeleteRcvFile aFileId fileId
_ -> pure ()
pure fileConnId
fileConnId = if isNothing xftpRcvFile && isNothing rcvFileInline then liveRcvFileTransferConnId ft else Nothing
@@ -4297,15 +4301,11 @@ deleteAgentConnectionsAsync _ [] = pure ()
deleteAgentConnectionsAsync user acIds =
withAgent (`deleteConnectionsAsync` acIds) `catchError` (toView . CRChatError (Just user))
-agentXFTPDeleteRcvFile :: ChatMonad m => User -> RcvFileId -> FileTransferId -> m ()
-agentXFTPDeleteRcvFile user aFileId fileId = do
- withAgent $ \a -> xftpDeleteRcvFile a (aUserId user) aFileId
+agentXFTPDeleteRcvFile :: ChatMonad m => RcvFileId -> FileTransferId -> m ()
+agentXFTPDeleteRcvFile aFileId fileId = do
+ withAgent (`xftpDeleteRcvFile` aFileId)
withStore' $ \db -> setRcvFTAgentDeleted db fileId
-agentXFTPDeleteSndFileInternal :: ChatMonad m => User -> SndFileId -> m ()
-agentXFTPDeleteSndFileInternal user aFileId = do
- withAgent (\a -> xftpDeleteSndFileInternal a (aUserId user) aFileId) `catchError` (toView . CRChatError (Just user))
-
agentXFTPDeleteSndFileRemote :: ChatMonad m => User -> XFTPSndFile -> FileTransferId -> m ()
agentXFTPDeleteSndFileRemote user XFTPSndFile {agentSndFileId = AgentSndFileId aFileId, privateSndFileDescr, agentSndFileDeleted} fileId =
unless agentSndFileDeleted $
diff --git a/stack.yaml b/stack.yaml
index d1e3ec844d..f7f074b9ef 100644
--- a/stack.yaml
+++ b/stack.yaml
@@ -49,7 +49,7 @@ extra-deps:
# - simplexmq-1.0.0@sha256:34b2004728ae396e3ae449cd090ba7410781e2b3cefc59259915f4ca5daa9ea8,8561
# - ../simplexmq
- github: simplex-chat/simplexmq
- commit: 4da637a565bb8eff3e4e0fd940f9fdd34ce981e7
+ commit: af3f70829dca2483425eb8702cd9aeac2c026e14
- github: kazu-yamamoto/http2
commit: b5a1b7200cf5bc7044af34ba325284271f6dff25
# - ../direct-sqlcipher
diff --git a/website/.eleventy.js b/website/.eleventy.js
index febbd7781a..7dc872b6aa 100644
--- a/website/.eleventy.js
+++ b/website/.eleventy.js
@@ -6,6 +6,8 @@ const uri = require('fast-uri')
const i18n = require('eleventy-plugin-i18n');
const fs = require("fs");
const path = require("path");
+const pluginRss = require('@11ty/eleventy-plugin-rss');
+
const globalConfig = {
onionLocation: "http://isdb4l77sjqoy2qq7ipum6x3at6hyn3jmxfx4zdhc72ufbmuq4ilwkqd.onion",
@@ -63,6 +65,8 @@ module.exports = function (ty) {
}
})
+ ty.addPlugin(pluginRss);
+
ty.addPlugin(i18n, {
translations,
fallbackLocales: {
diff --git a/website/package.json b/website/package.json
index 4afc721086..5560e7bece 100644
--- a/website/package.json
+++ b/website/package.json
@@ -17,12 +17,13 @@
"license": "ISC",
"devDependencies": {
"@11ty/eleventy": "^1.0.1",
+ "@11ty/eleventy-plugin-rss": "^1.2.0",
"@simplex-chat/webrtc": "^0.1.1",
"common-tags": "^1.8.2",
"fast-uri": "^2.1.0",
"markdown-it-anchor": "^8.6.4",
"markdown-it-replace-link": "^1.1.0",
- "qrcode": "^1.5.1",
+ "qrcode": "1.5.1",
"slugify": "^1.6.5",
"tailwindcss": "^3.2.7"
},
diff --git a/website/src/_includes/blog_previews/20230422.html b/website/src/_includes/blog_previews/20230422.html
new file mode 100644
index 0000000000..38d64f032b
--- /dev/null
+++ b/website/src/_includes/blog_previews/20230422.html
@@ -0,0 +1,19 @@
+SimpleX Chat vision and funding:
+
+
+ - why is it a commercial company?
+ - how is it funded and what is the business model?
+ - what is next?
+
+
+v5.0 is released:
+
+
+ - send videos and files up to 1gb
+ - app passcode independent from system authentication
+ - networking improvements
+
+
+Also, the app interface is now available in Polish - thanks our users.
+
+SimpleX Chat apps are now available in 10 languages!
\ No newline at end of file
diff --git a/website/src/_includes/navbar.html b/website/src/_includes/navbar.html
index 30cca05c59..a756701416 100644
--- a/website/src/_includes/navbar.html
+++ b/website/src/_includes/navbar.html
@@ -110,17 +110,17 @@
{% endfor %}
-
+
{% for language in languages.languages %}
{% if language.enabled %}
-
{% if language.flag %}
-
+
{{ language.name }}
{% else %}
-
+
diff --git a/website/src/_includes/sections/join_simplex.html b/website/src/_includes/sections/join_simplex.html
index 85395ba928..5b00d171d5 100644
--- a/website/src/_includes/sections/join_simplex.html
+++ b/website/src/_includes/sections/join_simplex.html
@@ -1,5 +1,5 @@
{# join simplex #}
-
+
{{ "join" | i18n({}, lang ) | safe }} SimpleX
{{ "we-invite-you-to-join-the-conversation" | i18n({}, lang ) | safe }}
diff --git a/website/src/blogs-atom-feed.njk b/website/src/blogs-atom-feed.njk
new file mode 100644
index 0000000000..ea58fa2d1d
--- /dev/null
+++ b/website/src/blogs-atom-feed.njk
@@ -0,0 +1,37 @@
+---
+permalink: feed.atom
+eleventyExcludeFromCollections: true
+metadata:
+ title: SimpleX Chat Blog
+ subtitle: It allows you to stay up to date with the latest Blogs from SimpleX Chat.
+ language: en
+ url: https://simplex.chat/,
+ author:
+ name: SimpleX Chat
+ email: chat@simplex.chat
+---
+
+
+ {{ metadata.title }}
+ {{ metadata.subtitle }}
+
+
+ {{ collections.blogs | getNewestCollectionItemDate | dateToRfc3339 }}
+ {{ metadata.url }}
+
+ {{ metadata.author.name }}
+ {{ metadata.author.email }}
+
+ {%- for blog in collections.blogs | reverse %}
+ {%- set absolutePostUrl = blog.url | absoluteUrl(metadata.url) %}
+
+ {{ blog.data.title }}
+
+ {# {{ blog.date | dateToRfc3339 }} #}
+ {{ blog.data.date.toUTCString().split(' ').slice(1, 4).join(' ') }}
+ {{ absolutePostUrl }}
+ {{ blog.templateContent | htmlToAbsoluteUrls(absolutePostUrl) }}
+ {# {{ blog.templateContent | striptags | truncate(200) }} #}
+
+ {%- endfor %}
+
\ No newline at end of file
diff --git a/website/src/blogs-rss-feed.njk b/website/src/blogs-rss-feed.njk
new file mode 100644
index 0000000000..5163a7520e
--- /dev/null
+++ b/website/src/blogs-rss-feed.njk
@@ -0,0 +1,35 @@
+---
+permalink: feed.rss
+eleventyExcludeFromCollections: true
+metadata:
+ title: SimpleX Chat Blog
+ subtitle: It allows you to stay up to date with the latest Blogs from SimpleX Chat.
+ language: en
+ url: https://simplex.chat/,
+ author:
+ name: SimpleX Chat
+ email: chat@simplex.chat
+---
+
+
+
+ {{ metadata.title }}
+ {{ metadata.url }}
+
+ {{ metadata.subtitle }}
+ {{ metadata.language }}
+ {%- for blog in collections.blogs %}
+ {%- set absolutePostUrl = blog.url | absoluteUrl(metadata.url) %}
+ -
+ {{ blog.data.title }}
+ {{ absolutePostUrl }}
+ {{ blog.templateContent | htmlToAbsoluteUrls(absolutePostUrl) }}
+ {# {{ blog.templateContent | striptags | truncate(200) }} #}
+ {# {{ blog.data.date | dateToRfc822 }} #}
+ {{ blog.data.date.toUTCString().split(' ').slice(1, 4).join(' ') }}
+ {{ metadata.author.name }}
+ {{ absolutePostUrl }}
+
+ {%- endfor %}
+
+
\ No newline at end of file
diff --git a/website/web.sh b/website/web.sh
index 58fecb48d6..c50a82ff2f 100755
--- a/website/web.sh
+++ b/website/web.sh
@@ -1,5 +1,7 @@
#!/bin/bash
+set -e
+
cp -R blog website/src
cp -R images website/src
rm website/src/blog/README.md
@@ -20,7 +22,7 @@ node merge_translations.js
# creating folders for each language for internationalization
for lang in "${langs[@]}"; do
- mkdir src/$lang
+ mkdir -p src/$lang
cp src/index.html src/$lang
cp src/contact.html src/$lang
cp src/invitation.html src/$lang