mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-10 10:11:46 +00:00
feat(menu): add more detail in Menu (#1570)
This commit is contained in:
@ -168,6 +168,7 @@
|
||||
"node-html-parser": "6.1.12",
|
||||
"node-id3": "0.2.6",
|
||||
"peerjs": "1.5.2",
|
||||
"semver": "7.5.4",
|
||||
"serve": "14.2.1",
|
||||
"simple-youtube-age-restriction-bypass": "github:organization/Simple-YouTube-Age-Restriction-Bypass#v2.5.9",
|
||||
"ts-morph": "21.0.1",
|
||||
@ -181,6 +182,7 @@
|
||||
"@types/electron-localshortcut": "3.1.3",
|
||||
"@types/howler": "2.2.11",
|
||||
"@types/html-to-text": "9.0.4",
|
||||
"@types/semver": "7.5.6",
|
||||
"@typescript-eslint/eslint-plugin": "6.16.0",
|
||||
"bufferutil": "4.0.8",
|
||||
"builtin-modules": "3.3.0",
|
||||
|
||||
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
@ -117,6 +117,9 @@ dependencies:
|
||||
peerjs:
|
||||
specifier: 1.5.2
|
||||
version: 1.5.2
|
||||
semver:
|
||||
specifier: 7.5.4
|
||||
version: 7.5.4
|
||||
serve:
|
||||
specifier: 14.2.1
|
||||
version: 14.2.1
|
||||
@ -152,6 +155,9 @@ devDependencies:
|
||||
'@types/html-to-text':
|
||||
specifier: 9.0.4
|
||||
version: 9.0.4
|
||||
'@types/semver':
|
||||
specifier: 7.5.6
|
||||
version: 7.5.6
|
||||
'@typescript-eslint/eslint-plugin':
|
||||
specifier: 6.16.0
|
||||
version: 6.16.0(@typescript-eslint/parser@6.14.0)(eslint@8.56.0)(typescript@5.3.3)
|
||||
@ -1113,7 +1119,7 @@ packages:
|
||||
resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
peerDependencies:
|
||||
rollup: 4.9.1
|
||||
rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
|
||||
peerDependenciesMeta:
|
||||
rollup:
|
||||
optional: true
|
||||
|
||||
@ -170,7 +170,8 @@
|
||||
},
|
||||
"plugins": {
|
||||
"enabled": "Enabled",
|
||||
"label": "Plugins"
|
||||
"label": "Plugins",
|
||||
"new": "NEW"
|
||||
},
|
||||
"view": {
|
||||
"label": "View",
|
||||
|
||||
@ -170,7 +170,8 @@
|
||||
},
|
||||
"plugins": {
|
||||
"enabled": "활성화",
|
||||
"label": "확장"
|
||||
"label": "확장",
|
||||
"new": "NEW"
|
||||
},
|
||||
"view": {
|
||||
"label": "보기",
|
||||
|
||||
25
src/menu.ts
25
src/menu.ts
@ -9,6 +9,7 @@ import {
|
||||
shell,
|
||||
} from 'electron';
|
||||
import prompt from 'custom-electron-prompt';
|
||||
import { satisfies } from 'semver';
|
||||
|
||||
import { allPlugins } from 'virtual:plugins';
|
||||
|
||||
@ -23,6 +24,8 @@ import promptOptions from './providers/prompt-options';
|
||||
import { getAllMenuTemplate, loadAllMenuPlugins } from './loader/menu';
|
||||
import { setLanguage, t } from '@/i18n';
|
||||
|
||||
import packageJson from '../package.json';
|
||||
|
||||
export type MenuTemplate = Electron.MenuItemConstructorOptions[];
|
||||
|
||||
// True only if in-app-menu was loaded on launch
|
||||
@ -31,10 +34,14 @@ const inAppMenuActive = config.plugins.isEnabled('in-app-menu');
|
||||
const pluginEnabledMenu = (
|
||||
plugin: string,
|
||||
label = '',
|
||||
description: string | undefined = undefined,
|
||||
isNew = false,
|
||||
hasSubmenu = false,
|
||||
refreshMenu: (() => void) | undefined = undefined,
|
||||
): Electron.MenuItemConstructorOptions => ({
|
||||
label: label || plugin,
|
||||
sublabel: isNew ? t('main.menu.plugins.new') : undefined,
|
||||
toolTip: description,
|
||||
type: 'checkbox',
|
||||
checked: config.plugins.isEnabled(plugin),
|
||||
click(item: Electron.MenuItem) {
|
||||
@ -66,12 +73,15 @@ export const mainMenuTemplate = async (
|
||||
|
||||
const menuResult = Object.entries(getAllMenuTemplate()).map(
|
||||
([id, template]) => {
|
||||
const pluginLabel = allPlugins[id]?.name?.() ?? id;
|
||||
const plugin = allPlugins[id];
|
||||
const pluginLabel = plugin?.name?.() ?? id;
|
||||
const pluginDescription = plugin?.description?.() ?? undefined;
|
||||
const isNew = plugin?.addedVersion ? satisfies(packageJson.version, plugin.addedVersion) : false;
|
||||
|
||||
if (!config.plugins.isEnabled(id)) {
|
||||
return [
|
||||
id,
|
||||
pluginEnabledMenu(id, pluginLabel, true, innerRefreshMenu),
|
||||
pluginEnabledMenu(id, pluginLabel, pluginDescription, isNew, true, innerRefreshMenu),
|
||||
] as const;
|
||||
}
|
||||
|
||||
@ -79,10 +89,14 @@ export const mainMenuTemplate = async (
|
||||
id,
|
||||
{
|
||||
label: pluginLabel,
|
||||
sublabel: isNew ? t('main.menu.plugins.new') : undefined,
|
||||
toolTip: pluginDescription,
|
||||
submenu: [
|
||||
pluginEnabledMenu(
|
||||
id,
|
||||
t('main.menu.plugins.enabled'),
|
||||
undefined,
|
||||
false,
|
||||
true,
|
||||
innerRefreshMenu,
|
||||
),
|
||||
@ -106,9 +120,12 @@ export const mainMenuTemplate = async (
|
||||
const predefinedTemplate = menuResult.find((it) => it[0] === id);
|
||||
if (predefinedTemplate) return predefinedTemplate[1];
|
||||
|
||||
const pluginLabel = allPlugins[id]?.name?.() ?? id;
|
||||
const plugin = allPlugins[id];
|
||||
const pluginLabel = plugin?.name?.() ?? id;
|
||||
const pluginDescription = plugin?.description?.() ?? undefined;
|
||||
const isNew = plugin?.addedVersion ? satisfies(packageJson.version, plugin.addedVersion) : false;
|
||||
|
||||
return pluginEnabledMenu(id, pluginLabel, true, innerRefreshMenu);
|
||||
return pluginEnabledMenu(id, pluginLabel, pluginDescription, isNew, true, innerRefreshMenu);
|
||||
});
|
||||
|
||||
const availableLanguages = Object.keys(languageResources);
|
||||
|
||||
@ -11,6 +11,7 @@ export default createPlugin({
|
||||
name: () => t('plugins.album-actions.name'),
|
||||
description: () => t('plugins.album-actions.description'),
|
||||
restartNeeded: false,
|
||||
addedVersion: '3.2.0',
|
||||
config: {
|
||||
enabled: false,
|
||||
},
|
||||
|
||||
@ -52,6 +52,18 @@ export const createPanel = (
|
||||
menu.appendChild(iconWrapper);
|
||||
menu.append(item.label);
|
||||
|
||||
if (item.sublabel) {
|
||||
menu.classList.add('badge');
|
||||
const menuBadge = document.createElement('menu-item-badge');
|
||||
menuBadge.append(item.sublabel);
|
||||
menu.append(menuBadge);
|
||||
}
|
||||
if (item.toolTip) {
|
||||
const menuTooltip = document.createElement('menu-item-tooltip');
|
||||
menuTooltip.append(item.toolTip);
|
||||
menu.append(menuTooltip);
|
||||
}
|
||||
|
||||
menu.addEventListener('click', async () => {
|
||||
await window.ipcRenderer.invoke('menu-event', item.commandId);
|
||||
const menuItem = (await window.ipcRenderer.invoke(
|
||||
|
||||
@ -97,6 +97,8 @@ menu-panel.position-by-bottom {
|
||||
}
|
||||
|
||||
menu-item {
|
||||
position: relative;
|
||||
|
||||
-webkit-app-region: none;
|
||||
min-height: 32px;
|
||||
height: 32px;
|
||||
@ -109,6 +111,9 @@ menu-item {
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
menu-item.badge {
|
||||
grid-template-columns: 32px 1fr auto minmax(32px, auto);
|
||||
}
|
||||
menu-item:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
@ -128,6 +133,56 @@ menu-separator {
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
menu-item-badge {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
min-width: 16px;
|
||||
height: 16px;
|
||||
padding: 0 4px;
|
||||
margin-left: 8px;
|
||||
|
||||
border-radius: 4px;
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
color: #f1f1f1;
|
||||
font-size: 10px;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
menu-item-tooltip {
|
||||
position: absolute;
|
||||
|
||||
left: 0;
|
||||
top: calc(100% + 4px);
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
min-width: 32px;
|
||||
padding: 4px;
|
||||
|
||||
border-radius: 4px;
|
||||
background-color: rgba(25, 25, 25, 0.8);
|
||||
color: #f1f1f1;
|
||||
font-size: 10px;
|
||||
|
||||
pointer-events: none;
|
||||
z-index: 1000;
|
||||
|
||||
opacity: 0;
|
||||
scale: 0.9;
|
||||
|
||||
transform-origin: 50% 0;
|
||||
transition: all 0.225s ease-out;
|
||||
}
|
||||
menu-item:hover > menu-item-tooltip {
|
||||
opacity: 1;
|
||||
scale: 1.0;
|
||||
}
|
||||
|
||||
/* classes */
|
||||
|
||||
.title-bar-icon {
|
||||
|
||||
@ -38,6 +38,7 @@ export default createPlugin({
|
||||
name: () => t('plugins.music-together.name'),
|
||||
description: () => t('plugins.music-together.description'),
|
||||
restartNeeded: false,
|
||||
addedVersion: '3.2.0',
|
||||
config: {
|
||||
enabled: false
|
||||
},
|
||||
|
||||
@ -47,6 +47,7 @@ export interface PluginDef<
|
||||
name: () => string;
|
||||
authors?: Author[];
|
||||
description?: () => string;
|
||||
addedVersion?: string;
|
||||
config?: Config;
|
||||
|
||||
menu?: (
|
||||
|
||||
Reference in New Issue
Block a user