song bridge
Seto Elkahfi committed
Aug 2, 2024 at 00:08 UTC
92ba30ad32975a76f3acdb5c1a4709a48e85b2a8
9 files changed
+138
-8
frontend/splitfire-desktop/app/_src/lib/tauriHandler.ts
+1
@@ -20,4 +20,5 @@ export const TAURI_ACCOUNT_REGISTER = 'account_register'
20
// Contents
21
export const TAURI_CONTENT_CAROUSEL = 'content_carousel'
22
export const TAURI_CONTENT_READY_TO_PLAY = 'content_ready_to_play'
23
+export const TAURI_CONTENT_SONG_BRIDGE_DETAIL = 'content_song_bridge_detail'
24
frontend/splitfire-desktop/app/split/page.tsx
+21
@@ -1,10 +1,31 @@
1
"use client";
2
3
import { useSearchParams } from "next/navigation";
4
+import { useLogger } from "../_src/lib/logger";
5
+import { useEffect } from "react";
6
+import { invoke } from "@tauri-apps/api";
7
+import { TAURI_CONTENT_SONG_BRIDGE_DETAIL } from "../_src/lib/tauriHandler";
8
9
export default function Page() {
10
+ const log = useLogger("Play");
11
const searchParams = useSearchParams();
12
const songProviderId = searchParams.get("songProviderId");
13
+
14
+ useEffect(() => {
15
+ log.debug("Play page loaded.");
16
+ async function fetchData() {
17
+ try {
18
+ const rest = await invoke(TAURI_CONTENT_SONG_BRIDGE_DETAIL, { songProviderId });
19
+ log.debug("PreparePlayerResponse", rest);
20
+
21
+ } catch (error) {
22
+ log.error(error);
23
+ }
24
+ }
25
+ fetchData();
26
+ // eslint-disable-next-line react-hooks/exhaustive-deps
27
+ }, []);
28
+
29
return (
30
<div className="prose prose-sm prose-invert max-w-none">
31
<div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
frontend/splitfire-desktop/src-tauri/Cargo.lock
+20
@@ -115,6 +115,7 @@ dependencies = [
115
"tauri-build",
116
"tauri-plugin-log",
117
"tauri-plugin-store",
118
+ "uri-template-system",
119
"url-builder",
120
]
121
@@ -4154,6 +4155,25 @@ version = "1.11.0"
4155
source = "registry+https://github.com/rust-lang/crates.io-index"
4156
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
4157
4158
+[[package]]
4159
+name = "uri-template-system"
4160
+version = "0.1.0"
4161
+source = "registry+https://github.com/rust-lang/crates.io-index"
4162
+checksum = "50ce47b579c9b300dd1540e30578b33854f86e7072d7ff505016705609261ca9"
4163
+dependencies = [
4164
+ "uri-template-system-core",
4165
+]
4166
+
4167
+[[package]]
4168
+name = "uri-template-system-core"
4169
+version = "0.1.5"
4170
+source = "registry+https://github.com/rust-lang/crates.io-index"
4171
+checksum = "26f254395af92efc86d9a0bb0a614dc76865c8a4ea0d71ba66ccd134d7f831fb"
4172
+dependencies = [
4173
+ "fnv",
4174
+ "thiserror",
4175
+]
4176
+
4177
[[package]]
4178
name = "url"
4179
version = "2.5.0"
frontend/splitfire-desktop/src-tauri/Cargo.toml
+1
@@ -31,6 +31,7 @@ tauri = { version = "1.7.1", features = [] }
31
tauri-plugin-log = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1", features = ["colored"] }
32
tauri-plugin-store = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }
33
url-builder = "0.1.1"
34
+uri-template-system = "=0.1.0"
35
36
[features]
37
# by default Tauri runs in production mode
frontend/splitfire-desktop/src-tauri/src/command/constants.rs
+1
@@ -29,6 +29,7 @@ pub const PATH_CAROUSEL: &str = "api/v1/carousel";
29
pub const PATH_READY_TO_PLAY: &str = "api/v1/ready-to-play";
30
pub const PATH_SEARCH: &str = "api/v1//search";
31
pub const PATH_TOP_VOTES: &str = "api/v1/top-votes";
32
+pub const PATH_SONG_BRIDGE_DETAIL: &str = "api/v1/song-bridge/{providerId}/detail";
33
34
pub fn base_url_builder() -> URLBuilder {
35
let mut url_builder = URLBuilder::new();
frontend/splitfire-desktop/src-tauri/src/main.rs
+4
-2
@@ -23,8 +23,9 @@ use app::{
23
account_logout, account_register,
24
},
25
content::{
26
- __cmd__content_carousel, __cmd__content_ready_to_play, content_carousel,
27
- content_ready_to_play,
26
+ __cmd__content_carousel, __cmd__content_ready_to_play,
27
+ __cmd__content_song_bridge_detail, content_carousel, content_ready_to_play,
28
+ content_song_bridge_detail,
29
},
30
},
31
sfai_home_dir_path,
@@ -76,6 +77,7 @@ fn main() {
77
player_recording_length,
78
content_carousel,
79
content_ready_to_play,
80
+ content_song_bridge_detail,
81
])
82
.run(tauri::generate_context!())
83
.expect("Error while running tauri application.");
frontend/splitfire-desktop/src-tauri/src/models/content.rs
+43
-2
@@ -20,7 +20,7 @@ pub struct CarouselResponse {
20
#[derive(Serialize, Deserialize)]
21
#[derive(Debug)]
22
pub struct SongProvider {
23
- pub id: i32,
23
+ pub id: i32, // API response code
24
pub name: String,
25
pub provider_id: String,
26
pub provider_type: ProviderType,
@@ -35,4 +35,45 @@ pub enum ProviderType {
35
Youtube,
36
#[serde(rename = "spotify")]
37
Spotify,
38
-}
\ No newline at end of file
38
+}
39
+
40
+#[derive(Serialize)]
41
+#[derive(Debug)]
42
+pub struct ContentSongBridgeResponse {
43
+ pub code: TauriResponse,
44
+ pub message: String,
45
+ pub song_provider: Option<SongProvider>,
46
+ pub votes: Vec<SongProviderVote>
47
+}
48
+
49
+#[derive(Serialize, Deserialize)]
50
+#[derive(Debug)]
51
+pub struct SongBridgeResponse {
52
+ pub code: i32, // API response code
53
+ pub message: String,
54
+ pub error: Option<String>,
55
+ pub song_provider: Option<SongProvider>,
56
+ pub votes: Vec<SongProviderVote>
57
+}
58
+
59
+#[derive(Serialize, Deserialize)]
60
+#[derive(Debug)]
61
+pub struct SongProviderVote {
62
+ pub id: i32,
63
+ pub user_id: i32,
64
+ pub song_provider_id: i32,
65
+ pub vote_type: VoteType,
66
+ pub voter_username_or_id: String,
67
+ pub voter_gravatar: String,
68
+ pub created_at: String,
69
+ pub updated_at: String
70
+}
71
+
72
+#[derive(Serialize, Deserialize)]
73
+#[derive(Debug)]
74
+pub enum VoteType {
75
+ #[serde(rename = "up")]
76
+ UP,
77
+ #[serde(rename = "down")]
78
+ DOWN
79
+}
frontend/splitfire-desktop/src-tauri/src/models/player.rs
+2
-2
@@ -1,6 +1,6 @@
1
use std::fmt::Display;
2
use serde::{Deserialize, Serialize};
3
-use serde_repr::Serialize_repr;
3
+use serde_repr::{Deserialize_repr, Serialize_repr};
4
5
6
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
@@ -49,7 +49,7 @@ pub struct AudioFileResponse {
49
pub audio_file: AudioFile,
50
}
51
52
-#[derive(Serialize_repr)]
52
+#[derive(Serialize_repr, Deserialize_repr)]
53
#[repr(u8)]
54
#[derive(Debug)]
55
pub enum TauriResponse {
frontend/splitfire-desktop/src-tauri/src/rest/content.rs
+45
-2
@@ -1,7 +1,7 @@
1
use crate::{
2
- command::constants::{base_url_builder, PATH_CAROUSEL, PATH_READY_TO_PLAY},
2
+ command::constants::{base_url_builder, PATH_CAROUSEL, PATH_READY_TO_PLAY, PATH_SONG_BRIDGE_DETAIL},
3
models::{
4
- content::{CarouselResponse, ContentCarouselResponse},
4
+ content::{CarouselResponse, ContentCarouselResponse, ContentSongBridgeResponse, SongBridgeResponse},
5
player::TauriResponse,
6
},
7
};
@@ -83,6 +83,49 @@ pub async fn content_ready_to_play() -> ContentCarouselResponse {
83
}
84
}
85
86
+#[tauri::command]
87
+pub async fn content_song_bridge_detail(song_provider_id: String) -> ContentSongBridgeResponse {
88
+ debug!("Song provider id: {:?}", song_provider_id);
89
+ let response: Result<reqwest::Response, reqwest::Error> = Client::new()
90
+ .get(content_url_builder(PATH_SONG_BRIDGE_DETAIL))
91
+ .send()
92
+ .await;
93
+
94
+ let response = match response {
95
+ Ok(response) => response,
96
+ Err(e) => {
97
+ error!("Failed to get response: {:?}", e);
98
+ return ContentSongBridgeResponse {
99
+ code: TauriResponse::Error,
100
+ message: e.to_string(),
101
+ song_provider: None,
102
+ votes: vec![],
103
+ };
104
+ }
105
+ };
106
+
107
+ let res: SongBridgeResponse= match response.json().await {
108
+ Ok(json) => json,
109
+ Err(e) => {
110
+ error!("Failed to parse response: {:?}", e);
111
+ return ContentSongBridgeResponse {
112
+ code: TauriResponse::Error,
113
+ message: e.to_string(),
114
+ song_provider: None,
115
+ votes: vec![],
116
+ };
117
+ }
118
+ };
119
+
120
+ debug!("Song bridge detail: {:?}", res);
121
+ ContentSongBridgeResponse {
122
+ code: TauriResponse::Success,
123
+ message: res.message,
124
+ song_provider: res.song_provider,
125
+ votes: res.votes,
126
+ }
127
+}
128
+
129
fn content_url_builder(path: &str) -> String {
130
let mut url_builder = base_url_builder();
131
url_builder.add_route(path);