Repository: oliverschwendener/ueli
Pull request #1172 (2024-08-21 05:33:30)

feat: added linux desktop environment resolver
@ke1v I added here the basic structure for a `LinuxDesktopEnvironmentResolver`. What do you think about this? Here we have a small module that is responsible of resolving the current Linux desktop environment. This can be then used by other modules like the `LinuxAppIconExtractor` or the `LinuxApplicationRepository`. You can target your implementation against this branch.

ke1v: Thanks for the help. I've just started school again so it'll be a few days before I can integrate this and finish #1159.
oliverschwendener: I'll merge this now, so you can add more desktop environments in your PR.

Patch:
diff --git a/src/main/Core/Dependencies.ts b/src/main/Core/Dependencies.ts
index f6e5cb9d..66f56c6c 100644
--- a/src/main/Core/Dependencies.ts
+++ b/src/main/Core/Dependencies.ts
@@ -25,6 +25,7 @@ export type Dependencies = {
     GlobalShortcut?: Electron.GlobalShortcut;
     IniFileParser?: Core.IniFileParser;
     IpcMain?: Electron.IpcMain;
+    LinuxDesktopEnvironmentResolver?: Core.LinuxDesktopEnvironmentResolver;
     Logger?: Core.Logger;
     NativeTheme?: Electron.NativeTheme;
     Net?: Electron.Net;
diff --git a/src/main/Core/LinuxDesktopEnvironment/Contract/LinuxDesktopEnvironment.ts b/src/main/Core/LinuxDesktopEnvironment/Contract/LinuxDesktopEnvironment.ts
new file mode 100644
index 00000000..053082b4
--- /dev/null
+++ b/src/main/Core/LinuxDesktopEnvironment/Contract/LinuxDesktopEnvironment.ts
@@ -0,0 +1,4 @@
+/**
+ * A list of known Linux desktop environments.
+ */
+export type LinuxDesktopEnvironment = "GNOME" | "KDE";
diff --git a/src/main/Core/LinuxDesktopEnvironment/Contract/LinuxDesktopEnvironmentResolver.ts b/src/main/Core/LinuxDesktopEnvironment/Contract/LinuxDesktopEnvironmentResolver.ts
new file mode 100644
index 00000000..437dbf61
--- /dev/null
+++ b/src/main/Core/LinuxDesktopEnvironment/Contract/LinuxDesktopEnvironmentResolver.ts
@@ -0,0 +1,13 @@
+import type { LinuxDesktopEnvironment } from "./LinuxDesktopEnvironment";
+
+/**
+ * A utility to resolve the current Linux desktop environment.
+ */
+export interface LinuxDesktopEnvironmentResolver {
+    /**
+     * Resolves the current Linux desktop environment.
+     *
+     * @returns The current Linux desktop environment or undefined if it could not be resolved.
+     */
+    resolve(): LinuxDesktopEnvironment | undefined;
+}
diff --git a/src/main/Core/LinuxDesktopEnvironment/Contract/index.ts b/src/main/Core/LinuxDesktopEnvironment/Contract/index.ts
new file mode 100644
index 00000000..957b60b8
--- /dev/null
+++ b/src/main/Core/LinuxDesktopEnvironment/Contract/index.ts
@@ -0,0 +1,2 @@
+export * from "./LinuxDesktopEnvironment";
+export * from "./LinuxDesktopEnvironmentResolver";
diff --git a/src/main/Core/LinuxDesktopEnvironment/LinuxDesktopEnvironmentModule.ts b/src/main/Core/LinuxDesktopEnvironment/LinuxDesktopEnvironmentModule.ts
new file mode 100644
index 00000000..e3d9e718
--- /dev/null
+++ b/src/main/Core/LinuxDesktopEnvironment/LinuxDesktopEnvironmentModule.ts
@@ -0,0 +1,12 @@
+import type { Dependencies } from "@Core/Dependencies";
+import type { DependencyRegistry } from "@Core/DependencyRegistry";
+import { LinuxDesktopEnvironmentResolver } from "./LinuxDesktopEnvironmentResolver";
+
+export class LinuxDesktopEnvironmentModule {
+    public static bootstrap(dependencyRegistry: DependencyRegistry<Dependencies>): void {
+        dependencyRegistry.register(
+            "LinuxDesktopEnvironmentResolver",
+            new LinuxDesktopEnvironmentResolver(dependencyRegistry.get("EnvironmentVariableProvider")),
+        );
+    }
+}
diff --git a/src/main/Core/LinuxDesktopEnvironment/LinuxDesktopEnvironmentResolver.ts b/src/main/Core/LinuxDesktopEnvironment/LinuxDesktopEnvironmentResolver.ts
new file mode 100644
index 00000000..6cddb7a8
--- /dev/null
+++ b/src/main/Core/LinuxDesktopEnvironment/LinuxDesktopEnvironmentResolver.ts
@@ -0,0 +1,18 @@
+import type { EnvironmentVariableProvider } from "@Core/EnvironmentVariableProvider";
+import type {
+    LinuxDesktopEnvironment,
+    LinuxDesktopEnvironmentResolver as LinuxDesktopEnvironmentResolverInterface,
+} from "./Contract";
+
+export class LinuxDesktopEnvironmentResolver implements LinuxDesktopEnvironmentResolverInterface {
+    public constructor(private readonly environmentVariableProvider: EnvironmentVariableProvider) {}
+
+    public resolve(): LinuxDesktopEnvironment | undefined {
+        const map: Record<string, string> = {
+            "ubuntu:GNOME": "GNOME",
+            KDE: "KDE",
+        };
+
+        return map[this.environmentVariableProvider.get("XDG_CURRENT_DESKTOP")] as LinuxDesktopEnvironment | undefined;
+    }
+}
diff --git a/src/main/Core/LinuxDesktopEnvironment/index.ts b/src/main/Core/LinuxDesktopEnvironment/index.ts
new file mode 100644
index 00000000..61f70c6b
--- /dev/null
+++ b/src/main/Core/LinuxDesktopEnvironment/index.ts
@@ -0,0 +1,2 @@
+export * from "./Contract";
+export * from "./LinuxDesktopEnvironmentModule";
diff --git a/src/main/Core/index.ts b/src/main/Core/index.ts
index a1b35de4..7b425114 100644
--- a/src/main/Core/index.ts
+++ b/src/main/Core/index.ts
@@ -25,6 +25,7 @@ export * from "./FileSystemUtility";
 export * from "./GlobalShortcut";
 export * from "./ImageGenerator";
 export * from "./IniFileParser";
+export * from "./LinuxDesktopEnvironment";
 export * from "./Logger";
 export * from "./NativeTheme";
 export * from "./OperatingSystem";
diff --git a/src/main/index.ts b/src/main/index.ts
index 6de94d9a..697237f2 100644
--- a/src/main/index.ts
+++ b/src/main/index.ts
@@ -32,6 +32,7 @@ import * as Extensions from "./Extensions";
     Core.CommandlineSwitchModule.bootstrap(dependencyRegistry);
     Core.TaskSchedulerModule.bootstrap(dependencyRegistry);
     Core.EnvironmentVariableProviderModule.bootstrap(dependencyRegistry);
+    Core.LinuxDesktopEnvironmentModule.bootstrap(dependencyRegistry);
     Core.IniFileParserModule.bootstrap(dependencyRegistry);
     Core.EventEmitterModule.bootstrap(dependencyRegistry);
     Core.EventSubscriberModule.bootstrap(dependencyRegistry);


Test patch:
diff --git a/src/main/Core/LinuxDesktopEnvironment/LinuxDesktopEnvironmentResolver.test.ts b/src/main/Core/LinuxDesktopEnvironment/LinuxDesktopEnvironmentResolver.test.ts
new file mode 100644
index 00000000..04e69834
--- /dev/null
+++ b/src/main/Core/LinuxDesktopEnvironment/LinuxDesktopEnvironmentResolver.test.ts
@@ -0,0 +1,30 @@
+import type { EnvironmentVariableProvider } from "@Core/EnvironmentVariableProvider";
+import { describe, expect, it, vi } from "vitest";
+import type { LinuxDesktopEnvironment } from "./Contract";
+import { LinuxDesktopEnvironmentResolver } from "./LinuxDesktopEnvironmentResolver";
+
+describe(LinuxDesktopEnvironmentResolver, () => {
+    const testResolve = ({
+        expected,
+        xdgCurrentDesktop,
+    }: {
+        expected?: LinuxDesktopEnvironment;
+        xdgCurrentDesktop: string;
+    }) => {
+        const getMock = vi.fn().mockReturnValue(xdgCurrentDesktop);
+        const environmentVariableProvider = <EnvironmentVariableProvider>{ get: (n) => getMock(n) };
+
+        expect(new LinuxDesktopEnvironmentResolver(environmentVariableProvider).resolve()).toBe(expected);
+        expect(getMock).toHaveBeenCalledOnce();
+        expect(getMock).toHaveBeenCalledWith("XDG_CURRENT_DESKTOP");
+    };
+
+    it("should return undefined when XDG_CURRENT_DESKTOP environment variable is not set", () =>
+        testResolve({ expected: undefined, xdgCurrentDesktop: "" }));
+
+    it("should return GNOME when XDG_CURRENT_DESKTOP is ubuntu:GNOME", () =>
+        testResolve({ expected: "GNOME", xdgCurrentDesktop: "ubuntu:GNOME" }));
+
+    it("should return KDE when XDG_CURRENT_DESKTOP is KDE", () =>
+        testResolve({ expected: "KDE", xdgCurrentDesktop: "KDE" }));
+});