Krolyxon
Commit bf531fa

rmptuisrcbrowser.rs

137 lines · 3.9 KB · Rust

1use std::ffi::OsStr;
2use std::path::Path;
3
4use mpd::Song;
5
6use crate::{app::AppResult, connection::Connection};
7
8#[derive(Debug)]
9pub struct FileBrowser {
10 pub filetree: Vec<(String, String)>,
11 pub selected: usize,
12 pub prev_selected: usize,
13 pub path: String,
14 pub prev_path: String,
15 pub songs: Vec<Song>,
16}
17
18// https://stackoverflow.com/questions/72392835/check-if-a-file-is-of-a-given-type
19pub trait FileExtension {
20 fn has_extension<S: AsRef<str>>(&self, extensions: &[S]) -> bool;
21}
22
23impl<P: AsRef<Path>> FileExtension for P {
24 fn has_extension<S: AsRef<str>>(&self, extensions: &[S]) -> bool {
25 if let Some(ref extension) = self.as_ref().extension().and_then(OsStr::to_str) {
26 return extensions
27 .iter()
28 .any(|x| x.as_ref().eq_ignore_ascii_case(extension));
29 }
30
31 false
32 }
33}
34
35impl FileBrowser {
36 pub fn new() -> FileBrowser {
37 FileBrowser {
38 filetree: Vec::new(),
39 selected: 0,
40 prev_selected: 0,
41 path: ".".to_string(),
42 prev_path: ".".to_string(),
43 songs: vec![],
44 }
45 }
46
47 pub fn update_directory(&mut self, conn: &mut Connection) -> AppResult<()> {
48 self.filetree.clear();
49 let mut file_vec: Vec<(String, String)> = vec![];
50 let mut dir_vec: Vec<(String, String)> = vec![];
51 for (t, f) in conn.conn.listfiles(self.path.as_str())?.into_iter() {
52 if t == "directory" {
53 dir_vec.push((t, f));
54 } else if t == "file"
55 && Path::new(&f).has_extension(&[
56 "mp3", "ogg", "flac", "m4a", "wav", "aac", "opus", "ape", "wma", "mpc", "aiff",
57 "dff", "mp2", "mka",
58 ])
59 {
60 file_vec.push((t, f));
61 }
62 }
63
64 dir_vec.extend(file_vec);
65 self.filetree = dir_vec;
66
67 self.songs.clear();
68 for (t, song) in self.filetree.iter() {
69 if t == "file" {
70 let v = conn
71 .conn
72 .lsinfo(Song {
73 file: conn
74 .get_full_path(song)
75 .unwrap_or_else(|| "Not a song".to_string()),
76 ..Default::default()
77 })
78 .unwrap_or_else(|_| {
79 vec![Song {
80 file: "Not a song".to_string(),
81 ..Default::default()
82 }]
83 });
84
85 self.songs.push(v.get(0).unwrap().clone());
86 } else {
87 let v = Song {
88 file: "".to_string(),
89 ..Default::default()
90 };
91
92 self.songs.push(v);
93 }
94 }
95
96 Ok(())
97 }
98
99 // Go to next item in filetree
100 pub fn next(&mut self) {
101 if self.selected < self.filetree.len() - 1 {
102 self.selected += 1;
103 }
104
105 // if self.selected == self.filetree.len() - 1 {
106 // self.selected = 0;
107 // } else {
108 // self.selected += 1;
109 // }
110 }
111
112 /// Go to previous item in filetree
113 pub fn prev(&mut self) {
114 if self.selected != 0 {
115 self.selected -= 1;
116 }
117 // if self.selected == 0 {
118 // self.selected = self.filetree.len() - 1;
119 // } else {
120 // self.selected -= 1;
121 // }
122 }
123
124 pub fn handle_go_back(&mut self, conn: &mut Connection) -> AppResult<()> {
125 if self.prev_path != "." {
126 let r = self.path.rfind("/").unwrap();
127 self.path = self.path.as_str()[..r].to_string();
128 self.update_directory(conn)?;
129 } else {
130 self.path = self.prev_path.clone();
131 self.update_directory(conn)?;
132 }
133
134 self.selected = self.prev_selected;
135 Ok(())
136 }
137}