convert plugins

This commit is contained in:
JellyBrick
2023-11-27 18:41:50 +09:00
parent 4fad456619
commit 3ffbfbe0e3
70 changed files with 1617 additions and 1836 deletions

View File

@ -1,6 +1,9 @@
import style from './style.css?inline';
import { createPlugin } from '@/utils';
import { createPluginBuilder } from '../utils/builder';
import { onConfigChange, onMainLoad } from './main';
import { onMenu } from './menu';
import { onPlayerApiReady, onRendererLoad } from './renderer';
export type PictureInPicturePluginConfig = {
'enabled': boolean;
@ -14,7 +17,7 @@ export type PictureInPicturePluginConfig = {
'useNativePiP': boolean;
}
const builder = createPluginBuilder('picture-in-picture', {
export default createPlugin({
name: 'Picture In Picture',
restartNeeded: true,
config: {
@ -28,13 +31,15 @@ const builder = createPluginBuilder('picture-in-picture', {
'isInPiP': false,
'useNativePiP': true,
} as PictureInPicturePluginConfig,
styles: [style],
});
stylesheets: [style],
menu: onMenu,
export default builder;
declare global {
interface PluginBuilderList {
[builder.id]: typeof builder;
backend: {
start: onMainLoad,
onConfigChange,
},
renderer: {
start: onRendererLoad,
onPlayerApiReady,
}
}
});

View File

@ -1,22 +1,18 @@
import { app, BrowserWindow, ipcMain } from 'electron';
import { app } from 'electron';
import style from './style.css?inline';
import type { PictureInPicturePluginConfig } from './index';
import builder, { PictureInPicturePluginConfig } from './index';
import type { BackendContext } from '@/types/contexts';
import { injectCSS } from '../utils/main';
let config: PictureInPicturePluginConfig;
export default builder.createMain(({ getConfig, setConfig, send, handle, on }) => {
export const onMainLoad = async ({ window, getConfig, setConfig, ipc: { send, handle, on } }: BackendContext<PictureInPicturePluginConfig>) => {
let isInPiP = false;
let originalPosition: number[];
let originalSize: number[];
let originalFullScreen: boolean;
let originalMaximized: boolean;
let win: BrowserWindow;
let config: PictureInPicturePluginConfig;
const pipPosition = () => (config.savePosition && config['pip-position']) || [10, 10];
const pipSize = () => (config.saveSize && config['pip-size']) || [450, 275];
@ -25,59 +21,59 @@ export default builder.createMain(({ getConfig, setConfig, send, handle, on }) =
setConfig({ isInPiP });
if (isInPiP) {
originalFullScreen = win.isFullScreen();
originalFullScreen = window.isFullScreen();
if (originalFullScreen) {
win.setFullScreen(false);
window.setFullScreen(false);
}
originalMaximized = win.isMaximized();
originalMaximized = window.isMaximized();
if (originalMaximized) {
win.unmaximize();
window.unmaximize();
}
originalPosition = win.getPosition();
originalSize = win.getSize();
originalPosition = window.getPosition();
originalSize = window.getSize();
handle('before-input-event', blockShortcutsInPiP);
win.setMaximizable(false);
win.setFullScreenable(false);
window.setMaximizable(false);
window.setFullScreenable(false);
send('pip-toggle', true);
app.dock?.hide();
win.setVisibleOnAllWorkspaces(true, {
window.setVisibleOnAllWorkspaces(true, {
visibleOnFullScreen: true,
});
app.dock?.show();
if (config.alwaysOnTop) {
win.setAlwaysOnTop(true, 'screen-saver', 1);
window.setAlwaysOnTop(true, 'screen-saver', 1);
}
} else {
win.webContents.removeListener('before-input-event', blockShortcutsInPiP);
win.setMaximizable(true);
win.setFullScreenable(true);
window.webContents.removeListener('before-input-event', blockShortcutsInPiP);
window.setMaximizable(true);
window.setFullScreenable(true);
send('pip-toggle', false);
win.setVisibleOnAllWorkspaces(false);
win.setAlwaysOnTop(false);
window.setVisibleOnAllWorkspaces(false);
window.setAlwaysOnTop(false);
if (originalFullScreen) {
win.setFullScreen(true);
window.setFullScreen(true);
}
if (originalMaximized) {
win.maximize();
window.maximize();
}
}
const [x, y] = isInPiP ? pipPosition() : originalPosition;
const [w, h] = isInPiP ? pipSize() : originalSize;
win.setPosition(x, y);
win.setSize(w, h);
window.setPosition(x, y);
window.setSize(w, h);
win.setWindowButtonVisibility?.(!isInPiP);
window.setWindowButtonVisibility?.(!isInPiP);
};
const blockShortcutsInPiP = (event: Electron.Event, input: Electron.Input) => {
@ -91,30 +87,25 @@ export default builder.createMain(({ getConfig, setConfig, send, handle, on }) =
}
};
return ({
async onLoad(window) {
config ??= await getConfig();
win ??= window;
setConfig({ isInPiP });
on('picture-in-picture', () => {
togglePiP();
});
config ??= await getConfig();
setConfig({ isInPiP });
on('picture-in-picture', () => {
togglePiP();
});
window.on('move', () => {
if (config.isInPiP && !config.useNativePiP) {
setConfig({ 'pip-position': window.getPosition() as [number, number] });
}
});
window.on('resize', () => {
if (config.isInPiP && !config.useNativePiP) {
setConfig({ 'pip-size': window.getSize() as [number, number] });
}
});
},
onConfigChange(newConfig) {
config = newConfig;
window.on('move', () => {
if (config.isInPiP && !config.useNativePiP) {
setConfig({ 'pip-position': window.getPosition() as [number, number] });
}
});
});
window.on('resize', () => {
if (config.isInPiP && !config.useNativePiP) {
setConfig({ 'pip-size': window.getSize() as [number, number] });
}
});
};
export const onConfigChange = (newConfig: PictureInPicturePluginConfig) => {
config = newConfig;
};

View File

@ -1,11 +1,14 @@
import prompt from 'custom-electron-prompt';
import builder from './index';
import promptOptions from '@/providers/prompt-options';
import promptOptions from '../../providers/prompt-options';
import type { PictureInPicturePluginConfig } from './index';
import type { MenuContext } from '@/types/contexts';
import type { MenuTemplate } from '@/menu';
export default builder.createMenu(async ({ window, getConfig, setConfig }) => {
export const onMenu = async ({ window, getConfig, setConfig }: MenuContext<PictureInPicturePluginConfig>): Promise<MenuTemplate> => {
const config = await getConfig();
return [
@ -71,4 +74,4 @@ export default builder.createMenu(async ({ window, getConfig, setConfig }) => {
},
},
];
});
};

View File

@ -3,12 +3,13 @@ import keyEventAreEqual from 'keyboardevents-areequal';
import pipHTML from './templates/picture-in-picture.html?raw';
import builder, { PictureInPicturePluginConfig } from './index';
import { getSongMenu } from '../../providers/dom-elements';
import { getSongMenu } from '@/providers/dom-elements';
import { ElementFromHtml } from '../utils/renderer';
import type { PictureInPicturePluginConfig } from './index';
import type { RendererContext } from '@/types/contexts';
function $<E extends Element = Element>(selector: string) {
return document.querySelector<E>(selector);
}
@ -133,42 +134,38 @@ const listenForToggle = () => {
});
};
export const onRendererLoad = async ({ getConfig }: RendererContext<PictureInPicturePluginConfig>) => {
const config = await getConfig();
export default builder.createRenderer(({ getConfig }) => {
return {
async onLoad() {
const config = await getConfig();
useNativePiP = config.useNativePiP;
useNativePiP = config.useNativePiP;
if (config.hotkey) {
const hotkeyEvent = toKeyEvent(config.hotkey);
window.addEventListener('keydown', (event) => {
if (
keyEventAreEqual(event, hotkeyEvent)
&& !$<HTMLElement & { opened: boolean }>('ytmusic-search-box')?.opened
) {
togglePictureInPicture();
}
});
if (config.hotkey) {
const hotkeyEvent = toKeyEvent(config.hotkey);
window.addEventListener('keydown', (event) => {
if (
keyEventAreEqual(event, hotkeyEvent)
&& !$<HTMLElement & { opened: boolean }>('ytmusic-search-box')?.opened
) {
togglePictureInPicture();
}
},
onPlayerApiReady() {
listenForToggle();
});
}
};
cloneButton('.player-minimize-button')?.addEventListener('click', async () => {
await togglePictureInPicture();
setTimeout(() => $<HTMLButtonElement>('#player')?.click());
});
export const onPlayerApiReady = () => {
listenForToggle();
// Allows easily closing the menu by programmatically clicking outside of it
$('#expanding-menu')?.removeAttribute('no-cancel-on-outside-click');
// TODO: think about wether an additional button in songMenu is needed
const popupContainer = $('ytmusic-popup-container');
if (popupContainer) observer.observe(popupContainer, {
childList: true,
subtree: true,
});
},
};
});
cloneButton('.player-minimize-button')?.addEventListener('click', async () => {
await togglePictureInPicture();
setTimeout(() => $<HTMLButtonElement>('#player')?.click());
});
// Allows easily closing the menu by programmatically clicking outside of it
$('#expanding-menu')?.removeAttribute('no-cancel-on-outside-click');
// TODO: think about wether an additional button in songMenu is needed
const popupContainer = $('ytmusic-popup-container');
if (popupContainer) observer.observe(popupContainer, {
childList: true,
subtree: true,
});
};