Compare commits

..

No commits in common. "1d3b0febde4ce69cdd10631262916d8771a54633" and "e762864b454322473b3238a7069c4382365cafac" have entirely different histories.

4 changed files with 47 additions and 66 deletions

View File

@ -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)
<| joinedRoomNotificationEvents sr <| notificationEvents 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

View File

@ -1,7 +1,6 @@
module Scylla.AccountData exposing (..) module Scylla.AccountData exposing (..)
import Scylla.Sync exposing (SyncResponse, AccountData, JoinedRoom, roomAccountData) import Scylla.Sync exposing (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
@ -21,10 +20,3 @@ 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

View File

@ -1,8 +1,5 @@
port module Scylla.Notification exposing (..) port module Scylla.Notification exposing (..)
import Scylla.Sync exposing (SyncResponse, RoomEvent, joinedRoomsTimelineEvents) import Json.Decode
import Scylla.AccountData exposing (..)
import Json.Decode as Decode exposing (string, field)
import Dict
type alias Notification = type alias Notification =
{ name : String { name : String
@ -12,25 +9,3 @@ 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

View File

@ -1,5 +1,6 @@
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)
@ -272,7 +273,7 @@ historyResponseDecoder =
|> required "end" string |> required "end" string
|> required "chunk" (list roomEventDecoder) |> required "chunk" (list roomEventDecoder)
-- Business Logic: Helper Functions -- Business Logic
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
@ -432,9 +433,8 @@ senderName s =
in in
String.slice 1 colonIndex s String.slice 1 colonIndex s
-- Business Logic: Events roomStateEvents : JoinedRoom -> List StateEvent
allRoomStateEvents : JoinedRoom -> List StateEvent roomStateEvents jr =
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,29 +452,6 @@ allRoomStateEvents 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
@ -485,10 +462,32 @@ 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_) <| allRoomStateEvents jr nameEvent = findLastEvent (((==) "m.room.name") << .type_) <| roomStateEvents 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)))
@ -496,6 +495,21 @@ 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
-- Business Logic: Users allRoomDictEvents : Dict String { a | timeline : Maybe Timeline } -> List RoomEvent
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 <| allTimelineEvents s allUsers s = uniqueBy (\u -> u) <| List.map .sender <| allEvents s