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.icon})
+
{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)
+ }
+}));