1
0
mirror of https://github.com/jhillyerd/inbucket.git synced 2025-12-18 01:57:02 +00:00

ui: Refactor Mailbox states to reduce cases.

This commit is contained in:
James Hillyerd
2018-11-05 21:20:55 -08:00
parent 5ab273b7b8
commit 54ca36c442

View File

@@ -38,10 +38,14 @@ type Body
type State type State
= LoadingList (Maybe MessageID) = LoadingList (Maybe MessageID)
| ShowingList MessageList (Maybe MessageID) | ShowingList MessageList MessageState
| LoadingMessage MessageList MessageID
| ShowingMessage MessageList VisibleMessage
| Transitioning MessageList VisibleMessage MessageID type MessageState
= NoMessage
| LoadingMessage MessageID
| ShowingMessage VisibleMessage
| Transitioning VisibleMessage MessageID
type alias MessageID = type alias MessageID =
@@ -88,7 +92,7 @@ load mailboxName =
subscriptions : Model -> Sub Msg subscriptions : Model -> Sub Msg
subscriptions model = subscriptions model =
case model.state of case model.state of
ShowingMessage _ { message } -> ShowingList _ (ShowingMessage { message }) ->
if message.seen then if message.seen then
Sub.none Sub.none
else else
@@ -122,7 +126,7 @@ update session msg model =
ClickMessage id -> ClickMessage id ->
( updateSelected model id ( updateSelected model id
, Cmd.batch , Cmd.batch
[ -- Update browser location [ -- Update browser location.
Route.newUrl (Route.Message model.mailboxName id) Route.newUrl (Route.Message model.mailboxName id)
, getMessage model.mailboxName id , getMessage model.mailboxName id
] ]
@@ -149,7 +153,7 @@ update session msg model =
LoadingList selection -> LoadingList selection ->
let let
newModel = newModel =
{ model | state = ShowingList (MessageList headers "") selection } { model | state = ShowingList (MessageList headers "") NoMessage }
in in
case selection of case selection of
Just id -> Just id ->
@@ -181,21 +185,23 @@ update session msg model =
( { model | bodyMode = bodyMode }, Cmd.none, Session.none ) ( { model | bodyMode = bodyMode }, Cmd.none, Session.none )
SearchInput searchInput -> SearchInput searchInput ->
updateSearch model searchInput updateSearchInput model searchInput
OpenedTime time -> OpenedTime time ->
case model.state of case model.state of
ShowingMessage list visible -> ShowingList list (ShowingMessage visible) ->
if visible.message.seen then if visible.message.seen then
( model, Cmd.none, Session.none ) ( model, Cmd.none, Session.none )
else else
-- Set delay to report message as seen to backend. -- Set delay before reporting message as seen to backend.
( { model ( { model
| state = | state =
ShowingMessage list ShowingList list
{ visible (ShowingMessage
| markSeenAt = Just (time + (1.5 * Time.second)) { visible
} | markSeenAt = Just (time + (1.5 * Time.second))
}
)
} }
, Cmd.none , Cmd.none
, Session.none , Session.none
@@ -206,7 +212,7 @@ update session msg model =
Tick now -> Tick now ->
case model.state of case model.state of
ShowingMessage _ { message, markSeenAt } -> ShowingList _ (ShowingMessage { message, markSeenAt }) ->
case markSeenAt of case markSeenAt of
Just deadline -> Just deadline ->
if now >= deadline then if now >= deadline then
@@ -221,6 +227,8 @@ update session msg model =
( model, Cmd.none, Session.none ) ( model, Cmd.none, Session.none )
{-| Replace the currently displayed message.
-}
updateMessageResult : Model -> Message -> ( Model, Cmd Msg, Session.Msg ) updateMessageResult : Model -> Message -> ( Model, Cmd Msg, Session.Msg )
updateMessageResult model message = updateMessageResult model message =
let let
@@ -229,80 +237,58 @@ updateMessageResult model message =
TextBody TextBody
else else
model.bodyMode model.bodyMode
updateMessage list message =
( { model
| state = ShowingMessage list { message = message, markSeenAt = Nothing }
, bodyMode = bodyMode
}
, Task.perform OpenedTime Time.now
, Session.none
)
in in
case model.state of case model.state of
LoadingList _ -> LoadingList _ ->
( model, Cmd.none, Session.none ) ( model, Cmd.none, Session.none )
ShowingList list _ -> ShowingList list _ ->
updateMessage list message ( { model
| state = ShowingList list (ShowingMessage (VisibleMessage message Nothing))
LoadingMessage list _ -> , bodyMode = bodyMode
updateMessage list message }
, Task.perform OpenedTime Time.now
ShowingMessage list _ -> , Session.none
updateMessage list message )
Transitioning list _ _ ->
updateMessage list message
updateSearch : Model -> String -> ( Model, Cmd Msg, Session.Msg ) updateSearchInput : Model -> String -> ( Model, Cmd Msg, Session.Msg )
updateSearch model searchInput = updateSearchInput model searchInput =
let let
updateList list = searchFilter =
{ list if String.length searchInput > 1 then
| searchFilter = String.toLower searchInput
if String.length searchInput > 1 then else
String.toLower searchInput ""
else
""
}
updateModel state =
( { model | searchInput = searchInput, state = state }
, Cmd.none
, Session.none
)
in in
case model.state of case model.state of
LoadingList _ -> LoadingList _ ->
( model, Cmd.none, Session.none ) ( model, Cmd.none, Session.none )
ShowingList list selection -> ShowingList list messageState ->
updateModel (ShowingList (updateList list) selection) ( { model
| searchInput = searchInput
LoadingMessage list id -> , state = ShowingList { list | searchFilter = searchFilter } messageState
updateModel (LoadingMessage (updateList list) id) }
, Cmd.none
ShowingMessage list visible -> , Session.none
updateModel (ShowingMessage (updateList list) visible) )
Transitioning list visible id ->
updateModel (Transitioning (updateList list) visible id)
{-| Set the selected message in our model.
-}
updateSelected : Model -> MessageID -> Model updateSelected : Model -> MessageID -> Model
updateSelected model id = updateSelected model id =
case model.state of case model.state of
ShowingList list _ -> ShowingList list NoMessage ->
{ model | state = LoadingMessage list id } { model | state = ShowingList list (LoadingMessage id) }
ShowingMessage list visible -> ShowingList list (ShowingMessage visible) ->
-- Use Transitioning state to prevent message flicker. -- Use Transitioning state to prevent blank message flicker.
{ model | state = Transitioning list visible id } { model | state = ShowingList list (Transitioning visible id) }
Transitioning list visible _ -> ShowingList list (Transitioning visible _) ->
{ model | state = Transitioning list visible id } { model | state = ShowingList list (Transitioning visible id) }
_ -> _ ->
model model
@@ -322,9 +308,10 @@ updateDeleteMessage model message =
{ messageList | headers = List.filter f messageList.headers } { messageList | headers = List.filter f messageList.headers }
in in
case model.state of case model.state of
ShowingMessage list _ -> ShowingList list _ ->
( { model ( { model
| state = ShowingList (filter (\x -> x.id /= message.id) list) Nothing | state =
ShowingList (filter (\x -> x.id /= message.id) list) NoMessage
} }
, cmd , cmd
, Session.none , Session.none
@@ -337,11 +324,8 @@ updateDeleteMessage model message =
updateMarkMessageSeen : Model -> Message -> ( Model, Cmd Msg, Session.Msg ) updateMarkMessageSeen : Model -> Message -> ( Model, Cmd Msg, Session.Msg )
updateMarkMessageSeen model message = updateMarkMessageSeen model message =
case model.state of case model.state of
ShowingMessage list visible -> ShowingList list (ShowingMessage visible) ->
let let
message =
visible.message
updateSeen header = updateSeen header =
if header.id == message.id then if header.id == message.id then
{ header | seen = True } { header | seen = True }
@@ -364,11 +348,13 @@ updateMarkMessageSeen model message =
in in
( { model ( { model
| state = | state =
ShowingMessage (map updateSeen list) ShowingList (map updateSeen list)
{ visible (ShowingMessage
| message = { message | seen = True } { visible
, markSeenAt = Nothing | message = { message | seen = True }
} , markSeenAt = Nothing
}
)
} }
, command , command
, Session.None , Session.None
@@ -407,36 +393,43 @@ view session model =
div [ id "page", class "mailbox" ] div [ id "page", class "mailbox" ]
[ aside [ id "message-list" ] [ aside [ id "message-list" ]
[ div [] [ div []
[ input [ type_ "search", placeholder "search", onInput SearchInput, value model.searchInput ] [] ] [ input
[ type_ "search"
, placeholder "search"
, onInput SearchInput
, value model.searchInput
]
[]
]
, case model.state of , case model.state of
LoadingList _ -> LoadingList _ ->
div [] [] div [] []
ShowingList list selection -> ShowingList list NoMessage ->
messageList list selection messageList list Nothing
LoadingMessage list selection -> ShowingList list (LoadingMessage id) ->
messageList list (Just selection) messageList list (Just id)
ShowingMessage list visible -> ShowingList list (ShowingMessage visible) ->
messageList list (Just visible.message.id) messageList list (Just visible.message.id)
Transitioning list _ selection -> ShowingList list (Transitioning _ id) ->
messageList list (Just selection) messageList list (Just id)
] ]
, main_ , main_
[ id "message" ] [ id "message" ]
[ case model.state of [ case model.state of
ShowingList _ _ -> ShowingList _ NoMessage ->
text text
("Select a message on the left," ("Select a message on the left,"
++ " or enter a different username into the box on upper right." ++ " or enter a different username into the box on upper right."
) )
ShowingMessage _ { message } -> ShowingList _ (ShowingMessage { message }) ->
viewMessage message model.bodyMode viewMessage message model.bodyMode
Transitioning _ { message } _ -> ShowingList _ (Transitioning { message } _) ->
viewMessage message model.bodyMode viewMessage message model.bodyMode
_ -> _ ->