modified: Cargo.lock
modified: Cargo.toml modified: src/config.rs modified: src/main.rs new file: src/screen.rs new file: src/tabs.rs
This commit is contained in:
parent
41aa3222a8
commit
60e92ee1d7
35
Cargo.lock
generated
35
Cargo.lock
generated
@ -827,8 +827,8 @@ checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itunesdb"
|
name = "itunesdb"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
source = "git+https://gitea.awain.net/alterwain/ITunesDB.git#9e20fe785dc9cd1268641dad9730a8fb3ff246c5"
|
source = "git+https://gitea.awain.net/alterwain/ITunesDB.git#5a6ca7a9f5eca42959e3498a6eb2700f502b5509"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bincode",
|
"bincode",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
@ -932,6 +932,7 @@ dependencies = [
|
|||||||
"rusb",
|
"rusb",
|
||||||
"serde",
|
"serde",
|
||||||
"soundcloud",
|
"soundcloud",
|
||||||
|
"strum 0.27.0",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"toml",
|
"toml",
|
||||||
@ -1204,7 +1205,7 @@ dependencies = [
|
|||||||
"itertools",
|
"itertools",
|
||||||
"lru",
|
"lru",
|
||||||
"paste",
|
"paste",
|
||||||
"strum",
|
"strum 0.26.3",
|
||||||
"time",
|
"time",
|
||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
"unicode-truncate",
|
"unicode-truncate",
|
||||||
@ -1562,8 +1563,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "soundcloud"
|
name = "soundcloud"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
source = "git+https://gitea.awain.net/alterwain/soundcloud_api.git#d4d51c64e9225763f6d40a7f450c673ab6e36ddf"
|
source = "git+https://gitea.awain.net/alterwain/soundcloud_api.git#87614c2a10c30f7d3e4b3cb0f8973d62ffec7916"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hyper-util",
|
"hyper-util",
|
||||||
"regex",
|
"regex",
|
||||||
@ -1603,7 +1604,16 @@ version = "0.26.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
|
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"strum_macros",
|
"strum_macros 0.26.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum"
|
||||||
|
version = "0.27.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce1475c515a4f03a8a7129bb5228b81a781a86cb0b3fbbc19e1c556d491a401f"
|
||||||
|
dependencies = [
|
||||||
|
"strum_macros 0.27.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1619,6 +1629,19 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum_macros"
|
||||||
|
version = "0.27.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9688894b43459159c82bfa5a5fa0435c19cbe3c9b427fa1dd7b1ce0c279b18a7"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rustversion",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "subtle"
|
name = "subtle"
|
||||||
version = "2.6.1"
|
version = "2.6.1"
|
||||||
|
@ -16,5 +16,6 @@ color-eyre = "0.6.3"
|
|||||||
crossterm = "0.28.1"
|
crossterm = "0.28.1"
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
tokio-util = { version = "0.7.12", features = ["codec"] }
|
tokio-util = { version = "0.7.12", features = ["codec"] }
|
||||||
soundcloud = { git = "https://gitea.awain.net/alterwain/soundcloud_api.git" }
|
strum = { version = "0.27", features = ["derive"] }
|
||||||
itunesdb = { git = "https://gitea.awain.net/alterwain/ITunesDB.git" }
|
soundcloud = { version = "0.1.1", git = "https://gitea.awain.net/alterwain/soundcloud_api.git" }
|
||||||
|
itunesdb = { version = "0.1.1", git = "https://gitea.awain.net/alterwain/ITunesDB.git" }
|
@ -1,12 +1,12 @@
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
struct YouTubeConfiguration {
|
pub struct YouTubeConfiguration {
|
||||||
pub user_id: u64
|
pub user_id: u64
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
struct SoundCloudConfiguration {
|
pub struct SoundCloudConfiguration {
|
||||||
pub user_id: u64
|
pub user_id: u64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
105
src/main.rs
105
src/main.rs
@ -1,15 +1,21 @@
|
|||||||
use std::{error::Error, io, path::{Path, PathBuf}};
|
use std::{error::Error, io, path::{Path, PathBuf}};
|
||||||
|
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
|
use config::LyricaConfiguration;
|
||||||
use crossterm::{event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEvent, KeyEventKind}, execute, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}};
|
use crossterm::{event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEvent, KeyEventKind}, execute, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}};
|
||||||
use ratatui::{buffer::Buffer, layout::Rect, prelude::{Backend, CrosstermBackend}, style::Stylize, symbols::border, text::{Line, Text}, widgets::{Block, Paragraph, Widget}, DefaultTerminal, Frame, Terminal};
|
use ratatui::{buffer::Buffer, layout::{Layout, Rect}, prelude::{Backend, CrosstermBackend}, style::{Color, Stylize}, symbols::border, text::{Line, Text}, widgets::{Block, Paragraph, Tabs, Widget}, DefaultTerminal, Frame, Terminal};
|
||||||
|
use screen::MainScreen;
|
||||||
|
use soundcloud::sobjects::CloudPlaylists;
|
||||||
|
use strum::IntoEnumIterator;
|
||||||
use tokio::{fs::File, io::AsyncReadExt, sync::mpsc::{self, Receiver, Sender, UnboundedReceiver, UnboundedSender}};
|
use tokio::{fs::File, io::AsyncReadExt, sync::mpsc::{self, Receiver, Sender, UnboundedReceiver, UnboundedSender}};
|
||||||
use tokio_util::sync::CancellationToken;
|
use tokio_util::sync::CancellationToken;
|
||||||
|
|
||||||
use itunesdb::xobjects::XDatabase;
|
use itunesdb::xobjects::XDatabase;
|
||||||
|
use ratatui::prelude::Constraint::{Length, Min};
|
||||||
|
|
||||||
mod util;
|
mod util;
|
||||||
mod config;
|
mod config;
|
||||||
|
mod tabs;
|
||||||
|
mod screen;
|
||||||
|
|
||||||
fn get_configs_dir() -> PathBuf {
|
fn get_configs_dir() -> PathBuf {
|
||||||
let mut p = dirs::home_dir().unwrap();
|
let mut p = dirs::home_dir().unwrap();
|
||||||
@ -20,10 +26,7 @@ fn get_configs_dir() -> PathBuf {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
enum AppState {
|
enum AppState {
|
||||||
IPodWait,
|
IPodWait,
|
||||||
MainScreen(String),
|
MainScreen(crate::screen::MainScreen)
|
||||||
SoundCloud,
|
|
||||||
Youtube,
|
|
||||||
Preferences
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum AppEvent {
|
enum AppEvent {
|
||||||
@ -31,7 +34,8 @@ enum AppEvent {
|
|||||||
IPodFound(String),
|
IPodFound(String),
|
||||||
IPodNotFound,
|
IPodNotFound,
|
||||||
ParseItunes(String),
|
ParseItunes(String),
|
||||||
ITunesParsed(XDatabase)
|
ITunesParsed(XDatabase),
|
||||||
|
SoundcloudGot(CloudPlaylists)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initialize_async_service(sender: Sender<AppEvent>, receiver: UnboundedReceiver<AppEvent>, token: CancellationToken) {
|
fn initialize_async_service(sender: Sender<AppEvent>, receiver: UnboundedReceiver<AppEvent>, token: CancellationToken) {
|
||||||
@ -44,31 +48,43 @@ fn initialize_async_service(sender: Sender<AppEvent>, receiver: UnboundedReceive
|
|||||||
if let Some(request) = r {
|
if let Some(request) = r {
|
||||||
match request {
|
match request {
|
||||||
AppEvent::SearchIPod => {
|
AppEvent::SearchIPod => {
|
||||||
if let Some(p) = util::search_ipod() {
|
/*if let Some(p) = util::search_ipod() {
|
||||||
let _ = sender.send(AppEvent::IPodFound(p)).await;
|
let _ = sender.send(AppEvent::IPodFound(p)).await;
|
||||||
} else {
|
} else {
|
||||||
let _ = sender.send(AppEvent::IPodNotFound).await;
|
let _ = sender.send(AppEvent::IPodNotFound).await;
|
||||||
}
|
}*/
|
||||||
|
let _ = sender.send(AppEvent::IPodFound("D:\\Documents\\RustroverProjects\\itunesdb\\ITunesDB\\two_tracks".to_string())).await;
|
||||||
},
|
},
|
||||||
AppEvent::ParseItunes(path) => {
|
AppEvent::ParseItunes(path) => {
|
||||||
// todo: parse itunes
|
// todo: parse itunes
|
||||||
let _ = std::fs::create_dir_all(get_configs_dir());
|
let _ = std::fs::create_dir_all(get_configs_dir());
|
||||||
let mut cd = get_configs_dir();
|
let mut cd = get_configs_dir();
|
||||||
cd.push("idb");
|
cd.push("idb");
|
||||||
/*let mut p = get_configs_dir();
|
|
||||||
p.push("config");
|
|
||||||
p.set_extension(".toml");
|
|
||||||
p.exists()*/
|
|
||||||
let mut p: PathBuf = Path::new(&path).into();
|
let mut p: PathBuf = Path::new(&path).into();
|
||||||
p.push("iPod_Control");
|
// p.push("iPod_Control");
|
||||||
p.push("iTunes");
|
// p.push("iTunes");
|
||||||
p.set_file_name("iTunesDB");
|
// p.set_file_name("iTunesDB");
|
||||||
let _ = std::fs::copy(p, &cd);
|
let _ = std::fs::copy(p, &cd);
|
||||||
let mut file = File::open(cd).await.unwrap();
|
let mut file = File::open(cd).await.unwrap();
|
||||||
let mut contents = vec![];
|
let mut contents = vec![];
|
||||||
file.read_to_end(&mut contents).await.unwrap();
|
file.read_to_end(&mut contents).await.unwrap();
|
||||||
let xdb = itunesdb::deserializer::parse_bytes(&contents);
|
let xdb = itunesdb::deserializer::parse_bytes(&contents);
|
||||||
let _ = sender.send(AppEvent::ITunesParsed(xdb)).await;
|
let _ = sender.send(AppEvent::ITunesParsed(xdb)).await;
|
||||||
|
|
||||||
|
let mut p = get_configs_dir();
|
||||||
|
p.push("config");
|
||||||
|
p.set_extension(".toml");
|
||||||
|
if !p.exists() { return; }
|
||||||
|
let mut file = File::open(p).await.unwrap();
|
||||||
|
let mut content = String::new();
|
||||||
|
file.read_to_string(&mut content).await.unwrap();
|
||||||
|
let config: LyricaConfiguration = toml::from_str(&content).unwrap();
|
||||||
|
|
||||||
|
let app_version = soundcloud::get_app().await.unwrap().unwrap();
|
||||||
|
let client_id = soundcloud::get_client_id().await.unwrap().unwrap();
|
||||||
|
let playlists = soundcloud::get_playlists(config.get_soundcloud().user_id, client_id, app_version).await.unwrap();
|
||||||
|
|
||||||
|
let _ = sender.send(AppEvent::SoundcloudGot(playlists)).await;
|
||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@ -121,11 +137,21 @@ impl App {
|
|||||||
if let Ok(event) = self.receiver.try_recv() {
|
if let Ok(event) = self.receiver.try_recv() {
|
||||||
match event {
|
match event {
|
||||||
AppEvent::IPodFound(path) => {
|
AppEvent::IPodFound(path) => {
|
||||||
self.state = AppState::MainScreen(path.clone());
|
self.state = AppState::MainScreen(MainScreen::new());
|
||||||
let _ = self.sender.send(AppEvent::ParseItunes(path));
|
let _ = self.sender.send(AppEvent::ParseItunes(path));
|
||||||
},
|
},
|
||||||
AppEvent::IPodNotFound => {
|
AppEvent::IPodNotFound => {
|
||||||
let _ = self.sender.send(AppEvent::SearchIPod);
|
let _ = self.sender.send(AppEvent::SearchIPod);
|
||||||
|
},
|
||||||
|
AppEvent::ITunesParsed(xdb) => {
|
||||||
|
|
||||||
|
},
|
||||||
|
AppEvent::SoundcloudGot(playlists) => {
|
||||||
|
if let AppState::MainScreen(screen) = &self.state {
|
||||||
|
let mut screen = screen.clone();
|
||||||
|
screen.soundcloud = Some(playlists);
|
||||||
|
self.state = AppState::MainScreen(screen);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@ -134,8 +160,14 @@ impl App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_key_event(&mut self, key_event: KeyEvent) {
|
fn handle_key_event(&mut self, key_event: KeyEvent) {
|
||||||
if key_event.code == KeyCode::Char('q') {
|
if let AppState::MainScreen(screen) = &self.state {
|
||||||
self.exit();
|
let mut screen = screen.clone();
|
||||||
|
screen.handle_key_event(key_event);
|
||||||
|
self.state = AppState::MainScreen(screen);
|
||||||
|
}
|
||||||
|
match key_event.code {
|
||||||
|
KeyCode::Char('q') => self.exit(),
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,32 +177,17 @@ impl App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AppState {
|
impl AppState {
|
||||||
fn render_main_screen(area: Rect, buf: &mut Buffer, path: String) {
|
fn render_main_screen(area: Rect, buf: &mut Buffer, screen: &mut MainScreen) {
|
||||||
let title = Line::from(" Lyrica ".bold());
|
let vertical = Layout::vertical([Length(1), Min(0), Length(1)]);
|
||||||
let instructions = Line::from(vec![
|
let [header_area, inner_area, footer_area] = vertical.areas(area);
|
||||||
" Quit ".into(),
|
|
||||||
"<Q> ".red().bold(),
|
|
||||||
]);
|
|
||||||
let block = Block::bordered()
|
|
||||||
.title(title.centered())
|
|
||||||
.title_bottom(instructions.centered())
|
|
||||||
.border_set(border::ROUNDED);
|
|
||||||
|
|
||||||
let counter_text = Text::from(
|
let horizontal = Layout::horizontal([Min(0), Length(7)]);
|
||||||
vec![
|
let [tabs_area, title_area] = horizontal.areas(header_area);
|
||||||
Line::from(
|
|
||||||
vec![
|
|
||||||
"Parsing iTunesDB...".into(),
|
|
||||||
path.blue().bold()
|
|
||||||
]
|
|
||||||
)
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
Paragraph::new(counter_text)
|
MainScreen::render_title(title_area, buf);
|
||||||
.centered()
|
screen.render_tabs(tabs_area, buf);
|
||||||
.block(block)
|
screen.selected_tab.render(inner_area, buf);
|
||||||
.render(area, buf);
|
MainScreen::render_footer(footer_area, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_waiting_screen(area: Rect, buf: &mut Buffer) {
|
fn render_waiting_screen(area: Rect, buf: &mut Buffer) {
|
||||||
@ -205,7 +222,7 @@ impl Widget for AppState {
|
|||||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||||
match self {
|
match self {
|
||||||
AppState::IPodWait => AppState::render_waiting_screen(area, buf),
|
AppState::IPodWait => AppState::render_waiting_screen(area, buf),
|
||||||
AppState::MainScreen(s) => AppState::render_main_screen(area, buf, s),
|
AppState::MainScreen(mut s) => AppState::render_main_screen(area, buf, &mut s),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
56
src/screen.rs
Normal file
56
src/screen.rs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
use crossterm::event::{KeyCode, KeyEvent};
|
||||||
|
use ratatui::{buffer::Buffer, layout::Rect, style::{Color, Stylize}, text::Line, widgets::{Tabs, Widget}};
|
||||||
|
use soundcloud::sobjects::CloudPlaylists;
|
||||||
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
|
use crate::tabs::SelectedTab;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct MainScreen {
|
||||||
|
pub selected_tab: SelectedTab,
|
||||||
|
pub soundcloud: Option<CloudPlaylists>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MainScreen {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
MainScreen { selected_tab: SelectedTab::Playlists, soundcloud: None }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_key_event(&mut self, key_event: KeyEvent) {
|
||||||
|
match key_event.code {
|
||||||
|
KeyCode::Char('l') | KeyCode::Right => self.next_tab(),
|
||||||
|
KeyCode::Char('h') | KeyCode::Left => self.previous_tab(),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_title(area: Rect, buf: &mut Buffer) {
|
||||||
|
"Lyrica".bold().render(area, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_footer(area: Rect, buf: &mut Buffer) {
|
||||||
|
Line::raw("◄ ► to change tab | <Q> to quit")
|
||||||
|
.centered()
|
||||||
|
.render(area, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_tabs(&self, area: Rect, buf: &mut Buffer) {
|
||||||
|
let titles = SelectedTab::iter().map(SelectedTab::title);
|
||||||
|
let highlight_style = (Color::default(), self.selected_tab.palette().c700);
|
||||||
|
let selected_tab_index = self.selected_tab.to_usize();
|
||||||
|
Tabs::new(titles)
|
||||||
|
.highlight_style(highlight_style)
|
||||||
|
.select(selected_tab_index)
|
||||||
|
.padding("", "")
|
||||||
|
.divider(" ")
|
||||||
|
.render(area, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_tab(&mut self) {
|
||||||
|
self.selected_tab = self.selected_tab.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn previous_tab(&mut self) {
|
||||||
|
self.selected_tab = self.selected_tab.previous();
|
||||||
|
}
|
||||||
|
}
|
97
src/tabs.rs
Normal file
97
src/tabs.rs
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
use ratatui::{buffer::Buffer, layout::Rect, style::{palette::tailwind, Stylize}, symbols, text::Line, widgets::{Block, Padding, Paragraph, Widget}};
|
||||||
|
use soundcloud::sobjects::CloudPlaylists;
|
||||||
|
use strum::{AsRefStr, Display, EnumIter, FromRepr, IntoEnumIterator};
|
||||||
|
|
||||||
|
use crate::screen::MainScreen;
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone, Display, FromRepr, EnumIter, AsRefStr)]
|
||||||
|
pub enum SelectedTab {
|
||||||
|
#[default]
|
||||||
|
#[strum(to_string = "Playlists")]
|
||||||
|
Playlists,
|
||||||
|
#[strum(to_string = "Albums")]
|
||||||
|
Albums,
|
||||||
|
#[strum(to_string = "Soundcloud")]
|
||||||
|
Soundcloud(Option<CloudPlaylists>),
|
||||||
|
#[strum(to_string = "Youtube")]
|
||||||
|
Youtube,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for SelectedTab {
|
||||||
|
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||||
|
let block = self.block();
|
||||||
|
match self {
|
||||||
|
Self::Albums => self.render_albums(area, buf),
|
||||||
|
Self::Playlists => self.render_playlists(area, buf),
|
||||||
|
Self::Soundcloud(playlists) => SelectedTab::render_soundcloud(block,area, buf, playlists),
|
||||||
|
Self::Youtube => self.render_youtube(area, buf),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SelectedTab {
|
||||||
|
/// Return tab's name as a styled `Line`
|
||||||
|
pub fn title(self) -> Line<'static> {
|
||||||
|
format!(" {self} ")
|
||||||
|
.fg(tailwind::SLATE.c200)
|
||||||
|
.bg(self.palette().c900)
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_albums(self, area: Rect, buf: &mut Buffer) {
|
||||||
|
Paragraph::new("Hello, World!")
|
||||||
|
.block(self.block())
|
||||||
|
.render(area, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_playlists(self, area: Rect, buf: &mut Buffer) {
|
||||||
|
Paragraph::new("Welcome to the Ratatui tabs example!")
|
||||||
|
.block(self.block())
|
||||||
|
.render(area, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_soundcloud(block: Block<'static>, area: Rect, buf: &mut Buffer, playlists: Option<CloudPlaylists>) {
|
||||||
|
Paragraph::new("Your playlists from soundcloud:")
|
||||||
|
.block(block)
|
||||||
|
.render(area, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_youtube(self, area: Rect, buf: &mut Buffer) {
|
||||||
|
Paragraph::new("I know, these are some basic changes. But I think you got the main idea.")
|
||||||
|
.block(self.block())
|
||||||
|
.render(area, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A block surrounding the tab's content
|
||||||
|
fn block(&self) -> Block<'static> {
|
||||||
|
Block::bordered()
|
||||||
|
.border_set(symbols::border::THICK)
|
||||||
|
.padding(Padding::horizontal(1))
|
||||||
|
.border_style(self.palette().c700)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn palette(&self) -> tailwind::Palette {
|
||||||
|
match self {
|
||||||
|
Self::Albums => tailwind::INDIGO,
|
||||||
|
Self::Playlists => tailwind::EMERALD,
|
||||||
|
Self::Soundcloud(_) => tailwind::ORANGE,
|
||||||
|
Self::Youtube => tailwind::RED,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn previous(self) -> Self {
|
||||||
|
let current_index = self.clone().to_usize();
|
||||||
|
let previous_index = current_index.saturating_sub(1);
|
||||||
|
Self::from_repr(previous_index).unwrap_or(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next(self) -> Self {
|
||||||
|
let current_index = self.clone().to_usize();
|
||||||
|
let next_index = current_index.saturating_add(1);
|
||||||
|
Self::from_repr(next_index).unwrap_or(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_usize(self) -> usize {
|
||||||
|
SelectedTab::iter().enumerate().find(|(_i, el)| el.as_ref() == self.as_ref()).unwrap().0
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user