Add operating system specific ap icon

This commit is contained in:
Oliver Schwendener 2024-02-23 17:12:56 +01:00
parent db4cde8be2
commit faa30edcae
8 changed files with 99 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 516 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 528 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 KiB

View File

@ -6,6 +6,7 @@ import type { SearchResultItemAction } from "@common/Core";
import type { BrowserWindow, BrowserWindowConstructorOptions } from "electron";
import { join } from "path";
import { createBrowserWindow } from "./createBrowserWindow";
import { getAppIconFilePath } from "./getAppIconFilePath";
import { getBackgroundMaterial } from "./getBackgroundMaterial";
import { getVibrancy } from "./getVibrancy";
import { openAndFocusBrowserWindow } from "./openAndFocusBrowserWindow";
@ -15,11 +16,22 @@ import { toggleBrowserWindow } from "./toggleBrowserWindow";
export class BrowserWindowModule {
public static async bootstrap(dependencyRegistry: DependencyRegistry<Dependencies>) {
const eventEmitter = dependencyRegistry.get("EventEmitter");
const nativeTheme = dependencyRegistry.get("NativeTheme");
const browserWindow = createBrowserWindow(dependencyRegistry);
eventEmitter.emitEvent("browserWindowCreated", { browserWindow });
nativeTheme.addListener("updated", () =>
browserWindow.setIcon(
getAppIconFilePath(
dependencyRegistry.get("NativeTheme"),
dependencyRegistry.get("AssetPathResolver"),
dependencyRegistry.get("OperatingSystem"),
),
),
);
BrowserWindowModule.registerBrowserWindowEventListeners(browserWindow, dependencyRegistry);
BrowserWindowModule.registerEvents(browserWindow, dependencyRegistry);
await BrowserWindowModule.loadFileOrUrl(browserWindow, dependencyRegistry);

View File

@ -3,6 +3,7 @@ import type { DependencyRegistry } from "@Core/DependencyRegistry";
import type { OperatingSystem } from "@common/Core";
import { BrowserWindow, type BrowserWindowConstructorOptions } from "electron";
import { join } from "path";
import { getAppIconFilePath } from "./getAppIconFilePath";
import { getBackgroundMaterial } from "./getBackgroundMaterial";
import { getVibrancy } from "./getVibrancy";
@ -28,6 +29,11 @@ export const createBrowserWindow = (dependencyRegistry: DependencyRegistry<Depen
spellcheck: false,
},
alwaysOnTop,
icon: getAppIconFilePath(
dependencyRegistry.get("NativeTheme"),
dependencyRegistry.get("AssetPathResolver"),
dependencyRegistry.get("OperatingSystem"),
),
};
const extendDefaultBrowserWindowOptions = (browserWindowOptions: BrowserWindowConstructorOptions) => {

View File

@ -0,0 +1,60 @@
import type { AssetPathResolver } from "@Core/AssetPathResolver";
import type { NativeTheme } from "electron";
import { describe, expect, it, vi } from "vitest";
import { getAppIconFilePath } from "./getAppIconFilePath";
describe(getAppIconFilePath, () => {
it("it should return the correct app icon file path on Windows' dark theme", () => {
const getModuleAssetPathMock = vi.fn().mockReturnValue("windows-dark-theme-icon.png");
const assetPathResolver = <AssetPathResolver>{ getModuleAssetPath: (m, a) => getModuleAssetPathMock(m, a) };
const nativeTheme = <NativeTheme>{ shouldUseDarkColors: true };
expect(getAppIconFilePath(nativeTheme, assetPathResolver, "Windows")).toBe("windows-dark-theme-icon.png");
expect(getModuleAssetPathMock).toHaveBeenCalledWith("BrowserWindow", "app-icon-dark-transparent.png");
});
it("it should return the correct app icon file path on Windows' light theme", () => {
const getModuleAssetPathMock = vi.fn().mockReturnValue("windows-light-theme-icon.png");
const assetPathResolver = <AssetPathResolver>{ getModuleAssetPath: (m, a) => getModuleAssetPathMock(m, a) };
const nativeTheme = <NativeTheme>{ shouldUseDarkColors: false };
expect(getAppIconFilePath(nativeTheme, assetPathResolver, "Windows")).toBe("windows-light-theme-icon.png");
expect(getModuleAssetPathMock).toHaveBeenCalledWith("BrowserWindow", "app-icon-light-transparent.png");
});
it("it should return the correct app icon file path on macOS' dark theme", () => {
const getModuleAssetPathMock = vi.fn().mockReturnValue("macos-dark-theme-icon.png");
const assetPathResolver = <AssetPathResolver>{ getModuleAssetPath: (m, a) => getModuleAssetPathMock(m, a) };
const nativeTheme = <NativeTheme>{ shouldUseDarkColors: true };
expect(getAppIconFilePath(nativeTheme, assetPathResolver, "macOS")).toBe("macos-dark-theme-icon.png");
expect(getModuleAssetPathMock).toHaveBeenCalledWith("BrowserWindow", "app-icon-dark.png");
});
it("it should return the correct app icon file path on macOS' light theme", () => {
const getModuleAssetPathMock = vi.fn().mockReturnValue("macos-light-theme-icon.png");
const assetPathResolver = <AssetPathResolver>{ getModuleAssetPath: (m, a) => getModuleAssetPathMock(m, a) };
const nativeTheme = <NativeTheme>{ shouldUseDarkColors: false };
expect(getAppIconFilePath(nativeTheme, assetPathResolver, "macOS")).toBe("macos-light-theme-icon.png");
expect(getModuleAssetPathMock).toHaveBeenCalledWith("BrowserWindow", "app-icon-light.png");
});
it("it should return the correct app icon file path on Linux' dark theme", () => {
const getModuleAssetPathMock = vi.fn().mockReturnValue("linux-dark-theme-icon.png");
const assetPathResolver = <AssetPathResolver>{ getModuleAssetPath: (m, a) => getModuleAssetPathMock(m, a) };
const nativeTheme = <NativeTheme>{ shouldUseDarkColors: true };
expect(getAppIconFilePath(nativeTheme, assetPathResolver, "macOS")).toBe("linux-dark-theme-icon.png");
expect(getModuleAssetPathMock).toHaveBeenCalledWith("BrowserWindow", "app-icon-dark.png");
});
it("it should return the correct app icon file path on Linux' light theme", () => {
const getModuleAssetPathMock = vi.fn().mockReturnValue("linux-light-theme-icon.png");
const assetPathResolver = <AssetPathResolver>{ getModuleAssetPath: (m, a) => getModuleAssetPathMock(m, a) };
const nativeTheme = <NativeTheme>{ shouldUseDarkColors: false };
expect(getAppIconFilePath(nativeTheme, assetPathResolver, "macOS")).toBe("linux-light-theme-icon.png");
expect(getModuleAssetPathMock).toHaveBeenCalledWith("BrowserWindow", "app-icon-light.png");
});
});

View File

@ -0,0 +1,21 @@
import type { AssetPathResolver } from "@Core/AssetPathResolver";
import type { OperatingSystem } from "@common/Core";
import type { NativeTheme } from "electron";
export const getAppIconFilePath = (
nativeTheme: NativeTheme,
assetPathResolver: AssetPathResolver,
operatingSystem: OperatingSystem,
): string => {
const fileNames: Record<OperatingSystem, { dark: string; light: string }> = {
Linux: { dark: "app-icon-dark.png", light: "app-icon-light.png" },
macOS: { dark: "app-icon-dark.png", light: "app-icon-light.png" },
Windows: { dark: "app-icon-dark-transparent.png", light: "app-icon-light-transparent.png" },
};
const filename = nativeTheme.shouldUseDarkColors
? fileNames[operatingSystem].dark
: fileNames[operatingSystem].light;
return assetPathResolver.getModuleAssetPath("BrowserWindow", filename);
};