1
0
mirror of https://github.com/jhillyerd/inbucket.git synced 2025-12-17 17:47:03 +00:00

ui: Refactor Mailbox model states

This commit is contained in:
James Hillyerd
2018-11-04 12:21:14 -08:00
parent 04a3f58e6d
commit bcf0cafb34

View File

@@ -24,22 +24,29 @@ type Body
| SafeHtmlBody | SafeHtmlBody
type State
= NoSelection
| Selected String
| Viewing Visible
type alias Visible =
{ message : Message
, markSeenAt : Maybe Time
}
type alias Model = type alias Model =
{ name : String { name : String
, selected : Maybe String , state : State
, headers : List MessageHeader , headers : List MessageHeader
, visible :
Maybe
{ message : Message
, markSeenAt : Maybe Time
}
, bodyMode : Body , bodyMode : Body
} }
init : String -> Maybe String -> Model init : String -> Maybe String -> Model
init name id = init name id =
Model name id [] Nothing SafeHtmlBody Model name NoSelection [] SafeHtmlBody
load : String -> Cmd Msg load : String -> Cmd Msg
@@ -56,16 +63,14 @@ load name =
subscriptions : Model -> Sub Msg subscriptions : Model -> Sub Msg
subscriptions model = subscriptions model =
case model.visible of case model.state of
Just { message, markSeenAt } -> Viewing { message } ->
case markSeenAt of if message.seen then
Just time -> Sub.none
Time.every (250 * Time.millisecond) Tick else
Time.every (250 * Time.millisecond) Tick
Nothing -> _ ->
Sub.none
Nothing ->
Sub.none Sub.none
@@ -90,7 +95,7 @@ update : Session -> Msg -> Model -> ( Model, Cmd Msg, Session.Msg )
update session msg model = update session msg model =
case msg of case msg of
ClickMessage id -> ClickMessage id ->
( { model | selected = Just id } ( { model | state = Selected id }
, Cmd.batch , Cmd.batch
[ Route.newUrl (Route.Message model.name id) [ Route.newUrl (Route.Message model.name id)
, getMessage model.name id , getMessage model.name id
@@ -99,7 +104,7 @@ update session msg model =
) )
ViewMessage id -> ViewMessage id ->
( { model | selected = Just id } ( { model | state = Selected id }
, getMessage model.name id , getMessage model.name id
, Session.AddRecent model.name , Session.AddRecent model.name
) )
@@ -118,14 +123,14 @@ update session msg model =
newModel = newModel =
{ model | headers = headers } { model | headers = headers }
in in
case model.selected of case model.state of
Nothing -> Selected id ->
( newModel, Cmd.none, Session.AddRecent model.name )
Just id ->
-- Recurse to select message id. -- Recurse to select message id.
update session (ViewMessage id) newModel update session (ViewMessage id) newModel
_ ->
( newModel, Cmd.none, Session.AddRecent model.name )
MailboxResult (Err err) -> MailboxResult (Err err) ->
( model, Cmd.none, Session.SetFlash (HttpUtil.errorString err) ) ( model, Cmd.none, Session.SetFlash (HttpUtil.errorString err) )
@@ -144,7 +149,7 @@ update session msg model =
model.bodyMode model.bodyMode
in in
( { model ( { model
| visible = Just { message = msg, markSeenAt = Nothing } | state = Viewing { message = msg, markSeenAt = Nothing }
, bodyMode = bodyMode , bodyMode = bodyMode
} }
, Task.perform OpenedTime Time.now , Task.perform OpenedTime Time.now
@@ -158,15 +163,15 @@ update session msg model =
( { model | bodyMode = bodyMode }, Cmd.none, Session.none ) ( { model | bodyMode = bodyMode }, Cmd.none, Session.none )
OpenedTime time -> OpenedTime time ->
case model.visible of case model.state of
Just visible -> Viewing 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 to report message as seen to backend.
( { model ( { model
| visible = | state =
Just Viewing
{ visible { visible
| markSeenAt = Just (time + (1.5 * Time.second)) | markSeenAt = Just (time + (1.5 * Time.second))
} }
@@ -175,12 +180,12 @@ update session msg model =
, Session.none , Session.none
) )
Nothing -> _ ->
( model, Cmd.none, Session.none ) ( model, Cmd.none, Session.none )
Tick now -> Tick now ->
case model.visible of case model.state of
Just { message, markSeenAt } -> Viewing { message, markSeenAt } ->
case markSeenAt of case markSeenAt of
Just deadline -> Just deadline ->
if now >= deadline then if now >= deadline then
@@ -191,7 +196,7 @@ update session msg model =
Nothing -> Nothing ->
( model, Cmd.none, Session.none ) ( model, Cmd.none, Session.none )
Nothing -> _ ->
( model, Cmd.none, Session.none ) ( model, Cmd.none, Session.none )
@@ -216,8 +221,7 @@ deleteMessage model msg =
|> Http.send DeleteMessageResult |> Http.send DeleteMessageResult
in in
( { model ( { model
| visible = Nothing | state = NoSelection
, selected = Nothing
, headers = List.filter (\x -> x.id /= msg.id) model.headers , headers = List.filter (\x -> x.id /= msg.id) model.headers
} }
, cmd , cmd
@@ -237,9 +241,12 @@ getMessage mailbox id =
markMessageSeen : Model -> Message -> ( Model, Cmd Msg, Session.Msg ) markMessageSeen : Model -> Message -> ( Model, Cmd Msg, Session.Msg )
markMessageSeen model message = markMessageSeen model message =
case model.visible of case model.state of
Just visible -> Viewing 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 }
@@ -258,14 +265,19 @@ markMessageSeen model message =
|> Http.send MarkSeenResult |> Http.send MarkSeenResult
in in
( { model ( { model
| visible = Just { visible | markSeenAt = Nothing } | state =
Viewing
{ visible
| message = { message | seen = True }
, markSeenAt = Nothing
}
, headers = List.map updateSeen model.headers , headers = List.map updateSeen model.headers
} }
, command , command
, Session.None , Session.None
) )
Nothing -> _ ->
( model, Cmd.none, Session.none ) ( model, Cmd.none, Session.none )
@@ -279,22 +291,37 @@ view session model =
[ aside [ id "message-list" ] [ messageList model ] [ aside [ id "message-list" ] [ messageList model ]
, main_ , main_
[ id "message" ] [ id "message" ]
[ case model.visible of [ case model.state of
Just { message } -> NoSelection ->
viewMessage message model.bodyMode
Nothing ->
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."
) )
Viewing { message } ->
viewMessage message model.bodyMode
_ ->
text ""
] ]
] ]
messageList : Model -> Html Msg messageList : Model -> Html Msg
messageList model = messageList model =
div [] (List.map (messageChip model.selected) (List.reverse model.headers)) let
selected =
case model.state of
Selected id ->
Just id
Viewing { message } ->
Just message.id
_ ->
Nothing
in
div [] (List.map (messageChip selected) (List.reverse model.headers))
messageChip : Maybe String -> MessageHeader -> Html Msg messageChip : Maybe String -> MessageHeader -> Html Msg