Merge pull request #1037 from vimaexd/discord-displaytype

implement discord status types
This commit is contained in:
Jeff 2025-08-27 21:00:52 -07:00 committed by GitHub
commit 352a8e71e6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 100 additions and 30 deletions

View file

@ -75,7 +75,7 @@
"@tanstack/react-query-devtools": "^4.32.1",
"@tanstack/react-query-persist-client": "^4.32.1",
"@ts-rest/core": "^3.23.0",
"@xhayper/discord-rpc": "^1.0.24",
"@xhayper/discord-rpc": "^1.3.0",
"audiomotion-analyzer": "^4.5.0",
"auto-text-size": "^0.2.3",
"axios": "^1.6.0",

57
pnpm-lock.yaml generated
View file

@ -72,8 +72,8 @@ importers:
specifier: ^3.23.0
version: 3.52.1(@types/node@22.15.32)(zod@3.25.23)
'@xhayper/discord-rpc':
specifier: ^1.0.24
version: 1.2.1
specifier: ^1.3.0
version: 1.3.0
audiomotion-analyzer:
specifier: ^4.5.0
version: 4.5.0
@ -506,8 +506,8 @@ packages:
resolution: {integrity: sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg==}
engines: {node: '>=18'}
'@discordjs/rest@2.5.0':
resolution: {integrity: sha512-PWhchxTzpn9EV3vvPRpwS0EE2rNYB9pvzDU/eLLW3mByJl0ZHZjHI2/wA8EbH2gRMQV7nu+0FoDF84oiPl8VAQ==}
'@discordjs/rest@2.5.1':
resolution: {integrity: sha512-Tg9840IneBcbrAjcGaQzHUJWFNq1MMWZjTdjJ0WS/89IffaNKc++iOvffucPxQTF/gviO9+9r8kEPea1X5J2Dw==}
engines: {node: '>=18'}
'@discordjs/util@1.1.1':
@ -1358,8 +1358,8 @@ packages:
resolution: {integrity: sha512-RaI5qZo6D2CVS6sTHFKg1v5Ohq/+Bo2LZ5gzUEwZ/WkHhwtGTCB/sVLw8ijOkAUxasZ+WshN/Rzj4ywsABJ5ZA==}
engines: {node: '>=v14.0.0', npm: '>=7.0.0'}
'@xhayper/discord-rpc@1.2.1':
resolution: {integrity: sha512-Ch04/7hq0nfV47nJzDcLIKx0SLUcPOMlkYV43faWpKtEO9SgLrTD4FAOMBBT+JORceQytnzBMPvktW2q9ZCMiw==}
'@xhayper/discord-rpc@1.3.0':
resolution: {integrity: sha512-0NmUTiODl7u3UEjmO6y0Syp3dmgVLAt2EHrH4QKTQcXRwtF8Wl7Eipdn/GSSZ8HkDwxQFvcDGJMxT9VWB0pH8g==}
engines: {node: '>=18.20.7'}
'@xmldom/xmldom@0.8.10':
@ -1959,11 +1959,8 @@ packages:
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
engines: {node: '>=8'}
discord-api-types@0.37.120:
resolution: {integrity: sha512-7xpNK0EiWjjDFp2nAhHXezE4OUWm7s1zhc/UXXN6hnFFU8dfoPHgV0Hx0RPiCa3ILRpdeh152icc68DGCyXYIw==}
discord-api-types@0.38.8:
resolution: {integrity: sha512-xuRXPD44FcbKHrQK15FS1HFlMRNJtsaZou/SVws18vQ7zHqmlxyDktMkZpyvD6gE2ctGOVYC/jUyoMMAyBWfcw==}
discord-api-types@0.38.18:
resolution: {integrity: sha512-ygenySjZKUaBf5JT8BNhZSxLzwpwdp41O0wVroOTu/N2DxFH7dxYTZUSnFJ6v+/2F3BMcnD47PC47u4aLOLxrQ==}
dmg-builder@26.0.12:
resolution: {integrity: sha512-59CAAjAhTaIMCN8y9kD573vDkxbs1uhDcrFLHSgutYdPcGOU35Rf95725snvzEOy4BFB7+eLJ8djCNPmGwG67w==}
@ -4451,10 +4448,6 @@ packages:
undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
undici@6.21.1:
resolution: {integrity: sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==}
engines: {node: '>=18.17'}
undici@6.21.3:
resolution: {integrity: sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==}
engines: {node: '>=18.17'}
@ -4698,6 +4691,18 @@ packages:
utf-8-validate:
optional: true
ws@8.18.3:
resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==}
engines: {node: '>=10.0.0'}
peerDependencies:
bufferutil: ^4.0.1
utf-8-validate: '>=5.0.2'
peerDependenciesMeta:
bufferutil:
optional: true
utf-8-validate:
optional: true
xml2js@0.4.23:
resolution: {integrity: sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==}
engines: {node: '>=4.0.0'}
@ -4954,17 +4959,17 @@ snapshots:
'@discordjs/collection@2.1.1': {}
'@discordjs/rest@2.5.0':
'@discordjs/rest@2.5.1':
dependencies:
'@discordjs/collection': 2.1.1
'@discordjs/util': 1.1.1
'@sapphire/async-queue': 1.5.5
'@sapphire/snowflake': 3.5.5
'@vladfrangu/async_event_emitter': 2.4.6
discord-api-types: 0.38.8
discord-api-types: 0.38.18
magic-bytes.js: 1.12.1
tslib: 2.8.1
undici: 6.21.1
undici: 6.21.3
'@discordjs/util@1.1.1': {}
@ -5849,12 +5854,12 @@ snapshots:
'@vladfrangu/async_event_emitter@2.4.6': {}
'@xhayper/discord-rpc@1.2.1':
'@xhayper/discord-rpc@1.3.0':
dependencies:
'@discordjs/rest': 2.5.0
'@discordjs/rest': 2.5.1
'@vladfrangu/async_event_emitter': 2.4.6
discord-api-types: 0.37.120
ws: 8.18.2
discord-api-types: 0.38.18
ws: 8.18.3
transitivePeerDependencies:
- bufferutil
- utf-8-validate
@ -6565,9 +6570,7 @@ snapshots:
dependencies:
path-type: 4.0.0
discord-api-types@0.37.120: {}
discord-api-types@0.38.8: {}
discord-api-types@0.38.18: {}
dmg-builder@26.0.12(electron-builder-squirrel-windows@26.0.12):
dependencies:
@ -9374,8 +9377,6 @@ snapshots:
undici-types@6.21.0: {}
undici@6.21.1: {}
undici@6.21.3: {}
unique-filename@2.0.1:
@ -9621,6 +9622,8 @@ snapshots:
ws@8.18.2: {}
ws@8.18.3: {}
xml2js@0.4.23:
dependencies:
sax: 1.4.1

