Skip to content

Commit a1b8f25

Browse files
committed
Closes #296
1 parent a27539e commit a1b8f25

File tree

8 files changed

+78
-16
lines changed

8 files changed

+78
-16
lines changed

src/Client/Im/Chat.purs

+13
Original file line numberDiff line numberDiff line change
@@ -539,3 +539,16 @@ editMessage message id model =
539539
setIt = liftEffect do
540540
input ← chatInput model.chatting
541541
CCD.setValue input (spy "msg" message)
542+
543+
deleteMessage Int WebSocket -> ImModel NoMessages
544+
deleteMessage id webSocket model =
545+
model
546+
{ toggleContextMenu = HideContextMenu
547+
} /\ [ deleteIt ]
548+
where
549+
chatting = SU.fromJust model.chatting
550+
551+
deleteIt = do
552+
liftEffect <<< CIW.sendPayload webSocket $ DeletedMessage { id, userId : (model.contacts !@ chatting).user.id }
553+
pure Nothing
554+

src/Client/Im/Main.purs

+1
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ update st model =
146146
FocusInput elementId → focusInput elementId model
147147
QuoteMessage message et → CIC.quoteMessage message et model
148148
EditMessage message id → CIC.editMessage message id model
149+
DeleteMessage id → CIC.deleteMessage id webSocket model
149150
CheckTyping text → CIC.checkTyping text (EU.unsafePerformEffect EN.nowDateTime) webSocket model
150151
NoTyping id → F.noMessages $ CIC.updateTyping id false model
151152
TypingId id → F.noMessages model { typingIds = DA.snoc model.typingIds $ SC.coerce id }

src/Client/Im/WebSocket/Events.purs

+12-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ import Server.WebSocket (WebSocketConnection)
3838
import Shared.Availability (Availability(..))
3939
import Shared.DateTime (DateTimeWrapper(..))
4040
import Shared.Experiments.Types as SET
41-
import Shared.Im.Types (ClientMessagePayload, Contact, FullWebSocketPayloadClient(..), HistoryMessage, ImMessage(..), MessageStatus(..), RetryableRequest(..), TimeoutIdWrapper(..), WebSocketPayloadClient(..), WebSocketPayloadServer(..), ImModel, EditedMessagePayload)
41+
import Shared.Im.Types (ClientMessagePayload, Contact, EditedMessagePayload, FullWebSocketPayloadClient(..), HistoryMessage, ImMessage(..), ImModel, MessageStatus(..), RetryableRequest(..), TimeoutIdWrapper(..), WebSocketPayloadClient(..), WebSocketPayloadServer(..), DeletedMessagePayload)
4242
import Shared.Json as SJ
4343
import Shared.Options.MountPoint (experimentsId, imId, profileId)
4444
import Shared.Privilege (Privilege)
@@ -171,6 +171,7 @@ receiveMessage webSocket isFocused payload model = case payload of
171171
ServerReceivedMessage rm → receiveAcknowledgement rm model
172172
NewIncomingMessage ni → receiveIncomingMessage webSocket isFocused ni model
173173
NewEditedMessage ni → receiveEditedMessage webSocket isFocused ni model
174+
NewDeletedMessage nd → receiveDeletedMessage nd model
174175
ContactTyping tp → receiveTyping tp model
175176
CurrentPrivileges kp → receivePrivileges kp model
176177
CurrentHash newHash → receiveHash newHash model
@@ -201,6 +202,16 @@ receiveAcknowledgement received model = F.noMessages model
201202
| history.id == received.previousId = history { id = received.id, status = Received }
202203
| otherwise = history
203204

205+
-- | Remove a message from contact's history
206+
receiveDeletedMessage DeletedMessagePayload ImModel NoMessages
207+
receiveDeletedMessage deleted model = F.noMessages model
208+
{ contacts = rm <$> model.contacts
209+
}
210+
where
211+
rm contact
212+
| contact.user.id == deleted.userId = contact { history = DA.filter ((deleted.id /= _) <<< _.id) contact.history }
213+
| otherwise = contact
214+
204215
-- | A new message from others users or sent by the logged user with another connection
205216
receiveIncomingMessage WebSocket Boolean ClientMessagePayload ImModel NextMessage
206217
receiveIncomingMessage webSocket isFocused payload model =

src/Server/Im/Action.purs

+3
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ editMessage loggedUserId userId messageId content = do
109109
else
110110
pure $ Left UserUnavailable
111111

112+
unsendMessage r. Int Int Int BaseEffect { configuration Configuration, pool Pool | r } Unit
113+
unsendMessage loggedUserId userId messageId = SID.deleteMessage loggedUserId userId messageId
114+
112115
markdownPrivileges r. Int BaseEffect { pool Pool | r } (Set Privilege)
113116
markdownPrivileges loggedUserId = (DST.fromFoldable <<< map _.feature) <$> SID.markdownPrivileges loggedUserId
114117

src/Server/Im/Database.purs

+6
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,12 @@ canEditMessage loggedUserId messageId =
278278
# from messages
279279
# wher (_id .=. messageId .&&. _sender .=. loggedUserId)
280280

