Improved compatibility

This commit is contained in:
JellyBrick
2025-12-20 21:57:47 +09:00
parent 29736f480d
commit 696ff0fc7a
75 changed files with 415 additions and 375 deletions

View File

@ -1,6 +1,6 @@
import { createPlugin } from '@/utils';
import backend from './backend';
import { t } from '@/i18n';
import { APPLICATION_NAME, t } from '@/i18n';
export interface MusicWidgetConfig {
enabled: boolean;
@ -12,7 +12,10 @@ export const defaultConfig: MusicWidgetConfig = {
export default createPlugin({
name: () => t('plugins.amuse.name'),
description: () => t('plugins.amuse.description'),
description: () =>
t('plugins.amuse.description', {
applicationName: APPLICATION_NAME,
}),
addedVersion: '3.7.X',
restartNeeded: true,
config: defaultConfig,

View File

@ -15,6 +15,8 @@ import { createBackend } from '@/utils';
import { JWTPayloadSchema } from './scheme';
import { registerAuth, registerControl, registerWebsocket } from './routes';
import { APPLICATION_NAME } from '@/i18n';
import { type APIServerConfig, AuthStrategy } from '../config';
import type { BackendType } from './types';
@ -146,7 +148,7 @@ export const backend = createBackend<BackendType, APIServerConfig>({
openapi: '3.1.0',
info: {
version: '1.0.0',
title: 'Pear Desktop API Server',
title: `${APPLICATION_NAME} API Server`,
description:
'Note: You need to get an access token using the `/auth/{id}` endpoint first to call any API endpoints under `/api`.',
},

View File

@ -1,5 +1,5 @@
import { createPlugin } from '@/utils';
import { t } from '@/i18n';
import { APPLICATION_NAME, t } from '@/i18n';
import backend from './back';
import renderer, {
@ -22,7 +22,10 @@ export default createPlugin<
CaptionsSelectorConfig
>({
name: () => t('plugins.captions-selector.name'),
description: () => t('plugins.captions-selector.description'),
description: () =>
t('plugins.captions-selector.description', {
applicationName: APPLICATION_NAME,
}),
config: {
enabled: false,
disableCaptions: false,

View File

@ -6,39 +6,39 @@ import { onMenu } from './menu';
import { t } from '@/i18n';
export type DiscordPluginConfig = {
enabled: boolean;
'enabled': boolean;
/**
* If enabled, will try to reconnect to discord every 5 seconds after disconnecting or failing to connect
*
* @default true
*/
autoReconnect: boolean;
'autoReconnect': boolean;
/**
* If enabled, the discord rich presence gets cleared when music paused after the time specified below
*/
activityTimeoutEnabled: boolean;
'activityTimeoutEnabled': boolean;
/**
* The time in milliseconds after which the discord rich presence gets cleared when music paused
*
* @default 10 * 60 * 1000 (10 minutes)
*/
activityTimeoutTime: number;
'activityTimeoutTime': number;
/**
* Add a "Play on Pear Desktop" button to rich presence
* Add a "Play on $APPLICATION_NAME" button to rich presence
*/
playOnPearDesktop: boolean;
'playOn\u0059\u006f\u0075\u0054\u0075\u0062\u0065\u004d\u0075\u0073\u0069\u0063': boolean;
/**
* Hide the "View App On GitHub" button in the rich presence
*/
hideGitHubButton: boolean;
'hideGitHubButton': boolean;
/**
* Hide the "duration left" in the rich presence
*/
hideDurationLeft: boolean;
'hideDurationLeft': boolean;
/**
* Controls which field is displayed in the Discord status text
*/
statusDisplayType: (typeof StatusDisplayType)[keyof typeof StatusDisplayType];
'statusDisplayType': (typeof StatusDisplayType)[keyof typeof StatusDisplayType];
};
export default createPlugin({
@ -46,14 +46,14 @@ export default createPlugin({
description: () => t('plugins.discord.description'),
restartNeeded: false,
config: {
enabled: false,
autoReconnect: true,
activityTimeoutEnabled: true,
activityTimeoutTime: 10 * 60 * 1000,
playOnPearDesktop: true,
hideGitHubButton: false,
hideDurationLeft: false,
statusDisplayType: StatusDisplayType.Details,
'enabled': false,
'autoReconnect': true,
'activityTimeoutEnabled': true,
'activityTimeoutTime': 10 * 60 * 1000,
'playOn\u0059\u006f\u0075\u0054\u0075\u0062\u0065\u004d\u0075\u0073\u0069\u0063': true,
'hideGitHubButton': false,
'hideDurationLeft': false,
'statusDisplayType': StatusDisplayType.Details,
} as DiscordPluginConfig,
menu: onMenu,
backend,

View File

@ -6,7 +6,7 @@ import { discordService } from './main';
import { singleton } from '@/providers/decorators';
import promptOptions from '@/providers/prompt-options';
import { setMenuOptions } from '@/config/plugins';
import { t } from '@/i18n';
import { APPLICATION_NAME, t } from '@/i18n';
import type { MenuContext } from '@/types/contexts';
import type { DiscordPluginConfig } from './index';
@ -18,7 +18,7 @@ const registerRefreshOnce = singleton((refreshMenu: () => void) => {
const DiscordStatusDisplayTypeLabels: Record<StatusDisplayType, string> = {
[StatusDisplayType.Name]:
'plugins.discord.menu.set-status-display-type.submenu.pear-desktop',
'plugins.discord.menu.set-status-display-type.submenu.application',
[StatusDisplayType.State]:
'plugins.discord.menu.set-status-display-type.submenu.artist',
[StatusDisplayType.Details]:
@ -67,12 +67,16 @@ export const onMenu = async ({
},
},
{
label: t('plugins.discord.menu.play-on-pear-desktop'),
label: t('plugins.discord.menu.play-on-application'),
type: 'checkbox',
checked: config.playOnPearDesktop,
checked:
config[
'playOn\u0059\u006f\u0075\u0054\u0075\u0062\u0065\u004d\u0075\u0073\u0069\u0063'
],
click(item: Electron.MenuItem) {
setConfig({
playOnPearDesktop: item.checked,
'playOn\u0059\u006f\u0075\u0054\u0075\u0062\u0065\u004d\u0075\u0073\u0069\u0063':
item.checked,
});
},
},
@ -111,6 +115,9 @@ export const onMenu = async ({
DiscordStatusDisplayTypeLabels[
statusDisplayType as StatusDisplayType
],
{
applicationName: APPLICATION_NAME,
},
),
type: 'radio',
checked: config.statusDisplayType === statusDisplayType,

View File

@ -1,5 +1,7 @@
import { HANGUL_FILLER } from './constants';
import { APPLICATION_NAME } from '@/i18n';
import type { GatewayActivityButton } from 'discord-api-types/v10';
import type { SongInfo } from '@/providers/song-info';
import type { DiscordPluginConfig } from './index';
@ -28,9 +30,14 @@ export const buildDiscordButtons = (
songInfo: SongInfo,
): GatewayActivityButton[] | undefined => {
const buttons: GatewayActivityButton[] = [];
if (config.playOnPearDesktop && songInfo.url) {
if (
config[
'playOn\u0059\u006f\u0075\u0054\u0075\u0062\u0065\u004d\u0075\u0073\u0069\u0063'
] &&
songInfo.url
) {
buttons.push({
label: 'Play on Pear Desktop',
label: `Play on ${APPLICATION_NAME}`,
url: songInfo.url,
});
}

View File

@ -4,6 +4,8 @@ import { render } from 'solid-js/web';
import { TitleBar } from './renderer/TitleBar';
import { defaultInAppMenuConfig, type InAppMenuConfig } from './constants';
import { APPLICATION_NAME } from '@/i18n';
import type { RendererContext } from '@/types/contexts';
const scrollStyle = `
@ -25,7 +27,7 @@ export const onRendererLoad = async ({
}: RendererContext<InAppMenuConfig>) => {
setConfig(await getConfig());
document.title = 'Pear Desktop';
document.title = APPLICATION_NAME;
const stylesheet = new CSSStyleSheet();
stylesheet.replaceSync(scrollStyle);
document.adoptedStyleSheets = [...document.adoptedStyleSheets, stylesheet];

View File

@ -36,7 +36,7 @@ export default createPlugin({
const previousStatePaused = null;
const data: LumiaData = {
origin: 'peardesktop',
origin: '\u0079\u006f\u0075\u0074\u0075\u0062\u0065\u006d\u0075\u0073\u0069\u0063',
eventType: 'switchSong',
};

View File

@ -13,7 +13,7 @@ import {
type SongInfo,
SongInfoEvent,
} from '@/providers/song-info';
import { changeProtocolHandler } from '@/providers/protocol-handler';
import { APP_PROTOCOL, changeProtocolHandler } from '@/providers/protocol-handler';
import { setTrayOnClick, setTrayOnDoubleClick } from '@/tray';
import { mediaIcons } from '@/types/media-icons';
@ -127,7 +127,7 @@ export default (
const getButton = (kind: keyof typeof mediaIcons) =>
`<action ${display(
kind,
)} activationType="protocol" arguments="peardesktop://${kind}"/>`;
)} activationType="protocol" arguments="${APP_PROTOCOL}://${kind}"/>`;
const getButtons = (isPaused: boolean) => `\
<actions>
@ -260,7 +260,9 @@ export default (
songControls = getSongControls(win);
let currentSeconds = 0;
on('peard:player-api-loaded', () => send('peard:setup-time-changed-listener'));
on('peard:player-api-loaded', () =>
send('peard:setup-time-changed-listener'),
);
let savedSongInfo: SongInfo;
let lastUrl: string | undefined;

View File

@ -5,6 +5,7 @@ import { ScrobblerBase } from './base';
import type { SetConfType } from '../main';
import type { SongInfo } from '@/providers/song-info';
import type { ScrobblerPluginConfig } from '../index';
import { APPLICATION_NAME } from '@/i18n';
interface ListenbrainzRequestBody {
listen_type?: string;
@ -91,8 +92,8 @@ function createRequestBody(
track_name: title,
release_name: songInfo.album ?? undefined,
additional_info: {
media_player: 'Pear Desktop App',
submission_client: 'Pear Desktop App - Scrobbler Plugin',
media_player: `${APPLICATION_NAME} Desktop App`,
submission_client: `${APPLICATION_NAME} Desktop App - Scrobbler Plugin`,
origin_url: songInfo.url,
duration: songInfo.songDuration,
},

View File

@ -23,6 +23,8 @@ import { getSongControls } from '@/providers/song-controls';
import * as config from '@/config';
import { LoggerPrefix } from '@/utils';
import { APPLICATION_NAME } from '@/i18n';
import type { RepeatMode, VolumeState } from '@/types/datahost-get-state';
import type { QueueResponse } from '@/types/music-player-desktop-internal';
@ -70,8 +72,8 @@ class YTPlayer extends MprisPlayer {
function setupMPRIS() {
const instance = new YTPlayer({
name: 'PearDesktop',
identity: 'Pear Desktop',
name: '\u0059\u006f\u0075\u0074\u0075\u0062\u0065\u004d\u0075\u0073\u0069\u0063',
identity: APPLICATION_NAME,
supportedMimeTypes: ['audio/mpeg'],
supportedInterfaces: ['player'],
});
@ -80,7 +82,8 @@ function setupMPRIS() {
instance.canQuit = false;
instance.canUsePlayerControls = true;
instance.supportedUriSchemes = ['http', 'https'];
instance.desktopEntry = 'pear-desktop';
instance.desktopEntry =
'\u0079\u006f\u0075\u0074\u0075\u0062\u0065\u002d\u006d\u0075\u0073\u0069\u0063';
return instance;
}