From b5dcb27c804afd4be188890c88b2b7603ce4dab6 Mon Sep 17 00:00:00 2001 From: dubisdev Date: Wed, 12 Jun 2024 20:11:56 +0200 Subject: [PATCH] feat: Add option to create icons on the tray --- src/App.tsx | 14 +++++++- src/components/CreateTrayAppForm.tsx | 28 ++++++++++++++++ src/components/TrayAppInfo.tsx | 20 ++++++++++++ .../TrayApp/application/hideTrayApp.ts | 6 ++++ .../TrayApp/application/showTrayApp.ts | 6 ++++ src/features/TrayApp/domain/TrayApp.ts | 11 +++++++ src/features/TrayApp/domain/TrayAppHider.ts | 5 +++ .../TrayApp/domain/TrayAppRepository.ts | 11 +++++++ .../domain/TrayAppVisibilityManager.ts | 6 ++++ .../infrastructure/TauriTrayAppDisplayer.ts | 23 +++++++++++++ src/services/createTrayApp.ts | 14 ++++++++ src/stores/useTrayAppsStore.ts | 32 +++++++++++++++++++ 12 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 src/components/CreateTrayAppForm.tsx create mode 100644 src/components/TrayAppInfo.tsx create mode 100644 src/features/TrayApp/application/hideTrayApp.ts create mode 100644 src/features/TrayApp/application/showTrayApp.ts create mode 100644 src/features/TrayApp/domain/TrayApp.ts create mode 100644 src/features/TrayApp/domain/TrayAppHider.ts create mode 100644 src/features/TrayApp/domain/TrayAppRepository.ts create mode 100644 src/features/TrayApp/domain/TrayAppVisibilityManager.ts create mode 100644 src/features/TrayApp/infrastructure/TauriTrayAppDisplayer.ts create mode 100644 src/services/createTrayApp.ts create mode 100644 src/stores/useTrayAppsStore.ts diff --git a/src/App.tsx b/src/App.tsx index 2ea4b30..4408a4a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,5 +1,17 @@ +import { useTrayAppsStore } from "./stores/useTrayAppsStore"; +import { CreateTrayAppForm } from "./components/CreateTrayAppForm"; +import { TrayAppInfo } from "./components/TrayAppInfo"; + function App() { - return <>Trayfier + const { trayApps } = useTrayAppsStore() + + return <> +

Add a Tray icon to your Tray

+ + + + {trayApps.map((trayApp) => )} + } export default App; diff --git a/src/components/CreateTrayAppForm.tsx b/src/components/CreateTrayAppForm.tsx new file mode 100644 index 0000000..f2078be --- /dev/null +++ b/src/components/CreateTrayAppForm.tsx @@ -0,0 +1,28 @@ +import { FormEvent } from "react"; +import { useTrayAppsStore } from "../stores/useTrayAppsStore"; + +export const CreateTrayAppForm = () => { + const { addTrayApp } = useTrayAppsStore() + + const handleCreateTrayApp = async (e: FormEvent) => { + e.preventDefault(); + + const fields = new FormData(e.target as HTMLFormElement); + + const name = fields.get("trayAppName"); + + if (!name) return + + if (typeof name !== "string") return + + addTrayApp({ name }) + } + + return
+ + + + + +
+} diff --git a/src/components/TrayAppInfo.tsx b/src/components/TrayAppInfo.tsx new file mode 100644 index 0000000..eeafc51 --- /dev/null +++ b/src/components/TrayAppInfo.tsx @@ -0,0 +1,20 @@ +import { TrayApp } from "../features/TrayApp/domain/TrayApp" +import { useTrayAppsStore } from "../stores/useTrayAppsStore" + +type TrayAppInfoProps = { + trayApp: TrayApp +} + +export const TrayAppInfo = ({ trayApp }: TrayAppInfoProps) => { + const { deleteTrayApp } = useTrayAppsStore() + + const handleDeleteTrayApp = async (trayAppId: TrayApp) => { + deleteTrayApp(trayAppId) + } + + return
+ {trayApp.name} + {trayApp.name} + +
+} diff --git a/src/features/TrayApp/application/hideTrayApp.ts b/src/features/TrayApp/application/hideTrayApp.ts new file mode 100644 index 0000000..115059d --- /dev/null +++ b/src/features/TrayApp/application/hideTrayApp.ts @@ -0,0 +1,6 @@ +import { TrayApp } from "../domain/TrayApp"; +import { TrayAppVisibilityManager } from "../domain/TrayAppVisibilityManager"; + +export const hideTrayApp = async (trayApp: TrayApp, displayer: TrayAppVisibilityManager) => { + await displayer.hide(trayApp); +} diff --git a/src/features/TrayApp/application/showTrayApp.ts b/src/features/TrayApp/application/showTrayApp.ts new file mode 100644 index 0000000..993f641 --- /dev/null +++ b/src/features/TrayApp/application/showTrayApp.ts @@ -0,0 +1,6 @@ +import { TrayApp } from "../domain/TrayApp"; +import { TrayAppVisibilityManager } from "../domain/TrayAppVisibilityManager"; + +export const showTrayApp = async (trayApp: TrayApp, displayer: TrayAppVisibilityManager) => { + await displayer.show(trayApp); +} diff --git a/src/features/TrayApp/domain/TrayApp.ts b/src/features/TrayApp/domain/TrayApp.ts new file mode 100644 index 0000000..af08358 --- /dev/null +++ b/src/features/TrayApp/domain/TrayApp.ts @@ -0,0 +1,11 @@ +export class TrayApp { + private constructor( + readonly id: string, + readonly icon: string = "./icons/icon.png", + readonly name: string, + ) { } + + static create({ id, icon, name }: { id: string, icon?: string, name: string }) { + return new TrayApp(id, icon, name); + } +} diff --git a/src/features/TrayApp/domain/TrayAppHider.ts b/src/features/TrayApp/domain/TrayAppHider.ts new file mode 100644 index 0000000..07def75 --- /dev/null +++ b/src/features/TrayApp/domain/TrayAppHider.ts @@ -0,0 +1,5 @@ +import { TrayApp } from "./TrayApp"; + +export interface TrayAppHider { + run: (trayApp: TrayApp) => Promise +} diff --git a/src/features/TrayApp/domain/TrayAppRepository.ts b/src/features/TrayApp/domain/TrayAppRepository.ts new file mode 100644 index 0000000..07d8402 --- /dev/null +++ b/src/features/TrayApp/domain/TrayAppRepository.ts @@ -0,0 +1,11 @@ +import { TrayApp } from "./TrayApp"; + +export interface TrayAppRepository { + subscribers: ((trayApps: TrayApp[]) => void)[]; + subscribeToTrayApps(callback: (trayApps: TrayApp[]) => void): void; + + addTrayApp(trayApp: TrayApp): void; + getTrayApps(): TrayApp[]; + + deleteTrayApp(trayAppId: string): void; +} diff --git a/src/features/TrayApp/domain/TrayAppVisibilityManager.ts b/src/features/TrayApp/domain/TrayAppVisibilityManager.ts new file mode 100644 index 0000000..06c345e --- /dev/null +++ b/src/features/TrayApp/domain/TrayAppVisibilityManager.ts @@ -0,0 +1,6 @@ +import { TrayApp } from "./TrayApp"; + +export interface TrayAppVisibilityManager { + show: (trayApp: TrayApp) => Promise + hide: (trayApp: TrayApp) => Promise +} diff --git a/src/features/TrayApp/infrastructure/TauriTrayAppDisplayer.ts b/src/features/TrayApp/infrastructure/TauriTrayAppDisplayer.ts new file mode 100644 index 0000000..148e3c8 --- /dev/null +++ b/src/features/TrayApp/infrastructure/TauriTrayAppDisplayer.ts @@ -0,0 +1,23 @@ +import { TrayIcon } from "@tauri-apps/api/tray"; +import { TrayApp } from "../domain/TrayApp"; +import { TrayAppVisibilityManager } from "../domain/TrayAppVisibilityManager"; + +export class TauriTrayAppVisibilityManager implements TrayAppVisibilityManager { + async show(trayApp: TrayApp) { + await TrayIcon.new({ + icon: trayApp.icon, + tooltip: trayApp.name, + id: trayApp.id, + }) + } + + async hide(trayApp: TrayApp) { + const tray = await TrayIcon.getById(trayApp.id) + + console.log(tray) + + if (!tray) return + + await tray.close().then(console.log).catch(console.error) + } +} diff --git a/src/services/createTrayApp.ts b/src/services/createTrayApp.ts new file mode 100644 index 0000000..847a91f --- /dev/null +++ b/src/services/createTrayApp.ts @@ -0,0 +1,14 @@ +import { TrayApp } from "../features/TrayApp/domain/TrayApp"; + +export interface TrayAppParams { + name: string; +} + +export const createTrayApp = (trayApp: TrayAppParams) => { + return TrayApp.create({ + name: trayApp.name, + id: crypto.randomUUID(), + icon: "./icons/icon.png" + }) + +} diff --git a/src/stores/useTrayAppsStore.ts b/src/stores/useTrayAppsStore.ts new file mode 100644 index 0000000..a177db5 --- /dev/null +++ b/src/stores/useTrayAppsStore.ts @@ -0,0 +1,32 @@ +import { create } from "zustand"; +import { TrayApp } from "../features/TrayApp/domain/TrayApp"; +import { showTrayApp } from "../features/TrayApp/application/showTrayApp"; +import { TauriTrayAppVisibilityManager } from "../features/TrayApp/infrastructure/TauriTrayAppDisplayer"; +import { hideTrayApp } from "../features/TrayApp/application/hideTrayApp"; +import { TrayAppParams, createTrayApp } from "../services/createTrayApp"; + +type TrayAppStore = { + trayApps: TrayApp[]; + addTrayApp: (trayApp: TrayAppParams) => void; + deleteTrayApp: (trayAppId: TrayApp) => void; +} + +const trayAppVisibilityManager = new TauriTrayAppVisibilityManager() + +export const useTrayAppsStore = create()((set) => ({ + trayApps: [], + + addTrayApp: (trayInfo: TrayAppParams) => { + const trayApp = createTrayApp(trayInfo) + + set((state) => ({ trayApps: [...state.trayApps, trayApp] })) + + showTrayApp(trayApp, trayAppVisibilityManager) + }, + + deleteTrayApp: (trayApp: TrayApp) => { + set((state) => ({ trayApps: state.trayApps.filter(app => app !== trayApp) })) + + hideTrayApp(trayApp, trayAppVisibilityManager) + } +}));