Compare commits
2 Commits
e762864b45
...
1d3b0febde
Author | SHA1 | Date | |
---|---|---|---|
1d3b0febde | |||
70d6eba427 |
|
@ -284,7 +284,7 @@ updateSyncResponse model r notify =
|
||||||
notification sr = findFirstBy
|
notification sr = findFirstBy
|
||||||
(\(s, e) -> e.originServerTs)
|
(\(s, e) -> e.originServerTs)
|
||||||
(\(s, e) -> e.sender /= model.loginUsername)
|
(\(s, e) -> e.sender /= model.loginUsername)
|
||||||
<| notificationEvents sr
|
<| joinedRoomNotificationEvents sr
|
||||||
notificationCmd sr = if notify
|
notificationCmd sr = if notify
|
||||||
then Maybe.withDefault Cmd.none
|
then Maybe.withDefault Cmd.none
|
||||||
<| Maybe.map (\(s, e) -> sendNotificationPort
|
<| Maybe.map (\(s, e) -> sendNotificationPort
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
module Scylla.AccountData exposing (..)
|
module Scylla.AccountData exposing (..)
|
||||||
import Scylla.Sync exposing (AccountData, JoinedRoom, roomAccountData)
|
import Scylla.Sync exposing (SyncResponse, AccountData, JoinedRoom, roomAccountData)
|
||||||
import Json.Decode as Decode
|
import Json.Decode as Decode
|
||||||
|
import Dict
|
||||||
|
|
||||||
type NotificationSetting = Normal | MentionsOnly | None
|
type NotificationSetting = Normal | MentionsOnly | None
|
||||||
|
|
||||||
|
@ -20,3 +21,10 @@ roomNotificationSetting jr = Maybe.withDefault Normal
|
||||||
<| Maybe.andThen Result.toMaybe
|
<| Maybe.andThen Result.toMaybe
|
||||||
<| Maybe.map (Decode.decodeValue notificationSettingDecoder)
|
<| Maybe.map (Decode.decodeValue notificationSettingDecoder)
|
||||||
<| roomAccountData jr "com.danilafe.scylla.notifications"
|
<| roomAccountData jr "com.danilafe.scylla.notifications"
|
||||||
|
|
||||||
|
roomIdNotificationSetting : SyncResponse -> String -> NotificationSetting
|
||||||
|
roomIdNotificationSetting sr s = Maybe.withDefault Normal
|
||||||
|
<| Maybe.map roomNotificationSetting
|
||||||
|
<| Maybe.andThen (Dict.get s)
|
||||||
|
<| Maybe.andThen .join sr.rooms
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
port module Scylla.Notification exposing (..)
|
port module Scylla.Notification exposing (..)
|
||||||
import Json.Decode
|
import Scylla.Sync exposing (SyncResponse, RoomEvent, joinedRoomsTimelineEvents)
|
||||||
|
import Scylla.AccountData exposing (..)
|
||||||
|
import Json.Decode as Decode exposing (string, field)
|
||||||
|
import Dict
|
||||||
|
|
||||||
type alias Notification =
|
type alias Notification =
|
||||||
{ name : String
|
{ name : String
|
||||||
|
@ -9,3 +12,25 @@ type alias Notification =
|
||||||
|
|
||||||
port sendNotificationPort : Notification -> Cmd msg
|
port sendNotificationPort : Notification -> Cmd msg
|
||||||
port onNotificationClickPort : (String -> msg) -> Sub msg
|
port onNotificationClickPort : (String -> msg) -> Sub msg
|
||||||
|
|
||||||
|
producesNotification : NotificationSetting -> RoomEvent -> Bool
|
||||||
|
producesNotification ns re = case ns of
|
||||||
|
Normal -> True
|
||||||
|
_ -> False
|
||||||
|
|
||||||
|
|
||||||
|
notificationText : RoomEvent -> String
|
||||||
|
notificationText re = case (Decode.decodeValue (field "msgtype" string) re.content) of
|
||||||
|
Ok "m.text" -> Result.withDefault "" <| (Decode.decodeValue (field "body" string) re.content)
|
||||||
|
_ -> ""
|
||||||
|
|
||||||
|
joinedRoomNotificationEvents : SyncResponse -> List (String, RoomEvent)
|
||||||
|
joinedRoomNotificationEvents s =
|
||||||
|
let
|
||||||
|
applyPair k = List.map (\v -> (k, v))
|
||||||
|
in
|
||||||
|
List.sortBy (\(k, v) -> v.originServerTs)
|
||||||
|
<| Dict.foldl (\k v a -> a ++ applyPair k v) []
|
||||||
|
<| Dict.map (\k v -> List.filter (producesNotification (roomIdNotificationSetting s k)) v)
|
||||||
|
<| joinedRoomsTimelineEvents s
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
module Scylla.Sync exposing (..)
|
module Scylla.Sync exposing (..)
|
||||||
import Scylla.Api exposing (..)
|
import Scylla.Api exposing (..)
|
||||||
import Scylla.Notification exposing (..)
|
|
||||||
import Scylla.Login exposing (Username)
|
import Scylla.Login exposing (Username)
|
||||||
import Scylla.Route exposing (RoomId)
|
import Scylla.Route exposing (RoomId)
|
||||||
import Dict exposing (Dict)
|
import Dict exposing (Dict)
|
||||||
|
@ -273,7 +272,7 @@ historyResponseDecoder =
|
||||||
|> required "end" string
|
|> required "end" string
|
||||||
|> required "chunk" (list roomEventDecoder)
|
|> required "chunk" (list roomEventDecoder)
|
||||||
|
|
||||||
-- Business Logic
|
-- Business Logic: Helper Functions
|
||||||
uniqueByRecursive : (a -> comparable) -> List a -> Set comparable -> List a
|
uniqueByRecursive : (a -> comparable) -> List a -> Set comparable -> List a
|
||||||
uniqueByRecursive f l s = case l of
|
uniqueByRecursive f l s = case l of
|
||||||
x::tail -> if Set.member (f x) s
|
x::tail -> if Set.member (f x) s
|
||||||
|
@ -433,8 +432,9 @@ senderName s =
|
||||||
in
|
in
|
||||||
String.slice 1 colonIndex s
|
String.slice 1 colonIndex s
|
||||||
|
|
||||||
roomStateEvents : JoinedRoom -> List StateEvent
|
-- Business Logic: Events
|
||||||
roomStateEvents jr =
|
allRoomStateEvents : JoinedRoom -> List StateEvent
|
||||||
|
allRoomStateEvents jr =
|
||||||
let
|
let
|
||||||
stateEvents = Maybe.withDefault [] <| Maybe.andThen .events jr.state
|
stateEvents = Maybe.withDefault [] <| Maybe.andThen .events jr.state
|
||||||
timelineEvents = Maybe.withDefault [] <| Maybe.andThen .events jr.timeline
|
timelineEvents = Maybe.withDefault [] <| Maybe.andThen .events jr.timeline
|
||||||
|
@ -452,6 +452,29 @@ roomStateEvents jr =
|
||||||
in
|
in
|
||||||
allStateEvents
|
allStateEvents
|
||||||
|
|
||||||
|
allRoomDictTimelineEvents : Dict String { a | timeline : Maybe Timeline } -> List RoomEvent
|
||||||
|
allRoomDictTimelineEvents dict = List.concatMap (Maybe.withDefault [] << .events)
|
||||||
|
<| List.filterMap .timeline
|
||||||
|
<| Dict.values dict
|
||||||
|
|
||||||
|
allTimelineEvents : SyncResponse -> List RoomEvent
|
||||||
|
allTimelineEvents s =
|
||||||
|
let
|
||||||
|
eventsFor f = Maybe.withDefault []
|
||||||
|
<| Maybe.map allRoomDictTimelineEvents
|
||||||
|
<| Maybe.andThen f s.rooms
|
||||||
|
joinedEvents = eventsFor .join
|
||||||
|
leftEvents = eventsFor .leave
|
||||||
|
in
|
||||||
|
uniqueBy .eventId <| leftEvents ++ joinedEvents
|
||||||
|
|
||||||
|
joinedRoomsTimelineEvents : SyncResponse -> Dict String (List RoomEvent)
|
||||||
|
joinedRoomsTimelineEvents s =
|
||||||
|
Maybe.withDefault Dict.empty
|
||||||
|
<| Maybe.map (Dict.map (\k v -> Maybe.withDefault [] <| Maybe.andThen .events v.timeline))
|
||||||
|
<| Maybe.andThen .join s.rooms
|
||||||
|
|
||||||
|
-- Business Logic: Room Info
|
||||||
roomAccountData : JoinedRoom -> String -> Maybe Decode.Value
|
roomAccountData : JoinedRoom -> String -> Maybe Decode.Value
|
||||||
roomAccountData jr et =
|
roomAccountData jr et =
|
||||||
Maybe.map .content
|
Maybe.map .content
|
||||||
|
@ -462,32 +485,10 @@ roomName : JoinedRoom -> Maybe String
|
||||||
roomName jr =
|
roomName jr =
|
||||||
let
|
let
|
||||||
name c = Result.toMaybe <| Decode.decodeValue (field "name" string) c
|
name c = Result.toMaybe <| Decode.decodeValue (field "name" string) c
|
||||||
nameEvent = findLastEvent (((==) "m.room.name") << .type_) <| roomStateEvents jr
|
nameEvent = findLastEvent (((==) "m.room.name") << .type_) <| allRoomStateEvents jr
|
||||||
in
|
in
|
||||||
Maybe.andThen (name << .content) nameEvent
|
Maybe.andThen (name << .content) nameEvent
|
||||||
|
|
||||||
-- Business Logic: Event Extraction
|
|
||||||
notificationText : RoomEvent -> String
|
|
||||||
notificationText re = case (Decode.decodeValue (field "msgtype" string) re.content) of
|
|
||||||
Ok "m.text" -> Result.withDefault "" <| (Decode.decodeValue (field "body" string) re.content)
|
|
||||||
_ -> ""
|
|
||||||
|
|
||||||
notificationEvents : SyncResponse -> List (String, RoomEvent)
|
|
||||||
notificationEvents s =
|
|
||||||
let
|
|
||||||
applyPair k = List.map (\v -> (k, v))
|
|
||||||
in
|
|
||||||
List.sortBy (\(k, v) -> v.originServerTs)
|
|
||||||
<| Dict.foldl (\k v a -> a ++ applyPair k v) []
|
|
||||||
<| joinedRoomsEvents s
|
|
||||||
|
|
||||||
joinedRoomsEvents : SyncResponse -> Dict String (List RoomEvent)
|
|
||||||
joinedRoomsEvents s =
|
|
||||||
Maybe.withDefault Dict.empty
|
|
||||||
<| Maybe.map (Dict.map (\k v -> Maybe.withDefault [] <| Maybe.andThen .events v.timeline))
|
|
||||||
<| Maybe.andThen .join s.rooms
|
|
||||||
|
|
||||||
-- Business Logic: User Extraction
|
|
||||||
roomTypingUsers : JoinedRoom -> List Username
|
roomTypingUsers : JoinedRoom -> List Username
|
||||||
roomTypingUsers jr = Maybe.withDefault []
|
roomTypingUsers jr = Maybe.withDefault []
|
||||||
<| Maybe.andThen (Result.toMaybe << Decode.decodeValue (Decode.field "user_ids" (list string)))
|
<| Maybe.andThen (Result.toMaybe << Decode.decodeValue (Decode.field "user_ids" (list string)))
|
||||||
|
@ -495,21 +496,6 @@ roomTypingUsers jr = Maybe.withDefault []
|
||||||
<| Maybe.andThen (findLast (((==) "m.typing") << .type_))
|
<| Maybe.andThen (findLast (((==) "m.typing") << .type_))
|
||||||
<| Maybe.andThen .events jr.ephemeral
|
<| Maybe.andThen .events jr.ephemeral
|
||||||
|
|
||||||
allRoomDictEvents : Dict String { a | timeline : Maybe Timeline } -> List RoomEvent
|
-- Business Logic: Users
|
||||||
allRoomDictEvents dict = List.concatMap (Maybe.withDefault [] << .events)
|
|
||||||
<| List.filterMap .timeline
|
|
||||||
<| Dict.values dict
|
|
||||||
|
|
||||||
allEvents : SyncResponse -> List RoomEvent
|
|
||||||
allEvents s =
|
|
||||||
let
|
|
||||||
eventsFor f = Maybe.withDefault []
|
|
||||||
<| Maybe.map allRoomDictEvents
|
|
||||||
<| Maybe.andThen f s.rooms
|
|
||||||
joinedEvents = eventsFor .join
|
|
||||||
leftEvents = eventsFor .leave
|
|
||||||
in
|
|
||||||
uniqueBy .eventId <| leftEvents ++ joinedEvents
|
|
||||||
|
|
||||||
allUsers : SyncResponse -> List Username
|
allUsers : SyncResponse -> List Username
|
||||||
allUsers s = uniqueBy (\u -> u) <| List.map .sender <| allEvents s
|
allUsers s = uniqueBy (\u -> u) <| List.map .sender <| allTimelineEvents s
|
||||||
|
|
Loading…
Reference in New Issue
Block a user