crabidy/cbd-tui/src/app/mod.rs

133 lines
3.4 KiB
Rust

mod library;
mod list;
mod now_playing;
mod queue;
use flume::{Receiver, Sender};
use ratatui::{
backend::Backend,
layout::{Alignment, Constraint, Corner, Direction, Layout, Rect},
style::{Color, Modifier, Style},
text::{Span, Spans},
widgets::{
Block, BorderType, Borders, Gauge, LineGauge, List, ListItem, ListState, Paragraph, Wrap,
},
Frame,
};
use crabidy_core::proto::crabidy::{
get_update_stream_response::Update as StreamUpdate, InitResponse as InitialData, LibraryNode,
};
pub use list::StatefulList;
use library::Library;
use now_playing::NowPlaying;
use queue::Queue;
#[derive(Clone, Copy)]
pub enum UiFocus {
Library,
Queue,
}
#[derive(Clone, Copy)]
enum UiItemKind {
Node,
Track,
}
struct UiItem {
uuid: String,
title: String,
kind: UiItemKind,
marked: bool,
is_queable: bool,
}
pub const COLOR_PRIMARY: Color = Color::Rgb(129, 161, 193);
// const COLOR_PRIMARY_DARK: Color = Color::Rgb(94, 129, 172);
pub const COLOR_PRIMARY_DARK: Color = Color::Rgb(59, 66, 82);
pub const COLOR_SECONDARY: Color = Color::Rgb(180, 142, 173);
pub const COLOR_RED: Color = Color::Rgb(191, 97, 106);
pub const COLOR_GREEN: Color = Color::Rgb(163, 190, 140);
// const COLOR_ORANGE: Color = Color::Rgb(208, 135, 112);
// const COLOR_BRIGHT: Color = Color::Rgb(216, 222, 233);
// FIXME: Rename this
pub enum MessageToUi {
Init(InitialData),
ReplaceLibraryNode(LibraryNode),
Update(StreamUpdate),
}
// FIXME: Rename this
pub enum MessageFromUi {
GetLibraryNode(String),
AppendTracks(Vec<String>),
QueueTracks(Vec<String>),
InsertTracks(Vec<String>, usize),
RemoveTracks(Vec<usize>),
ReplaceQueue(Vec<String>),
NextTrack,
PrevTrack,
RestartTrack,
SetCurrentTrack(usize),
TogglePlay,
ChangeVolume(f32),
ToggleMute,
ToggleShuffle,
ToggleRepeat,
}
pub struct App {
pub focus: UiFocus,
pub library: Library,
pub now_playing: NowPlaying,
pub queue: Queue,
}
impl App {
pub fn new(tx: Sender<MessageFromUi>) -> App {
let library = Library::new(tx.clone());
let queue = Queue::new(tx);
let now_playing = NowPlaying::default();
App {
focus: UiFocus::Library,
library,
now_playing,
queue,
}
}
pub fn cycle_active(&mut self) {
self.focus = match (self.focus, self.queue.is_empty()) {
(UiFocus::Library, false) => UiFocus::Queue,
(UiFocus::Library, true) => UiFocus::Library,
(UiFocus::Queue, _) => UiFocus::Library,
};
}
pub fn render<B: Backend>(&mut self, f: &mut Frame<B>) {
let full_screen = f.size();
let library_focused = matches!(self.focus, UiFocus::Library);
let queue_focused = matches!(self.focus, UiFocus::Queue);
let main = Layout::default()
.direction(Direction::Horizontal)
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
.split(f.size());
self.library.render(f, main[0], library_focused);
let right_side = Layout::default()
.direction(Direction::Vertical)
.constraints([Constraint::Percentage(70), Constraint::Max(10)].as_ref())
.split(main[1]);
self.queue.render(f, right_side[0], queue_focused);
self.now_playing.render(f, right_side[1]);
}
}