diff --git a/src/Scylla/Sync.elm b/src/Scylla/Sync.elm index d39ba13..2ff0e4e 100644 --- a/src/Scylla/Sync.elm +++ b/src/Scylla/Sync.elm @@ -269,11 +269,19 @@ uniqueByRecursive f l s = case l of uniqueBy : (a -> comparable) -> List a -> List a uniqueBy f l = uniqueByRecursive f l Set.empty +findFirst : (a -> Bool) -> List a -> Maybe a +findFirst cond l = case l of + x::xs -> if cond x then Just x else findFirst cond xs + [] -> Nothing + +findLast : (a -> Bool) -> List a -> Maybe a +findLast cond l = findFirst cond <| List.reverse l + findFirstBy : (a -> comparable) -> (a -> Bool) -> List a -> Maybe a -findFirstBy sortFunction cond l = List.head <| List.sortBy sortFunction <| List.filter cond l +findFirstBy sortFunction cond l = findFirst cond <| List.sortBy sortFunction l findLastBy : (a -> comparable) -> (a -> Bool) -> List a -> Maybe a -findLastBy sortFunction cond l = List.head <| List.reverse <| List.sortBy sortFunction <| List.filter cond l +findLastBy sortFunction cond l = findLast cond <| List.sortBy sortFunction l findFirstEvent : ({ a | originServerTs : Int } -> Bool) -> List { a | originServerTs : Int } -> Maybe { a | originServerTs : Int } findFirstEvent = findFirstBy .originServerTs @@ -407,6 +415,13 @@ joinedRoomsEvents s = <| Maybe.andThen .join s.rooms -- Business Logic: User Extraction +roomTypingUsers : JoinedRoom -> List Username +roomTypingUsers jr = Maybe.withDefault [] + <| Maybe.andThen (Result.toMaybe << Decode.decodeValue (Decode.field "user_ids" (list string))) + <| Maybe.map .content + <| Maybe.andThen (findLast (((==) "m.typing") << .type_)) + <| Maybe.andThen .events jr.ephemeral + roomsUsers : SyncResponse -> List Username roomsUsers s = let diff --git a/src/Scylla/Views.elm b/src/Scylla/Views.elm index 6d754d3..2d6b22d 100644 --- a/src/Scylla/Views.elm +++ b/src/Scylla/Views.elm @@ -86,6 +86,13 @@ joinedRoomView m roomId jr = events = Maybe.withDefault [] <| Maybe.andThen .events jr.timeline renderedEvents = List.filterMap (eventView m) events eventWrapper = eventWrapperView m renderedEvents + typing = List.map (displayName m) <| roomTypingUsers jr + typingText = String.join ", " typing + typingSuffix = case List.length typing of + 0 -> "" + 1 -> " is typing..." + _ -> " are typing..." + typingWrapper = div [ class "typing-wrapper" ] [ text <| typingText ++ typingSuffix ] messageInput = div [ class "message-wrapper" ] [ input [ type_ "text" @@ -98,6 +105,7 @@ joinedRoomView m roomId jr = div [ class "room-wrapper" ] [ h2 [] [ text <| Maybe.withDefault "" <| roomName jr ] , eventWrapper + , typingWrapper , messageInput ]