Merge branch 'stable'
This commit is contained in:
commit
ce9d583b39
@ -485,6 +485,7 @@ func doStartChat() -> DBMigrationResult? {
|
|||||||
logger.debug("NotificationService: doStartChat")
|
logger.debug("NotificationService: doStartChat")
|
||||||
haskell_init_nse()
|
haskell_init_nse()
|
||||||
let (_, dbStatus) = chatMigrateInit(confirmMigrations: defaultMigrationConfirmation(), backgroundMode: true)
|
let (_, dbStatus) = chatMigrateInit(confirmMigrations: defaultMigrationConfirmation(), backgroundMode: true)
|
||||||
|
logger.debug("NotificationService: doStartChat \(String(describing: dbStatus))")
|
||||||
if dbStatus != .ok {
|
if dbStatus != .ok {
|
||||||
resetChatCtrl()
|
resetChatCtrl()
|
||||||
NSEChatState.shared.set(.created)
|
NSEChatState.shared.set(.created)
|
||||||
|
@ -25,13 +25,15 @@ void haskell_init(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void haskell_init_nse(void) {
|
void haskell_init_nse(void) {
|
||||||
int argc = 5;
|
int argc = 7;
|
||||||
char *argv[] = {
|
char *argv[] = {
|
||||||
"simplex",
|
"simplex",
|
||||||
"+RTS", // requires `hs_init_with_rtsopts`
|
"+RTS", // requires `hs_init_with_rtsopts`
|
||||||
"-A1m", // chunk size for new allocations
|
"-A1m", // chunk size for new allocations
|
||||||
"-H1m", // initial heap size
|
"-H1m", // initial heap size
|
||||||
"-xn", // non-moving GC
|
"-F0.5", // heap growth triggering GC
|
||||||
|
"-Fd1", // memory return
|
||||||
|
"-c", // compacting garbage collector
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
char **pargv = argv;
|
char **pargv = argv;
|
||||||
|
@ -174,7 +174,7 @@ class SimplexApp: Application(), LifecycleEventObserver {
|
|||||||
androidAppContext = this
|
androidAppContext = this
|
||||||
APPLICATION_ID = BuildConfig.APPLICATION_ID
|
APPLICATION_ID = BuildConfig.APPLICATION_ID
|
||||||
ntfManager = object : chat.simplex.common.platform.NtfManager() {
|
ntfManager = object : chat.simplex.common.platform.NtfManager() {
|
||||||
override fun notifyCallInvitation(invitation: RcvCallInvitation) = NtfManager.notifyCallInvitation(invitation)
|
override fun notifyCallInvitation(invitation: RcvCallInvitation): Boolean = NtfManager.notifyCallInvitation(invitation)
|
||||||
override fun hasNotificationsForChat(chatId: String): Boolean = NtfManager.hasNotificationsForChat(chatId)
|
override fun hasNotificationsForChat(chatId: String): Boolean = NtfManager.hasNotificationsForChat(chatId)
|
||||||
override fun cancelNotificationsForChat(chatId: String) = NtfManager.cancelNotificationsForChat(chatId)
|
override fun cancelNotificationsForChat(chatId: String) = NtfManager.cancelNotificationsForChat(chatId)
|
||||||
override fun displayNotification(user: UserLike, chatId: String, displayName: String, msgText: String, image: String?, actions: List<Pair<NotificationAction, () -> Unit>>) = NtfManager.displayNotification(user, chatId, displayName, msgText, image, actions.map { it.first })
|
override fun displayNotification(user: UserLike, chatId: String, displayName: String, msgText: String, image: String?, actions: List<Pair<NotificationAction, () -> Unit>>) = NtfManager.displayNotification(user, chatId, displayName, msgText, image, actions.map { it.first })
|
||||||
|
@ -30,7 +30,7 @@ object NtfManager {
|
|||||||
const val ShowChatsAction: String = "chat.simplex.app.SHOW_CHATS"
|
const val ShowChatsAction: String = "chat.simplex.app.SHOW_CHATS"
|
||||||
|
|
||||||
// DO NOT change notification channel settings / names
|
// DO NOT change notification channel settings / names
|
||||||
const val CallChannel: String = "chat.simplex.app.CALL_NOTIFICATION_1"
|
const val CallChannel: String = "chat.simplex.app.CALL_NOTIFICATION_2"
|
||||||
const val AcceptCallAction: String = "chat.simplex.app.ACCEPT_CALL"
|
const val AcceptCallAction: String = "chat.simplex.app.ACCEPT_CALL"
|
||||||
const val RejectCallAction: String = "chat.simplex.app.REJECT_CALL"
|
const val RejectCallAction: String = "chat.simplex.app.REJECT_CALL"
|
||||||
const val CallNotificationId: Int = -1
|
const val CallNotificationId: Int = -1
|
||||||
@ -59,7 +59,7 @@ object NtfManager {
|
|||||||
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
|
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
|
||||||
.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
|
.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
|
||||||
.build()
|
.build()
|
||||||
val soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + context.packageName + "/" + R.raw.ring_once)
|
val soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + context.packageName + "/raw/ring_once")
|
||||||
Log.d(TAG, "callNotificationChannel sound: $soundUri")
|
Log.d(TAG, "callNotificationChannel sound: $soundUri")
|
||||||
callChannel.setSound(soundUri, attrs)
|
callChannel.setSound(soundUri, attrs)
|
||||||
callChannel.enableVibration(true)
|
callChannel.enableVibration(true)
|
||||||
@ -140,7 +140,7 @@ object NtfManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun notifyCallInvitation(invitation: RcvCallInvitation) {
|
fun notifyCallInvitation(invitation: RcvCallInvitation): Boolean {
|
||||||
val keyguardManager = getKeyguardManager(context)
|
val keyguardManager = getKeyguardManager(context)
|
||||||
Log.d(
|
Log.d(
|
||||||
TAG,
|
TAG,
|
||||||
@ -149,7 +149,7 @@ object NtfManager {
|
|||||||
"callOnLockScreen ${appPreferences.callOnLockScreen.get()}, " +
|
"callOnLockScreen ${appPreferences.callOnLockScreen.get()}, " +
|
||||||
"onForeground ${isAppOnForeground}"
|
"onForeground ${isAppOnForeground}"
|
||||||
)
|
)
|
||||||
if (isAppOnForeground) return
|
if (isAppOnForeground) return false
|
||||||
val contactId = invitation.contact.id
|
val contactId = invitation.contact.id
|
||||||
Log.d(TAG, "notifyCallInvitation $contactId")
|
Log.d(TAG, "notifyCallInvitation $contactId")
|
||||||
val image = invitation.contact.image
|
val image = invitation.contact.image
|
||||||
@ -163,7 +163,7 @@ object NtfManager {
|
|||||||
.setFullScreenIntent(fullScreenPendingIntent, true)
|
.setFullScreenIntent(fullScreenPendingIntent, true)
|
||||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||||
} else {
|
} else {
|
||||||
val soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + context.packageName + "/" + R.raw.ring_once)
|
val soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + context.packageName + "/raw/ring_once")
|
||||||
val fullScreenPendingIntent = PendingIntent.getActivity(context, 0, Intent(), PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
val fullScreenPendingIntent = PendingIntent.getActivity(context, 0, Intent(), PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
|
||||||
NotificationCompat.Builder(context, CallChannel)
|
NotificationCompat.Builder(context, CallChannel)
|
||||||
.setContentIntent(chatPendingIntent(OpenChatAction, invitation.user.userId, invitation.contact.id))
|
.setContentIntent(chatPendingIntent(OpenChatAction, invitation.user.userId, invitation.contact.id))
|
||||||
@ -206,6 +206,7 @@ object NtfManager {
|
|||||||
notify(CallNotificationId, notification)
|
notify(CallNotificationId, notification)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showMessage(title: String, text: String) {
|
fun showMessage(title: String, text: String) {
|
||||||
@ -280,6 +281,7 @@ object NtfManager {
|
|||||||
manager.createNotificationChannel(callNotificationChannel(CallChannel, generalGetString(MR.strings.ntf_channel_calls)))
|
manager.createNotificationChannel(callNotificationChannel(CallChannel, generalGetString(MR.strings.ntf_channel_calls)))
|
||||||
// Remove old channels since they can't be edited
|
// Remove old channels since they can't be edited
|
||||||
manager.deleteNotificationChannel("chat.simplex.app.CALL_NOTIFICATION")
|
manager.deleteNotificationChannel("chat.simplex.app.CALL_NOTIFICATION")
|
||||||
|
manager.deleteNotificationChannel("chat.simplex.app.CALL_NOTIFICATION_1")
|
||||||
manager.deleteNotificationChannel("chat.simplex.app.LOCK_SCREEN_CALL_NOTIFICATION")
|
manager.deleteNotificationChannel("chat.simplex.app.LOCK_SCREEN_CALL_NOTIFICATION")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ abstract class NtfManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract fun notifyCallInvitation(invitation: RcvCallInvitation)
|
abstract fun notifyCallInvitation(invitation: RcvCallInvitation): Boolean
|
||||||
abstract fun hasNotificationsForChat(chatId: String): Boolean
|
abstract fun hasNotificationsForChat(chatId: String): Boolean
|
||||||
abstract fun cancelNotificationsForChat(chatId: String)
|
abstract fun cancelNotificationsForChat(chatId: String)
|
||||||
abstract fun displayNotification(user: UserLike, chatId: String, displayName: String, msgText: String, image: String? = null, actions: List<Pair<NotificationAction, () -> Unit>> = emptyList())
|
abstract fun displayNotification(user: UserLike, chatId: String, displayName: String, msgText: String, image: String? = null, actions: List<Pair<NotificationAction, () -> Unit>> = emptyList())
|
||||||
|
@ -13,8 +13,8 @@ class CallManager(val chatModel: ChatModel) {
|
|||||||
callInvitations[invitation.contact.id] = invitation
|
callInvitations[invitation.contact.id] = invitation
|
||||||
if (invitation.user.showNotifications) {
|
if (invitation.user.showNotifications) {
|
||||||
if (Clock.System.now() - invitation.callTs <= 3.minutes) {
|
if (Clock.System.now() - invitation.callTs <= 3.minutes) {
|
||||||
|
invitation.sentNotification = ntfManager.notifyCallInvitation(invitation)
|
||||||
activeCallInvitation.value = invitation
|
activeCallInvitation.value = invitation
|
||||||
ntfManager.notifyCallInvitation(invitation)
|
|
||||||
} else {
|
} else {
|
||||||
val contact = invitation.contact
|
val contact = invitation.contact
|
||||||
ntfManager.displayNotification(user = invitation.user, chatId = contact.id, displayName = contact.displayName, msgText = invitation.callTypeText)
|
ntfManager.displayNotification(user = invitation.user, chatId = contact.id, displayName = contact.displayName, msgText = invitation.callTypeText)
|
||||||
|
@ -15,11 +15,10 @@ import dev.icerock.moko.resources.compose.painterResource
|
|||||||
import dev.icerock.moko.resources.compose.stringResource
|
import dev.icerock.moko.resources.compose.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import chat.simplex.common.model.*
|
import chat.simplex.common.model.*
|
||||||
|
import chat.simplex.common.platform.*
|
||||||
import chat.simplex.common.ui.theme.*
|
import chat.simplex.common.ui.theme.*
|
||||||
import chat.simplex.common.views.helpers.ProfileImage
|
import chat.simplex.common.views.helpers.ProfileImage
|
||||||
import chat.simplex.common.views.usersettings.ProfilePreview
|
import chat.simplex.common.views.usersettings.ProfilePreview
|
||||||
import chat.simplex.common.platform.ntfManager
|
|
||||||
import chat.simplex.common.platform.SoundPlayer
|
|
||||||
import chat.simplex.res.MR
|
import chat.simplex.res.MR
|
||||||
import kotlinx.datetime.Clock
|
import kotlinx.datetime.Clock
|
||||||
|
|
||||||
@ -27,7 +26,11 @@ import kotlinx.datetime.Clock
|
|||||||
fun IncomingCallAlertView(invitation: RcvCallInvitation, chatModel: ChatModel) {
|
fun IncomingCallAlertView(invitation: RcvCallInvitation, chatModel: ChatModel) {
|
||||||
val cm = chatModel.callManager
|
val cm = chatModel.callManager
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
LaunchedEffect(true) { SoundPlayer.start(scope, sound = !chatModel.showCallView.value) }
|
LaunchedEffect(Unit) {
|
||||||
|
if (chatModel.activeCallInvitation.value?.sentNotification == false || appPlatform.isDesktop) {
|
||||||
|
SoundPlayer.start(scope, sound = !chatModel.showCallView.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
DisposableEffect(true) { onDispose { SoundPlayer.stop() } }
|
DisposableEffect(true) { onDispose { SoundPlayer.stop() } }
|
||||||
IncomingCallAlertLayout(
|
IncomingCallAlertLayout(
|
||||||
invitation,
|
invitation,
|
||||||
|
@ -112,6 +112,9 @@ sealed class WCallResponse {
|
|||||||
CallMediaType.Video -> MR.strings.incoming_video_call
|
CallMediaType.Video -> MR.strings.incoming_video_call
|
||||||
CallMediaType.Audio -> MR.strings.incoming_audio_call
|
CallMediaType.Audio -> MR.strings.incoming_audio_call
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Shows whether notification was shown or not to prevent playing sound twice in both notification and in-app
|
||||||
|
var sentNotification: Boolean = false
|
||||||
}
|
}
|
||||||
@Serializable data class CallCapabilities(val encryption: Boolean)
|
@Serializable data class CallCapabilities(val encryption: Boolean)
|
||||||
@Serializable data class ConnectionInfo(private val localCandidate: RTCIceCandidate?, private val remoteCandidate: RTCIceCandidate?) {
|
@Serializable data class ConnectionInfo(private val localCandidate: RTCIceCandidate?, private val remoteCandidate: RTCIceCandidate?) {
|
||||||
|
@ -16,8 +16,8 @@ import javax.imageio.ImageIO
|
|||||||
object NtfManager {
|
object NtfManager {
|
||||||
private val prevNtfs = arrayListOf<Pair<ChatId, Slice>>()
|
private val prevNtfs = arrayListOf<Pair<ChatId, Slice>>()
|
||||||
|
|
||||||
fun notifyCallInvitation(invitation: RcvCallInvitation) {
|
fun notifyCallInvitation(invitation: RcvCallInvitation): Boolean {
|
||||||
if (simplexWindowState.windowFocused.value) return
|
if (simplexWindowState.windowFocused.value) return false
|
||||||
val contactId = invitation.contact.id
|
val contactId = invitation.contact.id
|
||||||
Log.d(TAG, "notifyCallInvitation $contactId")
|
Log.d(TAG, "notifyCallInvitation $contactId")
|
||||||
val image = invitation.contact.image
|
val image = invitation.contact.image
|
||||||
@ -45,6 +45,7 @@ object NtfManager {
|
|||||||
displayNotificationViaLib(contactId, title, text, prepareIconPath(largeIcon), actions) {
|
displayNotificationViaLib(contactId, title, text, prepareIconPath(largeIcon), actions) {
|
||||||
ntfManager.openChatAction(invitation.user.userId, contactId)
|
ntfManager.openChatAction(invitation.user.userId, contactId)
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showMessage(title: String, text: String) {
|
fun showMessage(title: String, text: String) {
|
||||||
|
@ -15,7 +15,7 @@ val defaultLocale: Locale = Locale.getDefault()
|
|||||||
|
|
||||||
fun initApp() {
|
fun initApp() {
|
||||||
ntfManager = object : NtfManager() {
|
ntfManager = object : NtfManager() {
|
||||||
override fun notifyCallInvitation(invitation: RcvCallInvitation) = chat.simplex.common.model.NtfManager.notifyCallInvitation(invitation)
|
override fun notifyCallInvitation(invitation: RcvCallInvitation): Boolean = chat.simplex.common.model.NtfManager.notifyCallInvitation(invitation)
|
||||||
override fun hasNotificationsForChat(chatId: String): Boolean = chat.simplex.common.model.NtfManager.hasNotificationsForChat(chatId)
|
override fun hasNotificationsForChat(chatId: String): Boolean = chat.simplex.common.model.NtfManager.hasNotificationsForChat(chatId)
|
||||||
override fun cancelNotificationsForChat(chatId: String) = chat.simplex.common.model.NtfManager.cancelNotificationsForChat(chatId)
|
override fun cancelNotificationsForChat(chatId: String) = chat.simplex.common.model.NtfManager.cancelNotificationsForChat(chatId)
|
||||||
override fun displayNotification(user: UserLike, chatId: String, displayName: String, msgText: String, image: String?, actions: List<Pair<NotificationAction, () -> Unit>>) = chat.simplex.common.model.NtfManager.displayNotification(user, chatId, displayName, msgText, image, actions)
|
override fun displayNotification(user: UserLike, chatId: String, displayName: String, msgText: String, image: String?, actions: List<Pair<NotificationAction, () -> Unit>>) = chat.simplex.common.model.NtfManager.displayNotification(user, chatId, displayName, msgText, image, actions)
|
||||||
|
@ -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: ca527b4d6cb83d24abdc9cbefcf56c870f694a63
|
tag: ad8cd1d5154617663065652b45c784ad5a0a584d
|
||||||
|
|
||||||
source-repository-package
|
source-repository-package
|
||||||
type: git
|
type: git
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"https://github.com/simplex-chat/simplexmq.git"."ca527b4d6cb83d24abdc9cbefcf56c870f694a63" = "06547v4n30xbk49c87frnvfbj6pihvxh4nx8rq9idpd8x2kxpyb1";
|
"https://github.com/simplex-chat/simplexmq.git"."ad8cd1d5154617663065652b45c784ad5a0a584d" = "19sinz1gynab776x8h9va7r6ifm9pmgzljsbc7z5cbkcnjl5sfh3";
|
||||||
"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";
|
||||||
|
Loading…
Reference in New Issue
Block a user