mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-10-22 21:52:28 +00:00
types and migration
This commit is contained in:
1 parent
e6ad21801f
commit
bf8dc4b3c5
12 files changed
+436
-122
No files matched your search
@@ -120,6 +120,7 @@ defaultChatConfig =
|
||||
highlyAvailable = False,
|
||||
deliveryWorkerDelay = 0,
|
||||
deliveryBucketSize = 10000,
|
||||
feedBucketSize = 1000,
|
||||
webPreviewConfig = Nothing,
|
||||
channelSubscriberRole = GRObserver,
|
||||
relayChecksInterval = 15 * 60, -- 15 minutes
|
||||
|
||||
@@ -165,6 +165,7 @@ data ChatConfig = ChatConfig
|
||||
ciExpirationInterval :: Int64, -- microseconds
|
||||
deliveryWorkerDelay :: Int64, -- microseconds
|
||||
deliveryBucketSize :: Int,
|
||||
feedBucketSize :: Int,
|
||||
webPreviewConfig :: Maybe WebPreviewConfig,
|
||||
channelSubscriberRole :: GroupMemberRole, -- TODO [relays] starting role should be communicated in protocol from owner to relays
|
||||
relayChecksInterval :: NominalDiffTime,
|
||||
@@ -392,6 +393,7 @@ data ChatCommand
|
||||
| APIUpdateChatTag ChatTagId ChatTagData
|
||||
| APIReorderChatTags (NonEmpty ChatTagId)
|
||||
| APICreateChatItems {noteFolderId :: NoteFolderId, composedMessages :: NonEmpty ComposedMessage}
|
||||
| APISendFeedMessage {feedId :: FeedId, composedMessage :: ComposedMessage}
|
||||
| APIReportMessage {groupId :: GroupId, chatItemId :: ChatItemId, reportReason :: ReportReason, reportText :: Text}
|
||||
| ReportMessage {groupName :: GroupName, contactName_ :: Maybe ContactName, reportReason :: ReportReason, reportedMessage :: Text}
|
||||
| APIUpdateChatItem {chatRef :: ChatRef, chatItemId :: ChatItemId, liveMessage :: Bool, updatedMessage :: UpdatedMessage}
|
||||
@@ -514,6 +516,7 @@ data ChatCommand
|
||||
| APIEnableGroupMember GroupId GroupMemberId
|
||||
| SetShowMessages ChatName MsgFilter
|
||||
| SetSendReceipts ChatName (Maybe Bool)
|
||||
| SetDropFeed ChatName Bool
|
||||
| SetShowMemberMessages GroupName ContactName Bool
|
||||
| ContactInfo ContactName
|
||||
| ShowGroupInfo GroupName
|
||||
|
||||
@@ -10,7 +10,8 @@ import Data.ByteString.Char8 (ByteString)
|
||||
import Data.Int (Int64)
|
||||
import Data.Maybe (fromMaybe)
|
||||
import Data.Time.Clock (UTCTime)
|
||||
import Simplex.Chat.Messages (GroupChatScopeInfo (..), MessageId, ShowGroupAsSender)
|
||||
import Simplex.Chat.Messages (ChatItemId, GroupChatScopeInfo (..), MessageId, ShowGroupAsSender)
|
||||
import Simplex.Chat.Messages.CIContent (CIDeleteMode (..))
|
||||
import Simplex.Chat.Options.DB (FromField (..), ToField (..))
|
||||
import Simplex.Chat.Protocol
|
||||
import Simplex.Chat.Types
|
||||
@@ -18,11 +19,15 @@ import Simplex.Chat.Types.Shared
|
||||
import Simplex.Messaging.Agent.Store.DB (fromTextField_)
|
||||
import Simplex.Messaging.Encoding.String
|
||||
|
||||
type DeliveryWorkerKey = (GroupId, DeliveryWorkerScope)
|
||||
data DeliveryEntity = DEGroup GroupId | DEFeed FeedId
|
||||
deriving (Eq, Ord, Show)
|
||||
|
||||
type DeliveryWorkerKey = (DeliveryEntity, DeliveryWorkerScope)
|
||||
|
||||
data DeliveryWorkerScope
|
||||
= DWSGroup
|
||||
| DWSMemberSupport
|
||||
| DWSFeed
|
||||
-- | DWSMemberProfileUpdate
|
||||
deriving (Eq, Ord, Show)
|
||||
|
||||
@@ -34,11 +39,13 @@ instance TextEncoding DeliveryWorkerScope where
|
||||
textDecode = \case
|
||||
"group" -> Just DWSGroup
|
||||
"member_support" -> Just DWSMemberSupport
|
||||
"feed" -> Just DWSFeed
|
||||
-- "member_profile_update" -> Just DWSMemberProfileUpdate
|
||||
_ -> Nothing
|
||||
textEncode = \case
|
||||
DWSGroup -> "group"
|
||||
DWSMemberSupport -> "member_support"
|
||||
DWSFeed -> "feed"
|
||||
-- DWSMemberProfileUpdate -> "member_profile_update"
|
||||
|
||||
-- Context for creating a delivery task. Separate from DeliveryJobScope because
|
||||
@@ -54,17 +61,30 @@ data DeliveryTaskContext = DeliveryTaskContext
|
||||
data DeliveryJobScope
|
||||
= DJSGroup {jobSpec :: DeliveryJobSpec}
|
||||
| DJSMemberSupport {supportGMId :: GroupMemberId}
|
||||
| DJSFeed {feedItemId :: ChatItemId, feedJobSpec :: FeedJobSpec}
|
||||
-- | DJSMemberProfileUpdate
|
||||
deriving (Show)
|
||||
|
||||
data DeliveryJobSpec
|
||||
= DJDeliveryJob {includePending :: Bool}
|
||||
| DJRelayRemoved
|
||||
| DJFeed FeedJobSpec
|
||||
deriving (Show)
|
||||
|
||||
data FeedJobSpec
|
||||
= FJNew
|
||||
| FJFileDescr
|
||||
| FJUpdate
|
||||
| FJDelete CIDeleteMode
|
||||
deriving (Show)
|
||||
|
||||
data DeliveryJobSpecTag
|
||||
= DJSTDeliveryJob
|
||||
| DJSTRelayRemoved
|
||||
| DJSTFeedNew
|
||||
| DJSTFeedFileDescr
|
||||
| DJSTFeedUpdate
|
||||
| DJSTFeedDelete
|
||||
deriving (Show)
|
||||
|
||||
instance FromField DeliveryJobSpecTag where fromField = fromTextField_ textDecode
|
||||
@@ -75,15 +95,24 @@ instance TextEncoding DeliveryJobSpecTag where
|
||||
textDecode = \case
|
||||
"delivery_job" -> Just DJSTDeliveryJob
|
||||
"relay_removed" -> Just DJSTRelayRemoved
|
||||
"feed_new" -> Just DJSTFeedNew
|
||||
"feed_file_descr" -> Just DJSTFeedFileDescr
|
||||
"feed_update" -> Just DJSTFeedUpdate
|
||||
"feed_delete" -> Just DJSTFeedDelete
|
||||
_ -> Nothing
|
||||
textEncode = \case
|
||||
DJSTDeliveryJob -> "delivery_job"
|
||||
DJSTRelayRemoved -> "relay_removed"
|
||||
DJSTFeedNew -> "feed_new"
|
||||
DJSTFeedFileDescr -> "feed_file_descr"
|
||||
DJSTFeedUpdate -> "feed_update"
|
||||
DJSTFeedDelete -> "feed_delete"
|
||||
|
||||
toWorkerScope :: DeliveryJobScope -> DeliveryWorkerScope
|
||||
toWorkerScope = \case
|
||||
DJSGroup _ -> DWSGroup
|
||||
DJSMemberSupport _ -> DWSMemberSupport
|
||||
DJSFeed {} -> DWSFeed
|
||||
-- DJSMemberProfileUpdate -> DWSMemberProfileUpdate
|
||||
|
||||
isRelayRemoved :: DeliveryJobScope -> Bool
|
||||
@@ -97,11 +126,13 @@ jobScopeImpliedSpec :: DeliveryJobScope -> DeliveryJobSpec
|
||||
jobScopeImpliedSpec = \case
|
||||
DJSGroup {jobSpec} -> jobSpec
|
||||
DJSMemberSupport {} -> DJDeliveryJob {includePending = False}
|
||||
DJSFeed {feedJobSpec} -> DJFeed feedJobSpec
|
||||
|
||||
jobSpecImpliedPending :: DeliveryJobSpec -> Bool
|
||||
jobSpecImpliedPending = \case
|
||||
DJDeliveryJob {includePending} -> includePending
|
||||
DJRelayRemoved -> True
|
||||
DJFeed _ -> False
|
||||
|
||||
infoToDeliveryContext :: GroupInfo -> Maybe GroupChatScopeInfo -> ShowGroupAsSender -> DeliveryTaskContext
|
||||
infoToDeliveryContext GroupInfo {membership} scopeInfo sentAsGroup = DeliveryTaskContext {jobScope, sentAsGroup}
|
||||
@@ -162,8 +193,11 @@ data MessageDeliveryJob = MessageDeliveryJob
|
||||
{ jobId :: Int64,
|
||||
jobScope :: DeliveryJobScope,
|
||||
senderGMIds :: [GroupMemberId],
|
||||
messageIds :: [MessageId],
|
||||
body :: ByteString,
|
||||
cursorGMId_ :: Maybe GroupMemberId
|
||||
cursorGMId_ :: Maybe GroupMemberId,
|
||||
cursorContactId_ :: Maybe ContactId,
|
||||
cursorGroupId_ :: Maybe GroupId
|
||||
}
|
||||
deriving (Show)
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ import Simplex.Messaging.Parsers (defaultJSON, dropPrefix, enumJSON, parseAll, s
|
||||
import Simplex.Messaging.Protocol (BlockingInfo, MsgBody, XFTPServer)
|
||||
import Simplex.Messaging.Util (eitherToMaybe, safeDecodeUtf8, (<$?>))
|
||||
|
||||
data ChatType = CTDirect | CTGroup | CTLocal | CTContactRequest | CTContactConnection
|
||||
data ChatType = CTDirect | CTGroup | CTLocal | CTFeed | CTContactRequest | CTContactConnection
|
||||
deriving (Eq, Show, Ord)
|
||||
|
||||
$(JQ.deriveJSON (enumJSON $ dropPrefix "CT") ''ChatType)
|
||||
@@ -67,6 +67,7 @@ data SChatType (c :: ChatType) where
|
||||
SCTDirect :: SChatType 'CTDirect
|
||||
SCTGroup :: SChatType 'CTGroup
|
||||
SCTLocal :: SChatType 'CTLocal
|
||||
SCTFeed :: SChatType 'CTFeed
|
||||
SCTContactRequest :: SChatType 'CTContactRequest
|
||||
SCTContactConnection :: SChatType 'CTContactConnection
|
||||
|
||||
@@ -76,6 +77,7 @@ instance TestEquality SChatType where
|
||||
testEquality SCTDirect SCTDirect = Just Refl
|
||||
testEquality SCTGroup SCTGroup = Just Refl
|
||||
testEquality SCTLocal SCTLocal = Just Refl
|
||||
testEquality SCTFeed SCTFeed = Just Refl
|
||||
testEquality SCTContactRequest SCTContactRequest = Just Refl
|
||||
testEquality SCTContactConnection SCTContactConnection = Just Refl
|
||||
testEquality _ _ = Nothing
|
||||
@@ -91,6 +93,8 @@ instance ChatTypeI 'CTGroup where chatTypeI = SCTGroup
|
||||
|
||||
instance ChatTypeI 'CTLocal where chatTypeI = SCTLocal
|
||||
|
||||
instance ChatTypeI 'CTFeed where chatTypeI = SCTFeed
|
||||
|
||||
instance ChatTypeI 'CTContactRequest where chatTypeI = SCTContactRequest
|
||||
|
||||
instance ChatTypeI 'CTContactConnection where chatTypeI = SCTContactConnection
|
||||
@@ -100,6 +104,7 @@ toChatType = \case
|
||||
SCTDirect -> CTDirect
|
||||
SCTGroup -> CTGroup
|
||||
SCTLocal -> CTLocal
|
||||
SCTFeed -> CTFeed
|
||||
SCTContactRequest -> CTContactRequest
|
||||
SCTContactConnection -> CTContactConnection
|
||||
|
||||
@@ -108,6 +113,7 @@ aChatType = \case
|
||||
CTDirect -> ACT SCTDirect
|
||||
CTGroup -> ACT SCTGroup
|
||||
CTLocal -> ACT SCTLocal
|
||||
CTFeed -> ACT SCTFeed
|
||||
CTContactRequest -> ACT SCTContactRequest
|
||||
CTContactConnection -> ACT SCTContactConnection
|
||||
|
||||
@@ -157,6 +163,7 @@ chatTypeStr = \case
|
||||
CTDirect -> "@"
|
||||
CTGroup -> "#"
|
||||
CTLocal -> "*"
|
||||
CTFeed -> "%"
|
||||
CTContactRequest -> "<@"
|
||||
CTContactConnection -> ":"
|
||||
|
||||
@@ -170,6 +177,7 @@ data ChatInfo (c :: ChatType) where
|
||||
DirectChat :: Contact -> ChatInfo 'CTDirect
|
||||
GroupChat :: GroupInfo -> Maybe GroupChatScopeInfo -> ChatInfo 'CTGroup
|
||||
LocalChat :: NoteFolder -> ChatInfo 'CTLocal
|
||||
FeedChat :: Feed -> ChatInfo 'CTFeed
|
||||
ContactRequest :: UserContactRequest -> ChatInfo 'CTContactRequest
|
||||
ContactConnection :: PendingContactConnection -> ChatInfo 'CTContactConnection
|
||||
CInfoInvalidJSON :: SChatType c -> J.Object -> ChatInfo c -- this constructor is needed to catch JSON errors for Remote connection parsing
|
||||
@@ -192,6 +200,7 @@ chatInfoToRef = \case
|
||||
DirectChat Contact {contactId} -> Just $ ChatRef CTDirect contactId Nothing
|
||||
GroupChat GroupInfo {groupId} scopeInfo -> Just $ ChatRef CTGroup groupId (toChatScope <$> scopeInfo)
|
||||
LocalChat NoteFolder {noteFolderId} -> Just $ ChatRef CTLocal noteFolderId Nothing
|
||||
FeedChat Feed {feedId} -> Just $ ChatRef CTFeed feedId Nothing
|
||||
ContactRequest UserContactRequest {contactRequestId} -> Just $ ChatRef CTContactRequest contactRequestId Nothing
|
||||
ContactConnection PendingContactConnection {pccConnId} -> Just $ ChatRef CTContactConnection pccConnId Nothing
|
||||
CInfoInvalidJSON {} -> Nothing
|
||||
@@ -205,6 +214,7 @@ data JSONChatInfo
|
||||
= JCInfoDirect {contact :: Contact}
|
||||
| JCInfoGroup {groupInfo :: GroupInfo, groupChatScope :: Maybe GroupChatScopeInfo}
|
||||
| JCInfoLocal {noteFolder :: NoteFolder}
|
||||
| JCInfoFeed {feed :: Feed}
|
||||
| JCInfoContactRequest {contactRequest :: UserContactRequest}
|
||||
| JCInfoContactConnection {contactConnection :: PendingContactConnection}
|
||||
| JCInfoInvalidJSON {chatType :: ChatType, json :: J.Object}
|
||||
@@ -231,6 +241,7 @@ jsonChatInfo = \case
|
||||
DirectChat c -> JCInfoDirect c
|
||||
GroupChat g s -> JCInfoGroup g s
|
||||
LocalChat l -> JCInfoLocal l
|
||||
FeedChat f -> JCInfoFeed f
|
||||
ContactRequest g -> JCInfoContactRequest g
|
||||
ContactConnection c -> JCInfoContactConnection c
|
||||
CInfoInvalidJSON c o -> JCInfoInvalidJSON (toChatType c) o
|
||||
@@ -244,6 +255,7 @@ jsonAChatInfo = \case
|
||||
JCInfoDirect c -> AChatInfo SCTDirect $ DirectChat c
|
||||
JCInfoGroup g s -> AChatInfo SCTGroup $ GroupChat g s
|
||||
JCInfoLocal l -> AChatInfo SCTLocal $ LocalChat l
|
||||
JCInfoFeed f -> AChatInfo SCTFeed $ FeedChat f
|
||||
JCInfoContactRequest g -> AChatInfo SCTContactRequest $ ContactRequest g
|
||||
JCInfoContactConnection c -> AChatInfo SCTContactConnection $ ContactConnection c
|
||||
JCInfoInvalidJSON cType o -> case aChatType cType of ACT c -> AChatInfo c $ CInfoInvalidJSON c o
|
||||
@@ -298,6 +310,7 @@ data CIDirection (c :: ChatType) (d :: MsgDirection) where
|
||||
CIChannelRcv :: CIDirection 'CTGroup 'MDRcv
|
||||
CILocalSnd :: CIDirection 'CTLocal 'MDSnd
|
||||
CILocalRcv :: CIDirection 'CTLocal 'MDRcv
|
||||
CIFeedSnd :: CIDirection 'CTFeed 'MDSnd
|
||||
|
||||
deriving instance Show (CIDirection c d)
|
||||
|
||||
@@ -313,6 +326,7 @@ data JSONCIDirection
|
||||
| JCIChannelRcv
|
||||
| JCILocalSnd
|
||||
| JCILocalRcv
|
||||
| JCIFeedSnd
|
||||
deriving (Show)
|
||||
|
||||
jsonCIDirection :: CIDirection c d -> JSONCIDirection
|
||||
@@ -324,6 +338,7 @@ jsonCIDirection = \case
|
||||
CIChannelRcv -> JCIChannelRcv
|
||||
CILocalSnd -> JCILocalSnd
|
||||
CILocalRcv -> JCILocalRcv
|
||||
CIFeedSnd -> JCIFeedSnd
|
||||
|
||||
jsonACIDirection :: JSONCIDirection -> ACIDirection
|
||||
jsonACIDirection = \case
|
||||
@@ -334,6 +349,7 @@ jsonACIDirection = \case
|
||||
JCIChannelRcv -> ACID SCTGroup SMDRcv CIChannelRcv
|
||||
JCILocalSnd -> ACID SCTLocal SMDSnd CILocalSnd
|
||||
JCILocalRcv -> ACID SCTLocal SMDRcv CILocalRcv
|
||||
JCIFeedSnd -> ACID SCTFeed SMDSnd CIFeedSnd
|
||||
|
||||
data CIReactionCount = CIReactionCount {reaction :: MsgReaction, userReacted :: Bool, totalReacted :: Int}
|
||||
deriving (Show)
|
||||
@@ -396,6 +412,7 @@ data ChatDirection (c :: ChatType) (d :: MsgDirection) where
|
||||
CDChannelRcv :: GroupInfo -> Maybe GroupChatScopeInfo -> ChatDirection 'CTGroup 'MDRcv
|
||||
CDLocalSnd :: NoteFolder -> ChatDirection 'CTLocal 'MDSnd
|
||||
CDLocalRcv :: NoteFolder -> ChatDirection 'CTLocal 'MDRcv
|
||||
CDFeedSnd :: Feed -> ChatDirection 'CTFeed 'MDSnd
|
||||
|
||||
toCIDirection :: ChatDirection c d -> CIDirection c d
|
||||
toCIDirection = \case
|
||||
@@ -406,6 +423,7 @@ toCIDirection = \case
|
||||
CDChannelRcv _ _ -> CIChannelRcv
|
||||
CDLocalSnd _ -> CILocalSnd
|
||||
CDLocalRcv _ -> CILocalRcv
|
||||
CDFeedSnd _ -> CIFeedSnd
|
||||
|
||||
toChatInfo :: ChatDirection c d -> ChatInfo c
|
||||
toChatInfo = \case
|
||||
@@ -416,6 +434,7 @@ toChatInfo = \case
|
||||
CDChannelRcv g s -> GroupChat g s
|
||||
CDLocalSnd l -> LocalChat l
|
||||
CDLocalRcv l -> LocalChat l
|
||||
CDFeedSnd f -> FeedChat f
|
||||
|
||||
signMessagesRequired :: ChatDirection c d -> Bool
|
||||
signMessagesRequired = \case
|
||||
@@ -525,6 +544,7 @@ data CIMeta (c :: ChatType) (d :: MsgDirection) = CIMeta
|
||||
forwardedByMember :: Maybe GroupMemberId,
|
||||
showGroupAsSender :: ShowGroupAsSender,
|
||||
msgVerified :: Maybe MsgVerified,
|
||||
itemFeed :: Maybe CIFeed,
|
||||
createdAt :: UTCTime,
|
||||
updatedAt :: UTCTime
|
||||
}
|
||||
@@ -532,12 +552,15 @@ data CIMeta (c :: ChatType) (d :: MsgDirection) = CIMeta
|
||||
|
||||
type ShowGroupAsSender = Bool
|
||||
|
||||
mkCIMeta :: forall c d. ChatTypeI c => ChatItemId -> CIContent d -> Text -> CIStatus d -> Maybe Bool -> Maybe SharedMsgId -> Maybe CIForwardedFrom -> Maybe (CIDeleted c) -> Bool -> Maybe CITimed -> Maybe Bool -> Bool -> Bool -> UTCTime -> ChatItemTs -> Maybe GroupMemberId -> Bool -> Maybe MsgVerified -> UTCTime -> UTCTime -> CIMeta c d
|
||||
mkCIMeta itemId itemContent itemText itemStatus sentViaProxy itemSharedMsgId itemForwarded itemDeleted itemEdited itemTimed itemLive userMention hasLink_ currentTs itemTs forwardedByMember showGroupAsSender msgVerified createdAt updatedAt =
|
||||
data CIFeed = CIFLinked | CIFDetached
|
||||
deriving (Eq, Show)
|
||||
|
||||
mkCIMeta :: forall c d. ChatTypeI c => ChatItemId -> CIContent d -> Text -> CIStatus d -> Maybe Bool -> Maybe SharedMsgId -> Maybe CIForwardedFrom -> Maybe (CIDeleted c) -> Bool -> Maybe CITimed -> Maybe Bool -> Bool -> Bool -> UTCTime -> ChatItemTs -> Maybe GroupMemberId -> Bool -> Maybe MsgVerified -> Maybe CIFeed -> UTCTime -> UTCTime -> CIMeta c d
|
||||
mkCIMeta itemId itemContent itemText itemStatus sentViaProxy itemSharedMsgId itemForwarded itemDeleted itemEdited itemTimed itemLive userMention hasLink_ currentTs itemTs forwardedByMember showGroupAsSender msgVerified itemFeed createdAt updatedAt =
|
||||
let deletable = deletable' itemContent itemDeleted itemTs nominalDay currentTs
|
||||
editable = deletable && isNothing itemForwarded
|
||||
hasLink = BoolDef hasLink_
|
||||
in CIMeta {itemId, itemTs, itemText, itemStatus, sentViaProxy, itemSharedMsgId, itemForwarded, itemDeleted, itemEdited, itemTimed, itemLive, userMention, hasLink, deletable, editable, forwardedByMember, showGroupAsSender, msgVerified, createdAt, updatedAt}
|
||||
in CIMeta {itemId, itemTs, itemText, itemStatus, sentViaProxy, itemSharedMsgId, itemForwarded, itemDeleted, itemEdited, itemTimed, itemLive, userMention, hasLink, deletable, editable, forwardedByMember, showGroupAsSender, msgVerified, itemFeed, createdAt, updatedAt}
|
||||
|
||||
deletable' :: forall c d. ChatTypeI c => CIContent d -> Maybe (CIDeleted c) -> UTCTime -> NominalDiffTime -> UTCTime -> Bool
|
||||
deletable' itemContent itemDeleted itemTs allowedInterval currentTs =
|
||||
@@ -569,6 +592,7 @@ dummyMeta itemId ts itemText =
|
||||
forwardedByMember = Nothing,
|
||||
showGroupAsSender = False,
|
||||
msgVerified = Nothing,
|
||||
itemFeed = Nothing,
|
||||
createdAt = ts,
|
||||
updatedAt = ts
|
||||
}
|
||||
@@ -673,6 +697,7 @@ jsonACIQDirection = \case
|
||||
JCIChannelRcv -> Right $ ACIQDirection SCTGroup $ CIQGroupRcv Nothing
|
||||
JCILocalSnd -> Left "unquotable"
|
||||
JCILocalRcv -> Left "unquotable"
|
||||
JCIFeedSnd -> Left "unquotable"
|
||||
|
||||
quoteMsgDirection :: CIQDirection c -> MsgDirection
|
||||
quoteMsgDirection = \case
|
||||
@@ -1187,7 +1212,7 @@ data RcvMessage = RcvMessage
|
||||
|
||||
type MessageId = Int64
|
||||
|
||||
data ConnOrGroupId = ConnectionId Int64 | GroupId Int64
|
||||
data ConnOrGroupId = ConnectionId Int64 | GroupId Int64 | FeedId Int64
|
||||
|
||||
data SndMsgDelivery = SndMsgDelivery
|
||||
{ connId :: Int64,
|
||||
@@ -1284,6 +1309,7 @@ data CIDeleted (c :: ChatType) where
|
||||
CIBlocked :: Maybe UTCTime -> CIDeleted 'CTGroup
|
||||
CIBlockedByAdmin :: Maybe UTCTime -> CIDeleted 'CTGroup
|
||||
CIModerated :: Maybe UTCTime -> GroupMember -> CIDeleted 'CTGroup
|
||||
CIDeleting :: Maybe UTCTime -> CIDeleted 'CTFeed
|
||||
|
||||
deriving instance Show (CIDeleted c)
|
||||
|
||||
@@ -1294,6 +1320,7 @@ data JSONCIDeleted
|
||||
| JCIDBlocked {deletedTs :: Maybe UTCTime}
|
||||
| JCIDBlockedByAdmin {deletedTs :: Maybe UTCTime}
|
||||
| JCIDModerated {deletedTs :: Maybe UTCTime, byGroupMember :: GroupMember}
|
||||
| JCIDDeleting {deletedTs :: Maybe UTCTime}
|
||||
deriving (Show)
|
||||
|
||||
jsonCIDeleted :: forall d. ChatTypeI d => CIDeleted d -> JSONCIDeleted
|
||||
@@ -1302,6 +1329,7 @@ jsonCIDeleted = \case
|
||||
CIBlocked ts -> JCIDBlocked ts
|
||||
CIBlockedByAdmin ts -> JCIDBlockedByAdmin ts
|
||||
CIModerated ts m -> JCIDModerated ts m
|
||||
CIDeleting ts -> JCIDDeleting ts
|
||||
|
||||
jsonACIDeleted :: JSONCIDeleted -> ACIDeleted
|
||||
jsonACIDeleted = \case
|
||||
@@ -1309,6 +1337,7 @@ jsonACIDeleted = \case
|
||||
JCIDBlocked ts -> ACIDeleted SCTGroup $ CIBlocked ts
|
||||
JCIDBlockedByAdmin ts -> ACIDeleted SCTGroup $ CIBlockedByAdmin ts
|
||||
JCIDModerated ts m -> ACIDeleted SCTGroup (CIModerated ts m)
|
||||
JCIDDeleting ts -> ACIDeleted SCTFeed $ CIDeleting ts
|
||||
|
||||
itemDeletedTs :: CIDeleted d -> Maybe UTCTime
|
||||
itemDeletedTs = \case
|
||||
@@ -1316,6 +1345,7 @@ itemDeletedTs = \case
|
||||
CIBlocked ts -> ts
|
||||
CIBlockedByAdmin ts -> ts
|
||||
CIModerated ts _ -> ts
|
||||
CIDeleting ts -> ts
|
||||
|
||||
data CIForwardedFrom
|
||||
= CIFFUnknown
|
||||
@@ -1445,6 +1475,8 @@ $(JQ.deriveJSON defaultJSON ''MemberDeliveryStatus)
|
||||
|
||||
$(JQ.deriveJSON defaultJSON ''ChatItemVersion)
|
||||
|
||||
$(JQ.deriveJSON (enumJSON $ dropPrefix "CIF") ''CIFeed)
|
||||
|
||||
instance (ChatTypeI c, MsgDirectionI d) => FromJSON (CIMeta c d) where
|
||||
parseJSON = $(JQ.mkParseJSON defaultJSON ''CIMeta)
|
||||
|
||||
|
||||
@@ -447,7 +447,7 @@ signChatMsgBody MsgSigning {bindingTag, bindingData, keyRef, privKey} msgBody =
|
||||
data ChatMsgEvent (e :: MsgEncoding) where
|
||||
XMsgNew :: MsgContainer -> ChatMsgEvent 'Json
|
||||
XMsgFileDescr :: {msgId :: SharedMsgId, fileDescr :: FileDescr, fileExpires :: Maybe UTCTime} -> ChatMsgEvent 'Json
|
||||
XMsgUpdate :: {msgId :: SharedMsgId, content :: MsgContent, mentions :: Map MemberName MsgMention, ttl :: Maybe Int, live :: Maybe Bool, scope :: Maybe MsgScope, asGroup :: Maybe Bool} -> ChatMsgEvent 'Json
|
||||
XMsgUpdate :: {msgId :: SharedMsgId, content :: MsgContent, mentions :: Map MemberName MsgMention, ttl :: Maybe Int, live :: Maybe Bool, scope :: Maybe MsgScope, asGroup :: Maybe Bool, feed :: Maybe Bool} -> ChatMsgEvent 'Json
|
||||
XMsgDel :: {msgId :: SharedMsgId, memberId :: Maybe MemberId, scope :: Maybe MsgScope, onlyHistory :: Bool} -> ChatMsgEvent 'Json
|
||||
XMsgDeleted :: ChatMsgEvent 'Json
|
||||
XMsgReact :: {msgId :: SharedMsgId, memberId :: Maybe MemberId, scope :: Maybe MsgScope, reaction :: MsgReaction, add :: Bool} -> ChatMsgEvent 'Json
|
||||
@@ -689,7 +689,8 @@ data MsgContainer = MsgContainer
|
||||
quote :: Maybe QuotedMsg,
|
||||
parent :: Maybe MsgRef,
|
||||
forward :: Maybe Bool,
|
||||
forwardLink :: Maybe ForwardLink
|
||||
forwardLink :: Maybe ForwardLink,
|
||||
feed :: Maybe Bool
|
||||
}
|
||||
deriving (Eq, Show)
|
||||
|
||||
@@ -715,7 +716,8 @@ mcSimple content =
|
||||
quote = Nothing,
|
||||
parent = Nothing,
|
||||
forward = Nothing,
|
||||
forwardLink = Nothing
|
||||
forwardLink = Nothing,
|
||||
feed = Nothing
|
||||
}
|
||||
|
||||
mcQuote :: QuotedMsg -> MsgContent -> MsgContainer
|
||||
@@ -1400,7 +1402,8 @@ appJsonToCM AppMessageJson {v, msgId, event, params} = do
|
||||
live <- opt "live"
|
||||
scope <- opt "scope"
|
||||
asGroup <- opt "asGroup"
|
||||
pure XMsgUpdate {msgId = msgId', content, mentions, ttl, live, scope, asGroup}
|
||||
feed <- opt "feed"
|
||||
pure XMsgUpdate {msgId = msgId', content, mentions, ttl, live, scope, asGroup, feed}
|
||||
XMsgDel_ -> XMsgDel <$> p "msgId" <*> opt "memberId" <*> opt "scope" <*> (fromMaybe False <$> opt "onlyHistory")
|
||||
XMsgDeleted_ -> pure XMsgDeleted
|
||||
XMsgReact_ -> XMsgReact <$> p "msgId" <*> opt "memberId" <*> opt "scope" <*> p "reaction" <*> p "add"
|
||||
@@ -1483,7 +1486,7 @@ chatToAppMessage chatMsg@ChatMessage {chatVRange, msgId, chatMsgEvent} = case en
|
||||
J.Object obj -> obj
|
||||
_ -> JM.empty
|
||||
XMsgFileDescr msgId' fileDescr fileExpires -> o $ ("fileExpires" .=? fileExpires) ["msgId" .= msgId', "fileDescr" .= fileDescr]
|
||||
XMsgUpdate {msgId = msgId', content, mentions, ttl, live, scope, asGroup} -> o $ ("asGroup" .=? asGroup) $ ("ttl" .=? ttl) $ ("live" .=? live) $ ("scope" .=? scope) $ ("mentions" .=? nonEmptyMap mentions) ["msgId" .= msgId', "content" .= content]
|
||||
XMsgUpdate {msgId = msgId', content, mentions, ttl, live, scope, asGroup, feed} -> o $ ("feed" .=? feed) $ ("asGroup" .=? asGroup) $ ("ttl" .=? ttl) $ ("live" .=? live) $ ("scope" .=? scope) $ ("mentions" .=? nonEmptyMap mentions) ["msgId" .= msgId', "content" .= content]
|
||||
XMsgDel msgId' memberId scope onlyHistory -> o $ ("memberId" .=? memberId) $ ("scope" .=? scope) $ ("onlyHistory" .=? justTrue onlyHistory) ["msgId" .= msgId']
|
||||
XMsgDeleted -> JM.empty
|
||||
XMsgReact msgId' memberId scope reaction add -> o $ ("memberId" .=? memberId) $ ("scope" .=? scope) ["msgId" .= msgId', "reaction" .= reaction, "add" .= add]
|
||||
|
||||
@@ -172,6 +172,7 @@ import Simplex.Chat.Store.SQLite.Migrations.M20260723_contact_request_rejection
|
||||
import Simplex.Chat.Store.SQLite.Migrations.M20260813_auto_accept_group_invitations
|
||||
import Simplex.Chat.Store.SQLite.Migrations.M20260822_forward_link
|
||||
import Simplex.Chat.Store.SQLite.Migrations.M20260828_file_expiry
|
||||
import Simplex.Chat.Store.SQLite.Migrations.M20260905_feeds
|
||||
import Simplex.Messaging.Agent.Store.Shared (Migration (..))
|
||||
|
||||
schemaMigrations :: [(String, Query, Maybe Query)]
|
||||
@@ -343,7 +344,8 @@ schemaMigrations =
|
||||
("20260723_contact_request_rejection", m20260723_contact_request_rejection, Just down_m20260723_contact_request_rejection),
|
||||
("20260813_auto_accept_group_invitations", m20260813_auto_accept_group_invitations, Just down_m20260813_auto_accept_group_invitations),
|
||||
("20260822_forward_link", m20260822_forward_link, Just down_m20260822_forward_link),
|
||||
("20260828_file_expiry", m20260828_file_expiry, Just down_m20260828_file_expiry)
|
||||
("20260828_file_expiry", m20260828_file_expiry, Just down_m20260828_file_expiry),
|
||||
("20260905_feeds", m20260905_feeds, Just down_m20260905_feeds)
|
||||
]
|
||||
|
||||
-- | The list of migrations in ascending order by date
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
|
||||
module Simplex.Chat.Store.SQLite.Migrations.M20260905_feeds where
|
||||
|
||||
import Database.SQLite.Simple (Query)
|
||||
import Database.SQLite.Simple.QQ (sql)
|
||||
|
||||
m20260905_feeds :: Query
|
||||
m20260905_feeds =
|
||||
[sql|
|
||||
CREATE TABLE feeds(
|
||||
feed_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
|
||||
created_at TEXT NOT NULL DEFAULT(datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT(datetime('now')),
|
||||
chat_ts TEXT NOT NULL DEFAULT(datetime('now')),
|
||||
favorite INTEGER NOT NULL DEFAULT 0,
|
||||
unread_chat INTEGER NOT NULL DEFAULT 0
|
||||
) STRICT;
|
||||
CREATE INDEX idx_feeds_user_id ON feeds(user_id);
|
||||
INSERT INTO feeds (user_id) SELECT user_id FROM users;
|
||||
|
||||
ALTER TABLE chat_items ADD COLUMN feed_id INTEGER DEFAULT NULL REFERENCES feeds ON DELETE CASCADE;
|
||||
ALTER TABLE chat_items ADD COLUMN feed_item_id INTEGER DEFAULT NULL REFERENCES chat_items ON DELETE SET NULL;
|
||||
ALTER TABLE chat_items ADD COLUMN item_feed INTEGER NOT NULL DEFAULT 0;
|
||||
CREATE INDEX idx_chat_items_feed_id ON chat_items(feed_id);
|
||||
CREATE INDEX idx_chat_items_feeds_created_at ON chat_items(user_id, feed_id, created_at);
|
||||
CREATE INDEX idx_chat_items_feed_item_contact ON chat_items(feed_item_id, contact_id);
|
||||
CREATE INDEX idx_chat_items_feed_item_group ON chat_items(feed_item_id, group_id);
|
||||
|
||||
ALTER TABLE messages ADD COLUMN feed_id INTEGER DEFAULT NULL REFERENCES feeds ON DELETE CASCADE;
|
||||
CREATE INDEX idx_messages_feed_id ON messages(feed_id);
|
||||
|
||||
ALTER TABLE files ADD COLUMN feed_id INTEGER DEFAULT NULL REFERENCES feeds ON DELETE CASCADE;
|
||||
CREATE INDEX idx_files_feed_id ON files(feed_id);
|
||||
|
||||
ALTER TABLE contacts ADD COLUMN drop_feed INTEGER NOT NULL DEFAULT 0;
|
||||
ALTER TABLE groups ADD COLUMN drop_feed INTEGER NOT NULL DEFAULT 0;
|
||||
CREATE INDEX idx_contacts_user_id ON contacts(user_id);
|
||||
CREATE INDEX idx_groups_user_id_business_chat ON groups(user_id, business_chat);
|
||||
|
||||
PRAGMA writable_schema=1;
|
||||
|
||||
UPDATE sqlite_master
|
||||
SET sql = replace(sql, 'group_id INTEGER NOT NULL REFERENCES groups ON DELETE CASCADE', 'group_id INTEGER REFERENCES groups ON DELETE CASCADE')
|
||||
WHERE type = 'table' AND name = 'delivery_jobs';
|
||||
|
||||
PRAGMA writable_schema=RESET;
|
||||
|
||||
ALTER TABLE delivery_jobs ADD COLUMN feed_id INTEGER REFERENCES feeds ON DELETE CASCADE;
|
||||
ALTER TABLE delivery_jobs ADD COLUMN chat_item_id INTEGER REFERENCES chat_items ON DELETE CASCADE;
|
||||
ALTER TABLE delivery_jobs ADD COLUMN delete_mode TEXT;
|
||||
ALTER TABLE delivery_jobs ADD COLUMN message_ids TEXT;
|
||||
ALTER TABLE delivery_jobs ADD COLUMN cursor_contact_id INTEGER;
|
||||
ALTER TABLE delivery_jobs ADD COLUMN cursor_group_id INTEGER;
|
||||
CREATE INDEX idx_delivery_jobs_feed_next ON delivery_jobs(feed_id, worker_scope, failed, job_status);
|
||||
CREATE INDEX idx_delivery_jobs_chat_item_id ON delivery_jobs(chat_item_id);
|
||||
|]
|
||||
|
||||
down_m20260905_feeds :: Query
|
||||
down_m20260905_feeds =
|
||||
[sql|
|
||||
DROP INDEX idx_delivery_jobs_chat_item_id;
|
||||
DROP INDEX idx_delivery_jobs_feed_next;
|
||||
DELETE FROM delivery_jobs WHERE group_id IS NULL;
|
||||
ALTER TABLE delivery_jobs DROP COLUMN cursor_group_id;
|
||||
ALTER TABLE delivery_jobs DROP COLUMN cursor_contact_id;
|
||||
ALTER TABLE delivery_jobs DROP COLUMN message_ids;
|
||||
ALTER TABLE delivery_jobs DROP COLUMN delete_mode;
|
||||
ALTER TABLE delivery_jobs DROP COLUMN chat_item_id;
|
||||
ALTER TABLE delivery_jobs DROP COLUMN feed_id;
|
||||
|
||||
PRAGMA writable_schema=1;
|
||||
|
||||
UPDATE sqlite_master
|
||||
SET sql = replace(sql, 'group_id INTEGER REFERENCES groups ON DELETE CASCADE', 'group_id INTEGER NOT NULL REFERENCES groups ON DELETE CASCADE')
|
||||
WHERE type = 'table' AND name = 'delivery_jobs';
|
||||
|
||||
PRAGMA writable_schema=RESET;
|
||||
|
||||
DROP INDEX idx_groups_user_id_business_chat;
|
||||
DROP INDEX idx_contacts_user_id;
|
||||
ALTER TABLE groups DROP COLUMN drop_feed;
|
||||
ALTER TABLE contacts DROP COLUMN drop_feed;
|
||||
|
||||
DROP INDEX idx_files_feed_id;
|
||||
ALTER TABLE files DROP COLUMN feed_id;
|
||||
|
||||
DROP INDEX idx_messages_feed_id;
|
||||
ALTER TABLE messages DROP COLUMN feed_id;
|
||||
|
||||
DROP INDEX idx_chat_items_feed_item_group;
|
||||
DROP INDEX idx_chat_items_feed_item_contact;
|
||||
DROP INDEX idx_chat_items_feeds_created_at;
|
||||
DROP INDEX idx_chat_items_feed_id;
|
||||
ALTER TABLE chat_items DROP COLUMN item_feed;
|
||||
ALTER TABLE chat_items DROP COLUMN feed_item_id;
|
||||
ALTER TABLE chat_items DROP COLUMN feed_id;
|
||||
|
||||
DROP INDEX idx_feeds_user_id;
|
||||
DROP TABLE feeds;
|
||||
|]
|
||||
@@ -106,6 +106,7 @@ CREATE TABLE contacts(
|
||||
grp_direct_inv_from_group_member_id INTEGER REFERENCES group_members(group_member_id) ON DELETE SET NULL,
|
||||
grp_direct_inv_from_member_conn_id INTEGER REFERENCES connections(connection_id) ON DELETE SET NULL,
|
||||
grp_direct_inv_started_connection INTEGER NOT NULL DEFAULT 0,
|
||||
drop_feed INTEGER NOT NULL DEFAULT 0,
|
||||
FOREIGN KEY(user_id, local_display_name)
|
||||
REFERENCES display_names(user_id, local_display_name)
|
||||
ON DELETE CASCADE
|
||||
@@ -208,7 +209,8 @@ CREATE TABLE groups(
|
||||
roster_blob BLOB,
|
||||
group_domain_verified INTEGER,
|
||||
stored_roster_version INTEGER,
|
||||
applied_complete_roster_version INTEGER, -- received
|
||||
applied_complete_roster_version INTEGER,
|
||||
drop_feed INTEGER NOT NULL DEFAULT 0, -- received
|
||||
FOREIGN KEY(user_id, local_display_name)
|
||||
REFERENCES display_names(user_id, local_display_name)
|
||||
ON DELETE CASCADE
|
||||
@@ -303,6 +305,8 @@ CREATE TABLE files(
|
||||
roster_transfer_id INTEGER,
|
||||
file_digest BLOB,
|
||||
file_expires_at TEXT
|
||||
,
|
||||
feed_id INTEGER DEFAULT NULL REFERENCES feeds ON DELETE CASCADE
|
||||
) STRICT;
|
||||
CREATE TABLE snd_files(
|
||||
file_id INTEGER NOT NULL REFERENCES files ON DELETE CASCADE,
|
||||
@@ -456,6 +460,8 @@ CREATE TABLE messages(
|
||||
broker_ts TEXT,
|
||||
msg_chat_binding TEXT,
|
||||
msg_signatures BLOB
|
||||
,
|
||||
feed_id INTEGER DEFAULT NULL REFERENCES feeds ON DELETE CASCADE
|
||||
) STRICT;
|
||||
CREATE TABLE pending_group_messages(
|
||||
pending_group_message_id INTEGER PRIMARY KEY,
|
||||
@@ -521,6 +527,10 @@ CREATE TABLE chat_items(
|
||||
fwd_from_public_group_id BLOB,
|
||||
fwd_from_member_id BLOB,
|
||||
fwd_from_shared_msg_id BLOB
|
||||
,
|
||||
feed_id INTEGER DEFAULT NULL REFERENCES feeds ON DELETE CASCADE,
|
||||
feed_item_id INTEGER DEFAULT NULL REFERENCES chat_items ON DELETE SET NULL,
|
||||
item_feed INTEGER NOT NULL DEFAULT 0
|
||||
) STRICT;
|
||||
CREATE TABLE sqlite_sequence(name,seq);
|
||||
CREATE TABLE chat_item_messages(
|
||||
@@ -785,7 +795,7 @@ CREATE TABLE delivery_tasks(
|
||||
) STRICT;
|
||||
CREATE TABLE delivery_jobs(
|
||||
delivery_job_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
group_id INTEGER NOT NULL REFERENCES groups ON DELETE CASCADE,
|
||||
group_id INTEGER REFERENCES groups ON DELETE CASCADE,
|
||||
worker_scope TEXT NOT NULL,
|
||||
job_scope_spec_tag TEXT,
|
||||
job_scope_include_pending INTEGER,
|
||||
@@ -799,6 +809,13 @@ CREATE TABLE delivery_jobs(
|
||||
updated_at TEXT NOT NULL DEFAULT(datetime('now'))
|
||||
,
|
||||
sender_group_member_ids TEXT
|
||||
,
|
||||
feed_id INTEGER REFERENCES feeds ON DELETE CASCADE,
|
||||
chat_item_id INTEGER REFERENCES chat_items ON DELETE CASCADE,
|
||||
delete_mode TEXT,
|
||||
message_ids TEXT,
|
||||
cursor_contact_id INTEGER,
|
||||
cursor_group_id INTEGER
|
||||
) STRICT;
|
||||
CREATE TABLE group_member_status_predicates(
|
||||
member_status TEXT NOT NULL PRIMARY KEY,
|
||||
@@ -1418,3 +1435,41 @@ BEGIN
|
||||
)
|
||||
WHERE group_id = NEW.group_id;
|
||||
END;
|
||||
CREATE TABLE feeds(
|
||||
feed_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL REFERENCES users ON DELETE CASCADE,
|
||||
created_at TEXT NOT NULL DEFAULT(datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT(datetime('now')),
|
||||
chat_ts TEXT NOT NULL DEFAULT(datetime('now')),
|
||||
favorite INTEGER NOT NULL DEFAULT 0,
|
||||
unread_chat INTEGER NOT NULL DEFAULT 0
|
||||
) STRICT;
|
||||
CREATE INDEX idx_feeds_user_id ON feeds(user_id);
|
||||
CREATE INDEX idx_chat_items_feed_id ON chat_items(feed_id);
|
||||
CREATE INDEX idx_chat_items_feeds_created_at ON chat_items(
|
||||
user_id,
|
||||
feed_id,
|
||||
created_at
|
||||
);
|
||||
CREATE INDEX idx_chat_items_feed_item_contact ON chat_items(
|
||||
feed_item_id,
|
||||
contact_id
|
||||
);
|
||||
CREATE INDEX idx_chat_items_feed_item_group ON chat_items(
|
||||
feed_item_id,
|
||||
group_id
|
||||
);
|
||||
CREATE INDEX idx_messages_feed_id ON messages(feed_id);
|
||||
CREATE INDEX idx_files_feed_id ON files(feed_id);
|
||||
CREATE INDEX idx_contacts_user_id ON contacts(user_id);
|
||||
CREATE INDEX idx_groups_user_id_business_chat ON groups(
|
||||
user_id,
|
||||
business_chat
|
||||
);
|
||||
CREATE INDEX idx_delivery_jobs_feed_next ON delivery_jobs(
|
||||
feed_id,
|
||||
worker_scope,
|
||||
failed,
|
||||
job_status
|
||||
);
|
||||
CREATE INDEX idx_delivery_jobs_chat_item_id ON delivery_jobs(chat_item_id);
|
||||
@@ -73,6 +73,7 @@ data ChatLockEntity
|
||||
| CLUserContact Int64
|
||||
| CLContactRequest Int64
|
||||
| CLFile Int64
|
||||
| CLFeed FeedId
|
||||
deriving (Eq, Ord)
|
||||
|
||||
-- These error type constructors must be added to mobile apps
|
||||
@@ -113,6 +114,9 @@ data StoreError
|
||||
| SENoteFolderAlreadyExists {noteFolderId :: NoteFolderId}
|
||||
| SENoteFolderNotFound {noteFolderId :: NoteFolderId}
|
||||
| SEUserNoteFolderNotFound
|
||||
| SEFeedAlreadyExists {feedId :: FeedId}
|
||||
| SEFeedNotFound {feedId :: FeedId}
|
||||
| SEUserFeedNotFound
|
||||
| SESndFileNotFound {fileId :: FileTransferId}
|
||||
| SESndFileInvalid {fileId :: FileTransferId}
|
||||
| SERcvFileNotFound {fileId :: FileTransferId}
|
||||
|
||||
@@ -588,20 +588,22 @@ data GroupLink = GroupLink
|
||||
}
|
||||
deriving (Show)
|
||||
|
||||
data ContactOrGroup = CGContact Contact | CGGroup GroupInfo [GroupMember]
|
||||
data ContactOrGroup = CGContact Contact | CGGroup GroupInfo [GroupMember] | CGFeed Feed
|
||||
|
||||
data PreparedChatEntity = PCEContact Contact | PCEGroup {groupInfo :: GroupInfo, hostMember :: GroupMember}
|
||||
|
||||
contactAndGroupIds :: ContactOrGroup -> (Maybe ContactId, Maybe GroupId)
|
||||
contactAndGroupIds :: ContactOrGroup -> (Maybe ContactId, Maybe GroupId, Maybe FeedId)
|
||||
contactAndGroupIds = \case
|
||||
CGContact Contact {contactId} -> (Just contactId, Nothing)
|
||||
CGGroup GroupInfo {groupId} _ -> (Nothing, Just groupId)
|
||||
CGContact Contact {contactId} -> (Just contactId, Nothing, Nothing)
|
||||
CGGroup GroupInfo {groupId} _ -> (Nothing, Just groupId, Nothing)
|
||||
CGFeed Feed {feedId} -> (Nothing, Nothing, Just feedId)
|
||||
|
||||
-- TODO when more settings are added we should create another type to allow partial setting updates (with all Maybe properties)
|
||||
data ChatSettings = ChatSettings
|
||||
{ enableNtfs :: MsgFilter,
|
||||
sendRcpts :: Maybe Bool,
|
||||
favorite :: Bool
|
||||
favorite :: Bool,
|
||||
dropFeed :: BoolDef
|
||||
}
|
||||
deriving (Eq, Show)
|
||||
|
||||
@@ -610,7 +612,8 @@ defaultChatSettings =
|
||||
ChatSettings
|
||||
{ enableNtfs = MFAll,
|
||||
sendRcpts = Nothing,
|
||||
favorite = False
|
||||
favorite = False,
|
||||
dropFeed = BoolDef False
|
||||
}
|
||||
|
||||
chatHasNtfs :: ChatSettings -> Bool
|
||||
@@ -2218,6 +2221,19 @@ data NoteFolder = NoteFolder
|
||||
|
||||
type NoteFolderId = Int64
|
||||
|
||||
data Feed = Feed
|
||||
{ feedId :: FeedId,
|
||||
userId :: UserId,
|
||||
createdAt :: UTCTime,
|
||||
updatedAt :: UTCTime,
|
||||
chatTs :: UTCTime,
|
||||
favorite :: Bool,
|
||||
unread :: Bool
|
||||
}
|
||||
deriving (Eq, Show)
|
||||
|
||||
type FeedId = Int64
|
||||
|
||||
data ChatVersion
|
||||
|
||||
instance VersionScope ChatVersion
|
||||
@@ -2410,4 +2426,6 @@ $(JQ.deriveJSON defaultJSON ''ContactRef)
|
||||
|
||||
$(JQ.deriveJSON defaultJSON ''NoteFolder)
|
||||
|
||||
$(JQ.deriveJSON defaultJSON ''Feed)
|
||||
|
||||
$(JQ.deriveJSON defaultJSON ''ChatTag)
|
||||
Reference in new issue
Block a user