packages feed

hum-0.1.0.0: src/Hum/Views/Common.hs

{-# LANGUAGE LambdaCase #-}
-- |

module Hum.Views.Common where
import           Hum.Types
import           Brick.Types
import           Brick.Widgets.Core
import           Brick.Widgets.Center
import           Brick.Widgets.Edit
import           Brick.Widgets.Border
import           Hum.Attributes
import           Hum.Utils
import qualified Network.MPD                   as MPD
import qualified Data.Map.Strict               as Map
import qualified Data.Text                     as T
import           Brick.Widgets.List
import           Control.Lens

drawNowPlaying :: HState -> Widget Name
drawNowPlaying st = reportExtent NowPlaying $ vLimit 5 . center $ maybe
  (txt "nothing.")
  nowPlaying
  (currentSong st)
 where
  nowPlaying song =
    txt "\n"
      <=> hCenter title
      <=> hCenter (artist <+> txt " - " <+> album)
      <=> progbar
      <=> (padRight Max playing <+> padLeft Max mode)
   where
    title = withAttr queueTitleAttr $ txt $ meta "<no title>" MPD.Title song
    album =
      withAttr queueAlbumAttr (txt $ meta "<no album>" MPD.Album song)
        <+> txt " ("
        <+> withAttr queueDateAttr (txt $ meta "????" MPD.Date song)
        <+> txt ")"
    artist  = withAttr queueArtistAttr $ txt $ meta "<no one>" MPD.Artist song
    progbar = withAttr queueTimeAttr $ drawProgressBar st
    playing = txt $ maybe
      "[       ]"
      ((\t -> "[" <> t <> "]") . T.toLower . show . MPD.stState)
      (status st)
    formatMode t modeFun = maybe
      "-"
      ( (\case
          False -> "-"
          True  -> t
        )
      . modeFun
      )
      (status st)
    repeatmpd = formatMode "r" MPD.stRepeat
    random    = formatMode "z" MPD.stRandom
    single    = formatMode "s" MPD.stSingle
    consume   = formatMode "c" MPD.stConsume
    crossfade = formatMode "x" ((/= 0) . MPD.stXFadeWidth)
    mode =
      txt $ "[" <> repeatmpd <> random <> single <> consume <> crossfade <> "]"

drawProgressBar :: HState -> Widget Name
drawProgressBar st = case width of
  0 -> txt $ Prelude.toText timeText
  _ -> bar
 where
  width =
    maybe 0 (fst . extentSize) (join (Map.lookup NowPlaying $ extentMap st))
  songTime = fromMaybe (0, 1) (MPD.stTime =<< status st)
  timeText =
    toString
      . (\(i, j) -> secondsToTime (round i) <> "/" <> secondsToTime (round j))
      $ songTime
  completed = (\w (i, j) -> round ((i / j) * fromIntegral w)) width songTime
  bar       = str
    (zipWith
      (\a b -> if a `elem` ("1234567890/:" :: String) then a else b)
      (replicate (-5 + div width 2) ' ' ++ timeText ++ replicate
        (-3 + div width 2)
        ' '
      )
      (replicate completed '=' ++ replicate (width - completed) ' ')
    )

--drawEx :: HState -> Widget Name
--drawEx st =

data PerCol = Per Int | Col Int
column :: Maybe PerCol -> Padding -> Padding -> Widget n -> Widget n
column maxWidth left right w = case maxWidth of
  Nothing      -> wpad
  Just (Per m) -> hLimitPercent m wpad
  Just (Col m) -> hLimit m wpad
  where wpad = padLeft left . padRight right $ w

songSearch :: Text -> [MPD.Metadata] -> MPD.Song -> Bool
songSearch text metadata song =
  let mtags = (T.toLower <$>) . (`mmeta` song) <$> metadata
  in  or $ fromMaybe False <$> (T.isInfixOf (T.toLower text) <<$>> mtags)


stringySearch :: MPD.ToString a => Text -> a -> Bool
stringySearch text value =
  T.isInfixOf (T.toLower text) (T.toLower . MPD.toText $ value)

drawPrompt :: HState -> Widget Name
drawPrompt st = case st ^. promptsL . currentPromptL of
  PlSelectPrompt ->
    centerLayer
      .   border
      .   setAvailableSize (30, 10)
      .   center
      $   (hCenter . txt $ st ^. promptsL . promptTitleL)
      <=> hBorder
      <=> renderListWithIndex choosePlRow
                              True
                              (st ^. promptsL . plSelectPromptL)
  TextPrompt ->
    centerLayer
      .   border
      .   setAvailableSize (30, 3)
      .   center
      $   (hCenter . txt $ st ^. promptsL . promptTitleL)
      <=> hBorder
      <=> (center . setAvailableSize (25, 1) . withDefAttr editorAttr)
            (renderEditor (txt . T.unlines) True (st ^. promptsL . textPromptL))
  YNPrompt ->
    centerLayer
      .   border
      .   hLimit 30
      $   (hCenter . txt $ st ^. promptsL . promptTitleL)
      <=> (hCenter . txt $ "[y/n]")


choosePlRow :: Int -> Bool -> Maybe MPD.PlaylistName -> Widget n
choosePlRow i _ pl = if i==0 then
  str "New Playlist" <=> modifyDefAttr (const wobAttr) hBorder
  else str (MPD.toString $ fromMaybe "<error getting playlist name>" pl)