Music, but without the subscription.
vleer.app
gpui
music
openmusic
openmetadata
rust
1use gpui::{App, BorrowAppContext, KeyBinding, actions};
2use tracing::{debug, error, info};
3
4use crate::{
5 data::{config::Config, db::repo::Database, scanner::Scanner},
6 media::playback::Playback,
7};
8
9actions!(vleer, [Quit, ReloadConfig, Scan, ForceScan]);
10actions!(player, [PlayPause, Next, Previous]);
11
12pub fn register_actions(cx: &mut App) {
13 cx.on_action(quit);
14 cx.on_action(reload_config);
15 cx.on_action(scan);
16 cx.on_action(force_scan);
17
18 cx.on_action(play_pause);
19 cx.on_action(next);
20 cx.on_action(previous);
21
22 cx.bind_keys([KeyBinding::new("secondary-alt-r", ReloadConfig, None)]);
23 cx.bind_keys([KeyBinding::new("secondary-w", Quit, None)]);
24 cx.bind_keys([KeyBinding::new("secondary-q", Quit, None)]);
25 cx.bind_keys([KeyBinding::new("secondary-r", Scan, None)]);
26 cx.bind_keys([KeyBinding::new("secondary-shift-r", ForceScan, None)]);
27
28 cx.bind_keys([KeyBinding::new("alt-right", Next, None)]);
29 cx.bind_keys([KeyBinding::new("alt-left", Previous, None)]);
30 cx.bind_keys([KeyBinding::new("space", PlayPause, None)]);
31
32 debug!("Actions: {:?}", cx.all_action_names());
33}
34
35fn quit(_: &Quit, cx: &mut App) {
36 info!("Quitting...");
37
38 cx.update_global::<Config, _>(|config, _| {
39 if let Err(e) = config.save() {
40 tracing::error!("Failed to save config: {}", e);
41 }
42 });
43
44 cx.quit();
45}
46
47fn play_pause(_: &PlayPause, cx: &mut App) {
48 cx.update_global::<Playback, _>(|playback, cx| {
49 playback.play_pause(cx);
50 });
51}
52
53fn previous(_: &Previous, cx: &mut App) {
54 cx.update_global::<Playback, _>(|playback, cx| {
55 playback.previous(cx);
56 });
57}
58
59fn next(_: &Next, cx: &mut App) {
60 cx.update_global::<Playback, _>(|playback, cx| {
61 playback.next(cx);
62 });
63}
64
65fn reload_config(_: &ReloadConfig, cx: &mut App) {
66 cx.update_global::<Config, _>(|config, _cx| {
67 if let Err(e) = config.reload() {
68 error!("Failed to reload config: {}", e);
69 }
70 });
71}
72
73fn scan(_: &Scan, cx: &mut App) {
74 let db = cx.global::<Database>().clone();
75 let scanner = cx.global::<Scanner>().clone();
76
77 cx.spawn(async move |_cx| match scanner.scan(&db).await {
78 Ok(stats) => {
79 info!(
80 "Manual scan complete - Scanned: {}, Added: {}, Updated: {}",
81 stats.scanned, stats.added, stats.updated
82 );
83 }
84 Err(e) => {
85 error!("Manual scan failed: {}", e);
86 }
87 })
88 .detach();
89}
90
91fn force_scan(_: &ForceScan, cx: &mut App) {
92 let db = cx.global::<Database>().clone();
93 let scanner = cx.global::<Scanner>().clone();
94
95 cx.spawn(async move |_cx| match scanner.force_scan(&db).await {
96 Ok(stats) => {
97 info!(
98 "Manual Full scan complete - Scanned: {}, Added: {}, Updated: {}",
99 stats.scanned, stats.added, stats.updated
100 );
101 }
102 Err(e) => {
103 error!("Manual Full scan failed: {}", e);
104 }
105 })
106 .detach();
107}