mirror of
https://github.com/jhillyerd/inbucket.git
synced 2025-12-17 09:37:02 +00:00
Merge branch 'feature/mouse-out-delay' into develop
This commit is contained in:
@@ -38,7 +38,10 @@ import Html.Attributes
|
|||||||
)
|
)
|
||||||
import Html.Events as Events
|
import Html.Events as Events
|
||||||
import Modal
|
import Modal
|
||||||
|
import Process
|
||||||
import Route exposing (Route)
|
import Route exposing (Route)
|
||||||
|
import Task
|
||||||
|
import Timer exposing (Timer)
|
||||||
|
|
||||||
|
|
||||||
{-| Used to highlight current page in navbar.
|
{-| Used to highlight current page in navbar.
|
||||||
@@ -52,8 +55,9 @@ type Page
|
|||||||
|
|
||||||
type alias Model msg =
|
type alias Model msg =
|
||||||
{ mapMsg : Msg -> msg
|
{ mapMsg : Msg -> msg
|
||||||
, menuVisible : Bool
|
, mainMenuVisible : Bool
|
||||||
, recentVisible : Bool
|
, recentMenuVisible : Bool
|
||||||
|
, recentMenuTimer : Timer
|
||||||
, mailboxName : String
|
, mailboxName : String
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,8 +65,9 @@ type alias Model msg =
|
|||||||
init : (Msg -> msg) -> Model msg
|
init : (Msg -> msg) -> Model msg
|
||||||
init mapMsg =
|
init mapMsg =
|
||||||
{ mapMsg = mapMsg
|
{ mapMsg = mapMsg
|
||||||
, menuVisible = False
|
, mainMenuVisible = False
|
||||||
, recentVisible = False
|
, recentMenuVisible = False
|
||||||
|
, recentMenuTimer = Timer.empty
|
||||||
, mailboxName = ""
|
, mailboxName = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,20 +77,24 @@ init mapMsg =
|
|||||||
reset : Model msg -> Model msg
|
reset : Model msg -> Model msg
|
||||||
reset model =
|
reset model =
|
||||||
{ model
|
{ model
|
||||||
| menuVisible = False
|
| mainMenuVisible = False
|
||||||
, recentVisible = False
|
, recentMenuVisible = False
|
||||||
|
, recentMenuTimer = Timer.cancel model.recentMenuTimer
|
||||||
, mailboxName = ""
|
, mailboxName = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type Msg
|
type Msg
|
||||||
= ClearFlash
|
= ClearFlash
|
||||||
|
| MainMenuToggled
|
||||||
| ModalFocused Modal.Msg
|
| ModalFocused Modal.Msg
|
||||||
| ModalUnfocused
|
| ModalUnfocused
|
||||||
| OnMailboxNameInput String
|
| OnMailboxNameInput String
|
||||||
| OpenMailbox
|
| OpenMailbox
|
||||||
| ShowRecent Bool
|
| RecentMenuMouseOver
|
||||||
| ToggleMenu
|
| RecentMenuMouseOut
|
||||||
|
| RecentMenuTimeout Timer
|
||||||
|
| RecentMenuToggled
|
||||||
|
|
||||||
|
|
||||||
update : Msg -> Model msg -> Session -> ( Model msg, Session, Cmd msg )
|
update : Msg -> Model msg -> Session -> ( Model msg, Session, Cmd msg )
|
||||||
@@ -97,6 +106,12 @@ update msg model session =
|
|||||||
, Cmd.none
|
, Cmd.none
|
||||||
)
|
)
|
||||||
|
|
||||||
|
MainMenuToggled ->
|
||||||
|
( { model | mainMenuVisible = not model.mainMenuVisible }
|
||||||
|
, session
|
||||||
|
, Cmd.none
|
||||||
|
)
|
||||||
|
|
||||||
ModalFocused message ->
|
ModalFocused message ->
|
||||||
( model
|
( model
|
||||||
, Modal.updateSession message session
|
, Modal.updateSession message session
|
||||||
@@ -122,14 +137,43 @@ update msg model session =
|
|||||||
, Route.pushUrl session.key (Route.Mailbox model.mailboxName)
|
, Route.pushUrl session.key (Route.Mailbox model.mailboxName)
|
||||||
)
|
)
|
||||||
|
|
||||||
ShowRecent visible ->
|
RecentMenuMouseOver ->
|
||||||
( { model | recentVisible = visible }
|
( { model
|
||||||
|
| recentMenuVisible = True
|
||||||
|
, recentMenuTimer = Timer.cancel model.recentMenuTimer
|
||||||
|
}
|
||||||
, session
|
, session
|
||||||
, Cmd.none
|
, Cmd.none
|
||||||
)
|
)
|
||||||
|
|
||||||
ToggleMenu ->
|
RecentMenuMouseOut ->
|
||||||
( { model | menuVisible = not model.menuVisible }
|
let
|
||||||
|
newTimer =
|
||||||
|
Timer.replace model.recentMenuTimer
|
||||||
|
in
|
||||||
|
( { model
|
||||||
|
| recentMenuTimer = newTimer
|
||||||
|
}
|
||||||
|
, session
|
||||||
|
, Timer.schedule (RecentMenuTimeout >> model.mapMsg) newTimer 400
|
||||||
|
)
|
||||||
|
|
||||||
|
RecentMenuTimeout timer ->
|
||||||
|
if timer == model.recentMenuTimer then
|
||||||
|
( { model
|
||||||
|
| recentMenuVisible = False
|
||||||
|
, recentMenuTimer = Timer.cancel timer
|
||||||
|
}
|
||||||
|
, session
|
||||||
|
, Cmd.none
|
||||||
|
)
|
||||||
|
|
||||||
|
else
|
||||||
|
-- Timer was no longer valid.
|
||||||
|
( model, session, Cmd.none )
|
||||||
|
|
||||||
|
RecentMenuToggled ->
|
||||||
|
( { model | recentMenuVisible = not model.recentMenuVisible }
|
||||||
, session
|
, session
|
||||||
, Cmd.none
|
, Cmd.none
|
||||||
)
|
)
|
||||||
@@ -150,11 +194,11 @@ frame { model, session, activePage, activeMailbox, modal, content } =
|
|||||||
div [ class "app" ]
|
div [ class "app" ]
|
||||||
[ header []
|
[ header []
|
||||||
[ nav [ class "navbar" ]
|
[ nav [ class "navbar" ]
|
||||||
[ button [ class "navbar-toggle", Events.onClick (ToggleMenu |> model.mapMsg) ]
|
[ button [ class "navbar-toggle", Events.onClick (MainMenuToggled |> model.mapMsg) ]
|
||||||
[ i [ class "fas fa-bars" ] [] ]
|
[ i [ class "fas fa-bars" ] [] ]
|
||||||
, span [ class "navbar-brand" ]
|
, span [ class "navbar-brand" ]
|
||||||
[ a [ Route.href Route.Home ] [ text "@ inbucket" ] ]
|
[ a [ Route.href Route.Home ] [ text "@ inbucket" ] ]
|
||||||
, ul [ class "main-nav", classList [ ( "active", model.menuVisible ) ] ]
|
, ul [ class "main-nav", classList [ ( "active", model.mainMenuVisible ) ] ]
|
||||||
[ if session.config.monitorVisible then
|
[ if session.config.monitorVisible then
|
||||||
navbarLink Monitor Route.Monitor [ text "Monitor" ] activePage
|
navbarLink Monitor Route.Monitor [ text "Monitor" ] activePage
|
||||||
|
|
||||||
@@ -256,15 +300,15 @@ navbarRecent page activeMailbox model session =
|
|||||||
[ class "navbar-dropdown-container"
|
[ class "navbar-dropdown-container"
|
||||||
, classList [ ( "navbar-active", active ) ]
|
, classList [ ( "navbar-active", active ) ]
|
||||||
, attribute "aria-haspopup" "true"
|
, attribute "aria-haspopup" "true"
|
||||||
, ariaExpanded model.recentVisible
|
, ariaExpanded model.recentMenuVisible
|
||||||
, Events.onMouseOver (ShowRecent True |> model.mapMsg)
|
, Events.onMouseOver (RecentMenuMouseOver |> model.mapMsg)
|
||||||
, Events.onMouseOut (ShowRecent False |> model.mapMsg)
|
, Events.onMouseOut (RecentMenuMouseOut |> model.mapMsg)
|
||||||
]
|
]
|
||||||
[ span [ class "navbar-dropdown" ]
|
[ span [ class "navbar-dropdown" ]
|
||||||
[ text title
|
[ text title
|
||||||
, button
|
, button
|
||||||
[ class "navbar-dropdown-button"
|
[ class "navbar-dropdown-button"
|
||||||
, Events.onClick (ShowRecent (not model.recentVisible) |> model.mapMsg)
|
, Events.onClick (RecentMenuToggled |> model.mapMsg)
|
||||||
]
|
]
|
||||||
[ i [ class "fas fa-chevron-down" ] [] ]
|
[ i [ class "fas fa-chevron-down" ] [] ]
|
||||||
]
|
]
|
||||||
|
|||||||
58
ui/src/Timer.elm
Normal file
58
ui/src/Timer.elm
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
module Timer exposing (Timer, cancel, empty, replace, schedule)
|
||||||
|
|
||||||
|
import Process
|
||||||
|
import Task
|
||||||
|
|
||||||
|
|
||||||
|
{-| Implements an identity to track an asynchronous timer.
|
||||||
|
-}
|
||||||
|
type Timer
|
||||||
|
= Empty
|
||||||
|
| Idle Int
|
||||||
|
| Timer Int
|
||||||
|
|
||||||
|
|
||||||
|
empty : Timer
|
||||||
|
empty =
|
||||||
|
Empty
|
||||||
|
|
||||||
|
|
||||||
|
schedule : (Timer -> msg) -> Timer -> Float -> Cmd msg
|
||||||
|
schedule message timer millis =
|
||||||
|
Task.perform (always (message timer)) (Process.sleep millis)
|
||||||
|
|
||||||
|
|
||||||
|
{-| Replaces the provided timer with a newly created one.
|
||||||
|
-}
|
||||||
|
replace : Timer -> Timer
|
||||||
|
replace previous =
|
||||||
|
case previous of
|
||||||
|
Empty ->
|
||||||
|
Timer 0
|
||||||
|
|
||||||
|
Idle index ->
|
||||||
|
Timer (next index)
|
||||||
|
|
||||||
|
Timer index ->
|
||||||
|
Timer (next index)
|
||||||
|
|
||||||
|
|
||||||
|
{-| Cancels the provided timer without creating a replacement.
|
||||||
|
-}
|
||||||
|
cancel : Timer -> Timer
|
||||||
|
cancel previous =
|
||||||
|
case previous of
|
||||||
|
Timer index ->
|
||||||
|
Idle index
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
previous
|
||||||
|
|
||||||
|
|
||||||
|
next : Int -> Int
|
||||||
|
next index =
|
||||||
|
if index > 2 ^ 30 then
|
||||||
|
0
|
||||||
|
|
||||||
|
else
|
||||||
|
index + 1
|
||||||
Reference in New Issue
Block a user