Compare commits

...

10 Commits

Author SHA1 Message Date
Evgeny Poberezkin ceecaf6592 simplexmq 2024-07-29 19:36:51 +01:00
Evgeny Poberezkin fb831439e9 ios: load chats and refresh call invitations before chat is started 2024-07-29 19:35:48 +01:00
Evgeny Poberezkin 018d9a1064 core: allow getting call invitations and notificationn token when chat is stopped 2024-07-29 19:17:44 +01:00
Evgeny Poberezkin 4b382841a1 check chat is running 2024-07-29 18:51:01 +01:00
Evgeny Poberezkin 6834138270 fix race in the tests 2024-07-29 18:19:01 +01:00
Evgeny Poberezkin bf83ba40a3 simplexmq 2024-07-29 17:39:49 +01:00
Evgeny Poberezkin ca166d7f96 use priority database access 2024-07-29 15:12:18 +01:00
Evgeny Poberezkin 42669454b0 multiplatform: load chat data before starting chat 2024-07-29 11:37:32 +01:00
Evgeny Poberezkin 243f3a7516 revert some 2024-07-29 10:57:40 +01:00
spaced4ndy aadba41e66 core: move db actions out of synchronous execution on chat start 2024-07-29 13:33:31 +04:00
8 changed files with 355 additions and 295 deletions
+12 -2
View File
@@ -225,6 +225,15 @@ func apiStartChat(ctrl: chat_ctrl? = nil) throws -> Bool {
}
}
func apiCheckChatRunning() throws -> Bool {
let r = chatSendCmdSync(.checkChatRunning)
switch r {
case .chatRunning: return true
case .chatStopped: return false
default: throw r
}
}
func apiStopChat() async throws {
let r = await chatSendCmd(.apiStopChat)
switch r {
@@ -1439,15 +1448,16 @@ func startChat(refreshInvitations: Bool = true) throws {
logger.debug("startChat")
let m = ChatModel.shared
try setNetworkConfig(getNetCfg())
let justStarted = try apiStartChat()
let chatRunning = try apiCheckChatRunning()
m.users = try listUsers()
if justStarted {
if !chatRunning {
try getUserChatData()
NtfManager.shared.setNtfBadgeCount(m.totalUnreadCountForAllUsers())
if (refreshInvitations) {
try refreshCallInvitations()
}
(m.savedToken, m.tokenStatus, m.notificationMode, m.notificationServer) = apiGetNtfToken()
_ = try apiStartChat()
// deviceToken is set when AppDelegate.application(didRegisterForRemoteNotificationsWithDeviceToken:) is called,
// when it is called before startChat
if let token = m.deviceToken {
+3
View File
@@ -27,6 +27,7 @@ public enum ChatCommand {
case apiUnmuteUser(userId: Int64)
case apiDeleteUser(userId: Int64, delSMPQueues: Bool, viewPwd: String?)
case startChat(mainApp: Bool, enableSndFiles: Bool)
case checkChatRunning
case apiStopChat
case apiActivateChat(restoreChat: Bool)
case apiSuspendChat(timeoutMicroseconds: Int)
@@ -173,6 +174,7 @@ public enum ChatCommand {
case let .apiUnmuteUser(userId): return "/_unmute user \(userId)"
case let .apiDeleteUser(userId, delSMPQueues, viewPwd): return "/_delete user \(userId) del_smp=\(onOff(delSMPQueues))\(maybePwd(viewPwd))"
case let .startChat(mainApp, enableSndFiles): return "/_start main=\(onOff(mainApp)) snd_files=\(onOff(enableSndFiles))"
case .checkChatRunning: return "/_check running"
case .apiStopChat: return "/_stop"
case let .apiActivateChat(restore): return "/_app activate restore=\(onOff(restore))"
case let .apiSuspendChat(timeoutMicroseconds): return "/_app suspend \(timeoutMicroseconds)"
@@ -334,6 +336,7 @@ public enum ChatCommand {
case .apiUnmuteUser: return "apiUnmuteUser"
case .apiDeleteUser: return "apiDeleteUser"
case .startChat: return "startChat"
case .checkChatRunning: return "checkChatRunning"
case .apiStopChat: return "apiStopChat"
case .apiActivateChat: return "apiActivateChat"
case .apiSuspendChat: return "apiSuspendChat"
@@ -461,12 +461,11 @@ object ChatController {
Log.d(TAG, "user: $user")
try {
apiSetNetworkConfig(getNetCfg())
val justStarted = apiStartChat()
appPrefs.chatStopped.set(false)
val chatRunning = apiCheckChatRunning()
val users = listUsers(null)
chatModel.users.clear()
chatModel.users.addAll(users)
if (justStarted) {
if (!chatRunning) {
chatModel.currentUser.value = user
chatModel.localUserCreated.value = true
getUserChatData(null)
@@ -485,6 +484,8 @@ object ChatController {
}
Log.d(TAG, "startChat: running")
}
apiStartChat()
appPrefs.chatStopped.set(false)
} catch (e: Throwable) {
Log.e(TAG, "failed starting chat $e")
throw e
@@ -738,6 +739,15 @@ object ChatController {
}
}
private suspend fun apiCheckChatRunning(): Boolean {
val r = sendCmd(null, CC.CheckChatRunning())
when (r) {
is CR.ChatRunning -> return true
is CR.ChatStopped -> return false
else -> throw Exception("failed check chat running: ${r.responseType} ${r.details}")
}
}
suspend fun apiStopChat(): Boolean {
val r = sendCmd(null, CC.ApiStopChat())
when (r) {
@@ -2709,6 +2719,7 @@ sealed class CC {
class ApiUnmuteUser(val userId: Long): CC()
class ApiDeleteUser(val userId: Long, val delSMPQueues: Boolean, val viewPwd: String?): CC()
class StartChat(val mainApp: Boolean): CC()
class CheckChatRunning: CC()
class ApiStopChat: CC()
@Serializable
class ApiSetAppFilePaths(val appFilesFolder: String, val appTempFolder: String, val appAssetsFolder: String, val appRemoteHostsFolder: String): CC()
@@ -2854,6 +2865,7 @@ sealed class CC {
is ApiUnmuteUser -> "/_unmute user $userId"
is ApiDeleteUser -> "/_delete user $userId del_smp=${onOff(delSMPQueues)}${maybePwd(viewPwd)}"
is StartChat -> "/_start main=${onOff(mainApp)}"
is CheckChatRunning -> "/_check running"
is ApiStopChat -> "/_stop"
is ApiSetAppFilePaths -> "/set file paths ${json.encodeToString(this)}"
is ApiSetEncryptLocalFiles -> "/_files_encrypt ${onOff(enable)}"
@@ -3007,6 +3019,7 @@ sealed class CC {
is ApiUnmuteUser -> "apiUnmuteUser"
is ApiDeleteUser -> "apiDeleteUser"
is StartChat -> "startChat"
is CheckChatRunning -> "checkChatRunning"
is ApiStopChat -> "apiStopChat"
is ApiSetAppFilePaths -> "apiSetAppFilePaths"
is ApiSetEncryptLocalFiles -> "apiSetEncryptLocalFiles"
+1 -1
View File
@@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd
source-repository-package
type: git
location: https://github.com/simplex-chat/simplexmq.git
tag: 2de16cfae89661605b468df71eff8b8e8188ef86
tag: 3753379ae47a1201c8e546eaabc7bdf245463a70
source-repository-package
type: git
+1 -1
View File
@@ -1,5 +1,5 @@
{
"https://github.com/simplex-chat/simplexmq.git"."2de16cfae89661605b468df71eff8b8e8188ef86" = "00bgpy3gygqhmcbb2r5i8kryc5vn667bdg5s3xl3lf7y9m13g047";
"https://github.com/simplex-chat/simplexmq.git"."3753379ae47a1201c8e546eaabc7bdf245463a70" = "1h6wnjp1bqcjn55h3d9jbfz6fp49shy50izp649cvpyvls3difcm";
"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";
+282 -279
View File
File diff suppressed because it is too large Load Diff
+17 -3
View File
@@ -73,7 +73,7 @@ import Simplex.Messaging.Agent.Client (AgentLocks, AgentQueuesInfo (..), AgentWo
import Simplex.Messaging.Agent.Env.SQLite (AgentConfig, NetworkConfig, ServerCfg)
import Simplex.Messaging.Agent.Lock
import Simplex.Messaging.Agent.Protocol
import Simplex.Messaging.Agent.Store.SQLite (MigrationConfirmation, SQLiteStore, UpMigration, withTransaction)
import Simplex.Messaging.Agent.Store.SQLite (MigrationConfirmation, SQLiteStore, UpMigration, withTransaction, withTransactionPriority)
import Simplex.Messaging.Agent.Store.SQLite.DB (SlowQueryStats (..))
import qualified Simplex.Messaging.Agent.Store.SQLite.DB as DB
import Simplex.Messaging.Client (SMPProxyFallback (..), SMPProxyMode (..), SocksMode (..))
@@ -264,6 +264,7 @@ data ChatCommand
| APIDeleteUser UserId Bool (Maybe UserPwd)
| DeleteUser UserName Bool (Maybe UserPwd)
| StartChat {mainApp :: Bool, enableSndFiles :: Bool} -- enableSndFiles has no effect when mainApp is True
| CheckChatRunning
| APIStopChat
| APIActivateChat {restoreChat :: Bool}
| APISuspendChat {suspendTimeout :: Int}
@@ -1393,11 +1394,24 @@ toView' ev = do
withStore' :: (DB.Connection -> IO a) -> CM a
withStore' action = withStore $ liftIO . action
{-# INLINE withStore' #-}
withFastStore' :: (DB.Connection -> IO a) -> CM a
withFastStore' action = withFastStore $ liftIO . action
{-# INLINE withFastStore' #-}
withStore :: (DB.Connection -> ExceptT StoreError IO a) -> CM a
withStore action = do
withStore = withStorePriority False
{-# INLINE withStore #-}
withFastStore :: (DB.Connection -> ExceptT StoreError IO a) -> CM a
withFastStore = withStorePriority True
{-# INLINE withFastStore #-}
withStorePriority :: Bool -> (DB.Connection -> ExceptT StoreError IO a) -> CM a
withStorePriority priority action = do
ChatController {chatStore} <- ask
liftIOEither $ withTransaction chatStore (runExceptT . withExceptT ChatErrorStore . action) `E.catches` handleDBErrors
liftIOEither $ withTransactionPriority chatStore priority (runExceptT . withExceptT ChatErrorStore . action) `E.catches` handleDBErrors
withStoreBatch :: Traversable t => (DB.Connection -> t (IO (Either ChatError a))) -> CM' (t (Either ChatError a))
withStoreBatch actions = do
+23 -6
View File
@@ -648,6 +648,7 @@ testGroupSameName :: HasCallStack => FilePath -> IO ()
testGroupSameName =
testChat2 aliceProfile bobProfile $
\alice _ -> do
threadDelay 100000
alice ##> "/g team"
alice <## "group #team is created"
alice <## "to add members use /a team <name> or /create link #team"
@@ -1844,6 +1845,7 @@ testGroupLink :: HasCallStack => FilePath -> IO ()
testGroupLink =
testChatCfg3 testCfgGroupLinkViaContact aliceProfile bobProfile cathProfile $
\alice bob cath -> do
threadDelay 100000
alice ##> "/g team"
alice <## "group #team is created"
alice <## "to add members use /a team <name> or /create link #team"
@@ -1947,6 +1949,7 @@ testGroupLinkDeleteGroupRejoin :: HasCallStack => FilePath -> IO ()
testGroupLinkDeleteGroupRejoin =
testChatCfg2 testCfgGroupLinkViaContact aliceProfile bobProfile $
\alice bob -> do
threadDelay 100000
alice ##> "/g team"
alice <## "group #team is created"
alice <## "to add members use /a team <name> or /create link #team"
@@ -2003,6 +2006,7 @@ testGroupLinkContactUsed :: HasCallStack => FilePath -> IO ()
testGroupLinkContactUsed =
testChatCfg2 testCfgGroupLinkViaContact aliceProfile bobProfile $
\alice bob -> do
threadDelay 100000
alice ##> "/g team"
alice <## "group #team is created"
alice <## "to add members use /a team <name> or /create link #team"
@@ -2151,6 +2155,7 @@ testGroupLinkUnusedHostContactDeleted =
testChatCfg2 cfg aliceProfile bobProfile $
\alice bob -> do
-- create group 1
threadDelay 100000
alice ##> "/g team"
alice <## "group #team is created"
alice <## "to add members use /a team <name> or /create link #team"
@@ -2285,6 +2290,7 @@ testGroupLinkMemberRole :: HasCallStack => FilePath -> IO ()
testGroupLinkMemberRole =
testChatCfg3 testCfgGroupLinkViaContact aliceProfile bobProfile cathProfile $
\alice bob cath -> do
threadDelay 100000
alice ##> "/g team"
alice <## "group #team is created"
alice <## "to add members use /a team <name> or /create link #team"
@@ -2420,6 +2426,7 @@ testPlanGroupLinkOkKnown :: HasCallStack => FilePath -> IO ()
testPlanGroupLinkOkKnown =
testChatCfg2 testCfgGroupLinkViaContact aliceProfile bobProfile $
\alice bob -> do
threadDelay 100000
alice ##> "/g team"
alice <## "group #team is created"
alice <## "to add members use /a team <name> or /create link #team"
@@ -2463,6 +2470,7 @@ testPlanHostContactDeletedGroupLinkKnown :: HasCallStack => FilePath -> IO ()
testPlanHostContactDeletedGroupLinkKnown =
testChatCfg2 testCfgGroupLinkViaContact aliceProfile bobProfile $
\alice bob -> do
threadDelay 100000
alice ##> "/g team"
alice <## "group #team is created"
alice <## "to add members use /a team <name> or /create link #team"
@@ -2569,14 +2577,15 @@ testPlanGroupLinkOwn tmp =
testPlanGroupLinkConnecting :: HasCallStack => FilePath -> IO ()
testPlanGroupLinkConnecting tmp = do
-- gLink <- withNewTestChatCfg tmp cfg "alice" aliceProfile $ \alice -> do
gLink <- withNewTestChatCfg tmp cfg "alice" aliceProfile $ \a -> withTestOutput a $ \alice -> do
gLink <- withNewTestChatCfg tmp cfg "alice" aliceProfile $ \alice -> do
threadDelay 100000
alice ##> "/g team"
alice <## "group #team is created"
alice <## "to add members use /a team <name> or /create link #team"
alice ##> "/create link #team"
getGroupLink alice "team" GRMember True
-- withNewTestChatCfg tmp cfg "bob" bobProfile $ \bob -> do
withNewTestChatCfg tmp cfg "bob" bobProfile $ \b -> withTestOutput b $ \bob -> do
withNewTestChatCfg tmp cfg "bob" bobProfile $ \bob -> do
threadDelay 100000
bob ##> ("/c " <> gLink)
@@ -2591,14 +2600,14 @@ testPlanGroupLinkConnecting tmp = do
threadDelay 100000
-- withTestChatCfg tmp cfg "alice" $ \alice -> do
withTestChatCfg tmp cfg "alice" $ \a -> withTestOutput a $ \alice -> do
withTestChatCfg tmp cfg "alice" $ \alice -> do
alice
<### [ "1 group links active",
"#team: group is empty",
"bob (Bob): accepting request to join group #team..."
]
-- withTestChatCfg tmp cfg "bob" $ \bob -> do
withTestChatCfg tmp cfg "bob" $ \b -> withTestOutput b $ \bob -> do
withTestChatCfg tmp cfg "bob" $ \bob -> do
threadDelay 500000
bob ##> ("/_connect plan 1 " <> gLink)
bob <## "group link: connecting"
@@ -2615,8 +2624,8 @@ testPlanGroupLinkConnecting tmp = do
testPlanGroupLinkLeaveRejoin :: HasCallStack => FilePath -> IO ()
testPlanGroupLinkLeaveRejoin =
testChatCfg2 testCfgGroupLinkViaContact aliceProfile bobProfile $
-- \alice bob -> do
\a b -> withTestOutput a $ \alice -> withTestOutput b $ \bob -> do
\alice bob -> do
threadDelay 100000
alice ##> "/g team"
alice <## "group #team is created"
alice <## "to add members use /a team <name> or /create link #team"
@@ -2705,6 +2714,7 @@ testGroupLinkNoContact :: HasCallStack => FilePath -> IO ()
testGroupLinkNoContact =
testChat3 aliceProfile bobProfile cathProfile $
\alice bob cath -> do
threadDelay 100000
alice ##> "/g team"
alice <## "group #team is created"
alice <## "to add members use /a team <name> or /create link #team"
@@ -2928,6 +2938,7 @@ testGroupLinkNoContactMemberRole :: HasCallStack => FilePath -> IO ()
testGroupLinkNoContactMemberRole =
testChat3 aliceProfile bobProfile cathProfile $
\alice bob cath -> do
threadDelay 100000
alice ##> "/g team"
alice <## "group #team is created"
alice <## "to add members use /a team <name> or /create link #team"
@@ -3041,6 +3052,7 @@ testGroupLinkNoContactInviteeIncognito :: HasCallStack => FilePath -> IO ()
testGroupLinkNoContactInviteeIncognito =
testChat2 aliceProfile bobProfile $
\alice bob -> do
threadDelay 100000
alice ##> "/g team"
alice <## "group #team is created"
alice <## "to add members use /a team <name> or /create link #team"
@@ -3145,6 +3157,7 @@ testPlanGroupLinkNoContactKnown :: HasCallStack => FilePath -> IO ()
testPlanGroupLinkNoContactKnown =
testChat2 aliceProfile bobProfile $
\alice bob -> do
threadDelay 100000
alice ##> "/g team"
alice <## "group #team is created"
alice <## "to add members use /a team <name> or /create link #team"
@@ -3180,6 +3193,7 @@ testPlanGroupLinkNoContactKnown =
testPlanGroupLinkNoContactConnecting :: HasCallStack => FilePath -> IO ()
testPlanGroupLinkNoContactConnecting tmp = do
gLink <- withNewTestChat tmp "alice" aliceProfile $ \alice -> do
threadDelay 100000
alice ##> "/g team"
alice <## "group #team is created"
alice <## "to add members use /a team <name> or /create link #team"
@@ -3226,6 +3240,7 @@ testPlanGroupLinkNoContactConnecting tmp = do
testPlanGroupLinkNoContactConnectingSlow :: HasCallStack => FilePath -> IO ()
testPlanGroupLinkNoContactConnectingSlow tmp = do
gLink <- withNewTestChatCfg tmp testCfgSlow "alice" aliceProfile $ \alice -> do
threadDelay 100000
alice ##> "/g team"
alice <## "group #team is created"
alice <## "to add members use /a team <name> or /create link #team"
@@ -4123,6 +4138,7 @@ testMemberContactIncognito =
testChatCfg3 testCfgGroupLinkViaContact aliceProfile bobProfile cathProfile $
\alice bob cath -> do
-- create group, bob joins incognito
threadDelay 100000
alice ##> "/g team"
alice <## "group #team is created"
alice <## "to add members use /a team <name> or /create link #team"
@@ -5371,6 +5387,7 @@ testMembershipProfileUpdateNextGroupMessage =
testChat3 aliceProfile bobProfile cathProfile $
\alice bob cath -> do
-- create group 1
threadDelay 100000
alice ##> "/g team"
alice <## "group #team is created"
alice <## "to add members use /a team <name> or /create link #team"