mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-05-24 19:35:33 +00:00
core: commands to set chat notification settings (#946)
* core: commands to set chat notification settings * add API
This commit is contained in:
committed by
GitHub
parent
3221c0abb5
commit
70168967a3
@@ -460,6 +460,7 @@ class Contact(
|
||||
val profile: Profile,
|
||||
val activeConn: Connection,
|
||||
val viaGroup: Long? = null,
|
||||
// val chatSettings: ChatSettings,
|
||||
override val createdAt: Instant,
|
||||
override val updatedAt: Instant
|
||||
): SomeChat, NamedChat {
|
||||
@@ -540,6 +541,7 @@ class GroupInfo (
|
||||
override val localDisplayName: String,
|
||||
val groupProfile: GroupProfile,
|
||||
val membership: GroupMember,
|
||||
// val chatSettings: ChatSettings,
|
||||
override val createdAt: Instant,
|
||||
override val updatedAt: Instant
|
||||
): SomeChat, NamedChat {
|
||||
|
||||
@@ -1136,6 +1136,7 @@ sealed class CC {
|
||||
class SetUserSMPServers(val smpServers: List<String>): CC()
|
||||
class APISetNetworkConfig(val networkConfig: NetCfg): CC()
|
||||
class APIGetNetworkConfig: CC()
|
||||
class APISetChatSettings(val type: ChatType, val id: Long, val chatSettings: ChatSettings): CC()
|
||||
class APIContactInfo(val contactId: Long): CC()
|
||||
class APIGroupMemberInfo(val groupId: Long, val groupMemberId: Long): CC()
|
||||
class AddContact: CC()
|
||||
@@ -1186,6 +1187,7 @@ sealed class CC {
|
||||
is SetUserSMPServers -> "/smp_servers ${smpServersStr(smpServers)}"
|
||||
is APISetNetworkConfig -> "/_network ${json.encodeToString(networkConfig)}"
|
||||
is APIGetNetworkConfig -> "/network"
|
||||
is APISetChatSettings -> "/_settings ${chatRef(type, id)} ${json.encodeToString(chatSettings)}"
|
||||
is APIContactInfo -> "/_info @$contactId"
|
||||
is APIGroupMemberInfo -> "/_info #$groupId $groupMemberId"
|
||||
is AddContact -> "/connect"
|
||||
@@ -1237,6 +1239,7 @@ sealed class CC {
|
||||
is SetUserSMPServers -> "setUserSMPServers"
|
||||
is APISetNetworkConfig -> "/apiSetNetworkConfig"
|
||||
is APIGetNetworkConfig -> "/apiGetNetworkConfig"
|
||||
is APISetChatSettings -> "/apiSetChatSettings"
|
||||
is APIContactInfo -> "apiContactInfo"
|
||||
is APIGroupMemberInfo -> "apiGroupMemberInfo"
|
||||
is AddContact -> "addContact"
|
||||
@@ -1348,6 +1351,11 @@ data class KeepAliveOpts(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class ChatSettings(
|
||||
val enableNtfs: Boolean
|
||||
)
|
||||
|
||||
val json = Json {
|
||||
prettyPrint = true
|
||||
ignoreUnknownKeys = true
|
||||
|
||||
@@ -45,6 +45,7 @@ public enum ChatCommand {
|
||||
case setUserSMPServers(smpServers: [String])
|
||||
case apiSetNetworkConfig(networkConfig: NetCfg)
|
||||
case apiGetNetworkConfig
|
||||
case apiSetChatSettings(type: ChatType, id: Int64, chatSettings: ChatSettings)
|
||||
case apiContactInfo(contactId: Int64)
|
||||
case apiGroupMemberInfo(groupId: Int64, groupMemberId: Int64)
|
||||
case addContact
|
||||
@@ -108,6 +109,7 @@ public enum ChatCommand {
|
||||
case let .setUserSMPServers(smpServers): return "/smp_servers \(smpServersStr(smpServers: smpServers))"
|
||||
case let .apiSetNetworkConfig(networkConfig): return "/_network \(encodeJSON(networkConfig))"
|
||||
case .apiGetNetworkConfig: return "/network"
|
||||
case let .apiSetChatSettings(type, id, chatSettings): return "/_settings \(ref(type, id)) \(encodeJSON(chatSettings))"
|
||||
case let .apiContactInfo(contactId): return "/_info @\(contactId)"
|
||||
case let .apiGroupMemberInfo(groupId, groupMemberId): return "/_info #\(groupId) \(groupMemberId)"
|
||||
case .addContact: return "/connect"
|
||||
@@ -170,6 +172,7 @@ public enum ChatCommand {
|
||||
case .setUserSMPServers: return "setUserSMPServers"
|
||||
case .apiSetNetworkConfig: return "apiSetNetworkConfig"
|
||||
case .apiGetNetworkConfig: return "apiGetNetworkConfig"
|
||||
case .apiSetChatSettings: return "apiSetChatSettings"
|
||||
case .apiContactInfo: return "apiContactInfo"
|
||||
case .apiGroupMemberInfo: return "apiGroupMemberInfo"
|
||||
case .addContact: return "addContact"
|
||||
@@ -591,6 +594,12 @@ public struct KeepAliveOpts: Codable, Equatable {
|
||||
public static let defaults: KeepAliveOpts = KeepAliveOpts(keepIdle: 30, keepIntvl: 15, keepCnt: 4)
|
||||
}
|
||||
|
||||
public struct ChatSettings: Codable {
|
||||
public var enableNtfs: Bool
|
||||
|
||||
public static let defaults: ChatSettings = ChatSettings(enableNtfs: true)
|
||||
}
|
||||
|
||||
public struct ConnectionStats: Codable {
|
||||
public var rcvServers: [String]?
|
||||
public var sndServers: [String]?
|
||||
|
||||
@@ -244,6 +244,7 @@ public struct Contact: Identifiable, Decodable, NamedChat {
|
||||
public var profile: Profile
|
||||
public var activeConn: Connection
|
||||
public var viaGroup: Int64?
|
||||
// public var chatSettings: ChatSettings
|
||||
var createdAt: Date
|
||||
var updatedAt: Date
|
||||
|
||||
@@ -433,6 +434,7 @@ public struct GroupInfo: Identifiable, Decodable, NamedChat {
|
||||
var localDisplayName: GroupName
|
||||
public var groupProfile: GroupProfile
|
||||
public var membership: GroupMember
|
||||
// public var chatSettings: ChatSettings
|
||||
var createdAt: Date
|
||||
var updatedAt: Date
|
||||
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ constraints: zip +disable-bzip2 +disable-zstd
|
||||
source-repository-package
|
||||
type: git
|
||||
location: https://github.com/simplex-chat/simplexmq.git
|
||||
tag: 3fc9afbb351033413dd84344ec603910e370a8ec
|
||||
tag: a33539bef9d31f5acbf9a21bfa0ef39a2dd421dd
|
||||
|
||||
source-repository-package
|
||||
type: git
|
||||
|
||||
@@ -44,6 +44,7 @@ library
|
||||
Simplex.Chat.Migrations.M20220715_groups_chat_item_id
|
||||
Simplex.Chat.Migrations.M20220811_chat_items_indices
|
||||
Simplex.Chat.Migrations.M20220812_incognito_profiles
|
||||
Simplex.Chat.Migrations.M20220818_chat_notifications
|
||||
Simplex.Chat.Mobile
|
||||
Simplex.Chat.Options
|
||||
Simplex.Chat.ProfileGenerator
|
||||
|
||||
+35
-16
@@ -261,7 +261,7 @@ processChatCommand = \case
|
||||
setupSndFileTransfer :: Contact -> m (Maybe (FileInvitation, CIFile 'MDSnd))
|
||||
setupSndFileTransfer ct = forM file_ $ \file -> do
|
||||
(fileSize, chSize) <- checkSndFile file
|
||||
(agentConnId, fileConnReq) <- withAgent (`createConnection` SCMInvitation)
|
||||
(agentConnId, fileConnReq) <- withAgent $ \a -> createConnection a True SCMInvitation
|
||||
let fileName = takeFileName file
|
||||
fileInvitation = FileInvitation {fileName, fileSize, fileConnReq = Just fileConnReq}
|
||||
fileId <- withStore' $ \db -> createSndFileTransfer db userId ct file fileInvitation agentConnId chSize
|
||||
@@ -597,6 +597,23 @@ processChatCommand = \case
|
||||
pure CRCmdOk
|
||||
APISetNetworkConfig cfg -> withUser' $ \_ -> withAgent (`setNetworkConfig` cfg) $> CRCmdOk
|
||||
APIGetNetworkConfig -> CRNetworkConfig <$> withUser' (\_ -> withAgent getNetworkConfig)
|
||||
APISetChatSettings (ChatRef cType chatId) chatSettings -> withUser $ \user@User {userId} -> case cType of
|
||||
CTDirect -> do
|
||||
ct <- withStore $ \db -> do
|
||||
ct <- getContact db userId chatId
|
||||
liftIO $ updateContactSettings db user chatId chatSettings
|
||||
pure ct
|
||||
withAgent $ \a -> toggleConnectionNtfs a (contactConnId ct) (enableNtfs chatSettings)
|
||||
pure CRCmdOk
|
||||
CTGroup -> do
|
||||
ms <- withStore $ \db -> do
|
||||
Group _ ms <- getGroup db user chatId
|
||||
liftIO $ updateGroupSettings db user chatId chatSettings
|
||||
pure ms
|
||||
withAgent $ \a -> forM_ ms $ \m ->
|
||||
forM_ (memberConnId m) $ \connId -> toggleConnectionNtfs a connId (enableNtfs chatSettings)
|
||||
pure CRCmdOk
|
||||
_ -> pure $ chatCmdError "not supported"
|
||||
APIContactInfo contactId -> withUser $ \User {userId} -> do
|
||||
-- [incognito] print user's incognito profile for this contact
|
||||
ct@Contact {activeConn = Connection {customUserProfileId}} <- withStore $ \db -> getContact db userId contactId
|
||||
@@ -621,7 +638,7 @@ processChatCommand = \case
|
||||
-- [incognito] generate profile for connection
|
||||
incognito <- readTVarIO =<< asks incognitoMode
|
||||
incognitoProfile <- if incognito then Just <$> liftIO generateRandomProfile else pure Nothing
|
||||
(connId, cReq) <- withAgent (`createConnection` SCMInvitation)
|
||||
(connId, cReq) <- withAgent $ \a -> createConnection a True SCMInvitation
|
||||
conn <- withStore' $ \db -> createDirectConnection db userId connId ConnNew incognitoProfile
|
||||
toView $ CRNewContactConnection conn
|
||||
pure $ CRInvitation cReq
|
||||
@@ -630,7 +647,7 @@ processChatCommand = \case
|
||||
incognito <- readTVarIO =<< asks incognitoMode
|
||||
incognitoProfile <- if incognito then Just <$> liftIO generateRandomProfile else pure Nothing
|
||||
let profileToSend = fromMaybe (fromLocalProfile profile) incognitoProfile
|
||||
connId <- withAgent $ \a -> joinConnection a cReq . directMessage $ XInfo profileToSend
|
||||
connId <- withAgent $ \a -> joinConnection a True cReq . directMessage $ XInfo profileToSend
|
||||
conn <- withStore' $ \db -> createDirectConnection db userId connId ConnJoined incognitoProfile
|
||||
toView $ CRNewContactConnection conn
|
||||
pure CRSentConfirmation
|
||||
@@ -649,7 +666,7 @@ processChatCommand = \case
|
||||
processChatCommand $ APIClearChat (ChatRef CTDirect contactId)
|
||||
ListContacts -> withUser $ \user -> CRContactsList <$> withStore' (`getUserContacts` user)
|
||||
CreateMyAddress -> withUser $ \User {userId} -> withChatLock . procCmd $ do
|
||||
(connId, cReq) <- withAgent (`createConnection` SCMContact)
|
||||
(connId, cReq) <- withAgent $ \a -> createConnection a True SCMContact
|
||||
withStore $ \db -> createUserContactLink db userId connId cReq
|
||||
pure $ CRUserContactLinkCreated cReq
|
||||
DeleteMyAddress -> withUser $ \user -> withChatLock $ do
|
||||
@@ -731,7 +748,7 @@ processChatCommand = \case
|
||||
case contactMember contact members of
|
||||
Nothing -> do
|
||||
gVar <- asks idsDrg
|
||||
(agentConnId, cReq) <- withAgent (`createConnection` SCMInvitation)
|
||||
(agentConnId, cReq) <- withAgent $ \a -> createConnection a True SCMInvitation
|
||||
member <- withStore $ \db -> createNewContactMember db gVar user groupId contact memRole agentConnId cReq
|
||||
sendInvitation member cReq
|
||||
Just member@GroupMember {groupMemberId, memberStatus}
|
||||
@@ -760,7 +777,7 @@ processChatCommand = \case
|
||||
else pure g
|
||||
-- [incognito] if membership is incognito, send its incognito profile in XGrpAcpt
|
||||
let incognitoProfile = if memberIncognito membership' then Just (fromLocalProfile $ memberProfile membership') else Nothing
|
||||
agentConnId <- withAgent $ \a -> joinConnection a connRequest . directMessage $ XGrpAcpt (memberId (membership' :: GroupMember)) incognitoProfile
|
||||
agentConnId <- withAgent $ \a -> joinConnection a True connRequest . directMessage $ XGrpAcpt (memberId (membership' :: GroupMember)) incognitoProfile
|
||||
withStore' $ \db -> do
|
||||
createMemberConnection db userId fromMember agentConnId
|
||||
updateGroupMemberStatus db userId fromMember GSMemAccepted
|
||||
@@ -959,7 +976,7 @@ processChatCommand = \case
|
||||
incognito <- readTVarIO =<< asks incognitoMode
|
||||
incognitoProfile <- if incognito then Just <$> liftIO generateRandomProfile else pure Nothing
|
||||
let profileToSend = fromMaybe profile incognitoProfile
|
||||
connId <- withAgent $ \a -> joinConnection a cReq $ directMessage (XContact profileToSend $ Just xContactId)
|
||||
connId <- withAgent $ \a -> joinConnection a True cReq $ directMessage (XContact profileToSend $ Just xContactId)
|
||||
conn <- withStore' $ \db -> createConnReqConnection db userId connId cReqHash xContactId incognitoProfile
|
||||
toView $ CRNewContactConnection conn
|
||||
pure $ CRSentInvitation incognitoProfile
|
||||
@@ -1108,7 +1125,7 @@ acceptFileReceive user@User {userId} RcvFileTransfer {fileId, fileInvitation = F
|
||||
case fileConnReq of
|
||||
-- direct file protocol
|
||||
Just connReq ->
|
||||
tryError (withAgent $ \a -> joinConnection a connReq . directMessage $ XFileAcpt fName) >>= \case
|
||||
tryError (withAgent $ \a -> joinConnection a True connReq . directMessage $ XFileAcpt fName) >>= \case
|
||||
Right agentConnId -> do
|
||||
filePath <- getRcvFilePath filePath_ fName
|
||||
withStore $ \db -> acceptRcvFileTransfer db user fileId agentConnId ConnJoined filePath
|
||||
@@ -1122,7 +1139,7 @@ acceptFileReceive user@User {userId} RcvFileTransfer {fileId, fileInvitation = F
|
||||
case activeConn of
|
||||
Just conn -> do
|
||||
sharedMsgId <- withStore $ \db -> getSharedMsgIdByFileId db userId fileId
|
||||
(agentConnId, fileInvConnReq) <- withAgent (`createConnection` SCMInvitation)
|
||||
(agentConnId, fileInvConnReq) <- withAgent $ \a -> createConnection a True SCMInvitation
|
||||
filePath <- getRcvFilePath filePath_ fName
|
||||
ci <- withStore $ \db -> acceptRcvFileTransfer db user fileId agentConnId ConnNew filePath
|
||||
void $ sendDirectMessage conn (XFileAcptInv sharedMsgId fileInvConnReq fName) (GroupId groupId)
|
||||
@@ -1173,7 +1190,7 @@ acceptContactRequest User {userId, profile} UserContactRequest {agentInvitationI
|
||||
incognito <- readTVarIO =<< asks incognitoMode
|
||||
incognitoProfile <- if incognito then Just <$> liftIO generateRandomProfile else pure Nothing
|
||||
let profileToSend = fromMaybe (fromLocalProfile profile) incognitoProfile
|
||||
connId <- withAgent $ \a -> acceptContact a invId . directMessage $ XInfo profileToSend
|
||||
connId <- withAgent $ \a -> acceptContact a True invId . directMessage $ XInfo profileToSend
|
||||
withStore' $ \db -> createAcceptedContact db userId connId cName profileId p userContactLinkId xContactId incognitoProfile
|
||||
|
||||
agentSubscriber :: (MonadUnliftIO m, MonadReader ChatController m) => m ()
|
||||
@@ -1455,7 +1472,7 @@ processAgentMessage (Just user@User {userId, profile}) agentConnId agentMessage
|
||||
_ -> pure ()
|
||||
|
||||
processGroupMessage :: ACommand 'Agent -> Connection -> GroupInfo -> GroupMember -> m ()
|
||||
processGroupMessage agentMsg conn gInfo@GroupInfo {groupId, localDisplayName = gName, membership} m@GroupMember {memberContactProfileId} = case agentMsg of
|
||||
processGroupMessage agentMsg conn gInfo@GroupInfo {groupId, localDisplayName = gName, membership, chatSettings} m@GroupMember {memberContactProfileId} = case agentMsg of
|
||||
CONF confId _ connInfo -> do
|
||||
ChatMessage {chatMsgEvent} <- liftEither $ parseChatMessage connInfo
|
||||
case memberCategory m of
|
||||
@@ -1497,6 +1514,7 @@ processAgentMessage (Just user@User {userId, profile}) agentConnId agentMessage
|
||||
unless (memberActive membership) $
|
||||
updateGroupMemberStatus db userId membership GSMemConnected
|
||||
sendPendingGroupMessages m conn
|
||||
unless (enableNtfs chatSettings) . withAgent $ \a -> toggleConnectionNtfs a (aConnId conn) False
|
||||
case memberCategory m of
|
||||
GCHostMember -> do
|
||||
-- [incognito] chat item & event with indication that host connected incognito
|
||||
@@ -1886,7 +1904,7 @@ processAgentMessage (Just user@User {userId, profile}) agentConnId agentMessage
|
||||
unless cancelled $
|
||||
if fName == fileName
|
||||
then
|
||||
tryError (withAgent $ \a -> joinConnection a fileConnReq . directMessage $ XOk) >>= \case
|
||||
tryError (withAgent $ \a -> joinConnection a True fileConnReq . directMessage $ XOk) >>= \case
|
||||
Right acId ->
|
||||
withStore' $ \db -> createSndGroupFileTransferConnection db userId fileId acId m
|
||||
Left e -> throwError e
|
||||
@@ -2091,8 +2109,8 @@ processAgentMessage (Just user@User {userId, profile}) agentConnId agentMessage
|
||||
if isMember memId gInfo members
|
||||
then messageWarning "x.grp.mem.intro ignored: member already exists"
|
||||
else do
|
||||
(groupConnId, groupConnReq) <- withAgent (`createConnection` SCMInvitation)
|
||||
(directConnId, directConnReq) <- withAgent (`createConnection` SCMInvitation)
|
||||
(groupConnId, groupConnReq) <- withAgent $ \a -> createConnection a True SCMInvitation
|
||||
(directConnId, directConnReq) <- withAgent $ \a -> createConnection a True SCMInvitation
|
||||
-- [incognito] direct connection with member has to be established using same incognito profile
|
||||
customUserProfileId <- if memberIncognito membership then Just <$> withStore (\db -> getGroupMemberProfileId db userId membership) else pure Nothing
|
||||
newMember <- withStore $ \db -> createIntroReMember db user gInfo m memInfo groupConnId directConnId customUserProfileId
|
||||
@@ -2126,8 +2144,8 @@ processAgentMessage (Just user@User {userId, profile}) agentConnId agentMessage
|
||||
withStore' $ \db -> saveMemberInvitation db toMember introInv
|
||||
-- [incognito] send membership incognito profile, create direct connection as incognito
|
||||
let msg = XGrpMemInfo (memberId (membership :: GroupMember)) (fromLocalProfile $ memberProfile membership)
|
||||
groupConnId <- withAgent $ \a -> joinConnection a groupConnReq $ directMessage msg
|
||||
directConnId <- withAgent $ \a -> joinConnection a directConnReq $ directMessage msg
|
||||
groupConnId <- withAgent $ \a -> joinConnection a True groupConnReq $ directMessage msg
|
||||
directConnId <- withAgent $ \a -> joinConnection a True directConnReq $ directMessage msg
|
||||
customUserProfileId <- if memberIncognito membership then Just <$> withStore (\db -> getGroupMemberProfileId db userId membership) else pure Nothing
|
||||
withStore' $ \db -> createIntroToMemberContact db userId m toMember groupConnId directConnId customUserProfileId
|
||||
|
||||
@@ -2579,6 +2597,7 @@ chatCommandP =
|
||||
"/_network " *> (APISetNetworkConfig <$> jsonP),
|
||||
("/network " <|> "/net ") *> (APISetNetworkConfig <$> netCfgP),
|
||||
("/network" <|> "/net") $> APIGetNetworkConfig,
|
||||
"/_settings" *> (APISetChatSettings <$> chatRefP <* A.space <*> jsonP),
|
||||
"/_info #" *> (APIGroupMemberInfo <$> A.decimal <* A.space <*> A.decimal),
|
||||
"/_info @" *> (APIContactInfo <$> A.decimal),
|
||||
("/info #" <|> "/i #") *> (GroupMemberInfo <$> displayName <* A.space <* optional (A.char '@') <*> displayName),
|
||||
|
||||
@@ -150,6 +150,7 @@ data ChatCommand
|
||||
| SetUserSMPServers [SMPServer]
|
||||
| APISetNetworkConfig NetworkConfig
|
||||
| APIGetNetworkConfig
|
||||
| APISetChatSettings ChatRef ChatSettings
|
||||
| APIContactInfo ContactId
|
||||
| APIGroupMemberInfo GroupId GroupMemberId
|
||||
| ContactInfo ContactName
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
|
||||
module Simplex.Chat.Migrations.M20220818_chat_notifications where
|
||||
|
||||
import Database.SQLite.Simple (Query)
|
||||
import Database.SQLite.Simple.QQ (sql)
|
||||
|
||||
m20220818_chat_notifications :: Query
|
||||
m20220818_chat_notifications =
|
||||
[sql|
|
||||
ALTER TABLE contacts ADD COLUMN enable_ntfs INTEGER;
|
||||
|
||||
ALTER TABLE groups ADD COLUMN enable_ntfs INTEGER;
|
||||
|]
|
||||
@@ -54,6 +54,7 @@ is_user INTEGER NOT NULL DEFAULT 0, -- 1 if this contact is a user
|
||||
created_at TEXT NOT NULL DEFAULT(datetime('now')),
|
||||
updated_at TEXT CHECK(updated_at NOT NULL),
|
||||
xcontact_id BLOB,
|
||||
enable_ntfs INTEGER,
|
||||
FOREIGN KEY(user_id, local_display_name)
|
||||
REFERENCES display_names(user_id, local_display_name)
|
||||
ON DELETE CASCADE
|
||||
@@ -119,7 +120,8 @@ CREATE TABLE groups(
|
||||
inv_queue_info BLOB,
|
||||
created_at TEXT CHECK(created_at NOT NULL),
|
||||
updated_at TEXT CHECK(updated_at NOT NULL),
|
||||
chat_item_id INTEGER DEFAULT NULL REFERENCES chat_items ON DELETE SET NULL, -- received
|
||||
chat_item_id INTEGER DEFAULT NULL REFERENCES chat_items ON DELETE SET NULL,
|
||||
enable_ntfs INTEGER, -- received
|
||||
FOREIGN KEY(user_id, local_display_name)
|
||||
REFERENCES display_names(user_id, local_display_name)
|
||||
ON DELETE CASCADE
|
||||
|
||||
+56
-37
@@ -176,6 +176,8 @@ module Simplex.Chat.Store
|
||||
getCalls,
|
||||
getPendingContactConnection,
|
||||
deletePendingContactConnection,
|
||||
updateContactSettings,
|
||||
updateGroupSettings,
|
||||
withTransaction,
|
||||
)
|
||||
where
|
||||
@@ -227,6 +229,7 @@ import Simplex.Chat.Migrations.M20220702_calls
|
||||
import Simplex.Chat.Migrations.M20220715_groups_chat_item_id
|
||||
import Simplex.Chat.Migrations.M20220811_chat_items_indices
|
||||
import Simplex.Chat.Migrations.M20220812_incognito_profiles
|
||||
import Simplex.Chat.Migrations.M20220818_chat_notifications
|
||||
import Simplex.Chat.Protocol
|
||||
import Simplex.Chat.Types
|
||||
import Simplex.Messaging.Agent.Protocol (AgentMsgId, ConnId, InvitationId, MsgMeta (..))
|
||||
@@ -257,7 +260,8 @@ schemaMigrations =
|
||||
("20220702_calls", m20220702_calls),
|
||||
("20220715_groups_chat_item_id", m20220715_groups_chat_item_id),
|
||||
("20220811_chat_items_indices", m20220811_chat_items_indices),
|
||||
("20220812_incognito_profiles", m20220812_incognito_profiles)
|
||||
("20220812_incognito_profiles", m20220812_incognito_profiles),
|
||||
("20220818_chat_notifications", m20220818_chat_notifications)
|
||||
]
|
||||
|
||||
-- | The list of migrations in ascending order by date
|
||||
@@ -362,7 +366,7 @@ getConnReqContactXContactId db userId cReqHash = do
|
||||
[sql|
|
||||
SELECT
|
||||
-- Contact
|
||||
ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, ct.created_at, ct.updated_at,
|
||||
ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, ct.enable_ntfs, ct.created_at, ct.updated_at,
|
||||
-- Connection
|
||||
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.custom_user_profile_id, c.conn_status, c.conn_type,
|
||||
c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, c.created_at
|
||||
@@ -445,7 +449,7 @@ createDirectContact :: DB.Connection -> UserId -> Connection -> Profile -> Excep
|
||||
createDirectContact db userId activeConn@Connection {connId} profile = do
|
||||
createdAt <- liftIO getCurrentTime
|
||||
(localDisplayName, contactId, profileId) <- createContact_ db userId connId profile Nothing createdAt
|
||||
pure $ Contact {contactId, localDisplayName, profile = toLocalProfile profileId profile, activeConn, viaGroup = Nothing, createdAt, updatedAt = createdAt}
|
||||
pure $ Contact {contactId, localDisplayName, profile = toLocalProfile profileId profile, activeConn, viaGroup = Nothing, chatSettings = defaultChatSettings, createdAt, updatedAt = createdAt}
|
||||
|
||||
createContact_ :: DB.Connection -> UserId -> Int64 -> Profile -> Maybe Int64 -> UTCTime -> ExceptT StoreError IO (Text, ContactId, ProfileId)
|
||||
createContact_ db userId connId Profile {displayName, fullName, image} viaGroup currentTs =
|
||||
@@ -566,20 +570,22 @@ updateContact_ db userId contactId displayName newName updatedAt = do
|
||||
(newName, updatedAt, userId, contactId)
|
||||
DB.execute db "DELETE FROM display_names WHERE local_display_name = ? AND user_id = ?" (displayName, userId)
|
||||
|
||||
type ContactRow = (ContactId, ProfileId, ContactName, Maybe Int64, ContactName, Text, Maybe ImageData, UTCTime, UTCTime)
|
||||
type ContactRow = (ContactId, ProfileId, ContactName, Maybe Int64, ContactName, Text, Maybe ImageData, Maybe Bool, UTCTime, UTCTime)
|
||||
|
||||
toContact :: ContactRow :. ConnectionRow -> Contact
|
||||
toContact ((contactId, profileId, localDisplayName, viaGroup, displayName, fullName, image, createdAt, updatedAt) :. connRow) =
|
||||
toContact ((contactId, profileId, localDisplayName, viaGroup, displayName, fullName, image, enableNtfs_, createdAt, updatedAt) :. connRow) =
|
||||
let profile = LocalProfile {profileId, displayName, fullName, image}
|
||||
activeConn = toConnection connRow
|
||||
in Contact {contactId, localDisplayName, profile, activeConn, viaGroup, createdAt, updatedAt}
|
||||
chatSettings = ChatSettings {enableNtfs = fromMaybe True enableNtfs_}
|
||||
in Contact {contactId, localDisplayName, profile, activeConn, viaGroup, chatSettings, createdAt, updatedAt}
|
||||
|
||||
toContactOrError :: ContactRow :. MaybeConnectionRow -> Either StoreError Contact
|
||||
toContactOrError ((contactId, profileId, localDisplayName, viaGroup, displayName, fullName, image, createdAt, updatedAt) :. connRow) =
|
||||
toContactOrError ((contactId, profileId, localDisplayName, viaGroup, displayName, fullName, image, enableNtfs_, createdAt, updatedAt) :. connRow) =
|
||||
let profile = LocalProfile {profileId, displayName, fullName, image}
|
||||
chatSettings = ChatSettings {enableNtfs = fromMaybe True enableNtfs_}
|
||||
in case toMaybeConnection connRow of
|
||||
Just activeConn ->
|
||||
Right Contact {contactId, localDisplayName, profile, activeConn, viaGroup, createdAt, updatedAt}
|
||||
Right Contact {contactId, localDisplayName, profile, activeConn, viaGroup, chatSettings, createdAt, updatedAt}
|
||||
_ -> Left $ SEContactNotReady localDisplayName
|
||||
|
||||
-- TODO return the last connection that is ready, not any last connection
|
||||
@@ -759,7 +765,7 @@ createOrUpdateContactRequest db userId userContactLinkId invId Profile {displayN
|
||||
[sql|
|
||||
SELECT
|
||||
-- Contact
|
||||
ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, ct.created_at, ct.updated_at,
|
||||
ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, ct.enable_ntfs, ct.created_at, ct.updated_at,
|
||||
-- Connection
|
||||
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.custom_user_profile_id, c.conn_status, c.conn_type,
|
||||
c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, c.created_at
|
||||
@@ -878,11 +884,11 @@ createAcceptedContact db userId agentConnId localDisplayName profileId profile u
|
||||
customUserProfileId <- createIncognitoProfile_ db userId createdAt incognitoProfile
|
||||
DB.execute
|
||||
db
|
||||
"INSERT INTO contacts (user_id, local_display_name, contact_profile_id, created_at, updated_at, xcontact_id) VALUES (?,?,?,?,?,?)"
|
||||
(userId, localDisplayName, profileId, createdAt, createdAt, xContactId)
|
||||
"INSERT INTO contacts (user_id, local_display_name, contact_profile_id, enable_ntfs, created_at, updated_at, xcontact_id) VALUES (?,?,?,?,?,?,?)"
|
||||
(userId, localDisplayName, profileId, True, createdAt, createdAt, xContactId)
|
||||
contactId <- insertedRowId db
|
||||
activeConn <- createConnection_ db userId ConnContact (Just contactId) agentConnId Nothing (Just userContactLinkId) customUserProfileId 0 createdAt
|
||||
pure $ Contact {contactId, localDisplayName, profile = toLocalProfile profileId profile, activeConn, viaGroup = Nothing, createdAt = createdAt, updatedAt = createdAt}
|
||||
pure $ Contact {contactId, localDisplayName, profile = toLocalProfile profileId profile, activeConn, viaGroup = Nothing, chatSettings = defaultChatSettings, createdAt = createdAt, updatedAt = createdAt}
|
||||
|
||||
getLiveSndFileTransfers :: DB.Connection -> User -> IO [SndFileTransfer]
|
||||
getLiveSndFileTransfers db User {userId} = do
|
||||
@@ -1153,16 +1159,17 @@ getConnectionEntity db user@User {userId, userContactId} agentConnId = do
|
||||
<$> DB.query
|
||||
db
|
||||
[sql|
|
||||
SELECT c.contact_profile_id, c.local_display_name, p.display_name, p.full_name, p.image, c.via_group, c.created_at, c.updated_at
|
||||
SELECT c.contact_profile_id, c.local_display_name, p.display_name, p.full_name, p.image, c.via_group, c.enable_ntfs, c.created_at, c.updated_at
|
||||
FROM contacts c
|
||||
JOIN contact_profiles p ON c.contact_profile_id = p.contact_profile_id
|
||||
WHERE c.user_id = ? AND c.contact_id = ?
|
||||
|]
|
||||
(userId, contactId)
|
||||
toContact' :: Int64 -> Connection -> [(ProfileId, ContactName, Text, Text, Maybe ImageData, Maybe Int64, UTCTime, UTCTime)] -> Either StoreError Contact
|
||||
toContact' contactId activeConn [(profileId, localDisplayName, displayName, fullName, image, viaGroup, createdAt, updatedAt)] =
|
||||
toContact' :: Int64 -> Connection -> [(ProfileId, ContactName, Text, Text, Maybe ImageData, Maybe Int64, Maybe Bool, UTCTime, UTCTime)] -> Either StoreError Contact
|
||||
toContact' contactId activeConn [(profileId, localDisplayName, displayName, fullName, image, viaGroup, enableNtfs_, createdAt, updatedAt)] =
|
||||
let profile = LocalProfile {profileId, displayName, fullName, image}
|
||||
in Right $ Contact {contactId, localDisplayName, profile, activeConn, viaGroup, createdAt, updatedAt}
|
||||
chatSettings = ChatSettings {enableNtfs = fromMaybe True enableNtfs_}
|
||||
in Right $ Contact {contactId, localDisplayName, profile, activeConn, viaGroup, chatSettings, createdAt, updatedAt}
|
||||
toContact' _ _ _ = Left $ SEInternalError "referenced contact not found"
|
||||
getGroupAndMember_ :: Int64 -> Connection -> ExceptT StoreError IO (GroupInfo, GroupMember)
|
||||
getGroupAndMember_ groupMemberId c = ExceptT $ do
|
||||
@@ -1172,7 +1179,7 @@ getConnectionEntity db user@User {userId, userContactId} agentConnId = do
|
||||
[sql|
|
||||
SELECT
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.image, g.created_at, g.updated_at,
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.image, g.enable_ntfs, g.created_at, g.updated_at,
|
||||
-- GroupInfo {membership}
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.member_role, mu.member_category,
|
||||
mu.member_status, mu.invited_by, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
|
||||
@@ -1260,7 +1267,7 @@ getGroupAndMember db User {userId, userContactId} groupMemberId =
|
||||
[sql|
|
||||
SELECT
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.image, g.created_at, g.updated_at,
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.image, g.enable_ntfs, g.created_at, g.updated_at,
|
||||
-- GroupInfo {membership}
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.member_role, mu.member_category,
|
||||
mu.member_status, mu.invited_by, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
|
||||
@@ -1311,13 +1318,14 @@ createNewGroup db gVar user@User {userId} groupProfile incognitoProfile = Except
|
||||
profileId <- insertedRowId db
|
||||
DB.execute
|
||||
db
|
||||
"INSERT INTO groups (local_display_name, user_id, group_profile_id, created_at, updated_at) VALUES (?,?,?,?,?)"
|
||||
(ldn, userId, profileId, currentTs, currentTs)
|
||||
"INSERT INTO groups (local_display_name, user_id, group_profile_id, enable_ntfs, created_at, updated_at) VALUES (?,?,?,?,?,?)"
|
||||
(ldn, userId, profileId, True, currentTs, currentTs)
|
||||
insertedRowId db
|
||||
memberId <- liftIO $ encodedRandomBytes gVar 12
|
||||
-- TODO ldn from incognito profile
|
||||
membership <- createContactMemberInv_ db user groupId user (MemberIdRole (MemberId memberId) GROwner) GCUserMember GSMemCreator IBUser incognitoProfile currentTs
|
||||
pure GroupInfo {groupId, localDisplayName = ldn, groupProfile, membership, createdAt = currentTs, updatedAt = currentTs}
|
||||
let chatSettings = ChatSettings {enableNtfs = True}
|
||||
pure GroupInfo {groupId, localDisplayName = ldn, groupProfile, membership, chatSettings, createdAt = currentTs, updatedAt = currentTs}
|
||||
|
||||
-- | creates a new group record for the group the current user was invited to, or returns an existing one
|
||||
createGroupInvitation :: DB.Connection -> User -> Contact -> GroupInvitation -> Maybe Profile -> ExceptT StoreError IO GroupInfo
|
||||
@@ -1345,12 +1353,13 @@ createGroupInvitation db user@User {userId} contact@Contact {contactId} GroupInv
|
||||
profileId <- insertedRowId db
|
||||
DB.execute
|
||||
db
|
||||
"INSERT INTO groups (group_profile_id, local_display_name, inv_queue_info, user_id, created_at, updated_at) VALUES (?,?,?,?,?,?)"
|
||||
(profileId, localDisplayName, connRequest, userId, currentTs, currentTs)
|
||||
"INSERT INTO groups (group_profile_id, local_display_name, inv_queue_info, user_id, enable_ntfs, created_at, updated_at) VALUES (?,?,?,?,?,?,?)"
|
||||
(profileId, localDisplayName, connRequest, userId, True, currentTs, currentTs)
|
||||
insertedRowId db
|
||||
_ <- createContactMemberInv_ db user groupId contact fromMember GCHostMember GSMemInvited IBUnknown fromMemberProfile currentTs
|
||||
membership <- createContactMemberInv_ db user groupId user invitedMember GCUserMember GSMemInvited (IBContact contactId) incognitoProfile currentTs
|
||||
pure GroupInfo {groupId, localDisplayName, groupProfile, membership, createdAt = currentTs, updatedAt = currentTs}
|
||||
let chatSettings = ChatSettings {enableNtfs = True}
|
||||
pure GroupInfo {groupId, localDisplayName, groupProfile, membership, chatSettings, createdAt = currentTs, updatedAt = currentTs}
|
||||
|
||||
createContactMemberInv_ :: IsContact a => DB.Connection -> User -> GroupId -> a -> MemberIdRole -> GroupMemberCategory -> GroupMemberStatus -> InvitedBy -> Maybe Profile -> UTCTime -> ExceptT StoreError IO GroupMember
|
||||
createContactMemberInv_ db User {userId, userContactId} groupId userOrContact MemberIdRole {memberId, memberRole} memberCategory memberStatus invitedBy incognitoProfile createdAt = do
|
||||
@@ -1461,7 +1470,7 @@ getUserGroupDetails db User {userId, userContactId} =
|
||||
<$> DB.query
|
||||
db
|
||||
[sql|
|
||||
SELECT g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.image, g.created_at, g.updated_at,
|
||||
SELECT g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.image, g.enable_ntfs, g.created_at, g.updated_at,
|
||||
m.group_member_id, g.group_id, m.member_id, m.member_role, m.member_category, m.member_status,
|
||||
m.invited_by, m.local_display_name, m.contact_id, m.contact_profile_id, mp.contact_profile_id, mp.display_name, mp.full_name, mp.image
|
||||
FROM groups g
|
||||
@@ -1477,12 +1486,13 @@ getGroupInfoByName db user gName = do
|
||||
gId <- getGroupIdByName db user gName
|
||||
getGroupInfo db user gId
|
||||
|
||||
type GroupInfoRow = (Int64, GroupName, GroupName, Text, Maybe ImageData, UTCTime, UTCTime) :. GroupMemberRow
|
||||
type GroupInfoRow = (Int64, GroupName, GroupName, Text, Maybe ImageData, Maybe Bool, UTCTime, UTCTime) :. GroupMemberRow
|
||||
|
||||
toGroupInfo :: Int64 -> GroupInfoRow -> GroupInfo
|
||||
toGroupInfo userContactId ((groupId, localDisplayName, displayName, fullName, image, createdAt, updatedAt) :. userMemberRow) =
|
||||
toGroupInfo userContactId ((groupId, localDisplayName, displayName, fullName, image, enableNtfs_, createdAt, updatedAt) :. userMemberRow) =
|
||||
let membership = toGroupMember userContactId userMemberRow
|
||||
in GroupInfo {groupId, localDisplayName, groupProfile = GroupProfile {displayName, fullName, image}, membership, createdAt, updatedAt}
|
||||
chatSettings = ChatSettings {enableNtfs = fromMaybe True enableNtfs_}
|
||||
in GroupInfo {groupId, localDisplayName, groupProfile = GroupProfile {displayName, fullName, image}, membership, chatSettings, createdAt, updatedAt}
|
||||
|
||||
getGroupMember :: DB.Connection -> User -> GroupId -> GroupMemberId -> ExceptT StoreError IO GroupMember
|
||||
getGroupMember db user@User {userId} groupId groupMemberId =
|
||||
@@ -1882,7 +1892,7 @@ getViaGroupMember db User {userId, userContactId} Contact {contactId} =
|
||||
[sql|
|
||||
SELECT
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.image, g.created_at, g.updated_at,
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.image, g.enable_ntfs, g.created_at, g.updated_at,
|
||||
-- GroupInfo {membership}
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.member_role, mu.member_category,
|
||||
mu.member_status, mu.invited_by, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
|
||||
@@ -1922,7 +1932,7 @@ getViaGroupContact db User {userId} GroupMember {groupMemberId} =
|
||||
db
|
||||
[sql|
|
||||
SELECT
|
||||
ct.contact_id, ct.contact_profile_id, ct.local_display_name, p.display_name, p.full_name, p.image, ct.via_group, ct.created_at, ct.updated_at,
|
||||
ct.contact_id, ct.contact_profile_id, ct.local_display_name, p.display_name, p.full_name, p.image, ct.via_group, ct.enable_ntfs, ct.created_at, ct.updated_at,
|
||||
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.custom_user_profile_id,
|
||||
c.conn_status, c.conn_type, c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, c.created_at
|
||||
FROM contacts ct
|
||||
@@ -1938,11 +1948,12 @@ getViaGroupContact db User {userId} GroupMember {groupMemberId} =
|
||||
|]
|
||||
(userId, groupMemberId)
|
||||
where
|
||||
toContact' :: (ContactId, ProfileId, ContactName, Text, Text, Maybe ImageData, Maybe Int64, UTCTime, UTCTime) :. ConnectionRow -> Contact
|
||||
toContact' ((contactId, profileId, localDisplayName, displayName, fullName, image, viaGroup, createdAt, updatedAt) :. connRow) =
|
||||
toContact' :: (ContactId, ProfileId, ContactName, Text, Text, Maybe ImageData, Maybe Int64, Maybe Bool, UTCTime, UTCTime) :. ConnectionRow -> Contact
|
||||
toContact' ((contactId, profileId, localDisplayName, displayName, fullName, image, viaGroup, enableNtfs_, createdAt, updatedAt) :. connRow) =
|
||||
let profile = LocalProfile {profileId, displayName, fullName, image}
|
||||
chatSettings = ChatSettings {enableNtfs = fromMaybe True enableNtfs_}
|
||||
activeConn = toConnection connRow
|
||||
in Contact {contactId, localDisplayName, profile, activeConn, viaGroup, createdAt, updatedAt}
|
||||
in Contact {contactId, localDisplayName, profile, activeConn, viaGroup, chatSettings, createdAt, updatedAt}
|
||||
|
||||
createSndFileTransfer :: DB.Connection -> UserId -> Contact -> FilePath -> FileInvitation -> ConnId -> Integer -> IO Int64
|
||||
createSndFileTransfer db userId Contact {contactId} filePath FileInvitation {fileName, fileSize} acId chunkSize = do
|
||||
@@ -2680,7 +2691,7 @@ getDirectChatPreviews_ db User {userId} = do
|
||||
[sql|
|
||||
SELECT
|
||||
-- Contact
|
||||
ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, ct.created_at, ct.updated_at,
|
||||
ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, ct.enable_ntfs, ct.created_at, ct.updated_at,
|
||||
-- Connection
|
||||
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.custom_user_profile_id, c.conn_status, c.conn_type,
|
||||
c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, c.created_at,
|
||||
@@ -2745,7 +2756,7 @@ getGroupChatPreviews_ db User {userId, userContactId} = do
|
||||
[sql|
|
||||
SELECT
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.image, g.created_at, g.updated_at,
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.image, g.enable_ntfs, g.created_at, g.updated_at,
|
||||
-- GroupMember - membership
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.member_role, mu.member_category,
|
||||
mu.member_status, mu.invited_by, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
|
||||
@@ -2875,6 +2886,14 @@ deletePendingContactConnection db userId connId =
|
||||
|]
|
||||
(userId, connId, ConnContact)
|
||||
|
||||
updateContactSettings :: DB.Connection -> User -> Int64 -> ChatSettings -> IO ()
|
||||
updateContactSettings db User {userId} contactId ChatSettings {enableNtfs} =
|
||||
DB.execute db "UPDATE contacts SET enable_ntfs = ? WHERE user_id = ? AND contact_id = ?" (enableNtfs, userId, contactId)
|
||||
|
||||
updateGroupSettings :: DB.Connection -> User -> Int64 -> ChatSettings -> IO ()
|
||||
updateGroupSettings db User {userId} groupId ChatSettings {enableNtfs} =
|
||||
DB.execute db "UPDATE groups SET enable_ntfs = ? WHERE user_id = ? AND group_id = ?" (enableNtfs, userId, groupId)
|
||||
|
||||
toPendingContactConnection :: (Int64, ConnId, ConnStatus, Maybe ByteString, Maybe Int64, Maybe Int64, UTCTime, UTCTime) -> PendingContactConnection
|
||||
toPendingContactConnection (pccConnId, acId, pccConnStatus, connReqHash, viaUserContactLink, customUserProfileId, createdAt, updatedAt) =
|
||||
PendingContactConnection {pccConnId, pccAgentConnId = AgentConnId acId, pccConnStatus, viaContactUri = isJust connReqHash, viaUserContactLink, customUserProfileId, createdAt, updatedAt}
|
||||
@@ -3012,7 +3031,7 @@ getContact db userId contactId =
|
||||
[sql|
|
||||
SELECT
|
||||
-- Contact
|
||||
ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, ct.created_at, ct.updated_at,
|
||||
ct.contact_id, ct.contact_profile_id, ct.local_display_name, ct.via_group, cp.display_name, cp.full_name, cp.image, ct.enable_ntfs, ct.created_at, ct.updated_at,
|
||||
-- Connection
|
||||
c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.custom_user_profile_id, c.conn_status, c.conn_type,
|
||||
c.contact_id, c.group_member_id, c.snd_file_id, c.rcv_file_id, c.user_contact_link_id, c.created_at
|
||||
@@ -3137,7 +3156,7 @@ getGroupInfo db User {userId, userContactId} groupId =
|
||||
[sql|
|
||||
SELECT
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.image, g.created_at, g.updated_at,
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.image, g.enable_ntfs, g.created_at, g.updated_at,
|
||||
-- GroupMember - membership
|
||||
mu.group_member_id, mu.group_id, mu.member_id, mu.member_role, mu.member_category,
|
||||
mu.member_status, mu.invited_by, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id,
|
||||
|
||||
@@ -76,6 +76,7 @@ data Contact = Contact
|
||||
profile :: LocalProfile,
|
||||
activeConn :: Connection,
|
||||
viaGroup :: Maybe Int64,
|
||||
chatSettings :: ChatSettings,
|
||||
createdAt :: UTCTime,
|
||||
updatedAt :: UTCTime
|
||||
}
|
||||
@@ -190,6 +191,7 @@ data GroupInfo = GroupInfo
|
||||
localDisplayName :: GroupName,
|
||||
groupProfile :: GroupProfile,
|
||||
membership :: GroupMember,
|
||||
chatSettings :: ChatSettings,
|
||||
createdAt :: UTCTime,
|
||||
updatedAt :: UTCTime
|
||||
}
|
||||
@@ -200,6 +202,17 @@ instance ToJSON GroupInfo where toEncoding = J.genericToEncoding J.defaultOption
|
||||
groupName' :: GroupInfo -> GroupName
|
||||
groupName' GroupInfo {localDisplayName = g} = g
|
||||
|
||||
-- TODO when more settings are added we should create another type to allow partial setting updates (with all Maybe properties)
|
||||
data ChatSettings = ChatSettings
|
||||
{ enableNtfs :: Bool
|
||||
}
|
||||
deriving (Eq, Show, Generic, FromJSON)
|
||||
|
||||
instance ToJSON ChatSettings where toEncoding = J.genericToEncoding J.defaultOptions
|
||||
|
||||
defaultChatSettings :: ChatSettings
|
||||
defaultChatSettings = ChatSettings {enableNtfs = True}
|
||||
|
||||
data Profile = Profile
|
||||
{ displayName :: ContactName,
|
||||
fullName :: Text,
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ extra-deps:
|
||||
# - simplexmq-1.0.0@sha256:34b2004728ae396e3ae449cd090ba7410781e2b3cefc59259915f4ca5daa9ea8,8561
|
||||
# - ../simplexmq
|
||||
- github: simplex-chat/simplexmq
|
||||
commit: 3fc9afbb351033413dd84344ec603910e370a8ec
|
||||
commit: a33539bef9d31f5acbf9a21bfa0ef39a2dd421dd
|
||||
# - terminal-0.2.0.0@sha256:de6770ecaae3197c66ac1f0db5a80cf5a5b1d3b64a66a05b50f442de5ad39570,2977
|
||||
- github: simplex-chat/aeson
|
||||
commit: 3eb66f9a68f103b5f1489382aad89f5712a64db7
|
||||
|
||||
Reference in New Issue
Block a user