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.util.Log
|
||||
import androidx.work.*
|
||||
import chat.simplex.app.*
|
||||
import chat.simplex.app.SimplexService.Companion.showPassphraseNotification
|
||||
import chat.simplex.common.model.ChatController
|
||||
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 java.util.Date
|
||||
import java.util.concurrent.TimeUnit
|
||||
@ -57,6 +58,10 @@ class MessagesFetcherWork(
|
||||
val durationSeconds = inputData.getInt(INPUT_DATA_DURATION, 60)
|
||||
var shouldReschedule = true
|
||||
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) {
|
||||
val chatController = ChatController
|
||||
SimplexService.waitDbMigrationEnds(chatController)
|
||||
|
@ -26,6 +26,7 @@ import kotlinx.coroutines.sync.withLock
|
||||
import java.io.*
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
const val TAG = "SIMPLEX"
|
||||
|
||||
@ -46,8 +47,8 @@ class SimplexApp: Application(), LifecycleEventObserver {
|
||||
try {
|
||||
Looper.loop()
|
||||
} catch (e: Throwable) {
|
||||
if (e.message != null && e.message!!.startsWith("Unable to start activity")) {
|
||||
android.os.Process.killProcess(android.os.Process.myPid())
|
||||
if (e is UnsatisfiedLinkError || e.message?.startsWith("Unable to start activity") == true) {
|
||||
Process.killProcess(Process.myPid())
|
||||
break
|
||||
} else {
|
||||
// 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.mkdir()
|
||||
|
||||
initChatControllerAndRunMigrations(false)
|
||||
if (DatabaseUtils.ksSelfDestructPassword.get() == null) {
|
||||
initChatControllerAndRunMigrations()
|
||||
}
|
||||
ProcessLifecycleOwner.get().lifecycle.addObserver(this@SimplexApp)
|
||||
}
|
||||
|
||||
|
@ -72,6 +72,10 @@ class SimplexService: Service() {
|
||||
stopSelf()
|
||||
} else {
|
||||
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(
|
||||
Modifier
|
||||
.fillMaxSize(),
|
||||
color = MaterialTheme.colors.background
|
||||
color = MaterialTheme.colors.background,
|
||||
contentColor = LocalContentColor.current
|
||||
) {
|
||||
if (showCallView) {
|
||||
Box {
|
||||
@ -200,7 +201,8 @@ private fun SimpleXLogo() {
|
||||
private fun LockScreenCallButton(text: String, icon: Painter, color: Color, action: () -> Unit) {
|
||||
Surface(
|
||||
shape = RoundedCornerShape(10.dp),
|
||||
color = Color.Transparent
|
||||
color = Color.Transparent,
|
||||
contentColor = LocalContentColor.current
|
||||
) {
|
||||
Column(
|
||||
Modifier
|
||||
@ -227,7 +229,8 @@ fun PreviewIncomingCallLockScreenAlert() {
|
||||
Surface(
|
||||
Modifier
|
||||
.fillMaxSize(),
|
||||
color = MaterialTheme.colors.background
|
||||
color = MaterialTheme.colors.background,
|
||||
contentColor = LocalContentColor.current
|
||||
) {
|
||||
IncomingCallLockScreenAlertLayout(
|
||||
invitation = RcvCallInvitation(
|
||||
|
@ -44,7 +44,7 @@ data class SettingsViewState(
|
||||
fun AppScreen() {
|
||||
SimpleXTheme {
|
||||
ProvideWindowInsets(windowInsetsAnimationsEnabled = true) {
|
||||
Surface(color = MaterialTheme.colors.background) {
|
||||
Surface(color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) {
|
||||
MainScreen()
|
||||
}
|
||||
}
|
||||
@ -85,7 +85,7 @@ fun MainScreen() {
|
||||
|
||||
@Composable
|
||||
fun AuthView() {
|
||||
Surface(color = MaterialTheme.colors.background) {
|
||||
Surface(color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) {
|
||||
Box(
|
||||
Modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.Center
|
||||
|
@ -1,8 +1,7 @@
|
||||
package chat.simplex.common
|
||||
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Surface
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.ui.Modifier
|
||||
import chat.simplex.common.model.*
|
||||
@ -107,7 +106,7 @@ object AppLock {
|
||||
private fun setPasscode() {
|
||||
val appPrefs = ChatController.appPrefs
|
||||
ModalManager.fullscreen.showCustomModal { close ->
|
||||
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
|
||||
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) {
|
||||
SetAppPasscodeView(
|
||||
submit = {
|
||||
ChatModel.performLA.value = true
|
||||
|
@ -41,21 +41,20 @@ val appPreferences: AppPreferences
|
||||
|
||||
val chatController: ChatController = ChatController
|
||||
|
||||
fun initChatControllerAndRunMigrations(ignoreSelfDestruct: Boolean) {
|
||||
if (ignoreSelfDestruct || DatabaseUtils.ksSelfDestructPassword.get() == null) {
|
||||
withBGApi {
|
||||
if (appPreferences.chatStopped.get() && appPreferences.storeDBPassphrase.get() && ksDatabasePassword.get() != null) {
|
||||
initChatController(startChat = ::showStartChatAfterRestartAlert)
|
||||
} else {
|
||||
initChatController()
|
||||
}
|
||||
runMigrations()
|
||||
fun initChatControllerAndRunMigrations() {
|
||||
withBGApi {
|
||||
if (appPreferences.chatStopped.get() && appPreferences.storeDBPassphrase.get() && ksDatabasePassword.get() != null) {
|
||||
initChatController(startChat = ::showStartChatAfterRestartAlert)
|
||||
} else {
|
||||
initChatController()
|
||||
}
|
||||
runMigrations()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun initChatController(useKey: String? = null, confirmMigrations: MigrationConfirmation? = null, startChat: () -> CompletableDeferred<Boolean> = { CompletableDeferred(true) }) {
|
||||
try {
|
||||
if (chatModel.ctrlInitInProgress.value) return
|
||||
chatModel.ctrlInitInProgress.value = true
|
||||
val dbKey = useKey ?: DatabaseUtils.useDatabaseKey()
|
||||
val confirm = confirmMigrations ?: if (appPreferences.confirmDBUpgrades.get()) MigrationConfirmation.Error else MigrationConfirmation.YesUp
|
||||
|
@ -1,5 +1,7 @@
|
||||
package chat.simplex.common.ui.theme
|
||||
|
||||
import androidx.compose.material.LocalContentColor
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
val Purple200 = Color(0xFFBB86FC)
|
||||
@ -25,4 +27,5 @@ val WarningOrange = Color(255, 127, 0, 255)
|
||||
val WarningYellow = Color(255, 192, 0, 255)
|
||||
val FileLight = Color(183, 190, 199, 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()
|
||||
MaterialTheme(
|
||||
colors = theme.colors,
|
||||
typography = Typography.copy(
|
||||
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)
|
||||
),
|
||||
typography = Typography,
|
||||
shapes = Shapes,
|
||||
content = {
|
||||
ProvideTextStyle(
|
||||
value = TextStyle(color = theme.colors.onBackground),
|
||||
content = content
|
||||
)
|
||||
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colors.onBackground, content = content)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
package chat.simplex.common.views
|
||||
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Surface
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
|
||||
@ -11,7 +10,8 @@ fun SplashView() {
|
||||
Surface(
|
||||
Modifier
|
||||
.fillMaxSize(),
|
||||
color = MaterialTheme.colors.background
|
||||
color = MaterialTheme.colors.background,
|
||||
contentColor = LocalContentColor.current
|
||||
) {
|
||||
// Image(
|
||||
// painter = painterResource(MR.images.logo),
|
||||
|
@ -101,13 +101,16 @@ fun TerminalLayout(
|
||||
)
|
||||
}
|
||||
},
|
||||
contentColor = LocalContentColor.current,
|
||||
drawerContentColor = LocalContentColor.current,
|
||||
modifier = Modifier.navigationBarsWithImePadding()
|
||||
) { contentPadding ->
|
||||
Surface(
|
||||
modifier = Modifier
|
||||
.padding(contentPadding)
|
||||
.fillMaxWidth(),
|
||||
color = MaterialTheme.colors.background
|
||||
color = MaterialTheme.colors.background,
|
||||
contentColor = LocalContentColor.current
|
||||
) {
|
||||
TerminalLog()
|
||||
}
|
||||
|
@ -239,7 +239,7 @@ fun OnboardingButtons(displayName: MutableState<String>, close: () -> Unit) {
|
||||
val enabled = canCreateProfile(displayName.value)
|
||||
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
|
||||
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) {
|
||||
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)
|
||||
|
@ -85,7 +85,8 @@ fun IncomingCallInfo(invitation: RcvCallInvitation, chatModel: ChatModel) {
|
||||
private fun CallButton(text: String, icon: Painter, color: Color, action: () -> Unit) {
|
||||
Surface(
|
||||
shape = RoundedCornerShape(10.dp),
|
||||
color = Color.Transparent
|
||||
color = Color.Transparent,
|
||||
contentColor = LocalContentColor.current
|
||||
) {
|
||||
Column(
|
||||
Modifier
|
||||
|
@ -570,6 +570,8 @@ fun ChatLayout(
|
||||
bottomBar = composeView,
|
||||
modifier = Modifier.navigationBarsWithImePadding(),
|
||||
floatingActionButton = { floatingButton.value() },
|
||||
contentColor = LocalContentColor.current,
|
||||
drawerContentColor = LocalContentColor.current,
|
||||
) { contentPadding ->
|
||||
BoxWithConstraints(Modifier
|
||||
.fillMaxHeight()
|
||||
|
@ -258,7 +258,8 @@ private fun CustomDisappearingMessageDialog(
|
||||
|
||||
DefaultDialog(onDismissRequest = { setShowDialog(false) }) {
|
||||
Surface(
|
||||
shape = RoundedCornerShape(corner = CornerSize(25.dp))
|
||||
shape = RoundedCornerShape(corner = CornerSize(25.dp)),
|
||||
contentColor = LocalContentColor.current
|
||||
) {
|
||||
Box(
|
||||
contentAlignment = Alignment.Center
|
||||
|
@ -131,7 +131,8 @@ fun CIFileView(
|
||||
Surface(
|
||||
Modifier.drawRingModifier(angle, strokeColor, strokeWidth),
|
||||
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))
|
||||
}
|
||||
|
@ -88,6 +88,7 @@ fun CIGroupInvitationView(
|
||||
}) else Modifier,
|
||||
shape = RoundedCornerShape(18.dp),
|
||||
color = if (sent) sentColor else receivedColor,
|
||||
contentColor = LocalContentColor.current
|
||||
) {
|
||||
Box(
|
||||
Modifier
|
||||
|
@ -142,6 +142,7 @@ fun DecryptionErrorItemFixButton(
|
||||
Modifier.clickable(onClick = onClick),
|
||||
shape = RoundedCornerShape(18.dp),
|
||||
color = receivedColor,
|
||||
contentColor = LocalContentColor.current
|
||||
) {
|
||||
Box(
|
||||
Modifier.padding(vertical = 6.dp, horizontal = 12.dp),
|
||||
@ -188,6 +189,7 @@ fun DecryptionErrorItem(
|
||||
Modifier.clickable(onClick = onClick),
|
||||
shape = RoundedCornerShape(18.dp),
|
||||
color = receivedColor,
|
||||
contentColor = LocalContentColor.current
|
||||
) {
|
||||
Box(
|
||||
Modifier.padding(vertical = 6.dp, horizontal = 12.dp),
|
||||
|
@ -153,7 +153,8 @@ private fun BoxScope.PlayButton(error: Boolean = false, onLongClick: () -> Unit,
|
||||
Surface(
|
||||
Modifier.align(Alignment.Center),
|
||||
color = Color.Black.copy(alpha = 0.25f),
|
||||
shape = RoundedCornerShape(percent = 50)
|
||||
shape = RoundedCornerShape(percent = 50),
|
||||
contentColor = LocalContentColor.current
|
||||
) {
|
||||
Box(
|
||||
Modifier
|
||||
@ -264,7 +265,8 @@ private fun progressCircle(progress: Long, total: Long) {
|
||||
Surface(
|
||||
Modifier.drawRingModifier(angle, strokeColor, strokeWidth),
|
||||
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))
|
||||
}
|
||||
|
@ -225,7 +225,8 @@ private fun PlayPauseButton(
|
||||
Surface(
|
||||
Modifier.drawRingModifier(angle, strokeColor, strokeWidth),
|
||||
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(
|
||||
Modifier
|
||||
|
@ -613,7 +613,7 @@ private fun ShrinkItemAction(revealed: MutableState<Boolean>, showMenu: MutableS
|
||||
@Composable
|
||||
fun ItemAction(text: String, icon: Painter, color: Color = Color.Unspecified, onClick: () -> Unit) {
|
||||
val finalColor = if (color == Color.Unspecified) {
|
||||
if (isInDarkTheme()) MenuTextColorDark else Color.Black
|
||||
MenuTextColor
|
||||
} else color
|
||||
DropdownMenuItem(onClick, contentPadding = PaddingValues(horizontal = DEFAULT_PADDING * 1.5f)) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
@ -633,7 +633,7 @@ fun ItemAction(text: String, icon: Painter, color: Color = Color.Unspecified, on
|
||||
@Composable
|
||||
fun ItemAction(text: String, icon: ImageVector, onClick: () -> Unit, color: Color = Color.Unspecified) {
|
||||
val finalColor = if (color == Color.Unspecified) {
|
||||
if (isInDarkTheme()) MenuTextColorDark else Color.Black
|
||||
MenuTextColor
|
||||
} else color
|
||||
DropdownMenuItem(onClick, contentPadding = PaddingValues(horizontal = DEFAULT_PADDING * 1.5f)) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
|
@ -23,6 +23,7 @@ fun DeletedItemView(ci: ChatItem, timedMessagesTTL: Int?) {
|
||||
Surface(
|
||||
shape = RoundedCornerShape(18.dp),
|
||||
color = if (sent) sentColor else receivedColor,
|
||||
contentColor = LocalContentColor.current
|
||||
) {
|
||||
Row(
|
||||
Modifier.padding(horizontal = 12.dp, vertical = 6.dp),
|
||||
|
@ -56,6 +56,7 @@ fun CIMsgError(ci: ChatItem, timedMessagesTTL: Int?, onClick: () -> Unit) {
|
||||
Modifier.clickable(onClick = onClick),
|
||||
shape = RoundedCornerShape(18.dp),
|
||||
color = receivedColor,
|
||||
contentColor = LocalContentColor.current
|
||||
) {
|
||||
Row(
|
||||
Modifier.padding(horizontal = 12.dp, vertical = 6.dp),
|
||||
|
@ -26,6 +26,7 @@ fun MarkedDeletedItemView(ci: ChatItem, timedMessagesTTL: Int?, revealed: Mutabl
|
||||
Surface(
|
||||
shape = RoundedCornerShape(18.dp),
|
||||
color = if (ci.chatDir.sent) sentColor else receivedColor,
|
||||
contentColor = LocalContentColor.current
|
||||
) {
|
||||
Row(
|
||||
Modifier.padding(horizontal = 12.dp, vertical = 6.dp),
|
||||
|
@ -75,6 +75,8 @@ fun ChatListView(chatModel: ChatModel, settingsState: SettingsViewState, setPerf
|
||||
SettingsView(chatModel, setPerformLA, scaffoldState.drawerState)
|
||||
}
|
||||
},
|
||||
contentColor = LocalContentColor.current,
|
||||
drawerContentColor = LocalContentColor.current,
|
||||
drawerScrimColor = MaterialTheme.colors.onSurface.copy(alpha = if (isInDarkTheme()) 0.16f else 0.32f),
|
||||
drawerGesturesEnabled = appPlatform.isAndroid,
|
||||
floatingActionButton = {
|
||||
|
@ -30,6 +30,8 @@ fun ShareListView(chatModel: ChatModel, settingsState: SettingsViewState, stoppe
|
||||
val endPadding = if (appPlatform.isDesktop) 56.dp else 0.dp
|
||||
Scaffold(
|
||||
Modifier.padding(end = endPadding),
|
||||
contentColor = LocalContentColor.current,
|
||||
drawerContentColor = LocalContentColor.current,
|
||||
scaffoldState = scaffoldState,
|
||||
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.res.MR
|
||||
import dev.icerock.moko.resources.compose.stringResource
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.math.roundToInt
|
||||
@ -303,7 +302,7 @@ fun UserProfileRow(u: User) {
|
||||
u.displayName,
|
||||
modifier = Modifier
|
||||
.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
|
||||
)
|
||||
}
|
||||
@ -346,7 +345,7 @@ fun RemoteHostRow(h: RemoteHostInfo) {
|
||||
Text(
|
||||
h.hostDeviceName,
|
||||
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,
|
||||
)
|
||||
}
|
||||
@ -387,7 +386,7 @@ fun LocalDeviceRow(active: Boolean) {
|
||||
Text(
|
||||
stringResource(MR.strings.this_device),
|
||||
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,
|
||||
)
|
||||
}
|
||||
@ -399,7 +398,7 @@ private fun UseFromDesktopPickerItem(onClick: () -> Unit) {
|
||||
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)
|
||||
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)
|
||||
Icon(painterResource(MR.images.ic_smartphone_300), 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)
|
||||
Text(text, color = MenuTextColor)
|
||||
}
|
||||
}
|
||||
|
||||
@ -419,7 +418,7 @@ private fun CreateInitialProfile(onClick: () -> Unit) {
|
||||
val text = generalGetString(MR.strings.create_chat_profile)
|
||||
Icon(painterResource(MR.images.ic_manage_accounts), 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)
|
||||
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)
|
||||
Icon(painterResource(MR.images.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)
|
||||
Text(text, color = MenuTextColor)
|
||||
}
|
||||
}
|
||||
|
||||
@ -439,7 +438,7 @@ private fun CancelPickerItem(onClick: () -> Unit) {
|
||||
val text = generalGetString(MR.strings.cancel_verb)
|
||||
Icon(painterResource(MR.images.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)
|
||||
Text(text, color = MenuTextColor)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -460,10 +460,10 @@ suspend fun deleteChatAsync(m: ChatModel) {
|
||||
m.controller.apiDeleteStorage()
|
||||
DatabaseUtils.ksDatabasePassword.remove()
|
||||
m.controller.appPrefs.storeDBPassphrase.set(true)
|
||||
deleteChatDatabaseFiles()
|
||||
deleteAppDatabaseAndFiles()
|
||||
}
|
||||
|
||||
fun deleteChatDatabaseFiles() {
|
||||
fun deleteAppDatabaseAndFiles() {
|
||||
val chat = File(dataDir, chatDatabaseFileName)
|
||||
val chatBak = File(dataDir, "$chatDatabaseFileName.bak")
|
||||
val agent = File(dataDir, agentDatabaseFileName)
|
||||
@ -473,6 +473,7 @@ fun deleteChatDatabaseFiles() {
|
||||
agent.delete()
|
||||
agentBak.delete()
|
||||
filesDir.deleteRecursively()
|
||||
filesDir.mkdir()
|
||||
remoteHostsDir.deleteRecursively()
|
||||
tmpDir.deleteRecursively()
|
||||
tmpDir.mkdir()
|
||||
|
@ -152,7 +152,8 @@ fun CustomTimePickerDialog(
|
||||
) {
|
||||
DefaultDialog(onDismissRequest = cancel) {
|
||||
Surface(
|
||||
shape = RoundedCornerShape(corner = CornerSize(25.dp))
|
||||
shape = RoundedCornerShape(corner = CornerSize(25.dp)),
|
||||
contentColor = LocalContentColor.current
|
||||
) {
|
||||
Box(
|
||||
contentAlignment = Alignment.Center
|
||||
|
@ -17,7 +17,7 @@ object DatabaseUtils {
|
||||
val ksAppPassword = KeyStoreItem(APP_PASSWORD_ALIAS, appPreferences.encryptedAppPassphrase, appPreferences.initializationVectorAppPassphrase)
|
||||
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? {
|
||||
return cryptor.decryptData(
|
||||
passphrase.get()?.toByteArrayFromBase64ForPassphrase() ?: return null,
|
||||
|
@ -70,7 +70,7 @@ fun <T> ExposedDropDownSetting(
|
||||
selectionOption.second + (if (label != null) " $label" else ""),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = if (isInDarkTheme()) MenuTextColorDark else Color.Black,
|
||||
color = MenuTextColor,
|
||||
fontSize = fontSize,
|
||||
)
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
package chat.simplex.common.views.helpers
|
||||
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Surface
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import chat.simplex.common.model.ChatController
|
||||
import chat.simplex.common.model.ChatModel
|
||||
@ -50,7 +49,7 @@ fun authenticateWithPasscode(
|
||||
close()
|
||||
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()) {
|
||||
close()
|
||||
completed(it)
|
||||
|
@ -26,7 +26,7 @@ fun ModalView(
|
||||
if (showClose) {
|
||||
BackHandler(onBack = close)
|
||||
}
|
||||
Surface(Modifier.fillMaxSize()) {
|
||||
Surface(Modifier.fillMaxSize(), contentColor = LocalContentColor.current) {
|
||||
Column(if (background != MaterialTheme.colors.background) Modifier.background(background) else Modifier.themedBackground()) {
|
||||
CloseSheetBar(close, showClose, endButtons)
|
||||
Box(modifier) { content() }
|
||||
|
@ -34,7 +34,7 @@ fun LocalAuthView(m: ChatModel, authRequest: LocalAuthRequest) {
|
||||
} else {
|
||||
val r: LAResult = if (passcode.value == authRequest.password) {
|
||||
if (authRequest.selfDestruct && sdPassword != null && controller.ctrl == -1L) {
|
||||
initChatControllerAndRunMigrations(true)
|
||||
initChatControllerAndRunMigrations()
|
||||
}
|
||||
LAResult.Success
|
||||
} else {
|
||||
@ -67,8 +67,8 @@ private fun deleteStorageAndRestart(m: ChatModel, password: String, completed: (
|
||||
* */
|
||||
chatCloseStore(ctrl)
|
||||
}
|
||||
deleteChatDatabaseFiles()
|
||||
// Clear sensitive data on screen just in case ModalManager will fail to prevent hiding its modals while database encrypts itself
|
||||
deleteAppDatabaseAndFiles()
|
||||
// Clear sensitive data on screen just in case ModalManager fails to hide its modals while new database is created
|
||||
m.chatId.value = null
|
||||
m.chatItems.clear()
|
||||
m.chats.clear()
|
||||
|
@ -12,6 +12,7 @@ import chat.simplex.res.MR
|
||||
@Composable
|
||||
fun SetAppPasscodeView(
|
||||
passcodeKeychain: DatabaseUtils.KeyStoreItem = ksAppPassword,
|
||||
prohibitedPasscodeKeychain: DatabaseUtils.KeyStoreItem = ksSelfDestructPassword,
|
||||
title: String = generalGetString(MR.strings.new_passcode),
|
||||
reason: String? = null,
|
||||
submit: () -> Unit,
|
||||
@ -51,7 +52,7 @@ fun SetAppPasscodeView(
|
||||
} else {
|
||||
SetPasswordView(title, generalGetString(MR.strings.save_verb),
|
||||
// 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
|
||||
passcode.value = ""
|
||||
confirming = true
|
||||
|
@ -175,7 +175,7 @@ fun ActionButton(
|
||||
disabled: Boolean = false,
|
||||
click: () -> Unit = {}
|
||||
) {
|
||||
Surface(shape = RoundedCornerShape(18.dp), color = Color.Transparent) {
|
||||
Surface(shape = RoundedCornerShape(18.dp), color = Color.Transparent, contentColor = LocalContentColor.current) {
|
||||
Column(
|
||||
Modifier
|
||||
.clickable(onClick = click)
|
||||
@ -220,7 +220,7 @@ fun ActionButton(
|
||||
disabled: Boolean = false,
|
||||
click: () -> Unit = {}
|
||||
) {
|
||||
Surface(modifier, shape = RoundedCornerShape(18.dp)) {
|
||||
Surface(modifier, shape = RoundedCornerShape(18.dp), contentColor = LocalContentColor.current) {
|
||||
Column(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
|
@ -380,7 +380,8 @@ fun SettingsSectionFooter(revert: () -> Unit, save: () -> Unit, disabled: Boolea
|
||||
fun FooterButton(icon: Painter, title: String, action: () -> Unit, disabled: Boolean) {
|
||||
Surface(
|
||||
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() }
|
||||
Row(
|
||||
|
@ -383,7 +383,7 @@ fun SimplexLockView(
|
||||
}
|
||||
LAMode.PASSCODE -> {
|
||||
ModalManager.fullscreen.showCustomModal { close ->
|
||||
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
|
||||
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) {
|
||||
SetAppPasscodeView(
|
||||
submit = {
|
||||
laLockDelay.set(30)
|
||||
@ -427,7 +427,7 @@ fun SimplexLockView(
|
||||
when (laResult) {
|
||||
LAResult.Success -> {
|
||||
ModalManager.fullscreen.showCustomModal { close ->
|
||||
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
|
||||
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) {
|
||||
SetAppPasscodeView(
|
||||
reason = generalGetString(MR.strings.la_app_passcode),
|
||||
submit = {
|
||||
@ -451,9 +451,10 @@ fun SimplexLockView(
|
||||
when (laResult) {
|
||||
LAResult.Success -> {
|
||||
ModalManager.fullscreen.showCustomModal { close ->
|
||||
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
|
||||
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) {
|
||||
SetAppPasscodeView(
|
||||
passcodeKeychain = ksSelfDestructPassword,
|
||||
prohibitedPasscodeKeychain = ksAppPassword,
|
||||
reason = generalGetString(MR.strings.self_destruct),
|
||||
submit = {
|
||||
selfDestructPasscodeAlert(generalGetString(MR.strings.self_destruct_passcode_changed))
|
||||
@ -487,7 +488,7 @@ fun SimplexLockView(
|
||||
}
|
||||
LAMode.PASSCODE -> {
|
||||
ModalManager.fullscreen.showCustomModal { close ->
|
||||
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
|
||||
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) {
|
||||
SetAppPasscodeView(
|
||||
submit = {
|
||||
laLockDelay.set(30)
|
||||
@ -598,9 +599,9 @@ private fun EnableSelfDestruct(
|
||||
selfDestruct: SharedPreference<Boolean>,
|
||||
close: () -> Unit
|
||||
) {
|
||||
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
|
||||
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background, contentColor = LocalContentColor.current) {
|
||||
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 = {
|
||||
selfDestruct.set(true)
|
||||
selfDestructPasscodeAlert(generalGetString(MR.strings.self_destruct_passcode_enabled))
|
||||
|
@ -155,7 +155,8 @@ fun RTCServersLayout(
|
||||
.height(160.dp)
|
||||
.fillMaxWidth(),
|
||||
shape = RoundedCornerShape(10.dp),
|
||||
border = BorderStroke(1.dp, MaterialTheme.colors.secondaryVariant)
|
||||
border = BorderStroke(1.dp, MaterialTheme.colors.secondaryVariant),
|
||||
contentColor = LocalContentColor.current
|
||||
) {
|
||||
SelectionContainer(
|
||||
Modifier.verticalScroll(rememberScrollState())
|
||||
|
@ -155,7 +155,7 @@ fun UserAddressView(
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
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(
|
||||
Modifier
|
||||
|
@ -24,7 +24,9 @@ fun initApp() {
|
||||
override fun cancelAllNotifications() = chat.simplex.common.model.NtfManager.cancelAllNotifications()
|
||||
}
|
||||
applyAppLocale()
|
||||
initChatControllerAndRunMigrations(false)
|
||||
if (DatabaseUtils.ksSelfDestructPassword.get() == null) {
|
||||
initChatControllerAndRunMigrations()
|
||||
}
|
||||
// LALAL
|
||||
//testCrypto()
|
||||
}
|
||||
|
@ -167,7 +167,8 @@ actual fun PlatformTextField(
|
||||
decorationBox = { innerTextField ->
|
||||
Surface(
|
||||
shape = RoundedCornerShape(18.dp),
|
||||
border = BorderStroke(1.dp, MaterialTheme.colors.secondary)
|
||||
border = BorderStroke(1.dp, MaterialTheme.colors.secondary),
|
||||
contentColor = LocalContentColor.current
|
||||
) {
|
||||
Row(
|
||||
Modifier.background(MaterialTheme.colors.background),
|
||||
|
@ -2,8 +2,7 @@ package chat.simplex.common.views.helpers
|
||||
|
||||
import androidx.compose.foundation.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Surface
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.key.*
|
||||
@ -39,7 +38,8 @@ actual fun DefaultDialog(
|
||||
) {
|
||||
Surface(
|
||||
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()
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd
|
||||
source-repository-package
|
||||
type: git
|
||||
location: https://github.com/simplex-chat/simplexmq.git
|
||||
tag: 6d4834f306963e2d3f2f62af212fe855ea9c7595
|
||||
tag: fa794d7878c82c370f1547f01e76f9691d229b92
|
||||
|
||||
source-repository-package
|
||||
type: git
|
||||
|
@ -8,9 +8,9 @@ u="$USER"
|
||||
tmp="$(mktemp -d -t)"
|
||||
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_hash="67aa37f0115195d8ddf32b5d6f471f1e60ecca0fdb3e98bcf54bc147c3078640"
|
||||
nix_hash="435f0d7e11f7c7dffeeab0ec9cc55723f6d3c03352379d785633cf4ddb5caf90"
|
||||
nix_config="sandbox = true
|
||||
max-jobs = auto
|
||||
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"
|
||||
|
||||
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_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"
|
||||
|
||||
rm -rf "$libs_folder/$android_arch"
|
||||
|
||||
if [ "$arch" = "armv7a" ] && [ -n "$tag_full" ] ; then
|
||||
git checkout "${tag_full}"
|
||||
fi
|
||||
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/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d";
|
||||
"https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl";
|
||||
|
@ -3,7 +3,7 @@
|
||||
module Simplex.Chat.Mobile.Shared where
|
||||
|
||||
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.Internal as LB
|
||||
import Foreign
|
||||
@ -21,7 +21,7 @@ getByteString ptr len = do
|
||||
|
||||
putByteString :: Ptr Word8 -> ByteString -> IO ()
|
||||
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 #-}
|
||||
|
||||
putLazyByteString :: Ptr Word8 -> LB.ByteString -> IO ()
|
||||
|
@ -415,6 +415,7 @@ xftpServerConfig =
|
||||
logStatsStartTime = 0,
|
||||
serverStatsLogFile = "tests/tmp/xftp-server-stats.daily.log",
|
||||
serverStatsBackupFile = Nothing,
|
||||
controlPort = Nothing,
|
||||
transportConfig = defaultTransportServerConfig
|
||||
}
|
||||
|
||||
|
@ -16,11 +16,12 @@ import qualified Data.Aeson.TH as JQ
|
||||
import Data.ByteString (ByteString)
|
||||
import qualified Data.ByteString as B
|
||||
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 Data.Word (Word8, Word32)
|
||||
import Foreign.C
|
||||
import Foreign.Marshal.Alloc (mallocBytes)
|
||||
import Foreign.Marshal.Utils (copyBytes)
|
||||
import Foreign.Ptr
|
||||
import Foreign.StablePtr
|
||||
import Foreign.Storable (peek)
|
||||
@ -291,7 +292,7 @@ testFileCApi fileName tmp = do
|
||||
peek ptr' `shouldReturn` (0 :: Word8)
|
||||
sz :: Word32 <- peek (ptr' `plusPtr` 1)
|
||||
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
|
||||
sz' `shouldBe` fromIntegral len
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user