Compare commits
	
		
			No commits in common. "1d3b0febde4ce69cdd10631262916d8771a54633" and "e762864b454322473b3238a7069c4382365cafac" have entirely different histories.
		
	
	
		
			1d3b0febde
			...
			e762864b45
		
	
		
@ -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
 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user