refactor: update UI components and styles for improved consistency and functionality

- Refactored Skeleton component to include data-slot attribute and updated class names.
- Enhanced Switch component with size prop and improved styling.
- Updated Tooltip components to include data-slot attributes and improved styling.
- Refactored global CSS to use custom properties for theming and improved dark mode support.
- Added useIsMobile hook for responsive design handling.
- Updated IPC link implementation for tRPC in Electron.
- Adjusted ProjectsPage layout for better responsiveness.
- Removed outdated Tailwind configuration file and integrated Tailwind CSS with Vite.
This commit is contained in:
Roberto Musso
2026-02-20 00:45:22 +01:00
parent 4180c3d215
commit 99140c2c48
32 changed files with 6390 additions and 1934 deletions

View File

@@ -1,9 +1,9 @@
import { app, BrowserWindow } from 'electron';
import path from 'node:path';
import started from 'electron-squirrel-startup';
import { createIPCHandler } from 'electron-trpc/main';
import { initDb } from './db';
import { appRouter } from './router';
import { createIPCHandler } from './ipc';
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (started) {

89
src/main/ipc.ts Normal file
View File

@@ -0,0 +1,89 @@
/**
* Custom electron IPC ↔ tRPC v11 bridge.
*
* Replaces the incompatible electron-trpc package (v0.7.x bundles tRPC v10's
* callProcedure which checks `procedure._def[type]`, while tRPC v11 uses
* `procedure._def.type`).
*/
import { ipcMain, type BrowserWindow } from 'electron';
import {
callTRPCProcedure,
getErrorShape,
getTRPCErrorFromUnknown,
transformTRPCResponse,
type AnyRouter,
} from '@trpc/server';
export const IPC_CHANNEL = 'trpc';
interface IPCRequest {
method: 'request';
operation: {
id: number;
type: 'query' | 'mutation' | 'subscription';
path: string;
input?: unknown;
};
}
export function createIPCHandler<TRouter extends AnyRouter>({
router,
windows = [],
}: {
router: TRouter;
windows?: BrowserWindow[];
}) {
const config = router._def._config;
ipcMain.on(IPC_CHANNEL, async (event, message: IPCRequest) => {
if (message.method !== 'request') return;
const { id, type, path, input } = message.operation;
// Deserialize input through transformer (identity by default)
const rawInput = input !== undefined
? config.transformer.input.deserialize(input)
: undefined;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const respond = (response: any) => {
if (event.sender.isDestroyed()) return;
const serialised = transformTRPCResponse(config, response);
event.reply(IPC_CHANNEL, serialised);
};
try {
const result = await callTRPCProcedure({
router,
path,
getRawInput: async () => rawInput,
ctx: {},
type,
signal: undefined as unknown as AbortSignal,
batchIndex: 0,
});
respond({ id, result: { type: 'data', data: result } });
} catch (cause) {
const error = getTRPCErrorFromUnknown(cause);
respond({
id,
error: getErrorShape({
config,
error,
type,
path,
input: rawInput,
ctx: {},
}),
});
}
});
// Attach additional windows later if needed
return {
attachWindow(_win: BrowserWindow) {
// No per-window setup needed — ipcMain.on is global
},
};
}