From 26df435db0350a51ce1454e64d1ad557915cdfe4 Mon Sep 17 00:00:00 2001 From: JellyBrick Date: Sun, 8 Oct 2023 14:57:58 +0900 Subject: [PATCH] fix: fallback to DOM window controls on platforms without native support --- .../assets/{restore.svg => unmaximize.svg} | 0 plugins/in-app-menu/back.ts | 13 ++-- plugins/in-app-menu/front.ts | 67 ++++++++++++++++++- plugins/in-app-menu/titlebar.css | 28 ++++++++ 4 files changed, 101 insertions(+), 7 deletions(-) rename plugins/in-app-menu/assets/{restore.svg => unmaximize.svg} (100%) diff --git a/plugins/in-app-menu/assets/restore.svg b/plugins/in-app-menu/assets/unmaximize.svg similarity index 100% rename from plugins/in-app-menu/assets/restore.svg rename to plugins/in-app-menu/assets/unmaximize.svg diff --git a/plugins/in-app-menu/back.ts b/plugins/in-app-menu/back.ts index 74896df3..0cceec91 100644 --- a/plugins/in-app-menu/back.ts +++ b/plugins/in-app-menu/back.ts @@ -1,5 +1,3 @@ -import path from 'node:path'; - import { register } from 'electron-localshortcut'; import { BrowserWindow, Menu, MenuItem, ipcMain } from 'electron'; @@ -25,7 +23,7 @@ export default (win: BrowserWindow) => { (key: string, value: unknown) => (key !== 'commandsMap' && key !== 'menu') ? value : undefined), ), ); - + const getMenuItemById = (commandId: number): MenuItem | null => { const menu = Menu.getApplicationMenu(); @@ -40,7 +38,7 @@ export default (win: BrowserWindow) => { break; } } - + return target; }; @@ -57,4 +55,11 @@ export default (win: BrowserWindow) => { (key: string, value: unknown) => (key !== 'commandsMap' && key !== 'menu') ? value : undefined), ); }); + + ipcMain.handle('window-is-maximized', () => win.isMaximized()); + + ipcMain.handle('window-close', () => win.close()); + ipcMain.handle('window-minimize', () => win.minimize()); + ipcMain.handle('window-maximize', () => win.maximize()); + ipcMain.handle('window-unmaximize', () => win.unmaximize()); }; diff --git a/plugins/in-app-menu/front.ts b/plugins/in-app-menu/front.ts index 2be654a9..a8a450b4 100644 --- a/plugins/in-app-menu/front.ts +++ b/plugins/in-app-menu/front.ts @@ -2,7 +2,12 @@ import { ipcRenderer, Menu } from 'electron'; import { createPanel } from './menu/panel'; -import logo from '../../assets/menu.svg'; +import logo from './assets/menu.svg'; +import close from './assets/close.svg'; +import minimize from './assets/minimize.svg'; +import maximize from './assets/maximize.svg'; +import unmaximize from './assets/unmaximize.svg'; + import { isEnabled } from '../../config/plugins'; import config from '../../config'; @@ -11,8 +16,9 @@ function $(selector: string) { } const isMacOS = navigator.userAgent.includes('Macintosh'); +const isNotWindowsOrMacOS = !navigator.userAgent.includes('Windows') && !isMacOS; -export default () => { +export default async () => { let hideMenu = config.get('options.hideMenu'); const titleBar = document.createElement('title-bar'); const navBar = document.querySelector('#nav-bar-background'); @@ -39,6 +45,60 @@ export default () => { if (!isMacOS) titleBar.appendChild(logo); document.body.appendChild(titleBar); + titleBar.appendChild(logo); + + const addWindowControls = async () => { + + // Create window control buttons + const minimizeButton = document.createElement('button'); + minimizeButton.classList.add('window-control'); + minimizeButton.appendChild(minimize); + minimizeButton.onclick = () => ipcRenderer.invoke('window-minimize'); + + const maximizeButton = document.createElement('button'); + if (await ipcRenderer.invoke('window-is-maximized')) { + maximizeButton.classList.add('window-control'); + maximizeButton.appendChild(unmaximize); + } else { + maximizeButton.classList.add('window-control'); + maximizeButton.appendChild(maximize); + } + maximizeButton.onclick = async () => { + if (await ipcRenderer.invoke('window-is-maximized')) { + // change icon to maximize + maximizeButton.removeChild(maximizeButton.firstChild!); + maximizeButton.appendChild(maximize); + + // call unmaximize + await ipcRenderer.invoke('window-unmaximize'); + } else { + // change icon to unmaximize + maximizeButton.removeChild(maximizeButton.firstChild!); + maximizeButton.appendChild(unmaximize); + + // call maximize + await ipcRenderer.invoke('window-maximize'); + } + }; + + const closeButton = document.createElement('button'); + closeButton.classList.add('window-control'); + closeButton.appendChild(close); + closeButton.onclick = () => ipcRenderer.invoke('window-close'); + + // Create a container div for the window control buttons + const windowControlsContainer = document.createElement('div'); + windowControlsContainer.classList.add('window-controls-container'); + windowControlsContainer.appendChild(minimizeButton); + windowControlsContainer.appendChild(maximizeButton); + windowControlsContainer.appendChild(closeButton); + + // Add window control buttons to the title bar + titleBar.appendChild(windowControlsContainer); + }; + + if (isNotWindowsOrMacOS) await addWindowControls(); + if (navBar) { const observer = new MutationObserver((mutations) => { mutations.forEach(() => { @@ -69,8 +129,9 @@ export default () => { menu.style.visibility = 'hidden'; } }); + if (isNotWindowsOrMacOS) await addWindowControls(); }; - updateMenu(); + await updateMenu(); document.title = 'Youtube Music'; diff --git a/plugins/in-app-menu/titlebar.css b/plugins/in-app-menu/titlebar.css index 8075b09c..3eb82807 100644 --- a/plugins/in-app-menu/titlebar.css +++ b/plugins/in-app-menu/titlebar.css @@ -121,6 +121,34 @@ menu-separator { margin-left: -4px; } +/* Window control container */ + +.window-controls-container { + -webkit-app-region: no-drag; + display: flex; + justify-content: flex-end; /* Align to the right end of the title-bar */ + align-items: center; + gap: 4px; /* Add spacing between the window control buttons */ + position: absolute; /* Position it absolutely within title-bar */ + right: 4px; /* Adjust the right position as needed */ +} + +/* Window control buttons */ + +.window-control { + width: 24px; + height: 24px; + background: none; + border: none; + cursor: pointer; + display: flex; + justify-content: center; + align-items: center; + color: #f1f1f1; + font-size: 14px; + padding: 0; +} + /* youtube-music style */ ytmusic-app-layout {