Skip to content

Commit 5c7343b

Browse files
committed
Add feature to open a note with Enter key
1 parent e90fa90 commit 5c7343b

File tree

2 files changed

+87
-31
lines changed

2 files changed

+87
-31
lines changed

ff-brick/Main.hs

Lines changed: 86 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,19 @@
33
{-# LANGUAGE OverloadedLabels #-}
44

55
import Brick (
6-
App (App),
76
AttrMap,
87
AttrName,
9-
BrickEvent (VtyEvent),
10-
EventM,
118
VScrollBarOrientation (OnRight),
12-
Widget,
9+
ViewportType (Both),
1310
attrMap,
1411
attrName,
1512
defaultMain,
13+
hBox,
1614
halt,
1715
neverShowCursor,
1816
on,
1917
str,
18+
viewport,
2019
withAttr,
2120
withVScrollBars,
2221
zoom,
@@ -30,15 +29,24 @@ import Brick.Widgets.List (
3029
handleListEvent,
3130
list,
3231
listSelectedAttr,
32+
listSelectedElementL,
3333
listSelectedFocusedAttr,
3434
renderList,
3535
)
3636
import Control.Monad (void)
37+
import Data.Foldable (toList)
3738
import Data.Function ((&))
3839
import Data.Generics.Labels ()
3940
import Data.Vector qualified as Vector
4041
import GHC.Generics (Generic)
41-
import Graphics.Vty (Event (EvKey), Key (KEsc), black, defAttr, white)
42+
import Graphics.Vty (
43+
Event (EvKey),
44+
Key (KChar, KEnter, KEsc),
45+
black,
46+
defAttr,
47+
white,
48+
)
49+
import Lens.Micro.Mtl (preuse, (.=))
4250
import RON.Storage.FS (runStorage)
4351
import RON.Storage.FS qualified as StorageFS
4452

@@ -47,17 +55,40 @@ import FF.Config (loadConfig)
4755
import FF.Types (Entity (Entity), EntityDoc, Note (Note))
4856
import FF.Types qualified
4957

50-
newtype Model = Model {notes :: List () (EntityDoc Note)} deriving (Generic)
58+
-- | Brick widget names
59+
data WN
60+
= NoteList
61+
| OpenNoteViewport
62+
deriving (Eq, Ord, Show)
63+
64+
data Model = Model
65+
{ notes :: List WN (EntityDoc Note)
66+
-- ^ all notes
67+
, openNoteM :: Maybe (EntityDoc Note)
68+
-- ^ currently opened note
69+
}
70+
deriving (Generic)
71+
72+
type Widget = Brick.Widget WN
73+
74+
type App = Brick.App Model () WN
75+
76+
type EventM = Brick.EventM WN Model
77+
78+
type BrickEvent = Brick.BrickEvent WN ()
5179

5280
main :: IO ()
5381
main = do
5482
cfg <- loadConfig
55-
dataDir <- getDataDir cfg
56-
handleM <- traverse StorageFS.newHandle dataDir
83+
dataDirM <- getDataDir cfg
84+
handleM <- traverse StorageFS.newHandle dataDirM
5785
handle <- handleM `orElse` fail noDataDirectoryMessage
5886
notes <- runStorage handle loadAllNotes
5987
let initialModel =
60-
Model{notes = list () (Vector.fromList notes) listItemHeight}
88+
Model
89+
{ notes = list NoteList (Vector.fromList notes) listItemHeight
90+
, openNoteM = Nothing
91+
}
6192
void $ defaultMain app initialModel
6293

6394
listItemHeight :: Int
@@ -66,9 +97,9 @@ listItemHeight = 1
6697
orElse :: (Applicative m) => Maybe a -> m a -> m a
6798
orElse m n = maybe n pure m
6899

69-
app :: App Model () ()
100+
app :: App
70101
app =
71-
App
102+
Brick.App
72103
{ appAttrMap = const appAttrMap
73104
, appChooseCursor = neverShowCursor
74105
, appDraw
@@ -85,33 +116,57 @@ appAttrMap =
85116
, (highlightAttr, black `on` white)
86117
]
87118

88-
appDraw :: Model -> [Widget ()]
89-
appDraw Model{notes} =
90-
[ borderWithLabel
91-
(str "Agenda")
92-
(renderList renderListItem True notes & withVScrollBars OnRight)
93-
<=> (withAttr highlightAttr (str "Esc") <+> str " exit")
94-
]
119+
appDraw :: Model -> [Widget]
120+
appDraw Model{notes, openNoteM} = [mainWidget <=> keysHelpLine]
121+
where
122+
mainWidget = hBox $ agenda : toList openNoteWidget
123+
124+
agenda =
125+
borderWithLabel
126+
(str "Agenda")
127+
(renderList renderListItem True notes & withVScrollBars OnRight)
128+
129+
openNoteWidget = do
130+
Entity{entityVal = note@Note{note_text}} <- openNoteM
131+
let title = noteTitle note
132+
text = fromRgaM note_text
133+
pure $
134+
borderWithLabel (str title) $
135+
viewport OpenNoteViewport Both $
136+
str text
137+
138+
keysHelpLine =
139+
withAttr highlightAttr (str "Esc")
140+
<+> str " "
141+
<+> withAttr highlightAttr (str "q")
142+
<+> str " exit "
143+
<+> withAttr highlightAttr (str "Enter")
144+
<+> str " open"
95145

96146
highlightAttr :: AttrName
97147
highlightAttr = attrName "highlight"
98148

99-
appHandleEvent :: BrickEvent () () -> EventM () Model ()
149+
appHandleEvent :: BrickEvent -> EventM ()
100150
appHandleEvent = \case
101-
VtyEvent e -> appHandleVtyEvent e
151+
Brick.VtyEvent e -> appHandleVtyEvent e
102152
_ -> pure ()
103153

104-
appHandleVtyEvent :: Event -> EventM () Model ()
154+
appHandleVtyEvent :: Event -> EventM ()
105155
appHandleVtyEvent = \case
106-
EvKey KEsc _ -> halt
156+
EvKey KEsc [] -> halt
157+
EvKey (KChar 'q') [] -> halt
158+
EvKey KEnter [] -> do
159+
-- open selected note
160+
selectedNoteM <- preuse $ #notes . listSelectedElementL
161+
#openNoteM .= selectedNoteM
107162
e -> zoom #notes $ handleListEvent e
108163

109-
renderListItem :: Bool -> EntityDoc Note -> Widget ()
110-
renderListItem _isSelected Entity{entityVal = Note{note_text}} =
111-
str
112-
case textLines of
113-
[] -> "..."
114-
[singleLine] -> singleLine
115-
firstLine : _ -> firstLine <> "..."
116-
where
117-
textLines = filter (not . null) $ lines $ fromRgaM note_text
164+
renderListItem :: Bool -> EntityDoc Note -> Widget
165+
renderListItem _isSelected Entity{entityVal} = str $ noteTitle entityVal
166+
167+
noteTitle :: Note -> String
168+
noteTitle Note{note_text} =
169+
case filter (not . null) $ lines $ fromRgaM note_text of
170+
[] -> "..."
171+
[singleLine] -> singleLine
172+
firstLine : _ -> firstLine <> "..."

ff-brick/ff-brick.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ executable ff-brick
99
base,
1010
brick,
1111
generic-lens,
12+
microlens-mtl,
1213
ron-storage,
1314
vector,
1415
vty,

0 commit comments

Comments
 (0)