mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2024-12-17 17:20:21 +01:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ceecaf6592 | |||
| fb831439e9 | |||
| 018d9a1064 | |||
| 4b382841a1 | |||
| 6834138270 | |||
| bf83ba40a3 | |||
| ca166d7f96 | |||
| 42669454b0 | |||
| 243f3a7516 | |||
| aadba41e66 |
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
|
||||
+16
-3
@@ -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
@@ -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,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
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user