Merge remote-tracking branch 'origin/master' into ab/self-chat
This commit is contained in:
commit
e43ed1ca43
@ -3,11 +3,12 @@ package chat.simplex.app
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.work.*
|
import androidx.work.*
|
||||||
import chat.simplex.app.*
|
|
||||||
import chat.simplex.app.SimplexService.Companion.showPassphraseNotification
|
import chat.simplex.app.SimplexService.Companion.showPassphraseNotification
|
||||||
import chat.simplex.common.model.ChatController
|
import chat.simplex.common.model.ChatController
|
||||||
import chat.simplex.common.views.helpers.DBMigrationResult
|
import chat.simplex.common.views.helpers.DBMigrationResult
|
||||||
import chat.simplex.app.BuildConfig
|
import chat.simplex.common.platform.chatModel
|
||||||
|
import chat.simplex.common.platform.initChatControllerAndRunMigrations
|
||||||
|
import chat.simplex.common.views.helpers.DatabaseUtils
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
@ -57,6 +58,10 @@ class MessagesFetcherWork(
|
|||||||
val durationSeconds = inputData.getInt(INPUT_DATA_DURATION, 60)
|
val durationSeconds = inputData.getInt(INPUT_DATA_DURATION, 60)
|
||||||
var shouldReschedule = true
|
var shouldReschedule = true
|
||||||
try {
|
try {
|
||||||
|
// In case of self-destruct is enabled the initialization process will not start in SimplexApp, Let's start it here
|
||||||
|
if (DatabaseUtils.ksSelfDestructPassword.get() != null && chatModel.chatDbStatus.value == null) {
|
||||||
|
initChatControllerAndRunMigrations()
|
||||||
|
}
|
||||||
withTimeout(durationSeconds * 1000L) {
|
withTimeout(durationSeconds * 1000L) {
|
||||||
val chatController = ChatController
|
val chatController = ChatController
|
||||||
SimplexService.waitDbMigrationEnds(chatController)
|
SimplexService.waitDbMigrationEnds(chatController)
|
||||||
|
@ -26,6 +26,7 @@ import kotlinx.coroutines.sync.withLock
|
|||||||
import java.io.*
|
import java.io.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
const val TAG = "SIMPLEX"
|
const val TAG = "SIMPLEX"
|
||||||
|
|
||||||
@ -46,8 +47,8 @@ class SimplexApp: Application(), LifecycleEventObserver {
|
|||||||
try {
|
try {
|
||||||
Looper.loop()
|
Looper.loop()
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
if (e.message != null && e.message!!.startsWith("Unable to start activity")) {
|
if (e is UnsatisfiedLinkError || e.message?.startsWith("Unable to start activity") == true) {
|
||||||
android.os.Process.killProcess(android.os.Process.myPid())
|
Process.killProcess(Process.myPid())
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
// Send it to our exception handled because it will not get the exception otherwise
|
// Send it to our exception handled because it will not get the exception otherwise
|
||||||
@ -63,7 +64,9 @@ class SimplexApp: Application(), LifecycleEventObserver {
|
|||||||
tmpDir.deleteRecursively()
|
tmpDir.deleteRecursively()
|
||||||
tmpDir.mkdir()
|
tmpDir.mkdir()
|
||||||
|
|
||||||
initChatControllerAndRunMigrations(false)
|
if (DatabaseUtils.ksSelfDestructPassword.get() == null) {
|
||||||
|
initChatControllerAndRunMigrations()
|
||||||
|
}
|
||||||
ProcessLifecycleOwner.get().lifecycle.addObserver(this@SimplexApp)
|
ProcessLifecycleOwner.get().lifecycle.addObserver(this@SimplexApp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,6 +72,10 @@ class SimplexService: Service() {
|
|||||||
stopSelf()
|
stopSelf()
|
||||||
} else {
|
} else {
|
||||||
isServiceStarted = true
|
isServiceStarted = true
|
||||||
|
// In case of self-destruct is enabled the initialization process will not start in SimplexApp, Let's start it here
|
||||||
|
if (DatabaseUtils.ksSelfDestructPassword.get() != null && chatModel.chatDbStatus.value == null) {
|
||||||
|
initChatControllerAndRunMigrations()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +97,8 @@ fun IncomingCallActivityView(m: ChatModel) {
|
|||||||
Surface(
|
Surface(
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxSize(),
|
.fillMaxSize(),
|
||||||
color = MaterialTheme.colors.background
|
color = MaterialTheme.colors.background,
|
||||||
|
contentColor = LocalContentColor.current
|
||||||
) {
|
) {
|
||||||
if (showCallView) {
|
if (showCallView) {
|
||||||
Box {
|
Box {
|
||||||
@ -200,7 +201,8 @@ private fun SimpleXLogo() {
|
|||||||
private fun LockScreenCallButton(text: String, icon: Painter, color: Color, action: () -> Unit) {
|
private fun LockScreenCallButton(text: String, icon: Painter, color: Color, action: () -> Unit) {
|
||||||
Surface(
|
Surface(
|
||||||
shape = RoundedCornerShape(10.dp),
|
shape = RoundedCornerShape(10.dp),
|
||||||
color = Color.Transparent
|
color = Color.Transparent,
|
||||||
|
contentColor = LocalContentColor.current
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
Modifier
|
Modifier
|
||||||
@ -227,7 +229,8 @@ fun PreviewIncomingCallLockScreenAlert() {
|
|||||||
Surface(
|
Surface(
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxSize(),
|
.fillMaxSize(),
|
||||||
color = MaterialTheme.colors.background
|
color = MaterialTheme.colors.background,
|
||||||
|
contentColor = LocalContentColor.current
|
||||||
) {
|
) {
|
||||||
IncomingCallLockScreenAlertLayout(
|
IncomingCallLockScreenAlertLayout(
|
||||||
invitation = RcvCallInvitation(
|
invitation = RcvCallInvitation(
|
||||||
|
@ -44,7 +44,7 @@ data class SettingsViewState(
|
|||||||
fun AppScreen() {
|
fun AppScreen() {
|
||||||
SimpleXTheme {
|
SimpleXTheme {
|
||||||
ProvideWindowInsets(windowInsetsAnimationsEnabled = true) {
|
ProvideWindowInsets(windowInsetsAnimationsEnabled = true) {
|
||||||
Surface(color = MaterialTheme.colors.background) {
|
Surface(color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) {
|
||||||
MainScreen()
|
MainScreen()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,7 +85,7 @@ fun MainScreen() {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AuthView() {
|
fun AuthView() {
|
||||||
Surface(color = MaterialTheme.colors.background) {
|
Surface(color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) {
|
||||||
Box(
|
Box(
|
||||||
Modifier.fillMaxSize(),
|
Modifier.fillMaxSize(),
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
package chat.simplex.common
|
package chat.simplex.common
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.material.MaterialTheme
|
import androidx.compose.material.*
|
||||||
import androidx.compose.material.Surface
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import chat.simplex.common.model.*
|
import chat.simplex.common.model.*
|
||||||
@ -107,7 +106,7 @@ object AppLock {
|
|||||||
private fun setPasscode() {
|
private fun setPasscode() {
|
||||||
val appPrefs = ChatController.appPrefs
|
val appPrefs = ChatController.appPrefs
|
||||||
ModalManager.fullscreen.showCustomModal { close ->
|
ModalManager.fullscreen.showCustomModal { close ->
|
||||||
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
|
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) {
|
||||||
SetAppPasscodeView(
|
SetAppPasscodeView(
|
||||||
submit = {
|
submit = {
|
||||||
ChatModel.performLA.value = true
|
ChatModel.performLA.value = true
|
||||||
|
@ -41,21 +41,20 @@ val appPreferences: AppPreferences
|
|||||||
|
|
||||||
val chatController: ChatController = ChatController
|
val chatController: ChatController = ChatController
|
||||||
|
|
||||||
fun initChatControllerAndRunMigrations(ignoreSelfDestruct: Boolean) {
|
fun initChatControllerAndRunMigrations() {
|
||||||
if (ignoreSelfDestruct || DatabaseUtils.ksSelfDestructPassword.get() == null) {
|
withBGApi {
|
||||||
withBGApi {
|
if (appPreferences.chatStopped.get() && appPreferences.storeDBPassphrase.get() && ksDatabasePassword.get() != null) {
|
||||||
if (appPreferences.chatStopped.get() && appPreferences.storeDBPassphrase.get() && ksDatabasePassword.get() != null) {
|
initChatController(startChat = ::showStartChatAfterRestartAlert)
|
||||||
initChatController(startChat = ::showStartChatAfterRestartAlert)
|
} else {
|
||||||
} else {
|
initChatController()
|
||||||
initChatController()
|
|
||||||
}
|
|
||||||
runMigrations()
|
|
||||||
}
|
}
|
||||||
|
runMigrations()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun initChatController(useKey: String? = null, confirmMigrations: MigrationConfirmation? = null, startChat: () -> CompletableDeferred<Boolean> = { CompletableDeferred(true) }) {
|
suspend fun initChatController(useKey: String? = null, confirmMigrations: MigrationConfirmation? = null, startChat: () -> CompletableDeferred<Boolean> = { CompletableDeferred(true) }) {
|
||||||
try {
|
try {
|
||||||
|
if (chatModel.ctrlInitInProgress.value) return
|
||||||
chatModel.ctrlInitInProgress.value = true
|
chatModel.ctrlInitInProgress.value = true
|
||||||
val dbKey = useKey ?: DatabaseUtils.useDatabaseKey()
|
val dbKey = useKey ?: DatabaseUtils.useDatabaseKey()
|
||||||
val confirm = confirmMigrations ?: if (appPreferences.confirmDBUpgrades.get()) MigrationConfirmation.Error else MigrationConfirmation.YesUp
|
val confirm = confirmMigrations ?: if (appPreferences.confirmDBUpgrades.get()) MigrationConfirmation.Error else MigrationConfirmation.YesUp
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package chat.simplex.common.ui.theme
|
package chat.simplex.common.ui.theme
|
||||||
|
|
||||||
|
import androidx.compose.material.LocalContentColor
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
|
||||||
val Purple200 = Color(0xFFBB86FC)
|
val Purple200 = Color(0xFFBB86FC)
|
||||||
@ -25,4 +27,5 @@ val WarningOrange = Color(255, 127, 0, 255)
|
|||||||
val WarningYellow = Color(255, 192, 0, 255)
|
val WarningYellow = Color(255, 192, 0, 255)
|
||||||
val FileLight = Color(183, 190, 199, 255)
|
val FileLight = Color(183, 190, 199, 255)
|
||||||
val FileDark = Color(101, 101, 106, 255)
|
val FileDark = Color(101, 101, 106, 255)
|
||||||
val MenuTextColorDark = Color.White.copy(alpha = 0.8f)
|
|
||||||
|
val MenuTextColor: Color @Composable get () = if (isInDarkTheme()) LocalContentColor.current.copy(alpha = 0.8f) else Color.Black
|
||||||
|
@ -283,27 +283,10 @@ fun SimpleXTheme(darkTheme: Boolean? = null, content: @Composable () -> Unit) {
|
|||||||
val theme by CurrentColors.collectAsState()
|
val theme by CurrentColors.collectAsState()
|
||||||
MaterialTheme(
|
MaterialTheme(
|
||||||
colors = theme.colors,
|
colors = theme.colors,
|
||||||
typography = Typography.copy(
|
typography = Typography,
|
||||||
h1 = Typography.h1.copy(color = theme.colors.onBackground),
|
|
||||||
h2 = Typography.h2.copy(color = theme.colors.onBackground),
|
|
||||||
h3 = Typography.h3.copy(color = theme.colors.onBackground),
|
|
||||||
h4 = Typography.h4.copy(color = theme.colors.onBackground),
|
|
||||||
h5 = Typography.h5.copy(color = theme.colors.onBackground),
|
|
||||||
h6 = Typography.h6.copy(color = theme.colors.onBackground),
|
|
||||||
subtitle1 = Typography.subtitle1.copy(color = theme.colors.onBackground),
|
|
||||||
subtitle2 = Typography.subtitle2.copy(color = theme.colors.onBackground),
|
|
||||||
body1 = Typography.body1.copy(color = theme.colors.onBackground),
|
|
||||||
body2 = Typography.body2.copy(color = theme.colors.onBackground),
|
|
||||||
button = Typography.button.copy(color = theme.colors.onBackground),
|
|
||||||
caption = Typography.caption.copy(color = theme.colors.onBackground),
|
|
||||||
overline = Typography.overline.copy(color = theme.colors.onBackground)
|
|
||||||
),
|
|
||||||
shapes = Shapes,
|
shapes = Shapes,
|
||||||
content = {
|
content = {
|
||||||
ProvideTextStyle(
|
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colors.onBackground, content = content)
|
||||||
value = TextStyle(color = theme.colors.onBackground),
|
|
||||||
content = content
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
package chat.simplex.common.views
|
package chat.simplex.common.views
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.material.MaterialTheme
|
import androidx.compose.material.*
|
||||||
import androidx.compose.material.Surface
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
|
||||||
@ -11,7 +10,8 @@ fun SplashView() {
|
|||||||
Surface(
|
Surface(
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxSize(),
|
.fillMaxSize(),
|
||||||
color = MaterialTheme.colors.background
|
color = MaterialTheme.colors.background,
|
||||||
|
contentColor = LocalContentColor.current
|
||||||
) {
|
) {
|
||||||
// Image(
|
// Image(
|
||||||
// painter = painterResource(MR.images.logo),
|
// painter = painterResource(MR.images.logo),
|
||||||
|
@ -101,13 +101,16 @@ fun TerminalLayout(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
contentColor = LocalContentColor.current,
|
||||||
|
drawerContentColor = LocalContentColor.current,
|
||||||
modifier = Modifier.navigationBarsWithImePadding()
|
modifier = Modifier.navigationBarsWithImePadding()
|
||||||
) { contentPadding ->
|
) { contentPadding ->
|
||||||
Surface(
|
Surface(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(contentPadding)
|
.padding(contentPadding)
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
color = MaterialTheme.colors.background
|
color = MaterialTheme.colors.background,
|
||||||
|
contentColor = LocalContentColor.current
|
||||||
) {
|
) {
|
||||||
TerminalLog()
|
TerminalLog()
|
||||||
}
|
}
|
||||||
|
@ -239,7 +239,7 @@ fun OnboardingButtons(displayName: MutableState<String>, close: () -> Unit) {
|
|||||||
val enabled = canCreateProfile(displayName.value)
|
val enabled = canCreateProfile(displayName.value)
|
||||||
val createModifier: Modifier = Modifier.clickable(enabled) { createProfileOnboarding(chatModel, displayName.value, close) }.padding(8.dp)
|
val createModifier: Modifier = Modifier.clickable(enabled) { createProfileOnboarding(chatModel, displayName.value, close) }.padding(8.dp)
|
||||||
val createColor: Color = if (enabled) MaterialTheme.colors.primary else MaterialTheme.colors.secondary
|
val createColor: Color = if (enabled) MaterialTheme.colors.primary else MaterialTheme.colors.secondary
|
||||||
Surface(shape = RoundedCornerShape(20.dp), color = Color.Transparent) {
|
Surface(shape = RoundedCornerShape(20.dp), color = Color.Transparent, contentColor = LocalContentColor.current) {
|
||||||
Row(verticalAlignment = Alignment.CenterVertically, modifier = createModifier) {
|
Row(verticalAlignment = Alignment.CenterVertically, modifier = createModifier) {
|
||||||
Text(stringResource(MR.strings.create_profile_button), style = MaterialTheme.typography.caption, color = createColor, fontWeight = FontWeight.Medium)
|
Text(stringResource(MR.strings.create_profile_button), style = MaterialTheme.typography.caption, color = createColor, fontWeight = FontWeight.Medium)
|
||||||
Icon(painterResource(MR.images.ic_arrow_forward_ios), stringResource(MR.strings.create_profile_button), tint = createColor)
|
Icon(painterResource(MR.images.ic_arrow_forward_ios), stringResource(MR.strings.create_profile_button), tint = createColor)
|
||||||
|
@ -85,7 +85,8 @@ fun IncomingCallInfo(invitation: RcvCallInvitation, chatModel: ChatModel) {
|
|||||||
private fun CallButton(text: String, icon: Painter, color: Color, action: () -> Unit) {
|
private fun CallButton(text: String, icon: Painter, color: Color, action: () -> Unit) {
|
||||||
Surface(
|
Surface(
|
||||||
shape = RoundedCornerShape(10.dp),
|
shape = RoundedCornerShape(10.dp),
|
||||||
color = Color.Transparent
|
color = Color.Transparent,
|
||||||
|
contentColor = LocalContentColor.current
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
Modifier
|
Modifier
|
||||||
|
@ -570,6 +570,8 @@ fun ChatLayout(
|
|||||||
bottomBar = composeView,
|
bottomBar = composeView,
|
||||||
modifier = Modifier.navigationBarsWithImePadding(),
|
modifier = Modifier.navigationBarsWithImePadding(),
|
||||||
floatingActionButton = { floatingButton.value() },
|
floatingActionButton = { floatingButton.value() },
|
||||||
|
contentColor = LocalContentColor.current,
|
||||||
|
drawerContentColor = LocalContentColor.current,
|
||||||
) { contentPadding ->
|
) { contentPadding ->
|
||||||
BoxWithConstraints(Modifier
|
BoxWithConstraints(Modifier
|
||||||
.fillMaxHeight()
|
.fillMaxHeight()
|
||||||
|
@ -258,7 +258,8 @@ private fun CustomDisappearingMessageDialog(
|
|||||||
|
|
||||||
DefaultDialog(onDismissRequest = { setShowDialog(false) }) {
|
DefaultDialog(onDismissRequest = { setShowDialog(false) }) {
|
||||||
Surface(
|
Surface(
|
||||||
shape = RoundedCornerShape(corner = CornerSize(25.dp))
|
shape = RoundedCornerShape(corner = CornerSize(25.dp)),
|
||||||
|
contentColor = LocalContentColor.current
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
|
@ -131,7 +131,8 @@ fun CIFileView(
|
|||||||
Surface(
|
Surface(
|
||||||
Modifier.drawRingModifier(angle, strokeColor, strokeWidth),
|
Modifier.drawRingModifier(angle, strokeColor, strokeWidth),
|
||||||
color = Color.Transparent,
|
color = Color.Transparent,
|
||||||
shape = MaterialTheme.shapes.small.copy(CornerSize(percent = 50))
|
shape = MaterialTheme.shapes.small.copy(CornerSize(percent = 50)),
|
||||||
|
contentColor = LocalContentColor.current
|
||||||
) {
|
) {
|
||||||
Box(Modifier.size(32.dp))
|
Box(Modifier.size(32.dp))
|
||||||
}
|
}
|
||||||
|
@ -88,6 +88,7 @@ fun CIGroupInvitationView(
|
|||||||
}) else Modifier,
|
}) else Modifier,
|
||||||
shape = RoundedCornerShape(18.dp),
|
shape = RoundedCornerShape(18.dp),
|
||||||
color = if (sent) sentColor else receivedColor,
|
color = if (sent) sentColor else receivedColor,
|
||||||
|
contentColor = LocalContentColor.current
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
Modifier
|
Modifier
|
||||||
|
@ -142,6 +142,7 @@ fun DecryptionErrorItemFixButton(
|
|||||||
Modifier.clickable(onClick = onClick),
|
Modifier.clickable(onClick = onClick),
|
||||||
shape = RoundedCornerShape(18.dp),
|
shape = RoundedCornerShape(18.dp),
|
||||||
color = receivedColor,
|
color = receivedColor,
|
||||||
|
contentColor = LocalContentColor.current
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
Modifier.padding(vertical = 6.dp, horizontal = 12.dp),
|
Modifier.padding(vertical = 6.dp, horizontal = 12.dp),
|
||||||
@ -188,6 +189,7 @@ fun DecryptionErrorItem(
|
|||||||
Modifier.clickable(onClick = onClick),
|
Modifier.clickable(onClick = onClick),
|
||||||
shape = RoundedCornerShape(18.dp),
|
shape = RoundedCornerShape(18.dp),
|
||||||
color = receivedColor,
|
color = receivedColor,
|
||||||
|
contentColor = LocalContentColor.current
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
Modifier.padding(vertical = 6.dp, horizontal = 12.dp),
|
Modifier.padding(vertical = 6.dp, horizontal = 12.dp),
|
||||||
|
@ -153,7 +153,8 @@ private fun BoxScope.PlayButton(error: Boolean = false, onLongClick: () -> Unit,
|
|||||||
Surface(
|
Surface(
|
||||||
Modifier.align(Alignment.Center),
|
Modifier.align(Alignment.Center),
|
||||||
color = Color.Black.copy(alpha = 0.25f),
|
color = Color.Black.copy(alpha = 0.25f),
|
||||||
shape = RoundedCornerShape(percent = 50)
|
shape = RoundedCornerShape(percent = 50),
|
||||||
|
contentColor = LocalContentColor.current
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
Modifier
|
Modifier
|
||||||
@ -264,7 +265,8 @@ private fun progressCircle(progress: Long, total: Long) {
|
|||||||
Surface(
|
Surface(
|
||||||
Modifier.drawRingModifier(angle, strokeColor, strokeWidth),
|
Modifier.drawRingModifier(angle, strokeColor, strokeWidth),
|
||||||
color = Color.Transparent,
|
color = Color.Transparent,
|
||||||
shape = MaterialTheme.shapes.small.copy(CornerSize(percent = 50))
|
shape = MaterialTheme.shapes.small.copy(CornerSize(percent = 50)),
|
||||||
|
contentColor = LocalContentColor.current
|
||||||
) {
|
) {
|
||||||
Box(Modifier.size(16.dp))
|
Box(Modifier.size(16.dp))
|
||||||
}
|
}
|
||||||
|
@ -225,7 +225,8 @@ private fun PlayPauseButton(
|
|||||||
Surface(
|
Surface(
|
||||||
Modifier.drawRingModifier(angle, strokeColor, strokeWidth),
|
Modifier.drawRingModifier(angle, strokeColor, strokeWidth),
|
||||||
color = if (sent) sentColor else receivedColor,
|
color = if (sent) sentColor else receivedColor,
|
||||||
shape = MaterialTheme.shapes.small.copy(CornerSize(percent = 50))
|
shape = MaterialTheme.shapes.small.copy(CornerSize(percent = 50)),
|
||||||
|
contentColor = LocalContentColor.current
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
Modifier
|
Modifier
|
||||||
|
@ -613,7 +613,7 @@ private fun ShrinkItemAction(revealed: MutableState<Boolean>, showMenu: MutableS
|
|||||||
@Composable
|
@Composable
|
||||||
fun ItemAction(text: String, icon: Painter, color: Color = Color.Unspecified, onClick: () -> Unit) {
|
fun ItemAction(text: String, icon: Painter, color: Color = Color.Unspecified, onClick: () -> Unit) {
|
||||||
val finalColor = if (color == Color.Unspecified) {
|
val finalColor = if (color == Color.Unspecified) {
|
||||||
if (isInDarkTheme()) MenuTextColorDark else Color.Black
|
MenuTextColor
|
||||||
} else color
|
} else color
|
||||||
DropdownMenuItem(onClick, contentPadding = PaddingValues(horizontal = DEFAULT_PADDING * 1.5f)) {
|
DropdownMenuItem(onClick, contentPadding = PaddingValues(horizontal = DEFAULT_PADDING * 1.5f)) {
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
@ -633,7 +633,7 @@ fun ItemAction(text: String, icon: Painter, color: Color = Color.Unspecified, on
|
|||||||
@Composable
|
@Composable
|
||||||
fun ItemAction(text: String, icon: ImageVector, onClick: () -> Unit, color: Color = Color.Unspecified) {
|
fun ItemAction(text: String, icon: ImageVector, onClick: () -> Unit, color: Color = Color.Unspecified) {
|
||||||
val finalColor = if (color == Color.Unspecified) {
|
val finalColor = if (color == Color.Unspecified) {
|
||||||
if (isInDarkTheme()) MenuTextColorDark else Color.Black
|
MenuTextColor
|
||||||
} else color
|
} else color
|
||||||
DropdownMenuItem(onClick, contentPadding = PaddingValues(horizontal = DEFAULT_PADDING * 1.5f)) {
|
DropdownMenuItem(onClick, contentPadding = PaddingValues(horizontal = DEFAULT_PADDING * 1.5f)) {
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
@ -23,6 +23,7 @@ fun DeletedItemView(ci: ChatItem, timedMessagesTTL: Int?) {
|
|||||||
Surface(
|
Surface(
|
||||||
shape = RoundedCornerShape(18.dp),
|
shape = RoundedCornerShape(18.dp),
|
||||||
color = if (sent) sentColor else receivedColor,
|
color = if (sent) sentColor else receivedColor,
|
||||||
|
contentColor = LocalContentColor.current
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
Modifier.padding(horizontal = 12.dp, vertical = 6.dp),
|
Modifier.padding(horizontal = 12.dp, vertical = 6.dp),
|
||||||
|
@ -56,6 +56,7 @@ fun CIMsgError(ci: ChatItem, timedMessagesTTL: Int?, onClick: () -> Unit) {
|
|||||||
Modifier.clickable(onClick = onClick),
|
Modifier.clickable(onClick = onClick),
|
||||||
shape = RoundedCornerShape(18.dp),
|
shape = RoundedCornerShape(18.dp),
|
||||||
color = receivedColor,
|
color = receivedColor,
|
||||||
|
contentColor = LocalContentColor.current
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
Modifier.padding(horizontal = 12.dp, vertical = 6.dp),
|
Modifier.padding(horizontal = 12.dp, vertical = 6.dp),
|
||||||
|
@ -26,6 +26,7 @@ fun MarkedDeletedItemView(ci: ChatItem, timedMessagesTTL: Int?, revealed: Mutabl
|
|||||||
Surface(
|
Surface(
|
||||||
shape = RoundedCornerShape(18.dp),
|
shape = RoundedCornerShape(18.dp),
|
||||||
color = if (ci.chatDir.sent) sentColor else receivedColor,
|
color = if (ci.chatDir.sent) sentColor else receivedColor,
|
||||||
|
contentColor = LocalContentColor.current
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
Modifier.padding(horizontal = 12.dp, vertical = 6.dp),
|
Modifier.padding(horizontal = 12.dp, vertical = 6.dp),
|
||||||
|
@ -75,6 +75,8 @@ fun ChatListView(chatModel: ChatModel, settingsState: SettingsViewState, setPerf
|
|||||||
SettingsView(chatModel, setPerformLA, scaffoldState.drawerState)
|
SettingsView(chatModel, setPerformLA, scaffoldState.drawerState)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
contentColor = LocalContentColor.current,
|
||||||
|
drawerContentColor = LocalContentColor.current,
|
||||||
drawerScrimColor = MaterialTheme.colors.onSurface.copy(alpha = if (isInDarkTheme()) 0.16f else 0.32f),
|
drawerScrimColor = MaterialTheme.colors.onSurface.copy(alpha = if (isInDarkTheme()) 0.16f else 0.32f),
|
||||||
drawerGesturesEnabled = appPlatform.isAndroid,
|
drawerGesturesEnabled = appPlatform.isAndroid,
|
||||||
floatingActionButton = {
|
floatingActionButton = {
|
||||||
|
@ -30,6 +30,8 @@ fun ShareListView(chatModel: ChatModel, settingsState: SettingsViewState, stoppe
|
|||||||
val endPadding = if (appPlatform.isDesktop) 56.dp else 0.dp
|
val endPadding = if (appPlatform.isDesktop) 56.dp else 0.dp
|
||||||
Scaffold(
|
Scaffold(
|
||||||
Modifier.padding(end = endPadding),
|
Modifier.padding(end = endPadding),
|
||||||
|
contentColor = LocalContentColor.current,
|
||||||
|
drawerContentColor = LocalContentColor.current,
|
||||||
scaffoldState = scaffoldState,
|
scaffoldState = scaffoldState,
|
||||||
topBar = { Column { ShareListToolbar(chatModel, userPickerState, stopped) { searchInList = it.trim() } } },
|
topBar = { Column { ShareListToolbar(chatModel, userPickerState, stopped) { searchInList = it.trim() } } },
|
||||||
) {
|
) {
|
||||||
|
@ -31,7 +31,6 @@ import chat.simplex.common.views.remote.*
|
|||||||
import chat.simplex.common.views.usersettings.doWithAuth
|
import chat.simplex.common.views.usersettings.doWithAuth
|
||||||
import chat.simplex.res.MR
|
import chat.simplex.res.MR
|
||||||
import dev.icerock.moko.resources.compose.stringResource
|
import dev.icerock.moko.resources.compose.stringResource
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
@ -303,7 +302,7 @@ fun UserProfileRow(u: User) {
|
|||||||
u.displayName,
|
u.displayName,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(start = 10.dp, end = 8.dp),
|
.padding(start = 10.dp, end = 8.dp),
|
||||||
color = if (isInDarkTheme()) MenuTextColorDark else Color.Black,
|
color = MenuTextColor,
|
||||||
fontWeight = if (u.activeUser) FontWeight.Medium else FontWeight.Normal
|
fontWeight = if (u.activeUser) FontWeight.Medium else FontWeight.Normal
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -346,7 +345,7 @@ fun RemoteHostRow(h: RemoteHostInfo) {
|
|||||||
Text(
|
Text(
|
||||||
h.hostDeviceName,
|
h.hostDeviceName,
|
||||||
modifier = Modifier.padding(start = 26.dp, end = 8.dp),
|
modifier = Modifier.padding(start = 26.dp, end = 8.dp),
|
||||||
color = if (h.activeHost) MaterialTheme.colors.onBackground else if (isInDarkTheme()) MenuTextColorDark else Color.Black,
|
color = if (h.activeHost) MaterialTheme.colors.onBackground else MenuTextColor,
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -387,7 +386,7 @@ fun LocalDeviceRow(active: Boolean) {
|
|||||||
Text(
|
Text(
|
||||||
stringResource(MR.strings.this_device),
|
stringResource(MR.strings.this_device),
|
||||||
modifier = Modifier.padding(start = 26.dp, end = 8.dp),
|
modifier = Modifier.padding(start = 26.dp, end = 8.dp),
|
||||||
color = if (active) MaterialTheme.colors.onBackground else if (isInDarkTheme()) MenuTextColorDark else Color.Black,
|
color = if (active) MaterialTheme.colors.onBackground else MenuTextColor,
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -399,7 +398,7 @@ private fun UseFromDesktopPickerItem(onClick: () -> Unit) {
|
|||||||
val text = generalGetString(MR.strings.settings_section_title_use_from_desktop).lowercase().capitalize(Locale.current)
|
val text = generalGetString(MR.strings.settings_section_title_use_from_desktop).lowercase().capitalize(Locale.current)
|
||||||
Icon(painterResource(MR.images.ic_desktop), text, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground)
|
Icon(painterResource(MR.images.ic_desktop), text, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground)
|
||||||
Spacer(Modifier.width(DEFAULT_PADDING + 6.dp))
|
Spacer(Modifier.width(DEFAULT_PADDING + 6.dp))
|
||||||
Text(text, color = if (isInDarkTheme()) MenuTextColorDark else Color.Black)
|
Text(text, color = MenuTextColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -409,7 +408,7 @@ private fun LinkAMobilePickerItem(onClick: () -> Unit) {
|
|||||||
val text = generalGetString(MR.strings.link_a_mobile)
|
val text = generalGetString(MR.strings.link_a_mobile)
|
||||||
Icon(painterResource(MR.images.ic_smartphone_300), text, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground)
|
Icon(painterResource(MR.images.ic_smartphone_300), text, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground)
|
||||||
Spacer(Modifier.width(DEFAULT_PADDING + 6.dp))
|
Spacer(Modifier.width(DEFAULT_PADDING + 6.dp))
|
||||||
Text(text, color = if (isInDarkTheme()) MenuTextColorDark else Color.Black)
|
Text(text, color = MenuTextColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,7 +418,7 @@ private fun CreateInitialProfile(onClick: () -> Unit) {
|
|||||||
val text = generalGetString(MR.strings.create_chat_profile)
|
val text = generalGetString(MR.strings.create_chat_profile)
|
||||||
Icon(painterResource(MR.images.ic_manage_accounts), text, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground)
|
Icon(painterResource(MR.images.ic_manage_accounts), text, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground)
|
||||||
Spacer(Modifier.width(DEFAULT_PADDING + 6.dp))
|
Spacer(Modifier.width(DEFAULT_PADDING + 6.dp))
|
||||||
Text(text, color = if (isInDarkTheme()) MenuTextColorDark else Color.Black)
|
Text(text, color = MenuTextColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -429,7 +428,7 @@ private fun SettingsPickerItem(onClick: () -> Unit) {
|
|||||||
val text = generalGetString(MR.strings.settings_section_title_settings).lowercase().capitalize(Locale.current)
|
val text = generalGetString(MR.strings.settings_section_title_settings).lowercase().capitalize(Locale.current)
|
||||||
Icon(painterResource(MR.images.ic_settings), text, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground)
|
Icon(painterResource(MR.images.ic_settings), text, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground)
|
||||||
Spacer(Modifier.width(DEFAULT_PADDING + 6.dp))
|
Spacer(Modifier.width(DEFAULT_PADDING + 6.dp))
|
||||||
Text(text, color = if (isInDarkTheme()) MenuTextColorDark else Color.Black)
|
Text(text, color = MenuTextColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,7 +438,7 @@ private fun CancelPickerItem(onClick: () -> Unit) {
|
|||||||
val text = generalGetString(MR.strings.cancel_verb)
|
val text = generalGetString(MR.strings.cancel_verb)
|
||||||
Icon(painterResource(MR.images.ic_close), text, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground)
|
Icon(painterResource(MR.images.ic_close), text, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground)
|
||||||
Spacer(Modifier.width(DEFAULT_PADDING + 6.dp))
|
Spacer(Modifier.width(DEFAULT_PADDING + 6.dp))
|
||||||
Text(text, color = if (isInDarkTheme()) MenuTextColorDark else Color.Black)
|
Text(text, color = MenuTextColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -460,10 +460,10 @@ suspend fun deleteChatAsync(m: ChatModel) {
|
|||||||
m.controller.apiDeleteStorage()
|
m.controller.apiDeleteStorage()
|
||||||
DatabaseUtils.ksDatabasePassword.remove()
|
DatabaseUtils.ksDatabasePassword.remove()
|
||||||
m.controller.appPrefs.storeDBPassphrase.set(true)
|
m.controller.appPrefs.storeDBPassphrase.set(true)
|
||||||
deleteChatDatabaseFiles()
|
deleteAppDatabaseAndFiles()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteChatDatabaseFiles() {
|
fun deleteAppDatabaseAndFiles() {
|
||||||
val chat = File(dataDir, chatDatabaseFileName)
|
val chat = File(dataDir, chatDatabaseFileName)
|
||||||
val chatBak = File(dataDir, "$chatDatabaseFileName.bak")
|
val chatBak = File(dataDir, "$chatDatabaseFileName.bak")
|
||||||
val agent = File(dataDir, agentDatabaseFileName)
|
val agent = File(dataDir, agentDatabaseFileName)
|
||||||
@ -473,6 +473,7 @@ fun deleteChatDatabaseFiles() {
|
|||||||
agent.delete()
|
agent.delete()
|
||||||
agentBak.delete()
|
agentBak.delete()
|
||||||
filesDir.deleteRecursively()
|
filesDir.deleteRecursively()
|
||||||
|
filesDir.mkdir()
|
||||||
remoteHostsDir.deleteRecursively()
|
remoteHostsDir.deleteRecursively()
|
||||||
tmpDir.deleteRecursively()
|
tmpDir.deleteRecursively()
|
||||||
tmpDir.mkdir()
|
tmpDir.mkdir()
|
||||||
|
@ -152,7 +152,8 @@ fun CustomTimePickerDialog(
|
|||||||
) {
|
) {
|
||||||
DefaultDialog(onDismissRequest = cancel) {
|
DefaultDialog(onDismissRequest = cancel) {
|
||||||
Surface(
|
Surface(
|
||||||
shape = RoundedCornerShape(corner = CornerSize(25.dp))
|
shape = RoundedCornerShape(corner = CornerSize(25.dp)),
|
||||||
|
contentColor = LocalContentColor.current
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
|
@ -17,7 +17,7 @@ object DatabaseUtils {
|
|||||||
val ksAppPassword = KeyStoreItem(APP_PASSWORD_ALIAS, appPreferences.encryptedAppPassphrase, appPreferences.initializationVectorAppPassphrase)
|
val ksAppPassword = KeyStoreItem(APP_PASSWORD_ALIAS, appPreferences.encryptedAppPassphrase, appPreferences.initializationVectorAppPassphrase)
|
||||||
val ksSelfDestructPassword = KeyStoreItem(SELF_DESTRUCT_PASSWORD_ALIAS, appPreferences.encryptedSelfDestructPassphrase, appPreferences.initializationVectorSelfDestructPassphrase)
|
val ksSelfDestructPassword = KeyStoreItem(SELF_DESTRUCT_PASSWORD_ALIAS, appPreferences.encryptedSelfDestructPassphrase, appPreferences.initializationVectorSelfDestructPassphrase)
|
||||||
|
|
||||||
class KeyStoreItem(val alias: String, val passphrase: SharedPreference<String?>, val initVector: SharedPreference<String?>) {
|
class KeyStoreItem(private val alias: String, val passphrase: SharedPreference<String?>, val initVector: SharedPreference<String?>) {
|
||||||
fun get(): String? {
|
fun get(): String? {
|
||||||
return cryptor.decryptData(
|
return cryptor.decryptData(
|
||||||
passphrase.get()?.toByteArrayFromBase64ForPassphrase() ?: return null,
|
passphrase.get()?.toByteArrayFromBase64ForPassphrase() ?: return null,
|
||||||
|
@ -70,7 +70,7 @@ fun <T> ExposedDropDownSetting(
|
|||||||
selectionOption.second + (if (label != null) " $label" else ""),
|
selectionOption.second + (if (label != null) " $label" else ""),
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
color = if (isInDarkTheme()) MenuTextColorDark else Color.Black,
|
color = MenuTextColor,
|
||||||
fontSize = fontSize,
|
fontSize = fontSize,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
package chat.simplex.common.views.helpers
|
package chat.simplex.common.views.helpers
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.material.MaterialTheme
|
import androidx.compose.material.*
|
||||||
import androidx.compose.material.Surface
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import chat.simplex.common.model.ChatController
|
import chat.simplex.common.model.ChatController
|
||||||
import chat.simplex.common.model.ChatModel
|
import chat.simplex.common.model.ChatModel
|
||||||
@ -50,7 +49,7 @@ fun authenticateWithPasscode(
|
|||||||
close()
|
close()
|
||||||
completed(LAResult.Error(generalGetString(MR.strings.authentication_cancelled)))
|
completed(LAResult.Error(generalGetString(MR.strings.authentication_cancelled)))
|
||||||
}
|
}
|
||||||
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
|
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) {
|
||||||
LocalAuthView(ChatModel, LocalAuthRequest(promptTitle, promptSubtitle, password, selfDestruct && ChatController.appPrefs.selfDestruct.get()) {
|
LocalAuthView(ChatModel, LocalAuthRequest(promptTitle, promptSubtitle, password, selfDestruct && ChatController.appPrefs.selfDestruct.get()) {
|
||||||
close()
|
close()
|
||||||
completed(it)
|
completed(it)
|
||||||
|
@ -26,7 +26,7 @@ fun ModalView(
|
|||||||
if (showClose) {
|
if (showClose) {
|
||||||
BackHandler(onBack = close)
|
BackHandler(onBack = close)
|
||||||
}
|
}
|
||||||
Surface(Modifier.fillMaxSize()) {
|
Surface(Modifier.fillMaxSize(), contentColor = LocalContentColor.current) {
|
||||||
Column(if (background != MaterialTheme.colors.background) Modifier.background(background) else Modifier.themedBackground()) {
|
Column(if (background != MaterialTheme.colors.background) Modifier.background(background) else Modifier.themedBackground()) {
|
||||||
CloseSheetBar(close, showClose, endButtons)
|
CloseSheetBar(close, showClose, endButtons)
|
||||||
Box(modifier) { content() }
|
Box(modifier) { content() }
|
||||||
|
@ -34,7 +34,7 @@ fun LocalAuthView(m: ChatModel, authRequest: LocalAuthRequest) {
|
|||||||
} else {
|
} else {
|
||||||
val r: LAResult = if (passcode.value == authRequest.password) {
|
val r: LAResult = if (passcode.value == authRequest.password) {
|
||||||
if (authRequest.selfDestruct && sdPassword != null && controller.ctrl == -1L) {
|
if (authRequest.selfDestruct && sdPassword != null && controller.ctrl == -1L) {
|
||||||
initChatControllerAndRunMigrations(true)
|
initChatControllerAndRunMigrations()
|
||||||
}
|
}
|
||||||
LAResult.Success
|
LAResult.Success
|
||||||
} else {
|
} else {
|
||||||
@ -67,8 +67,8 @@ private fun deleteStorageAndRestart(m: ChatModel, password: String, completed: (
|
|||||||
* */
|
* */
|
||||||
chatCloseStore(ctrl)
|
chatCloseStore(ctrl)
|
||||||
}
|
}
|
||||||
deleteChatDatabaseFiles()
|
deleteAppDatabaseAndFiles()
|
||||||
// Clear sensitive data on screen just in case ModalManager will fail to prevent hiding its modals while database encrypts itself
|
// Clear sensitive data on screen just in case ModalManager fails to hide its modals while new database is created
|
||||||
m.chatId.value = null
|
m.chatId.value = null
|
||||||
m.chatItems.clear()
|
m.chatItems.clear()
|
||||||
m.chats.clear()
|
m.chats.clear()
|
||||||
|
@ -12,6 +12,7 @@ import chat.simplex.res.MR
|
|||||||
@Composable
|
@Composable
|
||||||
fun SetAppPasscodeView(
|
fun SetAppPasscodeView(
|
||||||
passcodeKeychain: DatabaseUtils.KeyStoreItem = ksAppPassword,
|
passcodeKeychain: DatabaseUtils.KeyStoreItem = ksAppPassword,
|
||||||
|
prohibitedPasscodeKeychain: DatabaseUtils.KeyStoreItem = ksSelfDestructPassword,
|
||||||
title: String = generalGetString(MR.strings.new_passcode),
|
title: String = generalGetString(MR.strings.new_passcode),
|
||||||
reason: String? = null,
|
reason: String? = null,
|
||||||
submit: () -> Unit,
|
submit: () -> Unit,
|
||||||
@ -51,7 +52,7 @@ fun SetAppPasscodeView(
|
|||||||
} else {
|
} else {
|
||||||
SetPasswordView(title, generalGetString(MR.strings.save_verb),
|
SetPasswordView(title, generalGetString(MR.strings.save_verb),
|
||||||
// Do not allow to set app passcode == selfDestruct passcode
|
// Do not allow to set app passcode == selfDestruct passcode
|
||||||
submitEnabled = { pwd -> pwd != (if (passcodeKeychain.alias == ksSelfDestructPassword.alias) ksAppPassword else ksSelfDestructPassword).get() }) {
|
submitEnabled = { pwd -> pwd != prohibitedPasscodeKeychain.get() }) {
|
||||||
enteredPassword = passcode.value
|
enteredPassword = passcode.value
|
||||||
passcode.value = ""
|
passcode.value = ""
|
||||||
confirming = true
|
confirming = true
|
||||||
|
@ -175,7 +175,7 @@ fun ActionButton(
|
|||||||
disabled: Boolean = false,
|
disabled: Boolean = false,
|
||||||
click: () -> Unit = {}
|
click: () -> Unit = {}
|
||||||
) {
|
) {
|
||||||
Surface(shape = RoundedCornerShape(18.dp), color = Color.Transparent) {
|
Surface(shape = RoundedCornerShape(18.dp), color = Color.Transparent, contentColor = LocalContentColor.current) {
|
||||||
Column(
|
Column(
|
||||||
Modifier
|
Modifier
|
||||||
.clickable(onClick = click)
|
.clickable(onClick = click)
|
||||||
@ -220,7 +220,7 @@ fun ActionButton(
|
|||||||
disabled: Boolean = false,
|
disabled: Boolean = false,
|
||||||
click: () -> Unit = {}
|
click: () -> Unit = {}
|
||||||
) {
|
) {
|
||||||
Surface(modifier, shape = RoundedCornerShape(18.dp)) {
|
Surface(modifier, shape = RoundedCornerShape(18.dp), contentColor = LocalContentColor.current) {
|
||||||
Column(
|
Column(
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
@ -380,7 +380,8 @@ fun SettingsSectionFooter(revert: () -> Unit, save: () -> Unit, disabled: Boolea
|
|||||||
fun FooterButton(icon: Painter, title: String, action: () -> Unit, disabled: Boolean) {
|
fun FooterButton(icon: Painter, title: String, action: () -> Unit, disabled: Boolean) {
|
||||||
Surface(
|
Surface(
|
||||||
shape = RoundedCornerShape(20.dp),
|
shape = RoundedCornerShape(20.dp),
|
||||||
color = Color.Black.copy(alpha = 0f)
|
color = Color.Black.copy(alpha = 0f),
|
||||||
|
contentColor = LocalContentColor.current
|
||||||
) {
|
) {
|
||||||
val modifier = if (disabled) Modifier else Modifier.clickable { action() }
|
val modifier = if (disabled) Modifier else Modifier.clickable { action() }
|
||||||
Row(
|
Row(
|
||||||
|
@ -383,7 +383,7 @@ fun SimplexLockView(
|
|||||||
}
|
}
|
||||||
LAMode.PASSCODE -> {
|
LAMode.PASSCODE -> {
|
||||||
ModalManager.fullscreen.showCustomModal { close ->
|
ModalManager.fullscreen.showCustomModal { close ->
|
||||||
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
|
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) {
|
||||||
SetAppPasscodeView(
|
SetAppPasscodeView(
|
||||||
submit = {
|
submit = {
|
||||||
laLockDelay.set(30)
|
laLockDelay.set(30)
|
||||||
@ -427,7 +427,7 @@ fun SimplexLockView(
|
|||||||
when (laResult) {
|
when (laResult) {
|
||||||
LAResult.Success -> {
|
LAResult.Success -> {
|
||||||
ModalManager.fullscreen.showCustomModal { close ->
|
ModalManager.fullscreen.showCustomModal { close ->
|
||||||
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
|
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) {
|
||||||
SetAppPasscodeView(
|
SetAppPasscodeView(
|
||||||
reason = generalGetString(MR.strings.la_app_passcode),
|
reason = generalGetString(MR.strings.la_app_passcode),
|
||||||
submit = {
|
submit = {
|
||||||
@ -451,9 +451,10 @@ fun SimplexLockView(
|
|||||||
when (laResult) {
|
when (laResult) {
|
||||||
LAResult.Success -> {
|
LAResult.Success -> {
|
||||||
ModalManager.fullscreen.showCustomModal { close ->
|
ModalManager.fullscreen.showCustomModal { close ->
|
||||||
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
|
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) {
|
||||||
SetAppPasscodeView(
|
SetAppPasscodeView(
|
||||||
passcodeKeychain = ksSelfDestructPassword,
|
passcodeKeychain = ksSelfDestructPassword,
|
||||||
|
prohibitedPasscodeKeychain = ksAppPassword,
|
||||||
reason = generalGetString(MR.strings.self_destruct),
|
reason = generalGetString(MR.strings.self_destruct),
|
||||||
submit = {
|
submit = {
|
||||||
selfDestructPasscodeAlert(generalGetString(MR.strings.self_destruct_passcode_changed))
|
selfDestructPasscodeAlert(generalGetString(MR.strings.self_destruct_passcode_changed))
|
||||||
@ -487,7 +488,7 @@ fun SimplexLockView(
|
|||||||
}
|
}
|
||||||
LAMode.PASSCODE -> {
|
LAMode.PASSCODE -> {
|
||||||
ModalManager.fullscreen.showCustomModal { close ->
|
ModalManager.fullscreen.showCustomModal { close ->
|
||||||
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
|
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) {
|
||||||
SetAppPasscodeView(
|
SetAppPasscodeView(
|
||||||
submit = {
|
submit = {
|
||||||
laLockDelay.set(30)
|
laLockDelay.set(30)
|
||||||
@ -598,9 +599,9 @@ private fun EnableSelfDestruct(
|
|||||||
selfDestruct: SharedPreference<Boolean>,
|
selfDestruct: SharedPreference<Boolean>,
|
||||||
close: () -> Unit
|
close: () -> Unit
|
||||||
) {
|
) {
|
||||||
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
|
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) {
|
||||||
SetAppPasscodeView(
|
SetAppPasscodeView(
|
||||||
passcodeKeychain = ksSelfDestructPassword, title = generalGetString(MR.strings.set_passcode), reason = generalGetString(MR.strings.enabled_self_destruct_passcode),
|
passcodeKeychain = ksSelfDestructPassword, prohibitedPasscodeKeychain = ksAppPassword, title = generalGetString(MR.strings.set_passcode), reason = generalGetString(MR.strings.enabled_self_destruct_passcode),
|
||||||
submit = {
|
submit = {
|
||||||
selfDestruct.set(true)
|
selfDestruct.set(true)
|
||||||
selfDestructPasscodeAlert(generalGetString(MR.strings.self_destruct_passcode_enabled))
|
selfDestructPasscodeAlert(generalGetString(MR.strings.self_destruct_passcode_enabled))
|
||||||
|
@ -155,7 +155,8 @@ fun RTCServersLayout(
|
|||||||
.height(160.dp)
|
.height(160.dp)
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
shape = RoundedCornerShape(10.dp),
|
shape = RoundedCornerShape(10.dp),
|
||||||
border = BorderStroke(1.dp, MaterialTheme.colors.secondaryVariant)
|
border = BorderStroke(1.dp, MaterialTheme.colors.secondaryVariant),
|
||||||
|
contentColor = LocalContentColor.current
|
||||||
) {
|
) {
|
||||||
SelectionContainer(
|
SelectionContainer(
|
||||||
Modifier.verticalScroll(rememberScrollState())
|
Modifier.verticalScroll(rememberScrollState())
|
||||||
|
@ -155,7 +155,7 @@ fun UserAddressView(
|
|||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
if (userAddress.value != null) {
|
if (userAddress.value != null) {
|
||||||
Surface(Modifier.size(50.dp), color = MaterialTheme.colors.background.copy(0.9f), shape = RoundedCornerShape(50)){}
|
Surface(Modifier.size(50.dp), color = MaterialTheme.colors.background.copy(0.9f), contentColor = LocalContentColor.current, shape = RoundedCornerShape(50)){}
|
||||||
}
|
}
|
||||||
CircularProgressIndicator(
|
CircularProgressIndicator(
|
||||||
Modifier
|
Modifier
|
||||||
|
@ -24,7 +24,9 @@ fun initApp() {
|
|||||||
override fun cancelAllNotifications() = chat.simplex.common.model.NtfManager.cancelAllNotifications()
|
override fun cancelAllNotifications() = chat.simplex.common.model.NtfManager.cancelAllNotifications()
|
||||||
}
|
}
|
||||||
applyAppLocale()
|
applyAppLocale()
|
||||||
initChatControllerAndRunMigrations(false)
|
if (DatabaseUtils.ksSelfDestructPassword.get() == null) {
|
||||||
|
initChatControllerAndRunMigrations()
|
||||||
|
}
|
||||||
// LALAL
|
// LALAL
|
||||||
//testCrypto()
|
//testCrypto()
|
||||||
}
|
}
|
||||||
|
@ -167,7 +167,8 @@ actual fun PlatformTextField(
|
|||||||
decorationBox = { innerTextField ->
|
decorationBox = { innerTextField ->
|
||||||
Surface(
|
Surface(
|
||||||
shape = RoundedCornerShape(18.dp),
|
shape = RoundedCornerShape(18.dp),
|
||||||
border = BorderStroke(1.dp, MaterialTheme.colors.secondary)
|
border = BorderStroke(1.dp, MaterialTheme.colors.secondary),
|
||||||
|
contentColor = LocalContentColor.current
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
Modifier.background(MaterialTheme.colors.background),
|
Modifier.background(MaterialTheme.colors.background),
|
||||||
|
@ -2,8 +2,7 @@ package chat.simplex.common.views.helpers
|
|||||||
|
|
||||||
import androidx.compose.foundation.*
|
import androidx.compose.foundation.*
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.MaterialTheme
|
import androidx.compose.material.*
|
||||||
import androidx.compose.material.Surface
|
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.key.*
|
import androidx.compose.ui.input.key.*
|
||||||
@ -39,7 +38,8 @@ actual fun DefaultDialog(
|
|||||||
) {
|
) {
|
||||||
Surface(
|
Surface(
|
||||||
Modifier
|
Modifier
|
||||||
.border(border = BorderStroke(1.dp, MaterialTheme.colors.secondary.copy(alpha = 0.3F)), shape = RoundedCornerShape(8))
|
.border(border = BorderStroke(1.dp, MaterialTheme.colors.secondary.copy(alpha = 0.3F)), shape = RoundedCornerShape(8)),
|
||||||
|
contentColor = LocalContentColor.current
|
||||||
) {
|
) {
|
||||||
content()
|
content()
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd
|
|||||||
source-repository-package
|
source-repository-package
|
||||||
type: git
|
type: git
|
||||||
location: https://github.com/simplex-chat/simplexmq.git
|
location: https://github.com/simplex-chat/simplexmq.git
|
||||||
tag: 6d4834f306963e2d3f2f62af212fe855ea9c7595
|
tag: fa794d7878c82c370f1547f01e76f9691d229b92
|
||||||
|
|
||||||
source-repository-package
|
source-repository-package
|
||||||
type: git
|
type: git
|
||||||
|
@ -8,9 +8,9 @@ u="$USER"
|
|||||||
tmp="$(mktemp -d -t)"
|
tmp="$(mktemp -d -t)"
|
||||||
folder="$tmp/simplex-chat"
|
folder="$tmp/simplex-chat"
|
||||||
|
|
||||||
nix_ver="nix-2.15.1"
|
nix_ver="nix-2.19.2"
|
||||||
nix_url="https://releases.nixos.org/nix/$nix_ver/install"
|
nix_url="https://releases.nixos.org/nix/$nix_ver/install"
|
||||||
nix_hash="67aa37f0115195d8ddf32b5d6f471f1e60ecca0fdb3e98bcf54bc147c3078640"
|
nix_hash="435f0d7e11f7c7dffeeab0ec9cc55723f6d3c03352379d785633cf4ddb5caf90"
|
||||||
nix_config="sandbox = true
|
nix_config="sandbox = true
|
||||||
max-jobs = auto
|
max-jobs = auto
|
||||||
experimental-features = nix-command flakes"
|
experimental-features = nix-command flakes"
|
||||||
@ -102,8 +102,19 @@ build() {
|
|||||||
sed -i.bak '/android {/a lint {abortOnError = false}' "$folder/apps/multiplatform/android/build.gradle.kts"
|
sed -i.bak '/android {/a lint {abortOnError = false}' "$folder/apps/multiplatform/android/build.gradle.kts"
|
||||||
|
|
||||||
for arch in $arches; do
|
for arch in $arches; do
|
||||||
android_simplex_lib="${folder}#hydraJobs.${arch}-android:lib:simplex-chat.x86_64-linux"
|
|
||||||
android_support_lib="${folder}#hydraJobs.${arch}-android:lib:support.x86_64-linux"
|
tag_full="$(git tag --points-at HEAD)"
|
||||||
|
tag_version="${tag_full%%-*}"
|
||||||
|
|
||||||
|
if [ "$arch" = "armv7a" ] && [ -n "$tag_full" ] ; then
|
||||||
|
git checkout "${tag_version}-armv7a"
|
||||||
|
android_simplex_lib="${folder}#hydraJobs.${arch}-android:lib:simplex-chat.x86_64-linux"
|
||||||
|
android_support_lib="${folder}#hydraJobs.${arch}-android:lib:support.x86_64-linux"
|
||||||
|
else
|
||||||
|
android_simplex_lib="${folder}#hydraJobs.x86_64-linux.${arch}-android:lib:simplex-chat"
|
||||||
|
android_support_lib="${folder}#hydraJobs.x86_64-linux.${arch}-android:lib:support"
|
||||||
|
fi
|
||||||
|
|
||||||
android_simplex_lib_output="${PWD}/result/pkg-${arch}-android-libsimplex.zip"
|
android_simplex_lib_output="${PWD}/result/pkg-${arch}-android-libsimplex.zip"
|
||||||
android_support_lib_output="${PWD}/result/pkg-${arch}-android-libsupport.zip"
|
android_support_lib_output="${PWD}/result/pkg-${arch}-android-libsupport.zip"
|
||||||
|
|
||||||
@ -139,6 +150,10 @@ build() {
|
|||||||
zipalign -p -f 4 "$tmp/$android_apk_output_final" "$PWD/$android_apk_output_final"
|
zipalign -p -f 4 "$tmp/$android_apk_output_final" "$PWD/$android_apk_output_final"
|
||||||
|
|
||||||
rm -rf "$libs_folder/$android_arch"
|
rm -rf "$libs_folder/$android_arch"
|
||||||
|
|
||||||
|
if [ "$arch" = "armv7a" ] && [ -n "$tag_full" ] ; then
|
||||||
|
git checkout "${tag_full}"
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"https://github.com/simplex-chat/simplexmq.git"."6d4834f306963e2d3f2f62af212fe855ea9c7595" = "1603nlzkncrl8kg9xb8yi4kjbk8d8gmyw7wzvlni7lgbf0hjrffz";
|
"https://github.com/simplex-chat/simplexmq.git"."fa794d7878c82c370f1547f01e76f9691d229b92" = "0fmgq7yy42rlpf4a0agz3149iqkw5cri85xppwgicl4i9c7bs9gi";
|
||||||
"https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38";
|
"https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38";
|
||||||
"https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d";
|
"https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d";
|
||||||
"https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl";
|
"https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl";
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
module Simplex.Chat.Mobile.Shared where
|
module Simplex.Chat.Mobile.Shared where
|
||||||
|
|
||||||
import qualified Data.ByteString as B
|
import qualified Data.ByteString as B
|
||||||
import Data.ByteString.Internal (ByteString (..), memcpy)
|
import Data.ByteString.Internal (ByteString (..))
|
||||||
import qualified Data.ByteString.Lazy as LB
|
import qualified Data.ByteString.Lazy as LB
|
||||||
import qualified Data.ByteString.Lazy.Internal as LB
|
import qualified Data.ByteString.Lazy.Internal as LB
|
||||||
import Foreign
|
import Foreign
|
||||||
@ -21,7 +21,7 @@ getByteString ptr len = do
|
|||||||
|
|
||||||
putByteString :: Ptr Word8 -> ByteString -> IO ()
|
putByteString :: Ptr Word8 -> ByteString -> IO ()
|
||||||
putByteString ptr (PS fp offset len) =
|
putByteString ptr (PS fp offset len) =
|
||||||
withForeignPtr fp $ \p -> memcpy ptr (p `plusPtr` offset) len
|
withForeignPtr fp $ \p -> copyBytes ptr (p `plusPtr` offset) len
|
||||||
{-# INLINE putByteString #-}
|
{-# INLINE putByteString #-}
|
||||||
|
|
||||||
putLazyByteString :: Ptr Word8 -> LB.ByteString -> IO ()
|
putLazyByteString :: Ptr Word8 -> LB.ByteString -> IO ()
|
||||||
|
@ -415,6 +415,7 @@ xftpServerConfig =
|
|||||||
logStatsStartTime = 0,
|
logStatsStartTime = 0,
|
||||||
serverStatsLogFile = "tests/tmp/xftp-server-stats.daily.log",
|
serverStatsLogFile = "tests/tmp/xftp-server-stats.daily.log",
|
||||||
serverStatsBackupFile = Nothing,
|
serverStatsBackupFile = Nothing,
|
||||||
|
controlPort = Nothing,
|
||||||
transportConfig = defaultTransportServerConfig
|
transportConfig = defaultTransportServerConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,11 +16,12 @@ import qualified Data.Aeson.TH as JQ
|
|||||||
import Data.ByteString (ByteString)
|
import Data.ByteString (ByteString)
|
||||||
import qualified Data.ByteString as B
|
import qualified Data.ByteString as B
|
||||||
import qualified Data.ByteString.Char8 as BS
|
import qualified Data.ByteString.Char8 as BS
|
||||||
import Data.ByteString.Internal (create, memcpy)
|
import Data.ByteString.Internal (create)
|
||||||
import qualified Data.ByteString.Lazy.Char8 as LB
|
import qualified Data.ByteString.Lazy.Char8 as LB
|
||||||
import Data.Word (Word8, Word32)
|
import Data.Word (Word8, Word32)
|
||||||
import Foreign.C
|
import Foreign.C
|
||||||
import Foreign.Marshal.Alloc (mallocBytes)
|
import Foreign.Marshal.Alloc (mallocBytes)
|
||||||
|
import Foreign.Marshal.Utils (copyBytes)
|
||||||
import Foreign.Ptr
|
import Foreign.Ptr
|
||||||
import Foreign.StablePtr
|
import Foreign.StablePtr
|
||||||
import Foreign.Storable (peek)
|
import Foreign.Storable (peek)
|
||||||
@ -291,7 +292,7 @@ testFileCApi fileName tmp = do
|
|||||||
peek ptr' `shouldReturn` (0 :: Word8)
|
peek ptr' `shouldReturn` (0 :: Word8)
|
||||||
sz :: Word32 <- peek (ptr' `plusPtr` 1)
|
sz :: Word32 <- peek (ptr' `plusPtr` 1)
|
||||||
let sz' = fromIntegral sz
|
let sz' = fromIntegral sz
|
||||||
contents <- create sz' $ \toPtr -> memcpy toPtr (ptr' `plusPtr` 5) sz'
|
contents <- create sz' $ \toPtr -> copyBytes toPtr (ptr' `plusPtr` 5) sz'
|
||||||
contents `shouldBe` src
|
contents `shouldBe` src
|
||||||
sz' `shouldBe` fromIntegral len
|
sz' `shouldBe` fromIntegral len
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user