1 Commits

Author SHA1 Message Date
Alexander Heldt
0c4c085dd0 Add ability to switch View 2025-12-25 19:50:05 +01:00
5 changed files with 60 additions and 8 deletions

View File

@@ -1,4 +1,5 @@
import gleam/string
import musicplayer/ui/layout
import musicplayer/input/key.{type Key}
@@ -11,6 +12,8 @@ pub type Control {
TogglePlayPause
Search(input: String, capturing: Bool)
SetView(view_idx: layout.ViewIdx)
Exit
}
@@ -25,6 +28,10 @@ pub fn idle_from_key(key: Key) -> Result(Control, Nil) {
case key {
key.Char(char) -> {
case char {
// Views are zero indexed
"1" -> Ok(SetView(0))
"2" -> Ok(SetView(1))
" " -> Ok(TogglePlayPause)
"/" -> Ok(Search(input: "", capturing: True))
"q" -> Ok(Exit)

View File

@@ -51,6 +51,15 @@ fn handle_message(state: State, key: Key) -> actor.Next(State, Key) {
Error(_) -> actor.continue(state)
Ok(c) ->
case c {
control.SetView(view_idx) -> {
logging.log(
"musicplayer - setting current view to: "
<> string.inspect(view_idx),
)
update_current_view(state.ui, view_idx)
actor.continue(state)
}
control.Search(input, capturing) -> {
case capturing {
True -> {
@@ -146,6 +155,13 @@ fn update_search(ui: Subject(ui_control.Control), content: String) -> Nil {
process.send(ui, ui_control.UpdateState(layout.Search, content))
}
fn update_current_view(
ui: Subject(ui_control.Control),
view_idx: layout.ViewIdx,
) {
process.send(ui, ui_control.SetView(view_idx))
}
/// `forward_key` listens to a subject onto which `input` will send messages with `Key`s
/// that is then forwarded to the `musicplayer` agent to handle
fn forward_key(musicplayer: Subject(Key), input_keys: Subject(Key)) -> Nil {

View File

@@ -1,11 +1,11 @@
import gleam/erlang/process.{type Subject}
import musicplayer/ui/layout.{type Section}
import musicplayer/ui/layout.{type Section, type ViewIdx}
pub type Control {
UpdateDimensions(columns: Int, rows: Int)
UpdateState(section: Section, content: String)
SetView(view_idx: layout.ViewIdx)
SetView(view_idx: ViewIdx)
Exit(reply_to: Subject(Nil))
}

View File

@@ -1,4 +1,5 @@
import gleam/dict
import gleam/int
import gleam/list
import gleam/pair
import gleam/set
@@ -83,7 +84,7 @@ fn view_loop(i: ViewIdx, view_nodes: List(#(Section, Node))) -> View {
dict.from_list(view_nodes)
|> dict.insert(
Section(string.append("view_", string.inspect(i))),
view_index_section(i),
Row(
content: "",
style: Style(dimensions: Percent(width: 100, height: 100)),
@@ -92,6 +93,11 @@ fn view_loop(i: ViewIdx, view_nodes: List(#(Section, Node))) -> View {
)
}
/// Takes a ViewIndex and create a Section key from it
fn view_index_section(view_idx: ViewIdx) -> Section {
Section(string.append("view_", int.to_string(view_idx)))
}
pub fn update_section(
layout: Layout,
section: Section,
@@ -123,7 +129,7 @@ pub fn update_dimensions(layout: Layout, columns: Int, rows: Int) -> Layout {
Layout(..layout, columns:, rows:)
}
pub fn set_view(layout: Layout, view_idx: ViewIdx) -> Layout {
pub fn update_current_view(layout: Layout, view_idx: ViewIdx) -> Layout {
Layout(..layout, current_view: view_idx)
}
@@ -145,8 +151,7 @@ pub fn render(layout: Layout) -> Nil {
render_loop(
view,
context,
// TODO extract to function `view_index`
Section(string.append("view_", string.inspect(layout.current_view))),
view_index_section(layout.current_view),
buffer,
)
|> plot.flush_buffer(layout.columns, layout.rows)

View File

@@ -23,7 +23,31 @@ pub fn new() -> Result(Subject(Control), String) {
#(
layout.Header,
layout.Row(
content: "Foo (1) | Bar (2) | Baz (3)",
content: "Foo <1> | Bar (2)",
style: layout.Style(dimensions: layout.Percent(
width: 100,
height: 50,
)),
children: [],
),
),
#(
layout.PlaybackTime,
layout.Row(
content: "00:00",
style: layout.Style(dimensions: layout.Percent(
width: 100,
height: 50,
)),
children: [],
),
),
],
[
#(
layout.Header,
layout.Row(
content: "Foo (1) | Bar <2>",
style: layout.Style(dimensions: layout.Percent(
width: 100,
height: 33,
@@ -121,7 +145,7 @@ fn handle_message(
actor.stop()
}
control.SetView(view_idx) -> {
let layout = layout.set_view(state.layout, view_idx)
let layout = layout.update_current_view(state.layout, view_idx)
actor.send(state.redraw, layout)
actor.continue(State(..state, layout:))