Skip to content

Commit

Permalink
reimplement rust state tracking
Browse files Browse the repository at this point in the history
  • Loading branch information
fucksophie committed Jun 5, 2023
1 parent da5f347 commit fcad5a8
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 22 deletions.
32 changes: 25 additions & 7 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

use discord_presence::{Client, Event};
use discord_presence::{Client};
use once_cell::sync::Lazy;
use tauri_plugin_log::{TargetKind, Target};

// TODO: Eventually - when I get better at Rust I'm going to remove these static mutables
static mut CLIENT: Lazy<Client> = Lazy::new(|| Client::new(988215000676073532));
static mut STARTED_CLIENT: bool = false;
static mut CLIENT_CONNECTED: bool = false;

#[cfg(not(mobile))]
#[tauri::command]
Expand All @@ -21,27 +22,44 @@ fn start_discord_rpc() {
}
STARTED_CLIENT = true;
_ = CLIENT.start();

CLIENT.block_until_event(Event::Ready).unwrap();

CLIENT.on_ready(|_ctx| {
CLIENT_CONNECTED = true;
println!("[RUST] Client connected.");
});

CLIENT.on_error(|_ctx| {
CLIENT_CONNECTED = false;
println!("[RUST] Client disconnected.");
_ = CLIENT.start();
})
}

println!("[RUST] DiscordRPC connected to Client.")
println!("[RUST] Attempting to connect to Client.")
}

#[cfg(not(mobile))]
#[tauri::command]
fn clear_actvitiy() {
fn clear_activity() {
unsafe {
if STARTED_CLIENT {
CLIENT.clear_activity().expect("failed to clear activity");
}
}
}

#[cfg(not(mobile))]
#[tauri::command]
fn get_rpc_state() -> bool {
unsafe {
return CLIENT_CONNECTED;
}
}

#[cfg(not(mobile))]
#[tauri::command]
fn set_discord_rpc(state: String, details: String, image: String) {
println!("[RUST] Attempting to set DiscordRPC state to \"{}\" and details to \"{}\" and to \"{}\".", state, details, image);
println!("[RUST] Attempting to set DiscordRPC state to \"{}\" and details to \"{}\" and to \"{}\".", state, details, image);
if state.is_empty() { return; }
if details.is_empty() { return; }
if image.is_empty() { return; }
Expand All @@ -65,7 +83,7 @@ fn main() {
Target::new(TargetKind::Stdout),
Target::new(TargetKind::Webview),
]).build())
.invoke_handler(tauri::generate_handler![set_discord_rpc, start_discord_rpc, clear_actvitiy])
.invoke_handler(tauri::generate_handler![set_discord_rpc, start_discord_rpc, clear_activity, get_rpc_state])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
3 changes: 0 additions & 3 deletions src/components/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,7 @@ function Integrations({buttonClass}: {buttonClass:string}) {
if (phase.current === 0) {
const token = await generateToken();
localStorage.temporaryToken = token;
//@ts-expect-error
if(window.__TAURI__) {
//@ts-expect-error
window.__TAURI__.shell.open(`https://last.fm/api/auth/?api_key=${lastFmApiKey}&token=${token}`);
} else {
window.open(`https://last.fm/api/auth/?api_key=${lastFmApiKey}&token=${token}`, "_blank")
Expand Down Expand Up @@ -118,7 +116,6 @@ function Integrations({buttonClass}: {buttonClass:string}) {
</div>
{
(() => {
//@ts-expect-error
if(window.__TAURI__) {
return <>
<h2 className='text-2xl'>discordRPC</h2>
Expand Down
6 changes: 3 additions & 3 deletions src/components/player/Player.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import ProgressBar from './ProgressBar';
import DisplayTrack from './DisplayTrack';
import Subsonic from '../../lib/subsonic';
import { updateNowPlaying, scrobble } from '../../lib/LastFM';
import DiscordRPC from '../../lib/DiscordRPC'

const subsonic = new Subsonic(
localStorage.http,
Expand Down Expand Up @@ -136,9 +137,8 @@ function AudioPlayer({
);
}

if(localStorage.discordRPCEnabled) {
// @ts-expect-error
await window.__TAURI__.invoke("set_discord_rpc", {
if(localStorage.discordRPCEnabled == "true" && window.__TAURI__) {
DiscordRPC.queueActivity({
details: `${currentTrack.artist} (on ${currentTrack.album})`,
state: currentTrack.title,
image: "mp2"
Expand Down
12 changes: 12 additions & 0 deletions src/defs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
declare global {
interface Window {
__TAURI__?: {
invoke: (prop: string, ...args: any[]) => any;
shell: {
open: (url: string) => void;
}
};
}
}

export {};
63 changes: 63 additions & 0 deletions src/lib/DiscordRPC.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// yourfriend, 2023

// this wrapper is needed for keeping sync track of the
// state between tauri & react

// this could totally be avoided, but because of speed concerns I decided to implement it.

interface Activity {
details: string;
state: string;
image: string;
};

export class DiscordRPC {
activityQueue: (Activity)[] = []

lastKnownState: boolean = false;
interval: number;

constructor() {
this.interval = setInterval(async ()=>{
if(window.__TAURI__) {
this.lastKnownState = await window.__TAURI__.invoke("get_rpc_state");
if(this.activityQueue.length != 0 && this.lastKnownState) {
let last = this.activityQueue.at(-1)!;
this.activityQueue = [];
this.sendActivity(last);
}
}
}, 1000) as unknown as number
}

error() {
throw new Error("Every usage of the DiscordRPC module should be safeguarded with a if statement, checking __TAURI__.")
}

start() {
if(!window.__TAURI__) return this.error();
window.__TAURI__.invoke("start_discord_rpc");
}

clearActivity() {
if(!window.__TAURI__) return this.error();
window.__TAURI__.invoke("clear_activity");
}

private sendActivity(act: Activity) {
if(!window.__TAURI__) return this.error();
window.__TAURI__.invoke("set_discord_rpc", act);
}


queueActivity(act: Activity) {
if(!window.__TAURI__) return this.error();
if(!this.lastKnownState) {
this.activityQueue.push(act);
} else {
this.sendActivity(act);
}
}
}

export default new DiscordRPC();
14 changes: 5 additions & 9 deletions src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
RouterProvider,
redirect,
} from 'react-router-dom';

import DiscordRPC from './lib/DiscordRPC'
import { error, info } from "./logger";

import { install } from '@twind/core';
Expand Down Expand Up @@ -82,20 +82,16 @@ createRoot(document.getElementById('root')!).render(
</>
);

// @ts-expect-error
if(localStorage.discordRPCEnabled == "true" && window.__TAURI__) {
// INFO: start_discord_rpc blocks the main thread by default,
// so `await` just adds more delays here.

// @ts-expect-error
window.__TAURI__.invoke("start_discord_rpc");
// @ts-expect-error
window.__TAURI__.invoke("set_discord_rpc", {
DiscordRPC.start();
DiscordRPC.queueActivity({
details: "On page",
state: (location.pathname.substring(1)||"login"),
image: "mp2"
});
});
} else {
// @ts-expect-error
if(window.__TAURI__) window.__TAURI__.invoke("clear_actvitiy");
if(window.__TAURI__) DiscordRPC.clearActivity();
}

0 comments on commit fcad5a8

Please sign in to comment.