Skip to content

Commit

Permalink
feat: lastfm indicator on scrobble success or error, send currently l…
Browse files Browse the repository at this point in the history
…istening only once on change
  • Loading branch information
Venipa committed Nov 11, 2024
1 parent f56cb8a commit ab24ec1
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 6 deletions.
14 changes: 12 additions & 2 deletions src/main/plugins/lastfmProvider.plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ export default class LastFMProvider extends BaseProvider implements AfterInit, O
async handleTrackStart(track: TrackData) {
{
if (!this.client.isConnected()) return;
this.views.toolbarView?.webContents.send(IPC_EVENT_NAMES.LAST_FM_SUBMIT_STATE, "start");
await this.client
.updateNowPlaying({
artist: track.video.author,
Expand All @@ -193,14 +194,19 @@ export default class LastFMProvider extends BaseProvider implements AfterInit, O
})
.then(stringifyJson)
.then((d) => this.logger.debug(d))
.then(() => {
this.views.toolbarView?.webContents.send(IPC_EVENT_NAMES.LAST_FM_SUBMIT_STATE, true);
})
.catch((err) => {
this.logger.error(err);
});
this.views.toolbarView?.webContents.send(IPC_EVENT_NAMES.LAST_FM_SUBMIT_STATE, false);
})
}
}

