Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/config/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ export interface DefaultConfig {
likeButtons: string;
proxy: string;
startingPage: string;
backgroundMaterial?: 'none' | 'mica' | 'acrylic' | 'tabbed';
overrideUserAgent: boolean;
usePodcastParticipantAsArtist: boolean;
themes: string[];
Expand Down
5 changes: 5 additions & 0 deletions src/i18n/resources/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -914,8 +914,13 @@
"label": "Type",
"submenu": {
"acrylic": "Acrylic",
"content": "Content",
"fullscreen-ui": "Fullscreen UI",
"mica": "Mica",
"tabbed": "Tabbed",
"under-page": "Under Page",
"under-window": "Under Window",
"window": "Window",
"none": "None"
}
}
Expand Down
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(','));

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

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

import { MaterialType, WINDOWS_MATERIALS, MACOS_MATERIALS } from './types';

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

let mainWindow: BrowserWindow | null = null;

const setWindowTransparency = (material: MaterialType, opacity: number) => {
if (mainWindow === null) return;

// Background materials are only supported on macOS and Windows
if (is.windows()) {
if (WINDOWS_MATERIALS.includes(material)) {
mainWindow.setBackgroundMaterial(
material as Parameters<BrowserWindow['setBackgroundMaterial']>[0],
);
} else {
mainWindow.setBackgroundMaterial('none');
}
} else if (is.macOS()) {
if (MACOS_MATERIALS.includes(material)) {
mainWindow.setVibrancy(
material as Parameters<BrowserWindow['setVibrancy']>[0],
);
} else {
mainWindow.setVibrancy(null);
}
}

// Set the opacity
mainWindow.setBackgroundColor(`rgba(0, 0, 0, ${opacity})`);
};

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

const config = await getConfig();
setWindowTransparency(config.type, config.opacity);
};

export const onConfigChange = (newConfig: TransparentPlayerConfig) => {
setWindowTransparency(newConfig.type, newConfig.opacity);
};

export const onMainStop = () => {
setWindowTransparency(MaterialType.NONE, 1);
mainWindow = null;
};
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,
};

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
50 changes: 50 additions & 0 deletions src/plugins/transparent-player/menu.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import is from 'electron-is';

import { t } from '@/i18n';

import { MaterialType, WINDOWS_MATERIALS, MACOS_MATERIALS } 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()
? WINDOWS_MATERIALS
: is.macOS()
? MACOS_MATERIALS
: [MaterialType.NONE];

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 });
},
})),
},
];
};
25 changes: 24 additions & 1 deletion src/plugins/transparent-player/types.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,33 @@
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 const WINDOWS_MATERIALS = [
MaterialType.MICA,
MaterialType.ACRYLIC,
MaterialType.TABBED,
];

export const MACOS_MATERIALS = [
MaterialType.WINDOW,
MaterialType.FULLSCREEN_UI,
MaterialType.CONTENT,
MaterialType.UNDER_WINDOW,
MaterialType.UNDER_PAGE,
];

export type TransparentPlayerConfig = {
enabled: boolean;
opacity: number;
Expand Down