281+
deleteMessage r. Int Int Int -> BaseEffect { pool Pool | r } Unit
282+
deleteMessage loggedUserId userId messageId = SD.execute $
283+
delete
284+
# from messages
285+
# wher (_id .=. messageId .&&. _sender .=. loggedUserId .&&. _recipient .=. userId)
286+
281287
insertMessage r. Int Int String BaseEffect { pool Pool | r } Int
282288
insertMessage loggedUserId recipient content = SD.withTransaction $ \connection → do
283289
void $ SD.singleWith connection $ select (insert_history (loggedUserId /\ recipient) # as u)

src/Server/WebSocket/Events.purs

+32-9
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ import Server.WebSocket as SW
5252
import Shared.Availability (Availability(..))
5353
import Shared.DateTime (DateTimeWrapper(..))
5454
import Shared.DateTime as SDT
55-
import Shared.Im.Types (AfterLogout(..), FullWebSocketPayloadClient(..), MessageError(..), MessageStatus, OutgoingRecord, WebSocketPayloadClient(..), WebSocketPayloadServer(..), EditedRecord)
55+
import Shared.Im.Types (AfterLogout(..), EditedRecord, FullWebSocketPayloadClient(..), MessageError(..), MessageStatus, OutgoingRecord, WebSocketPayloadClient(..), WebSocketPayloadServer(..), DeletedRecord)
5656
import Shared.Json as SJ
5757
import Shared.Resource (updateHash)
5858
import Shared.ResponseError (DatabaseError, ResponseError(..))
@@ -166,6 +166,7 @@ handleMessage payload = do
166166
Ping ping → sendPong context.token context.loggedUserId context.allUsersAvailabilityRef ping
167167
OutgoingMessage message → sendOutgoingMessage context.token context.loggedUserId allUsersAvailability message
168168
EditedMessage message → sendEditedMessage context.token context.loggedUserId allUsersAvailability message
169+
DeletedMessage message → unsendMessage context.token context.loggedUserId allUsersAvailability message
169170
ChangeStatus changes → sendStatusChange context.token context.loggedUserId allUsersAvailability changes
170171
Typing { id } → sendTyping context.loggedUserId allUsersAvailability id
171172
SetOnline → setOnline context.loggedUserId
@@ -341,14 +342,14 @@ sendEditedMessage token loggedUserId allUsersAvailability edited = do
341342
case processed of
342343
Right content → do
343344
let receipientUserAvailability = DH.lookup edited.userId allUsersAvailability
344-
withConnections receipientUserAvailability (sendRecipient edited.id content)
345+
withConnections receipientUserAvailability (sendRecipient content)
345346

346347
let loggedUserConnections = (SU.fromJust loggedUserAvailability).connections
347348
let senderConnection = DH.values $ DH.filterKeys (token == _) loggedUserConnections
348-
DF.traverse_ (acknowledgeMessage edited.id) senderConnection
349+
DF.traverse_ acknowledgeMessage senderConnection
349350

350351
let otherConnections = DH.values $ DH.filterKeys (token /= _) loggedUserConnections
351-
DF.traverse_ (sendRecipient edited.id content) otherConnections
352+
DF.traverse_ (sendRecipient content) otherConnections
352353
Left UserUnavailable
353354
sendLoggedUser <<< Content $ ContactUnavailable
354355
{ userId: edited.userId
@@ -360,25 +361,47 @@ sendEditedMessage token loggedUserId allUsersAvailability edited = do
360361
, temporaryMessageId: Just edited.id
361362
}
362363
where
363-
sendRecipient messageId content connection =
364+
sendRecipient content connection =
364365
sendWebSocketMessage connection <<< Content $ NewEditedMessage
365-
{ id: messageId
366+
{ id: edited.id
366367
, senderId: loggedUserId
367368
, recipientId: edited.userId
368369
, content
369370
}
370371

371372
loggedUserAvailability = DH.lookup loggedUserId allUsersAvailability
372373

373-
acknowledgeMessage messageId connection = sendWebSocketMessage connection <<< Content $ ServerReceivedMessage
374-
{ previousId: messageId
375-
, id: messageId
374+
acknowledgeMessage connection = sendWebSocketMessage connection <<< Content $ ServerReceivedMessage
375+
{ previousId: edited.id
376+
, id: edited.id
376377
, userId: edited.userId
377378
}
378379

379380
sendLoggedUser payload = do
380381
withConnections loggedUserAvailability $ \connection → sendWebSocketMessage connection payload
381382

383+
unsendMessage String Int HashMap Int UserAvailability DeletedRecord WebSocketEffect
384+
unsendMessage token loggedUserId allUsersAvailability deleted = do
385+
SIA.unsendMessage loggedUserId deleted.userId deleted.id
386+
387+
let receipientUserAvailability = DH.lookup deleted.userId allUsersAvailability
388+
withConnections receipientUserAvailability (send loggedUserId)
389+
390+
let loggedUserConnections = (SU.fromJust loggedUserAvailability).connections
391+
let senderConnection = DH.values $ DH.filterKeys (token == _) loggedUserConnections
392+
DF.traverse_ (send deleted.userId) senderConnection
393+
394+
let otherConnections = DH.values $ DH.filterKeys (token /= _) loggedUserConnections
395+
DF.traverse_ (send deleted.userId) otherConnections
396+
where
397+
send userId connection =
398+
sendWebSocketMessage connection <<< Content $ NewDeletedMessage
399+
{ id: deleted.id
400+
, userId
401+
}
402+
403+
loggedUserAvailability = DH.lookup loggedUserId allUsersAvailability
404+
382405
makeUserAvailabity HashMap String WebSocketConnection Either String String Boolean DateTime Availability UserAvailability
383406
makeUserAvailabity connections token isActive lastSeen previousAvailability =
384407
{ lastSeen

src/Shared/Im/Types.purs

+10-6
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,11 @@ import Data.Either (Either(..))
1313
import Data.Enum (class BoundedEnum, class Enum, Cardinality(..))
1414
import Data.Enum as DE
1515
import Data.Generic.Rep (class Generic)
16-
import Data.Hashable (class Hashable)
17-
import Data.Hashable as HS
1816
import Data.Int as DI
1917
import Data.Maybe (Maybe(..))
2018
import Data.Maybe as DM
2119
import Data.Maybe.First (First)
2220
import Data.Show.Generic as DGRS
23-
import Data.String.Regex as DSRG
24-
import Data.String.Regex.Flags (noFlags)
25-
import Data.String.Regex.Unsafe as DSRU
2621
import Data.Tuple (Tuple)
2722
import Droplet.Language (class FromValue, class ToValue)
2823
import Droplet.Language as DL
@@ -33,7 +28,7 @@ import Foreign.Object as FO
3328
import Payload.Client.QueryParams (class EncodeQueryParam)
3429
import Payload.Server.QueryParams (class DecodeQueryParam, DecodeError(..))
3530
import Shared.DateTime (DateTimeWrapper(..))
36-
import Shared.Experiments.Types (Experiment)
31+
3732
import Shared.Privilege (Privilege)
3833
import Shared.Resource (Bundle)
3934
import Shared.ResponseError (DatabaseError)
@@ -72,6 +67,10 @@ type EditedMessagePayload = BasicMessage
7267
, senderIdInt
7368
)
7469

70+
type DeletedMessagePayload = BasicMessage
71+
( userIdInt
72+
)
73+
7574
type BaseContact fields =
7675
{ -- except for the last few messages, chat history is loaded when clicking on a contact for the first time
7776
shouldFetchChatHistory Boolean
@@ -305,6 +304,7 @@ data ImMessage
305304
| FocusInput ElementId
306305
| QuoteMessage String (Either Touch (Maybe Event))
307306
| EditMessage String Int
307+
| DeleteMessage Int
308308
| FocusCurrentSuggestion
309309
| EnterBeforeSendMessage Event
310310
| ForceBeforeSendMessage
@@ -359,6 +359,7 @@ data WebSocketPayloadServer
359359
| Typing { id Int }
360360
| OutgoingMessage OutgoingRecord
361361
| EditedMessage EditedRecord
362+
| DeletedMessage DeletedRecord
362363
| ChangeStatus
363364
{ status MessageStatus
364365
, ids Array (Tuple Int (Array Int))
@@ -377,6 +378,8 @@ type OutgoingRecord =
377378

378379
type EditedRecord = { id Int, userId Int, content MessageContent }
379380

381+
type DeletedRecord = { id Int, userId Int }
382+
380383
type AvailabilityStatus = Array { id Int, status Availability }
381384

382385
data FullWebSocketPayloadClient
@@ -389,6 +392,7 @@ data WebSocketPayloadClient
389392
| CurrentPrivileges { karma Int, privileges Array Privilege }
390393
| NewIncomingMessage ClientMessagePayload
391394
| NewEditedMessage EditedMessagePayload
395+
| NewDeletedMessage DeletedMessagePayload
392396
| ContactTyping { id Int }
393397
| ServerReceivedMessage
394398
{ previousId Int

src/Shared/Im/View/ChatHistory.purs

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ chatHistory model@{ user: { id: loggedUserId, messageTimestamps, joined, tempora
9191
, HE.div [ HA.class' { "user-menu in-message": true, visible: isContextMenuVisible, "menu-up": isContextMenuVisible && bottomMessage id } ]
9292
[ HE.div [ HA.class' "user-menu-item menu-item-heading", HA.onClick (QuoteMessage content (Right Nothing)) ] "Reply"
9393
, HE.div [ HA.class' { "user-menu-item menu-item-heading": true, "hidden": sender /= model.user.id || status < Received }, HA.onClick $ EditMessage content id ] "Edit"
94+
, HE.div [ HA.class' { "user-menu-item menu-item-heading": true, "hidden": sender /= model.user.id || status < Received }, HA.onClick $ DeleteMessage id ] "Unsend"
9495
]
9596
]
9697
]

0 commit comments

Comments
 (0)