Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/14ROVI/my-website
Browse files Browse the repository at this point in the history
  • Loading branch information
14ROVI committed Jul 21, 2024
2 parents ab71350 + a9fa3a0 commit cb7513f
Show file tree
Hide file tree
Showing 8 changed files with 283 additions and 15 deletions.
Binary file added assets/backgrounds/22.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/backgrounds/22.mp4
Binary file not shown.
Binary file added assets/backgrounds/22.webm
Binary file not shown.
Binary file added assets/default_album.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/copland.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ impl Component for Copland {
self.theme = theme;
let el = self.background_video.cast::<HtmlVideoElement>().unwrap();
el.load();
el.play().ok();
// el.onloadeddata().unwrap().
true
}
CoplandMsg::NewSticky => {
Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use yew::prelude::*;

use rand::Rng;

pub const MAX_BACKGROUND_INDEX: u32 = 22;
pub const MAX_BACKGROUND_INDEX: u32 = 23;

#[derive(Deserialize)]
pub struct NoteJson {
Expand Down
239 changes: 226 additions & 13 deletions src/windows/spotify.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
use std::vec;

use yew::prelude::*;
use gloo::net::websocket::{Message as WsMessage, futures::WebSocket};
use wasm_bindgen_futures::spawn_local;
use futures::{channel::mpsc::UnboundedSender, SinkExt, StreamExt};
use serde_json::Value;
use gloo::timers::callback::Interval;
use js_sys::Date;
use gloo::net::http::Request;
use serde_json::Value;


struct LanyardData {
album_art: String,
Expand All @@ -18,13 +22,19 @@ struct LanyardData {
#[derive(Debug)]
pub enum Msg {
LanyardMessage(WsMessage),
UpdateTime
UpdateTime,
UpdateHistory,
SaveHistory(Vec<LastFmHistoryHOCProps>),
ToggleShowHistory
}

pub struct Spotify {
lanyard_ws_write: UnboundedSender<String>,
lanyard_data: Option<LanyardData>,
update_timer: Option<Interval>
update_timer: Option<Interval>,
show_history: bool,
history: Vec<LastFmHistoryHOCProps>,
last_fm_current: Option<LastFmHistoryHOCProps>
}
impl Component for Spotify {
type Message = Msg;
Expand Down Expand Up @@ -53,10 +63,19 @@ impl Component for Spotify {
}
});

let link = ctx.link().clone();
link.send_message(Msg::UpdateHistory);
Interval::new(10_000, move ||
link.send_message(Msg::UpdateHistory)
).forget();

Self {
lanyard_ws_write: tx,
lanyard_data: None,
update_timer: None
update_timer: None,
show_history: false,
history: vec![],
last_fm_current: None,
}
}

Expand Down Expand Up @@ -108,14 +127,97 @@ impl Component for Spotify {
Msg::UpdateTime => {
true
},
Msg::UpdateHistory => {
let save_history = ctx.link().callback(Msg::SaveHistory);

spawn_local(async move {
let text = Request::get("https://api.rovi.me/lastfm")
.send()
.await
.unwrap()
.text()
.await
.unwrap();
let json: Value = serde_json::from_str(&text).unwrap();
let tracks = json["recenttracks"]["track"].as_array().unwrap();
let tracks: Vec<LastFmHistoryHOCProps> = tracks.iter().map(|t| {
let t = t.clone();
LastFmHistoryHOCProps {
current_time: Date::now() as u64 / 1000,
album_art: t["image"][3]["#text"].as_str().unwrap_or_default().to_string(),
album: t["album"]["#text"].as_str().unwrap_or_default().to_string(),
song: t["name"].as_str().unwrap_or_default().to_string(),
artist: t["artist"]["#text"].as_str().unwrap_or_default().to_string(),
listened_at: t["date"]["uts"].as_str().unwrap_or("0").parse().unwrap_or_default(),
}
})
.collect();

log::info!("Updated last fm history.");
save_history.emit(tracks);
});
false
},
Msg::SaveHistory(history) => {
if let Some(current) = history.iter().find(|p| p.listened_at == 0) {
self.last_fm_current = Some(current.clone());
} else {
self.last_fm_current = None;
}
self.history = history;
true
},
Msg::ToggleShowHistory => {
self.show_history = !self.show_history;
true
},
_ => {
log::info!("not covered!");
false
}
}
}

fn view(&self, _ctx: &Context<Self>) -> Html {
fn view(&self, ctx: &Context<Self>) -> Html {
let current_time = Date::now() as u64 / 1000;

let history = html! {
<div class="status-bar-field">
<div class="lastfm-scroll-container">
<div class="lastfm-container">
{ self.history.iter()
.filter(|p| p.listened_at != 0)
.map(|p| html! {
<LastFmHistoryHOC
key={p.listened_at}
{current_time}
..p.clone()/>
} ).collect::<Html>() }
</div>
</div>
</div>
};

let toggle_show_history = ctx.link().callback(|_| Msg::ToggleShowHistory);
let button_open = if self.show_history {
Some("open")
} else {
None
};


let history = html! {
<div class="history-container">
<button
class={classes!(button_open)}
onclick={toggle_show_history}
>{"History"}</button>
if self.show_history {
{ history }
}
</div>
};

if let Some(lanyard_data) = self.lanyard_data.as_ref() {

let current_time = Date::now() as u64;
Expand All @@ -129,20 +231,131 @@ impl Component for Spotify {
}

html!{
<div class="spotify-container">
<img alt="Spotify album art" width="100" height="100" src={ lanyard_data.album_art.clone() }/>
<div>
<p><b>{ lanyard_data.song_name.clone() }</b></p>
<p>{ "On " }{ lanyard_data.album_name.clone() }</p>
<p>{ "By " }{ lanyard_data.artist_name.clone() }</p>
<p id="spotify-song-duration">{ "Elapsed: " }{ format_time(elapsed_time) }{" / "}{ format_time(total_time) }</p>
<div class="music-container">
<div class="spotify-container">
<img alt="Spotify album art" width="100" height="100" src={ lanyard_data.album_art.clone() }/>
<div>
<p><b>{ lanyard_data.song_name.clone() }</b></p>
<p>{ "On " }{ lanyard_data.album_name.clone() }</p>
<p>{ "By " }{ lanyard_data.artist_name.clone() }</p>
<p id="spotify-song-duration">{ "Elapsed: " }{ format_time(elapsed_time) }{" / "}{ format_time(total_time) }</p>
</div>
</div>
{ history }
</div>
}
} else if let Some(last_fm_current) = self.last_fm_current.as_ref() {
html!{
<div class="music-container">
<div class="spotify-container">
<img alt="Spotify album art" width="100" height="100" src={ last_fm_current.album_art.clone() }/>
<div>
<p><b>{ last_fm_current.song.clone() }</b></p>
<p>{ "On " }{ last_fm_current.album.clone() }</p>
<p>{ "By " }{ last_fm_current.artist.clone() }</p>
<p id="spotify-song-duration">{"Currently listening"}</p>
</div>
</div>
{ history }
</div>
}
} else {
html! {
<p>{ "Not currently listening to anything :(" }</p>
<div class="music-container">
<p style="margin-bottom: 20px;">{ "Not currently listening to anything :(" }</p>
{ history }
</div>
}
}
}
}


#[derive(Properties, PartialEq, Debug, Clone)]
pub struct LastFmHistoryHOCProps {
pub current_time: u64,
pub album_art: String,
pub album: String,
pub song: String,
pub artist: String,
pub listened_at: u64,
}

#[derive(Properties, PartialEq)]
pub struct LastFmHistoryProps {
pub album_art: String,
pub song: String,
pub artist: String,
pub formatted_time: String,
}

#[function_component(LastFmHistoryHOC)]
pub fn last_fm_history_hoc(props: &LastFmHistoryHOCProps) -> Html {
let elapsed = props.current_time - props.listened_at;

let s_per_minute = 60;
let s_per_hour = 3600;
let s_per_day = 86400;
let s_per_month = 2592000;
let s_per_year = 31536000;

let minutes_passed = elapsed / s_per_minute;
let hours_passed = elapsed / s_per_hour;
let days_passed = elapsed / s_per_day;
let months_passed = elapsed / s_per_month;
let years_passed = elapsed / s_per_year;

let formatted_time = if years_passed > 1 {
format!("{} years ago", years_passed)
} else if years_passed == 1 {
String::from("1 year ago")
} else if months_passed > 1 {
format!("{} months ago", months_passed)
} else if months_passed == 1 {
String::from("1 month ago")
} else if days_passed > 1 {
format!("{} days ago", days_passed)
} else if days_passed == 1 {
String::from("1 day ago")
} else if hours_passed > 1 {
format!("{} hours ago", hours_passed)
} else if hours_passed == 1 {
String::from("1 hour ago")
} else if minutes_passed > 1 {
format!("{} minutes ago", minutes_passed)
} else if minutes_passed == 1 {
String::from("1 minute ago")
} else if elapsed > 1 {
format!("{} seconds ago", elapsed)
} else {
String::from("1 second ago")
};

html! {
<LastFmHistory
album_art={props.album_art.clone()}
song={props.song.clone()}
artist={props.artist.clone()}
formatted_time={formatted_time}
/>
}
}

#[function_component(LastFmHistory)]
pub fn last_fm_history(props: &LastFmHistoryProps) -> Html {
html!{
<div>
<img
alt="Track album art"
width="50"
height="50"
src={ props.album_art.clone() }
/>
<div>
<p><b>{ props.song.clone() }</b></p>
<p>{ props.artist.clone() }</p>
<p>{ props.formatted_time.clone() }</p>
</div>
</div>
}
}
55 changes: 55 additions & 0 deletions style.css
Original file line number Diff line number Diff line change
Expand Up @@ -153,4 +153,59 @@ video.background {
min-height: 50px;
max-height: 100px;
background-color: rgba(255, 255, 255, 0.4);
}
.history-container {
margin-top: 10px;
}
.history-container > button {
width: 100%;
position: relative;
}
.history-container > button::after {
content: url("data:image/svg+xml;charset=utf-8,<svg width='16' height='17' fill='none' xmlns='http://www.w3.org/2000/svg'><path fill-rule='evenodd' clip-rule='evenodd' d='M11 6H4v1h1v1h1v1h1v1h1V9h1V8h1V7h1V6z' fill='%23000'/></svg>");
bottom: 0px;
right: 5px;
position: absolute;
}
.history-container > button.open::after {
content: url("data:image/svg+xml;charset=utf-8,<svg width='16' height='17' fill='none' xmlns='http://www.w3.org/2000/svg'><path fill-rule='evenodd' clip-rule='evenodd' d='M8 6H7v1H6v1H5v1H4v1h7V9h-1V8H9V7H8V6z' fill='%23000'/></svg>");
}
.lastfm-scroll-container {
max-height: 200px;
overflow-y: scroll;
}
.lastfm-container {
display: flex;
flex-direction: column;
gap: 10px;
}
.lastfm-container img {
width: 50px;
height: 50px;
position: relative;
}
.lastfm-container img:before {
content: ' ';
display: block;
position: absolute;
height: 50px;
width: 50px;
background-image: url("/assets/default_album.png");
}
.lastfm-container > div {
display: flex;
flex-direction: row;
gap: 10px;
}
.lastfm-container > div > div {
min-width: 0;
display: flex;
flex-direction: column;
justify-content: space-around;
}
.lastfm-container > div > div > p {
margin: 0;
/* white-space: nowrap; */
/* overflow: hidden; */
/* text-overflow: ellipsis; */
}

0 comments on commit cb7513f

Please sign in to comment.