Skip to content
36 changes: 25 additions & 11 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ protocol.registerSchemesAsPrivileged([

// Ozone platform hint: Required for Wayland support
app.commandLine.appendSwitch('ozone-platform-hint', 'auto');

// SharedArrayBuffer: Required for downloader (@ffmpeg/core-mt)
// OverlayScrollbar: Required for overlay scrollbars
// UseOzonePlatform: Required for Wayland support
Expand All @@ -115,28 +116,41 @@ app.commandLine.appendSwitch(
'enable-features',
'OverlayScrollbar,SharedArrayBuffer,UseOzonePlatform,WaylandWindowDecorations',
);

// Disable Fluent Scrollbar (for OverlayScrollbar)
app.commandLine.appendSwitch('disable-features', 'FluentScrollbar');
if (config.get('options.disableHardwareAcceleration')) {
if (is.dev()) {
console.log('Disabling hardware acceleration');
const disabledFeatures = ['FluentScrollbar'];
let disableHardwareAcceleration = config.get(
'options.disableHardwareAcceleration',
);

// Linux specific fixes
if (is.linux()) {
// Stops chromium from launching its own MPRIS service
if (await config.plugins.isEnabled('shortcuts')) {
disabledFeatures.push('MediaSessionService');
}

app.disableHardwareAcceleration();
}
// https://github.com/electron/electron/issues/15947
if (await config.plugins.isEnabled('transparent-player')) {
disableHardwareAcceleration = true;
app.commandLine.appendSwitch('enable-transparent-visuals');
app.commandLine.appendSwitch('enable-unsafe-swiftshader');
}

if (is.linux()) {
// Overrides WM_CLASS for X11 to correspond to icon filename
app.setName(
'com.github.th_ch.\u0079\u006f\u0075\u0074\u0075\u0062\u0065\u005f\u006d\u0075\u0073\u0069\u0063',
);
}

// Stops chromium from launching its own MPRIS service
if (await config.plugins.isEnabled('shortcuts')) {
app.commandLine.appendSwitch('disable-features', 'MediaSessionService');
}
if (disableHardwareAcceleration) {
if (is.dev()) console.log('Disabling hardware acceleration');
app.disableHardwareAcceleration();
}

// Apply disabled features
app.commandLine.appendSwitch('disable-features', disabledFeatures.join(','));
Comment thread
JellyBrick marked this conversation as resolved.

if (config.get('options.proxy')) {
const authProxyEnabled = await config.plugins.isEnabled('auth-proxy-adapter');

Expand Down
49 changes: 49 additions & 0 deletions src/plugins/transparent-player/backend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import is from 'electron-is';

import { MaterialType } from './types';

import type { BrowserWindow } from 'electron';
import type { BackendContext } from '@/types/contexts';
import type { TransparentPlayerConfig } from './types';

let mainWindow: BrowserWindow | null = null;
Comment thread
This conversation was marked as resolved.
Outdated

const setWindowMaterial = (window: BrowserWindow, type: MaterialType) => {
if (type === MaterialType.NONE) {
if (is.windows()) window.setBackgroundMaterial?.('none');
else if (is.macOS()) window.setVibrancy?.(null);
return;
}

if (is.windows()) {
window.setBackgroundMaterial?.(
type as Parameters<BrowserWindow['setBackgroundMaterial']>[0],
);
} else if (is.macOS()) {
window.setVibrancy?.(type as Parameters<BrowserWindow['setVibrancy']>[0]);
}
Comment thread
This conversation was marked as resolved.
};
Comment thread
This conversation was marked as resolved.
Outdated

export const onMainLoad = async ({
window,
getConfig,
}: BackendContext<TransparentPlayerConfig>) => {
mainWindow = window;
const config = await getConfig();

setWindowMaterial(window, config.type);
window.setBackgroundColor?.(`rgba(0, 0, 0, ${config.opacity})`);
};

export const onConfigChange = (newConfig: TransparentPlayerConfig) => {
if (mainWindow) {
setWindowMaterial(mainWindow, newConfig.type);
mainWindow.setBackgroundColor?.(`rgba(0, 0, 0, ${newConfig.opacity})`);
}
};

export const onMainStop = ({
window,
}: BackendContext<TransparentPlayerConfig>) => {
setWindowMaterial(window, MaterialType.NONE);
Comment thread
This conversation was marked as resolved.
Outdated
};
58 changes: 7 additions & 51 deletions src/plugins/transparent-player/index.ts
Original file line number Diff line number Diff line change
@@ -1,74 +1,30 @@
import { t } from '@/i18n';
import { createPlugin } from '@/utils';
import { Platform } from '@/types/plugins';

import { onMenu } from './menu';
import { onMainLoad, onConfigChange, onMainStop } from './backend';
import { MaterialType, type TransparentPlayerConfig } from './types';

import style from './style.css?inline';

import type { BrowserWindow } from 'electron';

const defaultConfig: TransparentPlayerConfig = {
enabled: false,
opacity: 0.5,
type: MaterialType.ACRYLIC,
type: MaterialType.NONE,
Comment thread
This conversation was marked as resolved.
};

const opacityList = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1];
const typeList = Object.values(MaterialType);

export default createPlugin({
name: () => t('plugins.transparent-player.name'),
description: () => t('plugins.transparent-player.description'),
addedVersion: '3.11.x',
restartNeeded: true,
platform: Platform.Windows,
config: defaultConfig,
stylesheets: [style],
async menu({ getConfig, setConfig }) {
const config = await getConfig();
return [
{
label: t('plugins.transparent-player.menu.opacity.label'),
submenu: opacityList.map((opacity) => ({
label: t('plugins.transparent-player.menu.opacity.submenu.percent', {
opacity: opacity * 100,
}),
type: 'radio',
checked: config.opacity === opacity,
click() {
setConfig({ opacity });
},
})),
},
{
label: t('plugins.transparent-player.menu.type.label'),
submenu: typeList.map((type) => ({
label: t(`plugins.transparent-player.menu.type.submenu.${type}`),
type: 'radio',
checked: config.type === type,
click() {
setConfig({ type });
},
})),
},
];
},
menu: onMenu,
backend: {
mainWindow: null as BrowserWindow | null,
async start({ window, getConfig }) {
this.mainWindow = window;

const config = await getConfig();
window.setBackgroundMaterial?.(config.type);
window.setBackgroundColor?.(`rgba(0, 0, 0, ${config.opacity})`);
},
onConfigChange(newConfig) {
this.mainWindow?.setBackgroundMaterial?.(newConfig.type);
},
stop({ window }) {
window.setBackgroundMaterial?.('none');
},
start: onMainLoad,
onConfigChange,
stop: onMainStop,
},
renderer: {
props: {
Expand Down
62 changes: 62 additions & 0 deletions src/plugins/transparent-player/menu.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import is from 'electron-is';

import { t } from '@/i18n';

import { MaterialType } from './types';

import type { MenuContext } from '@/types/contexts';
import type { MenuTemplate } from '@/menu';
import type { TransparentPlayerConfig } from './types';

const opacityList = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1];

export const onMenu = async ({
getConfig,
setConfig,
}: MenuContext<TransparentPlayerConfig>): Promise<MenuTemplate> => {
const config = await getConfig();
const typeList = is.windows()
? [
MaterialType.MICA,
MaterialType.ACRYLIC,
MaterialType.TABBED,
MaterialType.NONE,
]
: is.macOS()
? [
MaterialType.WINDOW,
MaterialType.FULLSCREEN_UI,
MaterialType.CONTENT,
MaterialType.UNDER_WINDOW,
MaterialType.UNDER_PAGE,
MaterialType.NONE,
]
: [MaterialType.NONE];
Comment thread
coderabbitai[bot] marked this conversation as resolved.

return [
{
label: t('plugins.transparent-player.menu.opacity.label'),
submenu: opacityList.map((opacity) => ({
label: t('plugins.transparent-player.menu.opacity.submenu.percent', {
opacity: opacity * 100,
}),
type: 'radio',
checked: config.opacity === opacity,
click() {
setConfig({ opacity });
},
})),
},
{
label: t('plugins.transparent-player.menu.type.label'),
submenu: typeList.map((type) => ({
label: t(`plugins.transparent-player.menu.type.submenu.${type}`),
Comment thread
This conversation was marked as resolved.
type: 'radio',
checked: config.type === type,
click() {
setConfig({ type });
},
})),
},
];
};
11 changes: 10 additions & 1 deletion src/plugins/transparent-player/types.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
export enum MaterialType {
NONE = 'none',

// Windows materials
MICA = 'mica',
ACRYLIC = 'acrylic',
TABBED = 'tabbed',
NONE = 'none',

// macOS materials
WINDOW = 'window',
FULLSCREEN_UI = 'fullscreen-ui',
CONTENT = 'content',
UNDER_WINDOW = 'under-window',
UNDER_PAGE = 'under-page',
}

export type TransparentPlayerConfig = {
Expand Down
Loading