mirror of
https://github.com/jhillyerd/inbucket.git
synced 2026-01-10 13:15:56 +00:00
ui: Add an Effect system to handle global state and Elm Cmds (#176)
All pages now leverage Effects for most of their Session and Cmd requests. More work required for routing and other lingering Cmd use.
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
module Page.Mailbox exposing (Model, Msg, init, load, subscriptions, update, view)
|
||||
module Page.Mailbox exposing (Model, Msg, init, subscriptions, update, view)
|
||||
|
||||
import Api
|
||||
import Browser.Navigation as Nav
|
||||
import Data.Message as Message exposing (Message)
|
||||
import Data.MessageHeader exposing (MessageHeader)
|
||||
import Data.Session as Session exposing (Session)
|
||||
import Data.Session exposing (Session)
|
||||
import DateFormat as DF
|
||||
import DateFormat.Relative as Relative
|
||||
import Effect exposing (Effect)
|
||||
import Html
|
||||
exposing
|
||||
( Attribute
|
||||
@@ -54,7 +55,6 @@ import Json.Decode as D
|
||||
import Json.Encode as E
|
||||
import Modal
|
||||
import Route
|
||||
import Task
|
||||
import Time exposing (Posix)
|
||||
import Timer exposing (Timer)
|
||||
|
||||
@@ -103,7 +103,7 @@ type alias Model =
|
||||
}
|
||||
|
||||
|
||||
init : Session -> String -> Maybe MessageID -> ( Model, Cmd Msg )
|
||||
init : Session -> String -> Maybe MessageID -> ( Model, Effect Msg )
|
||||
init session mailboxName selection =
|
||||
( { session = session
|
||||
, mailboxName = mailboxName
|
||||
@@ -114,16 +114,11 @@ init session mailboxName selection =
|
||||
, markSeenTimer = Timer.empty
|
||||
, now = Time.millisToPosix 0
|
||||
}
|
||||
, load session mailboxName
|
||||
)
|
||||
|
||||
|
||||
load : Session -> String -> Cmd Msg
|
||||
load session mailboxName =
|
||||
Cmd.batch
|
||||
[ Task.perform Tick Time.now
|
||||
, Api.getHeaderList session ListLoaded mailboxName
|
||||
, Effect.batch
|
||||
[ Effect.posixTime Tick
|
||||
, Effect.getHeaderList ListLoaded mailboxName
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -159,38 +154,38 @@ type Msg
|
||||
| ModalFocused Modal.Msg
|
||||
|
||||
|
||||
update : Msg -> Model -> ( Model, Cmd Msg )
|
||||
update : Msg -> Model -> ( Model, Effect Msg )
|
||||
update msg model =
|
||||
case msg of
|
||||
ClickMessage id ->
|
||||
( updateSelected { model | session = Session.disableRouting model.session } id
|
||||
, Cmd.batch
|
||||
( updateSelected model id
|
||||
, Effect.batch
|
||||
[ -- Update browser location.
|
||||
Route.Message model.mailboxName id
|
||||
Effect.disableRouting
|
||||
, Route.Message model.mailboxName id
|
||||
|> model.session.router.toPath
|
||||
|> Nav.replaceUrl model.session.key
|
||||
, Api.getMessage model.session MessageLoaded model.mailboxName id
|
||||
|> Effect.wrap
|
||||
, Effect.getMessage MessageLoaded model.mailboxName id
|
||||
]
|
||||
)
|
||||
|
||||
CloseMessage ->
|
||||
case model.state of
|
||||
ShowingList list _ ->
|
||||
( { model | state = ShowingList list NoMessage }, Cmd.none )
|
||||
( { model | state = ShowingList list NoMessage }, Effect.none )
|
||||
|
||||
_ ->
|
||||
( model, Cmd.none )
|
||||
( model, Effect.none )
|
||||
|
||||
DeleteMessage message ->
|
||||
updateDeleteMessage model message
|
||||
|
||||
DeletedMessage (Ok _) ->
|
||||
( model, Cmd.none )
|
||||
( model, Effect.none )
|
||||
|
||||
DeletedMessage (Err err) ->
|
||||
( { model | session = Session.showFlash (HttpUtil.errorFlash err) model.session }
|
||||
, Cmd.none
|
||||
)
|
||||
( model, Effect.showFlash (HttpUtil.errorFlash err) )
|
||||
|
||||
ListKeyPress id keyCode ->
|
||||
case keyCode of
|
||||
@@ -198,7 +193,7 @@ update msg model =
|
||||
updateOpenMessage model id
|
||||
|
||||
_ ->
|
||||
( model, Cmd.none )
|
||||
( model, Effect.none )
|
||||
|
||||
ListLoaded (Ok headers) ->
|
||||
case model.state of
|
||||
@@ -214,63 +209,51 @@ update msg model =
|
||||
updateOpenMessage newModel id
|
||||
|
||||
Nothing ->
|
||||
( { newModel
|
||||
| session = Session.addRecent model.mailboxName model.session
|
||||
}
|
||||
, Cmd.none
|
||||
)
|
||||
( newModel, Effect.addRecent newModel.mailboxName )
|
||||
|
||||
_ ->
|
||||
( model, Cmd.none )
|
||||
( model, Effect.none )
|
||||
|
||||
ListLoaded (Err err) ->
|
||||
( { model | session = Session.showFlash (HttpUtil.errorFlash err) model.session }
|
||||
, Cmd.none
|
||||
)
|
||||
( model, Effect.showFlash (HttpUtil.errorFlash err) )
|
||||
|
||||
MarkSeenLoaded (Ok _) ->
|
||||
( model, Cmd.none )
|
||||
( model, Effect.none )
|
||||
|
||||
MarkSeenLoaded (Err err) ->
|
||||
( { model | session = Session.showFlash (HttpUtil.errorFlash err) model.session }
|
||||
, Cmd.none
|
||||
)
|
||||
( model, Effect.showFlash (HttpUtil.errorFlash err) )
|
||||
|
||||
MessageLoaded (Ok message) ->
|
||||
updateMessageResult model message
|
||||
|
||||
MessageLoaded (Err err) ->
|
||||
( { model | session = Session.showFlash (HttpUtil.errorFlash err) model.session }
|
||||
, Cmd.none
|
||||
)
|
||||
( model, Effect.showFlash (HttpUtil.errorFlash err) )
|
||||
|
||||
MessageBody bodyMode ->
|
||||
( { model | bodyMode = bodyMode }, Cmd.none )
|
||||
( { model | bodyMode = bodyMode }, Effect.none )
|
||||
|
||||
ModalFocused message ->
|
||||
( { model | session = Modal.updateSession message model.session }
|
||||
, Cmd.none
|
||||
, Effect.none
|
||||
)
|
||||
|
||||
OnSearchInput searchInput ->
|
||||
updateSearchInput model searchInput
|
||||
|
||||
PurgeMailboxPrompt ->
|
||||
( { model | promptPurge = True }, Modal.resetFocusCmd ModalFocused )
|
||||
( { model | promptPurge = True }, Modal.resetFocusCmd ModalFocused |> Effect.wrap )
|
||||
|
||||
PurgeMailboxCanceled ->
|
||||
( { model | promptPurge = False }, Cmd.none )
|
||||
( { model | promptPurge = False }, Effect.none )
|
||||
|
||||
PurgeMailboxConfirmed ->
|
||||
updateTriggerPurge model
|
||||
|
||||
PurgedMailbox (Ok _) ->
|
||||
( model, Cmd.none )
|
||||
( model, Effect.none )
|
||||
|
||||
PurgedMailbox (Err err) ->
|
||||
( { model | session = Session.showFlash (HttpUtil.errorFlash err) model.session }
|
||||
, Cmd.none
|
||||
)
|
||||
( model, Effect.showFlash (HttpUtil.errorFlash err) )
|
||||
|
||||
MarkSeenTriggered timer ->
|
||||
if timer == model.markSeenTimer then
|
||||
@@ -278,15 +261,15 @@ update msg model =
|
||||
updateMarkMessageSeen model
|
||||
|
||||
else
|
||||
( model, Cmd.none )
|
||||
( model, Effect.none )
|
||||
|
||||
Tick now ->
|
||||
( { model | now = now }, Cmd.none )
|
||||
( { model | now = now }, Effect.none )
|
||||
|
||||
|
||||
{-| Replace the currently displayed message.
|
||||
-}
|
||||
updateMessageResult : Model -> Message -> ( Model, Cmd Msg )
|
||||
updateMessageResult : Model -> Message -> ( Model, Effect Msg )
|
||||
updateMessageResult model message =
|
||||
let
|
||||
bodyMode =
|
||||
@@ -298,7 +281,7 @@ updateMessageResult model message =
|
||||
in
|
||||
case model.state of
|
||||
LoadingList _ ->
|
||||
( model, Cmd.none )
|
||||
( model, Effect.none )
|
||||
|
||||
ShowingList list _ ->
|
||||
let
|
||||
@@ -314,38 +297,38 @@ updateMessageResult model message =
|
||||
, markSeenTimer = newTimer
|
||||
}
|
||||
-- Set 1500ms delay before reporting message as seen to backend.
|
||||
, Timer.schedule MarkSeenTriggered newTimer 1500
|
||||
, Effect.schedule MarkSeenTriggered newTimer 1500
|
||||
)
|
||||
|
||||
|
||||
{-| Updates model and triggers commands to purge this mailbox.
|
||||
-}
|
||||
updateTriggerPurge : Model -> ( Model, Cmd Msg )
|
||||
updateTriggerPurge : Model -> ( Model, Effect Msg )
|
||||
updateTriggerPurge model =
|
||||
let
|
||||
cmd =
|
||||
Cmd.batch
|
||||
effects =
|
||||
Effect.batch
|
||||
[ Route.Mailbox model.mailboxName
|
||||
|> model.session.router.toPath
|
||||
|> Nav.replaceUrl model.session.key
|
||||
, Api.purgeMailbox model.session PurgedMailbox model.mailboxName
|
||||
|> Effect.wrap
|
||||
, Effect.purgeMailbox PurgedMailbox model.mailboxName
|
||||
]
|
||||
in
|
||||
case model.state of
|
||||
ShowingList _ _ ->
|
||||
( { model
|
||||
| promptPurge = False
|
||||
, session = Session.disableRouting model.session
|
||||
, state = ShowingList (MessageList [] Nothing "") NoMessage
|
||||
}
|
||||
, cmd
|
||||
, Effect.batch [ Effect.disableRouting, effects ]
|
||||
)
|
||||
|
||||
_ ->
|
||||
( model, cmd )
|
||||
( model, effects )
|
||||
|
||||
|
||||
updateSearchInput : Model -> String -> ( Model, Cmd Msg )
|
||||
updateSearchInput : Model -> String -> ( Model, Effect Msg )
|
||||
updateSearchInput model searchInput =
|
||||
let
|
||||
searchFilter =
|
||||
@@ -357,14 +340,14 @@ updateSearchInput model searchInput =
|
||||
in
|
||||
case model.state of
|
||||
LoadingList _ ->
|
||||
( model, Cmd.none )
|
||||
( model, Effect.none )
|
||||
|
||||
ShowingList list messageState ->
|
||||
( { model
|
||||
| searchInput = searchInput
|
||||
, state = ShowingList { list | searchFilter = searchFilter } messageState
|
||||
}
|
||||
, Cmd.none
|
||||
, Effect.none
|
||||
)
|
||||
|
||||
|
||||
@@ -396,7 +379,7 @@ updateSelected model id =
|
||||
{ model | state = ShowingList newList (Transitioning visible) }
|
||||
|
||||
|
||||
updateDeleteMessage : Model -> Message -> ( Model, Cmd Msg )
|
||||
updateDeleteMessage : Model -> Message -> ( Model, Effect Msg )
|
||||
updateDeleteMessage model message =
|
||||
let
|
||||
filter f messageList =
|
||||
@@ -404,26 +387,24 @@ updateDeleteMessage model message =
|
||||
in
|
||||
case model.state of
|
||||
ShowingList list _ ->
|
||||
( { model
|
||||
| session = Session.disableRouting model.session
|
||||
, state =
|
||||
ShowingList (filter (\x -> x.id /= message.id) list) NoMessage
|
||||
}
|
||||
, Cmd.batch
|
||||
[ Api.deleteMessage model.session DeletedMessage message.mailbox message.id
|
||||
( { model | state = ShowingList (filter (\x -> x.id /= message.id) list) NoMessage }
|
||||
, Effect.batch
|
||||
[ Effect.deleteMessage DeletedMessage message.mailbox message.id
|
||||
, Effect.disableRouting
|
||||
, Route.Mailbox model.mailboxName
|
||||
|> model.session.router.toPath
|
||||
|> Nav.replaceUrl model.session.key
|
||||
|> Effect.wrap
|
||||
]
|
||||
)
|
||||
|
||||
_ ->
|
||||
( model, Cmd.none )
|
||||
( model, Effect.none )
|
||||
|
||||
|
||||
{-| Updates both the active message, and the message list to mark the currently viewed message as seen.
|
||||
-}
|
||||
updateMarkMessageSeen : Model -> ( Model, Cmd Msg )
|
||||
updateMarkMessageSeen : Model -> ( Model, Effect Msg )
|
||||
updateMarkMessageSeen model =
|
||||
case model.state of
|
||||
ShowingList messages (ShowingMessage visibleMessage) ->
|
||||
@@ -442,21 +423,20 @@ updateMarkMessageSeen model =
|
||||
| state =
|
||||
ShowingList newMessages (ShowingMessage { visibleMessage | seen = True })
|
||||
}
|
||||
, Api.markMessageSeen model.session MarkSeenLoaded visibleMessage.mailbox visibleMessage.id
|
||||
, Effect.markMessageSeen MarkSeenLoaded visibleMessage.mailbox visibleMessage.id
|
||||
)
|
||||
|
||||
_ ->
|
||||
( model, Cmd.none )
|
||||
( model, Effect.none )
|
||||
|
||||
|
||||
updateOpenMessage : Model -> String -> ( Model, Cmd Msg )
|
||||
updateOpenMessage : Model -> String -> ( Model, Effect Msg )
|
||||
updateOpenMessage model id =
|
||||
let
|
||||
newModel =
|
||||
{ model | session = Session.addRecent model.mailboxName model.session }
|
||||
in
|
||||
( updateSelected newModel id
|
||||
, Api.getMessage model.session MessageLoaded model.mailboxName id
|
||||
( updateSelected model id
|
||||
, Effect.batch
|
||||
[ Effect.addRecent model.mailboxName
|
||||
, Effect.getMessage MessageLoaded model.mailboxName id
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user