feat: The ListenBrainz integration has been extended with a configurable (5 seconds by default) delay in song reporting

This commit is contained in:
Rick van Lieshout 2023-08-28 14:19:12 +02:00
parent cbb22ba688
commit 68f76a9e63
9 changed files with 52 additions and 13 deletions

View File

@ -6,8 +6,10 @@
"Flatpak",
"geqnfr",
"hifi",
"libnotify",
"listenbrainz",
"playpause",
"prs",
"rescrobbler",
"scrobble",
"scrobbling",

View File

@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added settings to customize the Discord rich presence information
- Discord settings are now also collapsible like the ListenBrainz ones are
- Restyled settings menu to include version number and useful links on the about page
- The ListenBrainz integration has been extended with a configurable (5 seconds by default) delay in song reporting so that it doesn't spam the API when you are cycling through songs.
## [5.6.0]

View File

@ -51,10 +51,11 @@ The web version of [listen.tidal.com](https://listen.tidal.com) running in elect
- Songwhip.com integration (hotkey `ctrl + w`)
- Discord RPC integration (showing "now listening", "Browsing", etc)
- MPRIS integration
- UI + Json config (`~/.config/tidal-hifi/`, or `~/.var/app/com.mastermindzh.tidal-hifi/` for Flatpak)
## Contributions
To contribute you can use the standard GitHub features (issues, prs, etc) or join the discord server to talk with like-minded individuals.
To contribute you can use the standard GitHub features (issues, prs, etc.) or join the discord server to talk with like-minded individuals.
- ![Discord logo](./docs/images/discord.png) [Join the Discord server](https://discord.gg/yhNwf4v4He)

View File

@ -1,6 +1,6 @@
{
"name": "tidal-hifi",
"version": "5.6.0",
"version": "5.7.0",
"description": "Tidal on Electron with widevine(hifi) support",
"main": "ts-dist/main.js",
"scripts": {
@ -72,4 +72,4 @@
"typescript": "^5.1.6"
},
"prettier": "@mastermindzh/prettier-config"
}
}

View File

@ -29,6 +29,7 @@ export const settings = {
enabled: "ListenBrainz.enabled",
api: "ListenBrainz.api",
token: "ListenBrainz.token",
delay: "ListenBrainz.delay",
},
flags: {
root: "flags",

View File

@ -44,6 +44,7 @@ let adBlock: HTMLInputElement,
enableListenBrainz: HTMLInputElement,
ListenBrainzAPI: HTMLInputElement,
ListenBrainzToken: HTMLInputElement,
listenbrainz_delay: HTMLInputElement,
enableWaylandSupport: HTMLInputElement,
discord_details_prefix: HTMLInputElement,
discord_button_text: HTMLInputElement;
@ -75,6 +76,7 @@ function handleFileUploads() {
const fileMessage = document.getElementById("file-message");
fileMessage.innerText = "or drag and drop files here";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
document.getElementById("theme-files").addEventListener("change", function (e: any) {
Array.from(e.target.files).forEach((file: File) => {
const destination = `${app.getPath("userData")}/themes/${file.name}`;
@ -128,6 +130,7 @@ function refreshSettings() {
enableListenBrainz.checked = settingsStore.get(settings.ListenBrainz.enabled);
ListenBrainzAPI.value = settingsStore.get(settings.ListenBrainz.api);
ListenBrainzToken.value = settingsStore.get(settings.ListenBrainz.token);
listenbrainz_delay.value = settingsStore.get(settings.ListenBrainz.delay);
discord_details_prefix.value = settingsStore.get(settings.discord.detailsPrefix);
discord_button_text.value = settingsStore.get(settings.discord.buttonText);
@ -240,6 +243,7 @@ window.addEventListener("DOMContentLoaded", () => {
ListenBrainzAPI = get("ListenBrainzAPI");
ListenBrainzToken = get("ListenBrainzToken");
discord_details_prefix = get("discord_details_prefix");
listenbrainz_delay = get("listenbrainz_delay");
discord_button_text = get("discord_button_text");
refreshSettings();
@ -269,8 +273,9 @@ window.addEventListener("DOMContentLoaded", () => {
settings.ListenBrainz.enabled,
switchesWithSettings.listenBrainz
);
addTextAreaListener(ListenBrainzAPI, settings.ListenBrainz.api);
addTextAreaListener(ListenBrainzToken, settings.ListenBrainz.token);
addInputListener(ListenBrainzAPI, settings.ListenBrainz.api);
addInputListener(ListenBrainzToken, settings.ListenBrainz.token);
addInputListener(listenbrainz_delay, settings.ListenBrainz.delay);
addInputListener(discord_details_prefix, settings.discord.detailsPrefix);
addInputListener(discord_button_text, settings.discord.buttonText);
});

View File

@ -250,16 +250,22 @@
<div class="group__description">
<h4>ListenBrainz API Url</h4>
<p>There are multiple instances for ListenBrainz you can set the corresponding API url below.</p>
<input id="ListenBrainzAPI" type="text" class="text-input" name="ListenBrainzAPI" />
</div>
</div>
<textarea id="ListenBrainzAPI" class="textarea" cols="1" rows="1" spellcheck="false"></textarea>
<div class="group__option">
<div class="group__description">
<h4>ListenBrainz User Token</h4>
<p>Provide the user token you can get from the settings page.</p>
<input id="ListenBrainzToken" type="text" class="text-input" name="ListenBrainzToken" />
</div>
</div>
<textarea id="ListenBrainzToken" class="textarea" cols="1" rows="1" spellcheck="false"></textarea>
</div>
<div class="group__description">
<h4>ScrobbleDelay</h4>
<p>The delay (in ms) to send a song to ListenBrainz. Prevents spamming the API when you fast forward
immediately</p>
<input id="listenbrainz_delay" type="number" class="text-input" name="listenbrainz_delay" />
</div>
</div>
</section>

View File

@ -24,6 +24,8 @@ const appName = "TIDAL Hi-Fi";
let currentSong = "";
let player: Player;
let currentPlayStatus = MediaStatus.paused;
let currentListenBrainzDelayId: ReturnType<typeof setTimeout>;
let scrobbleWaitingForDelay = false;
const elements = {
play: '*[data-test="play"]',
@ -395,6 +397,9 @@ function updateMpris(options: Options) {
}
}
/**
* Update the listenbrainz service with new data based on a few conditions
*/
function updateListenBrainz(options: Options) {
if (settingsStore.get(settings.ListenBrainz.enabled)) {
const oldData = ListenBrainzStore.get(ListenBrainzConstants.oldData) as StoreData;
@ -402,12 +407,22 @@ function updateListenBrainz(options: Options) {
(!oldData && options.status === MediaStatus.playing) ||
(oldData && oldData.title !== options.title)
) {
ListenBrainz.scrobble(
options.title,
options.artists,
options.status,
convertDuration(options.duration)
);
if (!scrobbleWaitingForDelay) {
scrobbleWaitingForDelay = true;
clearTimeout(currentListenBrainzDelayId);
currentListenBrainzDelayId = setTimeout(
() => {
ListenBrainz.scrobble(
options.title,
options.artists,
options.status,
convertDuration(options.duration)
);
scrobbleWaitingForDelay = false;
},
settingsStore.get(settings.ListenBrainz.delay) ?? 0
);
}
}
}
}

View File

@ -26,6 +26,7 @@ export const settingsStore = new Store({
enabled: false,
api: "https://api.listenbrainz.org",
token: "",
delay: 5000,
},
flags: {
disableHardwareMediaKeys: false,
@ -53,6 +54,13 @@ export const settingsStore = new Store({
migrationStore.get("disableHardwareMediaKeys") ?? false
);
},
"5.7.0": (migrationStore) => {
console.log("running migrations for 5.7.0");
migrationStore.set(
settings.ListenBrainz.delay,
migrationStore.get(settings.ListenBrainz.delay) ?? 5000
);
},
},
});