Skip to content

Commit

Permalink
feat: Add option to create icons on the tray
Browse files Browse the repository at this point in the history
  • Loading branch information
dubisdev committed Jun 12, 2024
1 parent c11b1da commit b5dcb27
Show file tree
Hide file tree
Showing 12 changed files with 175 additions and 1 deletion.
14 changes: 13 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
@@ -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 <>
<h1>Add a Tray icon to your Tray</h1>

<CreateTrayAppForm />

{trayApps.map((trayApp) => <TrayAppInfo key={trayApp.id} trayApp={trayApp} />)}
</>
}

export default App;
28 changes: 28 additions & 0 deletions src/components/CreateTrayAppForm.tsx
Original file line number Diff line number Diff line change
@@ -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 <form onSubmit={handleCreateTrayApp}>

<label htmlFor="trayAppName">Name</label>
<input id="trayAppName" name="trayAppName" />

<button type="submit">Add Tray App</button>
</form>
}
20 changes: 20 additions & 0 deletions src/components/TrayAppInfo.tsx
Original file line number Diff line number Diff line change
@@ -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 <div>
<img src={trayApp.icon} alt={trayApp.name} />
<span>{trayApp.name}</span>
<button onClick={() => handleDeleteTrayApp(trayApp)}>Delete</button>
</div>
}
6 changes: 6 additions & 0 deletions src/features/TrayApp/application/hideTrayApp.ts
Original file line number Diff line number Diff line change
@@ -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);
}
6 changes: 6 additions & 0 deletions src/features/TrayApp/application/showTrayApp.ts
Original file line number Diff line number Diff line change
@@ -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);
}
11 changes: 11 additions & 0 deletions src/features/TrayApp/domain/TrayApp.ts
Original file line number Diff line number Diff line change
@@ -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);
}
}
5 changes: 5 additions & 0 deletions src/features/TrayApp/domain/TrayAppHider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { TrayApp } from "./TrayApp";

export interface TrayAppHider {
run: (trayApp: TrayApp) => Promise<void>
}
11 changes: 11 additions & 0 deletions src/features/TrayApp/domain/TrayAppRepository.ts
Original file line number Diff line number Diff line change
@@ -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;
}
6 changes: 6 additions & 0 deletions src/features/TrayApp/domain/TrayAppVisibilityManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { TrayApp } from "./TrayApp";

export interface TrayAppVisibilityManager {
show: (trayApp: TrayApp) => Promise<void>
hide: (trayApp: TrayApp) => Promise<void>
}
23 changes: 23 additions & 0 deletions src/features/TrayApp/infrastructure/TauriTrayAppDisplayer.ts
Original file line number Diff line number Diff line change
@@ -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)
}
}
14 changes: 14 additions & 0 deletions src/services/createTrayApp.ts
Original file line number Diff line number Diff line change
@@ -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"
})

}
32 changes: 32 additions & 0 deletions src/stores/useTrayAppsStore.ts
Original file line number Diff line number Diff line change
@@ -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<TrayAppStore>()((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)
}
}));

0 comments on commit b5dcb27

Please # to comment.