async handleTrackChange(track: TrackData) {
if (!this.client.isConnected()) return;
this.views.toolbarView?.webContents.send(IPC_EVENT_NAMES.LAST_FM_SUBMIT_STATE, "change");
await this.client
.scrobble({
artist: track.video.author,
Expand All @@ -210,8 +216,12 @@ export default class LastFMProvider extends BaseProvider implements AfterInit, O
})
.then(stringifyJson)
.then((d) => this.logger.debug(d))
.then(() => {
this.views.toolbarView?.webContents.send(IPC_EVENT_NAMES.LAST_FM_SUBMIT_STATE, true);
})
.catch((err) => {
this.logger.error(err);
});
this.views.toolbarView?.webContents.send(IPC_EVENT_NAMES.LAST_FM_SUBMIT_STATE, false);
})
}
}
7 changes: 4 additions & 3 deletions src/main/plugins/trackProvider.plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,9 @@ export default class TrackProvider extends BaseProvider implements AfterInit {
track.video.videoId === this._activeTrackId ||
(await this.getActiveTrackByDOM()) === track.video.videoId
) {
const lastTrackId = this._activeTrackId;
this._activeTrackId = track.video.videoId;
this.pushTrackToViews(track as TrackData);
this.pushTrackToViews(track as TrackData, lastTrackId !== track.video.videoId);
}
}
@IpcOn("track:title-change", {
Expand Down Expand Up @@ -169,7 +170,7 @@ export default class TrackProvider extends BaseProvider implements AfterInit {
}
}
private trackChangeTimeout: any;
public async pushTrackToViews(trackRef: TrackData) {
public async pushTrackToViews(trackRef: TrackData, updateLastFm: boolean = true) {
trackRef.meta.startedAt = new Date().getTime() / 1000;
const track = clone(trackRef);
this.views.toolbarView.webContents.send("track:title", track?.video?.title);
Expand All @@ -181,7 +182,7 @@ export default class TrackProvider extends BaseProvider implements AfterInit {
api.sendMessage("track:change", track);
const lastfm = this.getProvider("lastfm");
const lastfmState = lastfm.getState();
if (lastfm && lastfmState.connected && !lastfmState.processing) {
if (updateLastFm && lastfm && lastfmState.connected && !lastfmState.processing && track.video.videoId) {
await lastfm.handleTrackStart(track);
if (this.trackChangeTimeout) clearTimeout(this.trackChangeTimeout);
this.trackChangeTimeout = setTimeout(
Expand Down
1 change: 1 addition & 0 deletions src/main/utils/eventNames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const IPC_EVENT_NAMES = {
LAST_FM_STATUS: "lastfm.status",
LAST_FM_PROFILE: "lastfm.profile",
LAST_FM_TOGGLE: "lastfm.toggle",
LAST_FM_SUBMIT_STATE: "lastfm.stateObserver",
...API_ROUTES,
};
export default IPC_EVENT_NAMES;
1 change: 1 addition & 0 deletions src/preload/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const setContext = (key: string, value: any) =>
process.contextIsolated
? contextBridge.exposeInMainWorld(key, value)
: (window[key] = Object.freeze(value));
ipcRenderer.setMaxListeners(100);
export default {
ipcRenderer: {
emit: (event, ...data) => ipcRenderer.send(event, ...data),
Expand Down
27 changes: 27 additions & 0 deletions src/renderer/src/views/youtube/toolbar-options.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,18 @@
}"
@click="authorizeLastFM"
>
<template v-if="lastFM.connected && !lastFM.error && lastFMState !== null">
<Spinner size="sm" v-if="typeof lastFMState === 'string'" />
<CheckIcon v-else-if="lastFMState === true" class="text-green-500" />
<AlertCircleIcon v-else-if="lastFMState === false" class="text-red-500" />
</template>

<LastFMIcon
:class="{
'text-green-500': lastFM.connected && !lastFM.error,
'text-red-500': lastFM.error,
}"
v-else
></LastFMIcon>
<span v-if="lastFM.name" :class="{ 'text-gray-100 text-sm': true }">{{ lastFM.name }}</span>
</button>
Expand Down Expand Up @@ -86,14 +93,17 @@
</template>

<script lang="ts" setup>
import IPC_EVENT_NAMES from "@main/utils/eventNames";
import DevIcon from "@renderer/assets/icons/chip.svg";
import RPCIcon from "@renderer/assets/icons/discord-rpc.svg";
import HomeIcon from "@renderer/assets/icons/home.svg";
import LastFMIcon from "@renderer/assets/icons/lastfm.svg";
import MiniPlayerIcon from "@renderer/assets/icons/mini-player.svg";
import RefreshIcon from "@renderer/assets/icons/refresh.svg";
import Spinner from "@renderer/components/Spinner.vue";
import { logger } from "@shared/utils/console";
import { refIpc } from "@shared/utils/Ipc";
import { AlertCircleIcon, CheckIcon } from "lucide-vue-next";
import { onMounted, ref } from "vue";
const [discordConnected, setDiscordConnected] = refIpc(
Expand All @@ -120,6 +130,23 @@ const [lastFM] = refIpc("LAST_FM_STATUS", {
defaultValue: { connected: false, name: null, error: null },
ignoreUndefined: true,
});
const stateHandle = ref<NodeJS.Timeout>();
const [lastFMState, setFmState] = refIpc<"start" | "change" | boolean | null>(
IPC_EVENT_NAMES.LAST_FM_SUBMIT_STATE,
{
defaultValue: null,
ignoreUndefined: true,
onTrigger: (_fmstate, _prevfmstate) => {
if (typeof _prevfmstate === "string" && typeof _fmstate === "boolean") {
if (stateHandle.value) clearTimeout(stateHandle.value);
stateHandle.value = setTimeout(() => {
setFmState(null);
logger.debug("clear fm submit state");
}, 2000);
}
},
},
);
const lastFMLoading = ref(false);
const [discordEnabled, setDiscordEnabled] = refIpc("settingsProvider.change", {
defaultValue: window.settings.get("discord.enabled"),
Expand Down
5 changes: 4 additions & 1 deletion src/shared/utils/Ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import { onBeforeMount, onMounted, onUnmounted, Ref, ref } from "vue";
type Map<T, R> =
| ((item: T, name: string, prev: any) => T)
| ((item: T, name: string, prev: any) => R);
type Trigger<T> = ((item: T, prev: T) => void)
type IpcHandler = (ev: IpcRendererEvent, ...args: any[]) => void;
type RefReturn<R> = [Ref<R>, (val: R) => void];
type RefIpcOptions<T, R> = {
defaultValue?: R;
mapper?: Map<T, R>;
onTrigger?: Trigger<T>;
ignoreUndefined?: boolean;
rawArgs?: boolean;
debug?: boolean;
Expand All @@ -30,7 +32,7 @@ export function refIpc<T, R = T>(
eventName: string | string[],
options?: Partial<RefIpcOptions<T, R>>,
): RefReturn<R> {
const { defaultValue, mapper, ignoreUndefined, rawArgs } = options ?? {};
const { defaultValue, mapper, onTrigger, ignoreUndefined, rawArgs } = options ?? {};
const defaultMapper = (item: T) => item;
const objMap = (mapper || defaultMapper) as (item: T, name: string, prev: any) => R;
const state = ref<R>(defaultValue as R) as Ref<R>;
Expand All @@ -40,6 +42,7 @@ export function refIpc<T, R = T>(
const vArgs = rawArgs !== true ? data.flat()?.[0] : data;
const newVal = objMap(vArgs as any as T, handlerName, state.value);
if (ignoreUndefined && typeof newVal === "undefined") return;
onTrigger?.(newVal as any, state.value as any);
state.value = newVal;
if (options?.debug) console.log(`[IPC:Receiving@${handlerName}] `, ev, ...data);
}) as IpcHandler;
Expand Down

0 comments on commit ab24ec1

Please sign in to comment.