hum-0.2.0.0: src/Hum/Views/Queue.hs
-- | Module : Hum.Views.Queue
-- Copyright : (c) Itai Y. Efrat 2020-2021
-- License : GPLv2-or-later (see LICENSE)
-- Maintainer : Itai Y. Efrat <itai3397@gmail.com>
--
-- Functions for the Queue view.
module Hum.Views.Queue where
import Hum.Types
import Brick.Main
import Graphics.Vty.Input.Events
import Brick.Types
import Brick.Widgets.Core
import Brick.Widgets.Center
import Brick.Widgets.List
import Hum.Attributes
import Hum.Utils
import Hum.Rebuild
import Hum.Views.Common
import Network.MPD ( withMPD )
import qualified Network.MPD as MPD
import Control.Lens
-- | Draw the queue.
drawViewQueue :: HumState -> Widget Name
drawViewQueue st = reportExtent Queue $
Widget Greedy Greedy $ do
ctx <- getContext
let vsize = ctx ^. windowHeightL - 6 -- HACK Don't hardcode nowplaying size?
render $ hCenter
( vLimit vsize
. center
$ hCenter header
<=> hCenter
(renderList (const (queueRow st))
((focQueue . focus $ st) == FocQueue)
(queue st)
)
)
where
{-songIdx = column (Just (Col 4)) Max (Pad 1) $ txt "Inx"
songId = column (Just (Col 3)) Max (Pad 1) $ txt "ID"-}
album =
withAttr albumAttr $ column (Just (Per 25)) (Pad 1) Max $ txt "Album"
track = withAttr trackAttr $ column (Just (Col 3)) Max (Pad 1) $ txt "#"
title = withAttr titleAttr $ column Nothing Max Max $ txt "Title"
artist =
withAttr artistAttr $ column (Just (Per 25)) Max (Pad 1) $ txt "Artist"
time =
withAttr timeAttr $ column (Just (Col 5)) Max (Pad 1) $ txt "Time"
header = withDefAttr headerAttr
({-songIdx <+> songId <+>-}
album <+> track <+> title <+> artist <+> time)
-- | Draw individual row in queue.
queueRow :: HumState -> (MPD.Song, Highlight) -> Widget n
queueRow st (song, hl) =
(if hl then highlightOverAttrs else id)
. (if Just (MPD.sgIndex song) == (MPD.sgIndex <$> nowPlaying)
then withDefAttr queueNowPlayingAttr
else id
)
$ hCenter ( {-songIdx
<+> songId
<+> -}
album <+> track <+> title <+> artist <+> time)
where
nowPlaying = currentSong st
{-songIdx =
column (Just (Col 4)) Max (Pad 1) $ txt $ maybe "?" show $ MPD.sgIndex song
songId =
column (Just (Col 3)) Max (Pad 1)
$ txt
$ maybe "?" (\(MPD.Id x) -> show x)
$ MPD.sgId song-}
album =
withAttr albumAttr $ column (Just (Per 25)) (Pad 1) Max $ txt $ meta
"<no album>"
MPD.Album
song
track =
withAttr trackAttr $ column (Just (Col 3)) Max (Pad 1) $ txt $ meta
"?"
MPD.Track
song
title = withAttr titleAttr $ column Nothing Max Max $ txt $ meta
"<no title>"
MPD.Title
song
artist =
withAttr artistAttr $ column (Just (Per 25)) Max (Pad 1) $ txt $ meta
"<no artist>"
MPD.Artist
song
time =
withAttr timeAttr
$ column (Just (Col 5)) Max (Pad 1)
$ txt
$ secondsToTime
$ MPD.sgLength song
-- | Search queue for next instance of last search.
queueSearch
:: Bool -- ^ Search direction, True for forward.
-> HumState
-> EventM Name HumState
queueSearch direction s =
let
dir = if direction then id else listReverse
searchkey = fromMaybe "" ((s ^. exL . searchHistoryL) !!? 0)
in
if searchkey == ""
then pure s
else do
pure
$ s
& queueL
%~ ( dir
. listFindBy
( songSearch searchkey [MPD.Title, MPD.Album, MPD.Artist]
. fst
)
. dir
)
-- | Add highlighted songs to given playlist.
queueAddToPl
:: HumState
-> String -- ^ Playlist name
-> EventM Name HumState
queueAddToPl s plName =
let songs =
(s ^. queueL)
& getHighlighted
& listElements
<&> fst
in songBulkAddtoPl plName songs s
-- | handle key inputs for Queue view.
handleEventQueue
:: HumState -> BrickEvent Name HumEvent -> EventM Name (Next HumState)
handleEventQueue s e = case e of
VtyEvent vtye -> case vtye of
EvKey (KChar 'j') [] -> continue $ s & queueL %~ listMoveDown
EvKey (KChar 'k') [] -> continue $ s & queueL %~ listMoveUp
EvKey (KChar 'n') [] -> continue =<< queueSearch (s ^. exL . searchDirectionL) s
EvKey (KChar 'N') [] -> continue =<< queueSearch (s ^. exL . searchDirectionL & not) s
EvKey (KChar 'a') [] ->
continue $ s & modeL .~ PromptMode
& promptsL . plSelectPromptL .~ listInsert 0 Nothing (Just <$> (s ^. playlistsL . plListL))
& promptsL . currentPromptL .~ PlSelectPrompt
& promptsL . promptTitleL .~ "Add selected Item(s) to:"
EvKey KEnter [] -> do
let maybeSelectedId =
MPD.sgId . fst . snd =<< listSelectedElement (queue s)
traverse_ (\sel -> liftIO (withMPD $ MPD.playId sel)) maybeSelectedId
rebuildStatus s >>= continue
EvKey (KChar ' ') [] -> continue $ s & queueL %~ (listMoveDown . listToggleHighlight)
EvKey (KChar 'd') [] -> do
let clSongs' = s ^. queueL & getHighlighted
_ <- liftIO (withMPD $ deleteHighlightedfromQ (s ^. queueL))
let s' = s & clipboardL . clSongsL .~ clSongs'
rebuildQueue s' >>= rebuildStatus >>= continue
EvKey (KChar 'D') [] -> do
let clSongs' = s^. queueL
let s' = s & clipboardL . clSongsL .~ clSongs'
_ <- liftIO (withMPD MPD.clear)
rebuildQueue s' >>= rebuildStatus >>= continue
EvKey (KChar 'y') [] -> continue $ yankHighlighted s queueL
EvKey (KChar 'p') [] -> do
let clSongs' = s ^. clipboardL . clSongsL
_ <- liftIO (withMPD $ pasteSongstoQ clSongs' (s ^. queueL))
rebuildQueue s >>= rebuildStatus >>= continue
EvKey (KChar 'G') [] -> continue $ s & queueL %~ listMoveTo (-1)
EvKey (KChar 'g') [] -> continue $ s & queueL %~ listMoveTo 0 -- TODO change this to 'gg', somehow
_ -> continue s
_ -> continue s