View file

@ -529,6 +529,10 @@
"discordServeImage_description": "share cover art for {{discord}} rich presence from server itself, only available for jellyfin and navidrome",
"discordUpdateInterval": "{{discord}} rich presence update interval",
"discordUpdateInterval_description": "the time in seconds between each update (minimum 15 seconds)",
"discordDisplayType": "{{discord}} presence display type",
"discordDisplayType_description": "changes what you are listening to in your status",
"discordDisplayType_songname": "song name",
"discordDisplayType_artistname": "artist name(s)",
"doubleClickBehavior": "queue all searched tracks when double clicking",
"doubleClickBehavior_description": "if true, all matching tracks in a track search will be queued. otherwise, only the clicked one will be queued",
"enableRemote": "enable remote control server",

View file

@ -1,9 +1,10 @@
import { SetActivity } from '@xhayper/discord-rpc';
import { SetActivity, StatusDisplayType } from '@xhayper/discord-rpc';
import isElectron from 'is-electron';
import { useCallback, useEffect, useState } from 'react';
import { controller } from '/@/renderer/api/controller';
import {
DiscordDisplayType,
getServerById,
useDiscordSetttings,
useGeneralSettings,
@ -54,6 +55,12 @@ export const useDiscordRpc = () => {
const artists = song?.artists.map((artist) => artist.name).join(', ');
const statusDisplayMap = {
[DiscordDisplayType.ARTIST_NAME]: StatusDisplayType.STATE,
[DiscordDisplayType.FEISHIN]: StatusDisplayType.NAME,
[DiscordDisplayType.SONG_NAME]: StatusDisplayType.DETAILS,
};
const activity: SetActivity = {
details: song?.name.padEnd(2, ' ') || 'Idle',
instance: false,
@ -61,7 +68,8 @@ export const useDiscordRpc = () => {
largeImageText: song?.album || 'Unknown album',
smallImageKey: undefined,
smallImageText: current[2] as string,
state: (artists && `By ${artists}`) || 'Unknown artist',
state: artists || 'Unknown artist',
statusDisplayType: statusDisplayMap[discordSettings.displayType],
// I would love to use the actual type as opposed to hardcoding to 2,
// but manually installing the discord-types package appears to break things
type: discordSettings.showAsListening ? 2 : 0,
@ -134,6 +142,7 @@ export const useDiscordRpc = () => {
discordSettings.showPaused,
generalSettings.lastfmApiKey,
discordSettings.clientId,
discordSettings.displayType,
lastUniqueId,
],
);

View file

@ -6,10 +6,12 @@ import {
SettingsSection,
} from '/@/renderer/features/settings/components/settings-section';
import {
DiscordDisplayType,
useDiscordSetttings,
useGeneralSettings,
useSettingsStoreActions,
} from '/@/renderer/store';
import { Select } from '/@/shared/components/select/select';
import { Switch } from '/@/shared/components/switch/switch';
import { TextInput } from '/@/shared/components/text-input/text-input';
@ -120,6 +122,50 @@ export const DiscordSettings = () => {
postProcess: 'sentenceCase',
}),
},
{
control: (
<Select
aria-label={t('setting.discordDisplayType')}
clearable={false}
data={[
{ label: 'Feishin', value: DiscordDisplayType.FEISHIN },
{
label: t('setting.discordDisplayType', {
context: 'songname',
postProcess: 'sentenceCase',
}),
value: DiscordDisplayType.SONG_NAME,
},
{
label: t('setting.discordDisplayType_artistname', {
context: 'artistname',
postProcess: 'sentenceCase',
}),
value: DiscordDisplayType.ARTIST_NAME,
},
]}
defaultValue={settings.displayType}
onChange={(e) => {
if (!e) return;
setSettings({
discord: {
...settings,
displayType: e as DiscordDisplayType,
},
});
}}
/>
),
description: t('setting.discordDisplayType', {
context: 'description',
postProcess: 'sentenceCase',
}),
isHidden: !isElectron(),
title: t('setting.discordDisplayType', {
discord: 'Discord',
postProcess: 'sentenceCase',
}),
},
{
control: (
<Switch

View file

@ -157,6 +157,12 @@ export enum BindingActions {
ZOOM_OUT = 'zoomOut',
}
export enum DiscordDisplayType {
ARTIST_NAME = 'artist',
FEISHIN = 'feishin',
SONG_NAME = 'song',
}
export enum GenreTarget {
ALBUM = 'album',
TRACK = 'track',
@ -198,6 +204,7 @@ export interface SettingsState {
};
discord: {
clientId: string;
displayType: DiscordDisplayType;
enabled: boolean;
showAsListening: boolean;
showPaused: boolean;
@ -353,6 +360,7 @@ const initialState: SettingsState = {
},
discord: {
clientId: '1165957668758900787',
displayType: DiscordDisplayType.FEISHIN,
enabled: false,
showAsListening: false,
showPaused: true,