diff --git a/src/main/themes.ts b/src/main/themes.ts index c8f48473..c529b503 100644 --- a/src/main/themes.ts +++ b/src/main/themes.ts @@ -2,11 +2,12 @@ // This mirrors src/renderer/constants/themes.ts for use in the main process // When themes are updated in the renderer, this file should also be updated -import type { WebTheme } from './web-server'; +import type { Theme, ThemeId } from '../shared/theme-types'; -export type ThemeId = 'dracula' | 'monokai' | 'github-light' | 'solarized-light' | 'nord' | 'tokyo-night' | 'one-light' | 'gruvbox-light' | 'catppuccin-mocha' | 'gruvbox-dark' | 'catppuccin-latte' | 'ayu-light' | 'pedurple' | 'maestros-choice' | 'dre-synth' | 'inquest'; +// Re-export types from shared for convenience +export type { Theme, ThemeId } from '../shared/theme-types'; -export const THEMES: Record = { +export const THEMES: Record = { // Dark themes dracula: { id: 'dracula', @@ -320,6 +321,6 @@ export const THEMES: Record = { * Get a theme by its ID * Returns null if the theme ID is not found */ -export function getThemeById(themeId: string): WebTheme | null { +export function getThemeById(themeId: string): Theme | null { return THEMES[themeId as ThemeId] || null; } diff --git a/src/main/web-server.ts b/src/main/web-server.ts index c11ae36b..464babbb 100644 --- a/src/main/web-server.ts +++ b/src/main/web-server.ts @@ -5,6 +5,7 @@ import rateLimit from '@fastify/rate-limit'; import { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify'; import { WebSocket } from 'ws'; import crypto from 'crypto'; +import type { Theme } from '../shared/theme-types'; // Types for web client messages interface WebClientMessage { @@ -105,29 +106,11 @@ export type WriteToSessionCallback = (sessionId: string, data: string) => boolea // Returns true if successful, false if session not found or interrupt failed export type InterruptSessionCallback = (sessionId: string) => boolean; -// Theme type for web clients (matches renderer/types/index.ts) -export interface WebTheme { - id: string; - name: string; - mode: 'light' | 'dark' | 'vibe'; - colors: { - bgMain: string; - bgSidebar: string; - bgActivity: string; - border: string; - textMain: string; - textDim: string; - accent: string; - accentDim: string; - accentText: string; - success: string; - warning: string; - error: string; - }; -} +// Re-export Theme type from shared for backwards compatibility +export type { Theme } from '../shared/theme-types'; // Callback type for fetching current theme -export type GetThemeCallback = () => WebTheme | null; +export type GetThemeCallback = () => Theme | null; // Default rate limit configuration const DEFAULT_RATE_LIMIT_CONFIG: RateLimitConfig = { @@ -1002,7 +985,7 @@ export class WebServer { * Broadcast theme change to all connected web clients * Called when the user changes the theme in the desktop app */ - broadcastThemeChange(theme: WebTheme) { + broadcastThemeChange(theme: Theme) { this.broadcastToWebClients({ type: 'theme', theme, diff --git a/src/renderer/types/index.ts b/src/renderer/types/index.ts index c6addc38..67fa3207 100644 --- a/src/renderer/types/index.ts +++ b/src/renderer/types/index.ts @@ -1,34 +1,16 @@ // Type definitions for Maestro renderer +// Re-export theme types from shared location +export { Theme, ThemeId, ThemeMode, ThemeColors, isValidThemeId } from '../../shared/theme-types'; + export type ToolType = 'claude' | 'aider' | 'opencode' | 'terminal'; export type SessionState = 'idle' | 'busy' | 'waiting_input' | 'connecting' | 'error'; export type FileChangeType = 'modified' | 'added' | 'deleted'; export type RightPanelTab = 'files' | 'history' | 'scratchpad'; export type ScratchPadMode = 'raw' | 'preview' | 'wysiwyg'; -export type ThemeId = 'dracula' | 'monokai' | 'github-light' | 'solarized-light' | 'nord' | 'tokyo-night' | 'one-light' | 'gruvbox-light' | 'catppuccin-mocha' | 'gruvbox-dark' | 'catppuccin-latte' | 'ayu-light' | 'pedurple' | 'maestros-choice' | 'dre-synth' | 'inquest'; export type FocusArea = 'sidebar' | 'main' | 'right'; export type LLMProvider = 'openrouter' | 'anthropic' | 'ollama'; -export interface Theme { - id: ThemeId; - name: string; - mode: 'light' | 'dark' | 'vibe'; - colors: { - bgMain: string; - bgSidebar: string; - bgActivity: string; - border: string; - textMain: string; - textDim: string; - accent: string; - accentDim: string; - accentText: string; - success: string; - warning: string; - error: string; - }; -} - export interface Shortcut { id: string; label: string; diff --git a/src/shared/index.ts b/src/shared/index.ts new file mode 100644 index 00000000..064eb293 --- /dev/null +++ b/src/shared/index.ts @@ -0,0 +1,10 @@ +/** + * Shared types and utilities for Maestro + * + * This module exports types that are used across multiple parts of the application: + * - Main process (Electron) + * - Renderer process (Desktop React app) + * - Web interface (Mobile and Desktop web builds) + */ + +export * from './theme-types'; diff --git a/src/shared/theme-types.ts b/src/shared/theme-types.ts new file mode 100644 index 00000000..1bc7ba71 --- /dev/null +++ b/src/shared/theme-types.ts @@ -0,0 +1,106 @@ +/** + * Shared theme type definitions for Maestro + * + * This file contains theme types used across: + * - Main process (Electron) + * - Renderer process (Desktop React app) + * - Web interface (Mobile and Desktop web builds) + * + * Keep this file dependency-free to ensure it can be imported anywhere. + */ + +/** + * Available theme identifiers + */ +export type ThemeId = + | 'dracula' + | 'monokai' + | 'github-light' + | 'solarized-light' + | 'nord' + | 'tokyo-night' + | 'one-light' + | 'gruvbox-light' + | 'catppuccin-mocha' + | 'gruvbox-dark' + | 'catppuccin-latte' + | 'ayu-light' + | 'pedurple' + | 'maestros-choice' + | 'dre-synth' + | 'inquest'; + +/** + * Theme mode indicating the overall brightness/style + */ +export type ThemeMode = 'light' | 'dark' | 'vibe'; + +/** + * Color palette for a theme + * Each color serves a specific purpose in the UI + */ +export interface ThemeColors { + /** Main background color for primary content areas */ + bgMain: string; + /** Sidebar background color */ + bgSidebar: string; + /** Background for interactive/activity elements */ + bgActivity: string; + /** Border color for dividers and outlines */ + border: string; + /** Primary text color */ + textMain: string; + /** Dimmed/secondary text color */ + textDim: string; + /** Accent color for highlights and interactive elements */ + accent: string; + /** Dimmed accent (typically with alpha transparency) */ + accentDim: string; + /** Text color for accent contexts */ + accentText: string; + /** Success state color (green tones) */ + success: string; + /** Warning state color (yellow/orange tones) */ + warning: string; + /** Error state color (red tones) */ + error: string; +} + +/** + * Complete theme definition + */ +export interface Theme { + /** Unique identifier for the theme */ + id: ThemeId; + /** Human-readable display name */ + name: string; + /** Theme mode (light, dark, or vibe) */ + mode: ThemeMode; + /** Color palette */ + colors: ThemeColors; +} + +/** + * Type guard to check if a string is a valid ThemeId + */ +export function isValidThemeId(id: string): id is ThemeId { + const validIds: ThemeId[] = [ + 'dracula', + 'monokai', + 'github-light', + 'solarized-light', + 'nord', + 'tokyo-night', + 'one-light', + 'gruvbox-light', + 'catppuccin-mocha', + 'gruvbox-dark', + 'catppuccin-latte', + 'ayu-light', + 'pedurple', + 'maestros-choice', + 'dre-synth', + 'inquest', + ]; + return validIds.includes(id as ThemeId); +}