Skip to content

Commit

Permalink
feat(FileImageGenerator): added generic app icon and folder icon extr…
Browse files Browse the repository at this point in the history
…actor on macos
  • Loading branch information
oliverschwendener committed Mar 4, 2024
1 parent c73138a commit 5883511
Show file tree
Hide file tree
Showing 18 changed files with 83 additions and 6 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 9 additions & 1 deletion src/main/Core/ImageGenerator/ImageGeneratorModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type { FileIconExtractor } from "./FileIconExtractor";
import { FileImageGenerator } from "./FileImageGenerator";
import { GenericFileIconExtractor } from "./GenericFileIconExtractor";
import { MacOsApplicationIconExtractor } from "./MacOsApplicationIconExtractor";
import { MacOsFolderIconExtractor } from "./MacOsFolderIconExtractor";
import { UrlImageGenerator } from "./UrlImageGenerator";

export class ImageGeneratorModule {
Expand Down Expand Up @@ -46,11 +47,18 @@ export class ImageGeneratorModule {
const operatingSystemSpecificIconExtractors: Record<OperatingSystem, FileIconExtractor[]> = {
Linux: [],
macOS: [
new MacOsFolderIconExtractor(
dependencyRegistry.get("AssetPathResolver"),
dependencyRegistry.get("FileSystemUtility"),
dependencyRegistry.get("App"),
),
new MacOsApplicationIconExtractor(
dependencyRegistry.get("FileSystemUtility"),
dependencyRegistry.get("CommandlineUtility"),
cacheFolderPath,
dependencyRegistry.get("AssetPathResolver"),
dependencyRegistry.get("Logger"),
cacheFileNameGenerator,
cacheFolderPath,
),
],
Windows: [],
Expand Down
26 changes: 21 additions & 5 deletions src/main/Core/ImageGenerator/MacOsApplicationIconExtractor.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { AssetPathResolver } from "@Core/AssetPathResolver";
import type { CommandlineUtility } from "@Core/CommandlineUtility";
import type { FileSystemUtility } from "@Core/FileSystemUtility";
import type { Logger } from "@Core/Logger";
import type { Image } from "@common/Core/Image";
import { join } from "path";
import type { CacheFileNameGenerator } from "./CacheFileNameGenerator";
Expand All @@ -9,8 +11,10 @@ export class MacOsApplicationIconExtractor implements FileIconExtractor {
public constructor(
private readonly fileSystemUtility: FileSystemUtility,
private readonly commandlineUtility: CommandlineUtility,
private readonly cacheFolder: string,
private readonly assetPathResolver: AssetPathResolver,
private readonly logger: Logger,
private readonly cacheFileNameGenerator: CacheFileNameGenerator,
private readonly cacheFolder: string,
) {}

public machtes(filePath: string) {
Expand All @@ -25,15 +29,27 @@ export class MacOsApplicationIconExtractor implements FileIconExtractor {
private async ensureCachedIconExists(applicationFilePath: string): Promise<string> {
const iconFilePath = this.getIconFilePath(applicationFilePath);

if (await this.fileSystemUtility.pathExists(iconFilePath)) {
return iconFilePath;
const iconFileAlreadyExists = await this.fileSystemUtility.pathExists(iconFilePath);

if (!iconFileAlreadyExists) {
try {
await this.generateAppIcon(applicationFilePath, iconFilePath);
} catch (error) {
this.logger.warn(
`Unable to generate app icon for "${applicationFilePath}". Reason: ${error}. Using generic app icon instead.`,
);

return this.assetPathResolver.getModuleAssetPath("FileImageGenerator", "GenericApplicationIcon.png");
}
}

return iconFilePath;
}

private async generateAppIcon(applicationFilePath: string, iconFilePath: string): Promise<void> {
const icnsIconFilePath = await this.getIcnsIconFilePath(applicationFilePath);

await this.commandlineUtility.executeCommand(`sips -s format png "${icnsIconFilePath}" -o "${iconFilePath}"`);

return iconFilePath;
}

private getIconFilePath(applicationFilePath: string): string {
Expand Down
53 changes: 53 additions & 0 deletions src/main/Core/ImageGenerator/MacOsFolderIconExtractor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import type { AssetPathResolver } from "@Core/AssetPathResolver";
import type { FileSystemUtility } from "@Core/FileSystemUtility";
import type { App } from "electron";
import { join } from "path";
import type { FileIconExtractor } from "./FileIconExtractor";

export class MacOsFolderIconExtractor implements FileIconExtractor {
private readonly folderPaths: Record<string, string>;

public constructor(
private readonly assetPathResolver: AssetPathResolver,
private readonly fileSystemUtility: FileSystemUtility,
app: App,
) {
const homeFolderPath = app.getPath("home");

this.folderPaths = {
[homeFolderPath]: "HomeFolderIcon.png",
[join(homeFolderPath, "Applications")]: "ApplicationsFolderIcon.png",
[join(homeFolderPath, "Desktop")]: "DesktopFolderIcon.png",
[join(homeFolderPath, "Documents")]: "DocumentsFolderIcon.png",
[join(homeFolderPath, "Downloads")]: "DownloadsFolderIcon.png",
[join(homeFolderPath, "Library")]: "LibraryFolderIcon.png",
[join(homeFolderPath, "Movies")]: "MovieFolderIcon.png",
[join(homeFolderPath, "Music")]: "MusicFolderIcon.png",
[join(homeFolderPath, "Pictures")]: "PicturesFolderIcon.png",
[join(homeFolderPath, "Public")]: "PublicFolderIcon.png",
[join("/", "Applications")]: "ApplicationsFolderIcon.png",
[join("/", "Library")]: "LibraryFolderIcon.png",
[join("/", "System", "Applications")]: "ApplicationsFolderIcon.png",
["/Users"]: "UsersFolderIcon.png",
["/System"]: "SystemFolderIcon.png",
["/System/Library"]: "LibraryFolderIcon.png",
};
}

public machtes(filePath: string) {
return (
Object.keys(this.folderPaths).some((f) => f === filePath) ||
(this.fileSystemUtility.isDirectory(filePath) && !filePath.endsWith(".app"))
);
}

public async extractFileIcon(filePath: string) {
const assetFileName = Object.keys(this.folderPaths).includes(filePath)
? this.folderPaths[filePath]
: "GenericFolderIcon.png";

return {
url: `file://${this.assetPathResolver.getModuleAssetPath("FileImageGenerator", assetFileName)}`,
};
}
}

0 comments on commit 5883511

Please sign in to comment.