feat(app): improve image picker, markdown rendering, and UI interactions

This commit is contained in:
Mohamed Boudra
2026-03-12 23:29:26 +07:00
parent 4b5cb5a3e2
commit 9190d86148
16 changed files with 642 additions and 91 deletions
@@ -0,0 +1,59 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
const tauriMock = vi.hoisted(() => {
let listenerCleanup: (() => void) | null = null;
const connect = vi.fn(async () => {
let listenerActive = false;
return {
addListener: vi.fn(() => {
listenerActive = true;
listenerCleanup = vi.fn(() => {
if (!listenerActive) {
throw new TypeError(
"undefined is not an object (evaluating 'listeners[eventId].handlerId')"
);
}
listenerActive = false;
});
return listenerCleanup;
}),
send: vi.fn(async () => undefined),
disconnect: vi.fn(async () => {
listenerCleanup?.();
}),
};
});
return {
connect,
getListenerCleanup: () => listenerCleanup,
};
});
vi.mock("./tauri", () => ({
getTauri: () => ({
websocket: {
connect: tauriMock.connect,
},
}),
}));
describe("tauri-daemon-transport", () => {
beforeEach(() => {
tauriMock.connect.mockClear();
});
it("does not unregister the websocket listener twice during close", async () => {
const mod = await import("./tauri-daemon-transport");
const transportFactory = mod.createTauriWebSocketTransportFactory();
expect(transportFactory).not.toBeNull();
const transport = transportFactory!({ url: "ws://localhost:6767/ws" });
await Promise.resolve();
expect(() => transport.close()).not.toThrow();
expect(tauriMock.getListenerCleanup()).toHaveBeenCalledTimes(1);
});
});
@@ -229,14 +229,10 @@ export function createTauriWebSocketTransportFactory(): DaemonTransportFactory |
return {
...transport,
close: (code?: number, reason?: string) => {
wsListenerCleanup = null;
transport.close(code, reason);
disposed = true;
try {
wsListenerCleanup?.();
} catch {
// no-op
}
wsListenerCleanup = null;
ws = null;
},
};
};
+14
View File
@@ -7,8 +7,22 @@ export interface TauriDialogAskOptions {
kind?: "info" | "warning" | "error";
}
export interface TauriDialogOpenOptions {
title?: string;
defaultPath?: string;
directory?: boolean;
multiple?: boolean;
filters?: Array<{
name: string;
extensions: string[];
}>;
}
export interface TauriDialogApi {
ask?: (message: string, options?: TauriDialogAskOptions) => Promise<boolean>;
open?: (
options?: TauriDialogOpenOptions
) => Promise<string | string[] | null>;
}
export interface TauriCoreApi {