diff --git a/index.ts b/index.ts index 4fabd42a..64149126 100644 --- a/index.ts +++ b/index.ts @@ -225,16 +225,26 @@ function createMainWindow() { }); loadPlugins(win); + const scaleFactor = screen.getAllDisplays().length > 1 ? screen.getPrimaryDisplay().scaleFactor : 1; + + if (windowSize) { + const scaledSize = { + width: windowSize.width / scaleFactor, + height: windowSize.height / scaleFactor, + }; + win.setSize(scaledSize.width, scaledSize.height); + } + if (windowPosition) { - const { x, y } = windowPosition; + const { x: windowX, y: windowY } = windowPosition; const winSize = win.getSize(); const displaySize = screen.getDisplayNearestPoint(windowPosition).bounds; if ( - x + winSize[0] < displaySize.x - 8 - || x - winSize[0] > displaySize.x + displaySize.width - || y < displaySize.y - 8 - || y > displaySize.y + displaySize.height + windowX + winSize[0] < displaySize.x - 8 + || windowX - winSize[0] > displaySize.x + displaySize.width + || windowY < displaySize.y - 8 + || windowY > displaySize.y + displaySize.height ) { // Window is offscreen if (is.dev()) { @@ -243,7 +253,11 @@ function createMainWindow() { ); } } else { - win.setPosition(x, y); + const scaledPosition = { + x: windowX / scaleFactor, + y: windowY / scaleFactor, + }; + win.setPosition(scaledPosition.x, scaledPosition.y); } } @@ -261,26 +275,6 @@ function createMainWindow() { win.webContents.loadURL(urlToLoad); win.on('closed', onClosed); - const scaleFactor = screen.getAllDisplays().length > 1 ? screen.getPrimaryDisplay().scaleFactor : 1; - const size = config.get('window-size'); - const position = config.get('window-position'); - - if (size && size.width && size.height) { - const scaledSize = { - width: size.width / scaleFactor, - height: size.height / scaleFactor, - }; - win.setSize(scaledSize.width, scaledSize.height); - } - - if (position && position.x && position.y) { - const scaledPosition = { - x: position.x / scaleFactor, - y: position.y / scaleFactor, - }; - win.setPosition(scaledPosition.x, scaledPosition.y); - } - type PiPOptions = typeof config.defaultConfig.plugins['picture-in-picture']; const setPiPOptions = config.plugins.isEnabled('picture-in-picture') // eslint-disable-next-line @typescript-eslint/no-var-requires diff --git a/plugins/discord/back.ts b/plugins/discord/back.ts index 6fb34675..3b9844b1 100644 --- a/plugins/discord/back.ts +++ b/plugins/discord/back.ts @@ -4,7 +4,7 @@ import { dev } from 'electron-is'; import { SetActivity } from '@xhayper/discord-rpc/dist/structures/ClientUser'; -import registerCallback from '../../providers/song-info'; +import registerCallback, { type SongInfoCallback, type SongInfo } from '../../providers/song-info'; import type { ConfigType } from '../../config/dynamic'; @@ -15,7 +15,7 @@ export interface Info { rpc: DiscordClient; ready: boolean; autoReconnect: boolean; - lastSongInfo?: import('../../providers/song-info').SongInfo; + lastSongInfo?: SongInfo; } const info: Info = { @@ -39,36 +39,14 @@ const resetInfo = () => { console.log('discord disconnected'); } - for (const cb of refreshCallbacks) { - cb(); - } + setTimeout(() => { + for (const cb of refreshCallbacks) { + cb(); + } + }, 100); + }; -info.rpc.on('connected', () => { - if (dev()) { - console.log('discord connected'); - } - - for (const cb of refreshCallbacks) { - cb(); - } -}); - -info.rpc.on('ready', () => { - info.ready = true; - if (info.lastSongInfo) { - updateActivity(info.lastSongInfo); - } -}); - -info.rpc.on('disconnected', () => { - resetInfo(); - - if (info.autoReconnect) { - connectTimeout(); - } -}); - const connectTimeout = () => new Promise((resolve, reject) => setTimeout(() => { if (!info.autoReconnect || info.rpc.isConnected) { return; @@ -117,7 +95,7 @@ export const connect = (showError = false) => { }; let clearActivity: NodeJS.Timeout | undefined; -let updateActivity: import('../../providers/song-info').SongInfoCallback; +let updateActivity: SongInfoCallback; type DiscordOptions = ConfigType<'discord'>; @@ -125,6 +103,31 @@ export default ( win: Electron.BrowserWindow, options: DiscordOptions, ) => { + info.rpc.on('connected', () => { + if (dev()) { + console.log('discord connected'); + } + + for (const cb of refreshCallbacks) { + cb(); + } + }); + + info.rpc.on('ready', () => { + info.ready = true; + if (info.lastSongInfo) { + updateActivity(info.lastSongInfo); + } + }); + + info.rpc.on('disconnected', () => { + resetInfo(); + + if (info.autoReconnect) { + connectTimeout(); + } + }); + info.autoReconnect = options.autoReconnect; window = win; diff --git a/plugins/in-app-menu/menu/panel.ts b/plugins/in-app-menu/menu/panel.ts index 1dd2ea16..c15057b3 100644 --- a/plugins/in-app-menu/menu/panel.ts +++ b/plugins/in-app-menu/menu/panel.ts @@ -101,6 +101,15 @@ export const createPanel = ( } panel.setAttribute('open', 'true'); + + // Children are placed below their parent item, which can cause + // long lists to squeeze their children at the bottom of the screen + // (This needs to be done *after* setAttribute) + panel.classList.remove('position-by-bottom'); + if (options.placement === 'right' && panel.scrollHeight > panel.clientHeight ) { + panel.style.setProperty('--y', `${rect.y + rect.height}px`); + panel.classList.add('position-by-bottom'); + } }; anchor.addEventListener('click', () => { diff --git a/plugins/in-app-menu/titlebar.css b/plugins/in-app-menu/titlebar.css index 3eb82807..fe1ccbe1 100644 --- a/plugins/in-app-menu/titlebar.css +++ b/plugins/in-app-menu/titlebar.css @@ -80,6 +80,11 @@ menu-panel[open="true"] { opacity: 1; transform: scale(1); } +menu-panel.position-by-bottom { + top: unset; + bottom: calc(100vh - var(--y, 100%)); + max-height: calc(var(--y, 0) - var(--menu-bar-height, 36px) - 16px); +} menu-item { -webkit-app-region: none;