feature: open playing/hovered track/album on touhoudb
opens the touhoudb page for a hovered or playing track/album. closes b8aff40
diff --git a/Cargo.lock b/Cargo.lock
@@ -314,6 +314,16 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
+[[package]]
+name = "combine"
+version = "4.6.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
+dependencies = [
+ "bytes",
+ "memchr",
+]
+
[[package]]
name = "compact_str"
version = "0.8.1"
@@ -1239,6 +1249,55 @@ version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
+[[package]]
+name = "jni"
+version = "0.22.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498"
+dependencies = [
+ "cfg-if",
+ "combine",
+ "jni-macros",
+ "jni-sys",
+ "log",
+ "simd_cesu8",
+ "thiserror 2.0.18",
+ "walkdir",
+ "windows-link",
+]
+
+[[package]]
+name = "jni-macros"
+version = "0.22.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "rustc_version",
+ "simd_cesu8",
+ "syn",
+]
+
+[[package]]
+name = "jni-sys"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2"
+dependencies = [
+ "jni-sys-macros",
+]
+
+[[package]]
+name = "jni-sys-macros"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264"
+dependencies = [
+ "quote",
+ "syn",
+]
+
[[package]]
name = "jobserver"
version = "0.1.34"
@@ -1414,7 +1473,7 @@ dependencies = [
[[package]]
name = "myn-grrs"
-version = "0.1.3"
+version = "0.1.4"
dependencies = [
"arboard",
"crossterm",
@@ -1428,6 +1487,8 @@ dependencies = [
"souvlaki",
"tokio",
"tokio-tungstenite",
+ "urlencoding",
+ "webbrowser",
]
[[package]]
@@ -1447,6 +1508,12 @@ dependencies = [
"tempfile",
]
+[[package]]
+name = "ndk-context"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b"
+
[[package]]
name = "new_debug_unreachable"
version = "1.0.6"
@@ -2087,6 +2154,15 @@ dependencies = [
"windows-sys 0.52.0",
]
+[[package]]
+name = "rustc_version"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
+dependencies = [
+ "semver",
+]
+
[[package]]
name = "rustix"
version = "0.38.44"
@@ -2158,6 +2234,15 @@ version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
[[package]]
name = "schannel"
version = "0.1.29"
@@ -2311,6 +2396,16 @@ version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214"
+[[package]]
+name = "simd_cesu8"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520"
+dependencies = [
+ "rustc_version",
+ "simdutf8",
+]
+
[[package]]
name = "simd_helpers"
version = "0.1.0"
@@ -2320,6 +2415,12 @@ dependencies = [
"quote",
]
+[[package]]
+name = "simdutf8"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
+
[[package]]
name = "slab"
version = "0.4.12"
@@ -2776,6 +2877,12 @@ dependencies = [
"serde",
]
+[[package]]
+name = "urlencoding"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
+
[[package]]
name = "utf-8"
version = "0.7.6"
@@ -2811,6 +2918,16 @@ version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
+[[package]]
+name = "walkdir"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
+dependencies = [
+ "same-file",
+ "winapi-util",
+]
+
[[package]]
name = "want"
version = "0.3.1"
@@ -3013,6 +3130,22 @@ dependencies = [
"wasm-bindgen",
]
+[[package]]
+name = "webbrowser"
+version = "1.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62c35be770821a214dbc362fc26908c853e776c0004294d0b10b8a6bad582f94"
+dependencies = [
+ "jni",
+ "log",
+ "ndk-context",
+ "objc2",
+ "objc2-app-kit",
+ "objc2-foundation",
+ "url",
+ "web-sys",
+]
+
[[package]]
name = "weezl"
version = "0.1.12"
@@ -3035,6 +3168,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+[[package]]
+name = "winapi-util"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
+dependencies = [
+ "windows-sys 0.61.2",
+]
+
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
diff --git a/Cargo.toml b/Cargo.toml
@@ -1,8 +1,8 @@
[package]
name = "myn-grrs"
-version = "0.1.3"
+version = "0.1.4"
edition = "2024"
-repository = "https://seed.radicle.xyz/rad:z3dnwE7h9y4ndGdqeafNLP8eDPn3Y.git"
+repository = "https://git.myn.sh/grrs.git"
description = "a minimal tui for gensokyo radio"
license = "Unlicense"
@@ -19,6 +19,8 @@ serde_json = "1.0"
image = "0.25"
ratatui-image = { version = "3.0", features = ["crossterm"] }
arboard = { version = "3.6.1", features = ["wayland-data-control"] }
+webbrowser = "1.2.4"
+urlencoding = "2.1.3"
[[bin]]
name = "grrs"
diff --git a/README.md b/README.md
@@ -39,7 +39,7 @@ nix run "git+rad://z3dnwE7h9y4ndGdqeafNLP8eDPn3Y#grrs"
- `c` - Copy track name/artist to clipboard
- `C` - Copy full track metadata to clipboard
- `t` - Cycle theme colors
-- `Enter` - Open detailed song info in library
+- `o`/`Enter` - Open album info in browser
- `Tab` - Switch between the library and player
- `?` - Show the help menu
- `q/^c` - Quit
diff --git a/src/input.rs b/src/input.rs
@@ -142,13 +142,6 @@ pub async fn handle_input(
should_quit: false,
should_clear: clear,
};
- } else if key.code == KeyCode::Char('o') || key.code == KeyCode::Enter {
- state.status_message = "album web links coming! (wip)".to_string();
- state.status_message_time = Some(std::time::Instant::now());
- return InputOutcome {
- should_quit: false,
- should_clear: clear,
- };
}
// MODE SPECIFIC KEYBINDS
@@ -166,6 +159,20 @@ pub async fn handle_input(
picker.clone(),
);
}
+ } else if key.code == KeyCode::Char('o') || key.code == KeyCode::Enter {
+ if !state.song.album.is_empty() {
+ let query = urlencoding::encode(&state.song.album);
+ let url = format!(
+ "https://touhoudb.com/Search?searchType=Album&filter={}",
+ query
+ );
+ if webbrowser::open(&url).is_ok() {
+ state.status_message = "opened touhoudb in browser!".to_string();
+ } else {
+ state.status_message = "failed to open browser".to_string();
+ }
+ state.status_message_time = Some(std::time::Instant::now());
+ }
} else if key.code == KeyCode::Char('l') {
let was_liked = state.likes.contains_key(&state.song.id);
state.toggle_like();
@@ -299,6 +306,23 @@ pub async fn handle_input(
clear = true;
}
}
+ } else if key.code == KeyCode::Char('o') || key.code == KeyCode::Enter {
+ if let Some(idx) = state.liked_list_state.selected() {
+ let sorted_likes = state.get_sorted_likes();
+ if let Some(song) = sorted_likes.get(idx) {
+ let query = urlencoding::encode(&song.album);
+ let url = format!(
+ "https://touhoudb.com/Search?searchType=Album&filter={}",
+ query
+ );
+ if webbrowser::open(&url).is_ok() {
+ state.status_message = "opened touhoudb in browser!".to_string();
+ } else {
+ state.status_message = "failed to open browser".to_string();
+ }
+ state.status_message_time = Some(std::time::Instant::now());
+ }
+ }
}
}
}
diff --git a/src/ui.rs b/src/ui.rs
@@ -332,7 +332,7 @@ fn draw_library(f: &mut Frame, state: &mut AppState, content: Rc<[Rect]>, bottom
}
fn draw_help_popup(f: &mut Frame, state: &AppState) {
- let area = centered_rect(44, 14, f.area());
+ let area = centered_rect(46, 16, f.area());
f.render_widget(Clear, area);
let block = Block::default()
@@ -385,6 +385,10 @@ fn draw_help_popup(f: &mut Frame, state: &AppState) {
Span::styled("[t]", Style::default().bold().fg(state.theme_color)),
Span::raw("Cycle theme colors"),
]),
+ Row::new(vec![
+ Span::styled("[o/Enter]", Style::default().bold().fg(state.theme_color)),
+ Span::raw("Open album in browser"),
+ ]),
Row::new(vec![
Span::styled("[?]", Style::default().bold().fg(state.theme_color)),
Span::raw("Close help menu"),
@@ -405,7 +409,7 @@ fn draw_help_popup(f: &mut Frame, state: &AppState) {
]),
Row::new(vec![
Span::styled("[o/Enter]", Style::default().bold().fg(state.theme_color)),
- Span::raw("Open album info (WIP)"),
+ Span::raw("Open album in browser"),
]),
Row::new(vec![
Span::styled("[j/k]", Style::default().bold().fg(state.theme_color)),