feat: add about dialog with custom information
This commit is contained in:
Generated
+1
-1
@@ -2847,7 +2847,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openchamber-desktop"
|
name = "openchamber-desktop"
|
||||||
version = "1.2.6"
|
version = "1.2.7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"axum",
|
"axum",
|
||||||
|
|||||||
@@ -90,6 +90,8 @@ const MENU_ITEM_REQUEST_FEATURE_ID: &str = "openchamber_request_feature";
|
|||||||
|
|
||||||
// App menu
|
// App menu
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
|
const MENU_ITEM_ABOUT_ID: &str = "openchamber_about";
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
const MENU_ITEM_SETTINGS_ID: &str = "openchamber_settings";
|
const MENU_ITEM_SETTINGS_ID: &str = "openchamber_settings";
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
const MENU_ITEM_COMMAND_PALETTE_ID: &str = "openchamber_command_palette";
|
const MENU_ITEM_COMMAND_PALETTE_ID: &str = "openchamber_command_palette";
|
||||||
@@ -329,17 +331,17 @@ fn prevent_app_nap() {
|
|||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
fn build_macos_menu<R: tauri::Runtime>(app: &tauri::AppHandle<R>) -> tauri::Result<tauri::menu::Menu<R>> {
|
fn build_macos_menu<R: tauri::Runtime>(app: &tauri::AppHandle<R>) -> tauri::Result<tauri::menu::Menu<R>> {
|
||||||
use tauri::menu::{AboutMetadata, Menu, MenuItem, PredefinedMenuItem, Submenu, HELP_SUBMENU_ID, WINDOW_SUBMENU_ID};
|
use tauri::menu::{Menu, MenuItem, PredefinedMenuItem, Submenu, HELP_SUBMENU_ID, WINDOW_SUBMENU_ID};
|
||||||
|
|
||||||
let pkg_info = app.package_info();
|
let pkg_info = app.package_info();
|
||||||
let config = app.config();
|
|
||||||
let about_metadata = AboutMetadata {
|
let about = MenuItem::with_id(
|
||||||
name: Some(pkg_info.name.clone()),
|
app,
|
||||||
version: Some(pkg_info.version.to_string()),
|
MENU_ITEM_ABOUT_ID,
|
||||||
copyright: config.bundle.copyright.clone(),
|
format!("About {}", pkg_info.name),
|
||||||
authors: config.bundle.publisher.clone().map(|p| vec![p]),
|
true,
|
||||||
..Default::default()
|
None::<&str>,
|
||||||
};
|
)?;
|
||||||
|
|
||||||
let check_for_updates = MenuItem::with_id(
|
let check_for_updates = MenuItem::with_id(
|
||||||
app,
|
app,
|
||||||
@@ -378,7 +380,7 @@ fn build_macos_menu<R: tauri::Runtime>(app: &tauri::AppHandle<R>) -> tauri::Resu
|
|||||||
let worktree_creator = MenuItem::with_id(
|
let worktree_creator = MenuItem::with_id(
|
||||||
app,
|
app,
|
||||||
MENU_ITEM_WORKTREE_CREATOR_ID,
|
MENU_ITEM_WORKTREE_CREATOR_ID,
|
||||||
"New Worktree…",
|
"New Worktree",
|
||||||
true,
|
true,
|
||||||
Some("Ctrl+Shift+N"),
|
Some("Ctrl+Shift+N"),
|
||||||
)?;
|
)?;
|
||||||
@@ -386,7 +388,7 @@ fn build_macos_menu<R: tauri::Runtime>(app: &tauri::AppHandle<R>) -> tauri::Resu
|
|||||||
let change_workspace = MenuItem::with_id(
|
let change_workspace = MenuItem::with_id(
|
||||||
app,
|
app,
|
||||||
MENU_ITEM_CHANGE_WORKSPACE_ID,
|
MENU_ITEM_CHANGE_WORKSPACE_ID,
|
||||||
"Change Workspace…",
|
"Change Workspace",
|
||||||
true,
|
true,
|
||||||
None::<&str>,
|
None::<&str>,
|
||||||
)?;
|
)?;
|
||||||
@@ -476,7 +478,7 @@ fn build_macos_menu<R: tauri::Runtime>(app: &tauri::AppHandle<R>) -> tauri::Resu
|
|||||||
let report_bug = MenuItem::with_id(
|
let report_bug = MenuItem::with_id(
|
||||||
app,
|
app,
|
||||||
MENU_ITEM_REPORT_BUG_ID,
|
MENU_ITEM_REPORT_BUG_ID,
|
||||||
"Report a Bug…",
|
"Report a Bug",
|
||||||
true,
|
true,
|
||||||
None::<&str>,
|
None::<&str>,
|
||||||
)?;
|
)?;
|
||||||
@@ -484,7 +486,7 @@ fn build_macos_menu<R: tauri::Runtime>(app: &tauri::AppHandle<R>) -> tauri::Resu
|
|||||||
let request_feature = MenuItem::with_id(
|
let request_feature = MenuItem::with_id(
|
||||||
app,
|
app,
|
||||||
MENU_ITEM_REQUEST_FEATURE_ID,
|
MENU_ITEM_REQUEST_FEATURE_ID,
|
||||||
"Request a Feature…",
|
"Request a Feature",
|
||||||
true,
|
true,
|
||||||
None::<&str>,
|
None::<&str>,
|
||||||
)?;
|
)?;
|
||||||
@@ -531,7 +533,7 @@ fn build_macos_menu<R: tauri::Runtime>(app: &tauri::AppHandle<R>) -> tauri::Resu
|
|||||||
pkg_info.name.clone(),
|
pkg_info.name.clone(),
|
||||||
true,
|
true,
|
||||||
&[
|
&[
|
||||||
&PredefinedMenuItem::about(app, None, Some(about_metadata))?,
|
&about,
|
||||||
&check_for_updates,
|
&check_for_updates,
|
||||||
&PredefinedMenuItem::separator(app)?,
|
&PredefinedMenuItem::separator(app)?,
|
||||||
&settings,
|
&settings,
|
||||||
@@ -870,6 +872,11 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// App menu actions
|
// App menu actions
|
||||||
|
if event_id == MENU_ITEM_ABOUT_ID {
|
||||||
|
let _ = app.emit("openchamber:menu-action", "about");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if event_id == MENU_ITEM_SETTINGS_ID {
|
if event_id == MENU_ITEM_SETTINGS_ID {
|
||||||
let _ = app.emit("openchamber:menu-action", "settings");
|
let _ = app.emit("openchamber:menu-action", "settings");
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -2,9 +2,11 @@ import { defineConfig } from 'vite';
|
|||||||
import react from '@vitejs/plugin-react';
|
import react from '@vitejs/plugin-react';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { fileURLToPath } from 'node:url';
|
import { fileURLToPath } from 'node:url';
|
||||||
|
import { readFileSync } from 'node:fs';
|
||||||
import { themeStoragePlugin } from '../../vite-theme-plugin';
|
import { themeStoragePlugin } from '../../vite-theme-plugin';
|
||||||
|
|
||||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
const packageJson = JSON.parse(readFileSync(path.resolve(__dirname, 'package.json'), 'utf-8'));
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: path.resolve(__dirname, '.'),
|
root: path.resolve(__dirname, '.'),
|
||||||
@@ -23,6 +25,7 @@ export default defineConfig({
|
|||||||
'process.version': JSON.stringify('v20.0.0'),
|
'process.version': JSON.stringify('v20.0.0'),
|
||||||
'process.versions': JSON.stringify({}),
|
'process.versions': JSON.stringify({}),
|
||||||
global: 'globalThis',
|
global: 'globalThis',
|
||||||
|
__APP_VERSION__: JSON.stringify(packageJson.version),
|
||||||
},
|
},
|
||||||
optimizeDeps: {
|
optimizeDeps: {
|
||||||
include: ['@opencode-ai/sdk'],
|
include: ['@opencode-ai/sdk'],
|
||||||
|
|||||||
@@ -18,12 +18,24 @@ import { opencodeClient } from '@/lib/opencode/client';
|
|||||||
import { useFontPreferences } from '@/hooks/useFontPreferences';
|
import { useFontPreferences } from '@/hooks/useFontPreferences';
|
||||||
import { CODE_FONT_OPTION_MAP, DEFAULT_MONO_FONT, DEFAULT_UI_FONT, UI_FONT_OPTION_MAP } from '@/lib/fontOptions';
|
import { CODE_FONT_OPTION_MAP, DEFAULT_MONO_FONT, DEFAULT_UI_FONT, UI_FONT_OPTION_MAP } from '@/lib/fontOptions';
|
||||||
import { ConfigUpdateOverlay } from '@/components/ui/ConfigUpdateOverlay';
|
import { ConfigUpdateOverlay } from '@/components/ui/ConfigUpdateOverlay';
|
||||||
|
import { AboutDialog } from '@/components/ui/AboutDialog';
|
||||||
import { RuntimeAPIProvider } from '@/contexts/RuntimeAPIProvider';
|
import { RuntimeAPIProvider } from '@/contexts/RuntimeAPIProvider';
|
||||||
import { registerRuntimeAPIs } from '@/contexts/runtimeAPIRegistry';
|
import { registerRuntimeAPIs } from '@/contexts/runtimeAPIRegistry';
|
||||||
import { OnboardingScreen } from '@/components/onboarding/OnboardingScreen';
|
import { OnboardingScreen } from '@/components/onboarding/OnboardingScreen';
|
||||||
import { isCliAvailable } from '@/lib/desktop';
|
import { isCliAvailable } from '@/lib/desktop';
|
||||||
|
import { useUIStore } from '@/stores/useUIStore';
|
||||||
import type { RuntimeAPIs } from '@/lib/api/types';
|
import type { RuntimeAPIs } from '@/lib/api/types';
|
||||||
|
|
||||||
|
const AboutDialogWrapper: React.FC = () => {
|
||||||
|
const { isAboutDialogOpen, setAboutDialogOpen } = useUIStore();
|
||||||
|
return (
|
||||||
|
<AboutDialog
|
||||||
|
open={isAboutDialogOpen}
|
||||||
|
onOpenChange={setAboutDialogOpen}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
type AppProps = {
|
type AppProps = {
|
||||||
apis: RuntimeAPIs;
|
apis: RuntimeAPIs;
|
||||||
};
|
};
|
||||||
@@ -200,6 +212,7 @@ function App({ apis }: AppProps) {
|
|||||||
<MainLayout />
|
<MainLayout />
|
||||||
<Toaster />
|
<Toaster />
|
||||||
<ConfigUpdateOverlay />
|
<ConfigUpdateOverlay />
|
||||||
|
<AboutDialogWrapper />
|
||||||
{showMemoryDebug && (
|
{showMemoryDebug && (
|
||||||
<MemoryDebugPanel onClose={() => setShowMemoryDebug(false)} />
|
<MemoryDebugPanel onClose={() => setShowMemoryDebug(false)} />
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { RiDownloadLine, RiSettings3Line } from '@remixicon/react';
|
import { RiDownloadLine, RiInformationLine, RiSettings3Line } from '@remixicon/react';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
import { ErrorBoundary } from '../ui/ErrorBoundary';
|
import { ErrorBoundary } from '../ui/ErrorBoundary';
|
||||||
import { useUIStore } from '@/stores/useUIStore';
|
import { useUIStore } from '@/stores/useUIStore';
|
||||||
import { useUpdateCheck } from '@/hooks/useUpdateCheck';
|
import { useUpdateCheck } from '@/hooks/useUpdateCheck';
|
||||||
import { UpdateDialog } from '../ui/UpdateDialog';
|
import { UpdateDialog } from '../ui/UpdateDialog';
|
||||||
|
import { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip';
|
||||||
|
|
||||||
export const SIDEBAR_CONTENT_WIDTH = 264;
|
export const SIDEBAR_CONTENT_WIDTH = 264;
|
||||||
const SIDEBAR_MIN_WIDTH = 200;
|
const SIDEBAR_MIN_WIDTH = 200;
|
||||||
@@ -20,7 +21,7 @@ interface SidebarProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const Sidebar: React.FC<SidebarProps> = ({ isOpen, isMobile, children }) => {
|
export const Sidebar: React.FC<SidebarProps> = ({ isOpen, isMobile, children }) => {
|
||||||
const { sidebarWidth, setSidebarWidth, setSettingsDialogOpen } = useUIStore();
|
const { sidebarWidth, setSidebarWidth, setSettingsDialogOpen, setAboutDialogOpen } = useUIStore();
|
||||||
const [isResizing, setIsResizing] = React.useState(false);
|
const [isResizing, setIsResizing] = React.useState(false);
|
||||||
const startXRef = React.useRef(0);
|
const startXRef = React.useRef(0);
|
||||||
const startWidthRef = React.useRef(sidebarWidth || SIDEBAR_CONTENT_WIDTH);
|
const startWidthRef = React.useRef(sidebarWidth || SIDEBAR_CONTENT_WIDTH);
|
||||||
@@ -229,7 +230,7 @@ export const Sidebar: React.FC<SidebarProps> = ({ isOpen, isMobile, children })
|
|||||||
<RiSettings3Line className="h-4 w-4" />
|
<RiSettings3Line className="h-4 w-4" />
|
||||||
<span>Settings</span>
|
<span>Settings</span>
|
||||||
</button>
|
</button>
|
||||||
{(available || downloaded) && (
|
{(available || downloaded) ? (
|
||||||
<button
|
<button
|
||||||
onClick={() => setUpdateDialogOpen(true)}
|
onClick={() => setUpdateDialogOpen(true)}
|
||||||
className={cn(
|
className={cn(
|
||||||
@@ -243,6 +244,23 @@ export const Sidebar: React.FC<SidebarProps> = ({ isOpen, isMobile, children })
|
|||||||
<RiDownloadLine className="h-3.5 w-3.5" />
|
<RiDownloadLine className="h-3.5 w-3.5" />
|
||||||
<span>Update</span>
|
<span>Update</span>
|
||||||
</button>
|
</button>
|
||||||
|
) : !isDesktopApp && (
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<button
|
||||||
|
onClick={() => setAboutDialogOpen(true)}
|
||||||
|
className={cn(
|
||||||
|
'flex items-center justify-center rounded-md p-1.5',
|
||||||
|
'text-muted-foreground',
|
||||||
|
'hover:text-foreground hover:bg-muted/50',
|
||||||
|
'transition-colors'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<RiInformationLine className="h-4 w-4" />
|
||||||
|
</button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent side="top">About OpenChamber</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
} from '@/components/ui/dialog';
|
||||||
|
import { OpenChamberLogo } from '@/components/ui/OpenChamberLogo';
|
||||||
|
import { RiGithubFill, RiTwitterXFill } from '@remixicon/react';
|
||||||
|
|
||||||
|
declare const __APP_VERSION__: string | undefined;
|
||||||
|
|
||||||
|
interface AboutDialogProps {
|
||||||
|
open: boolean;
|
||||||
|
onOpenChange: (open: boolean) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AboutDialog: React.FC<AboutDialogProps> = ({
|
||||||
|
open,
|
||||||
|
onOpenChange,
|
||||||
|
}) => {
|
||||||
|
const [version, setVersion] = React.useState<string | null>(null);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!open) return;
|
||||||
|
|
||||||
|
const isDesktop = typeof window !== 'undefined' && !!window.opencodeDesktop;
|
||||||
|
|
||||||
|
if (isDesktop) {
|
||||||
|
const fetchVersion = async () => {
|
||||||
|
try {
|
||||||
|
const { getVersion } = await import('@tauri-apps/api/app');
|
||||||
|
const v = await getVersion();
|
||||||
|
setVersion(v);
|
||||||
|
} catch {
|
||||||
|
setVersion(typeof __APP_VERSION__ !== 'undefined' ? __APP_VERSION__ : null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fetchVersion();
|
||||||
|
} else {
|
||||||
|
setVersion(typeof __APP_VERSION__ !== 'undefined' ? __APP_VERSION__ : null);
|
||||||
|
}
|
||||||
|
}, [open]);
|
||||||
|
|
||||||
|
const displayVersion = version;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||||
|
<DialogContent className="max-w-xs p-6">
|
||||||
|
<div className="flex flex-col items-center text-center space-y-4">
|
||||||
|
<OpenChamberLogo width={64} height={64} />
|
||||||
|
|
||||||
|
<div className="space-y-1">
|
||||||
|
<h2 className="text-lg font-semibold">OpenChamber</h2>
|
||||||
|
{displayVersion && (
|
||||||
|
<p className="typography-meta text-muted-foreground">
|
||||||
|
Version {displayVersion}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p className="typography-meta text-muted-foreground">
|
||||||
|
A beautiful interface for OpenCode AI coding agent
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="flex items-center gap-4 pt-2">
|
||||||
|
<a
|
||||||
|
href="https://github.com/btriapitsyn/openchamber"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="flex items-center gap-1.5 typography-meta text-muted-foreground hover:text-foreground transition-colors"
|
||||||
|
>
|
||||||
|
<RiGithubFill className="h-4 w-4" />
|
||||||
|
<span>GitHub</span>
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="https://x.com/btriapitsyn"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="flex items-center gap-1.5 typography-meta text-muted-foreground hover:text-foreground transition-colors"
|
||||||
|
>
|
||||||
|
<RiTwitterXFill className="h-4 w-4" />
|
||||||
|
<span>@btriapitsyn</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p className="typography-meta text-muted-foreground/60 pt-2">
|
||||||
|
Made with care for developers
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -12,6 +12,7 @@ import { isDesktopRuntime } from '@/lib/desktop';
|
|||||||
const MENU_ACTION_EVENT = 'openchamber:menu-action';
|
const MENU_ACTION_EVENT = 'openchamber:menu-action';
|
||||||
|
|
||||||
type MenuAction =
|
type MenuAction =
|
||||||
|
| 'about'
|
||||||
| 'settings'
|
| 'settings'
|
||||||
| 'command-palette'
|
| 'command-palette'
|
||||||
| 'new-session'
|
| 'new-session'
|
||||||
@@ -39,6 +40,7 @@ export const useMenuActions = (
|
|||||||
setSessionCreateDialogOpen,
|
setSessionCreateDialogOpen,
|
||||||
setActiveMainTab,
|
setActiveMainTab,
|
||||||
setSettingsDialogOpen,
|
setSettingsDialogOpen,
|
||||||
|
setAboutDialogOpen,
|
||||||
} = useUIStore();
|
} = useUIStore();
|
||||||
const { agents } = useConfigStore();
|
const { agents } = useConfigStore();
|
||||||
const { setDirectory } = useDirectoryStore();
|
const { setDirectory } = useDirectoryStore();
|
||||||
@@ -72,6 +74,10 @@ export const useMenuActions = (
|
|||||||
const action = (event as CustomEvent<MenuAction>).detail;
|
const action = (event as CustomEvent<MenuAction>).detail;
|
||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
|
case 'about':
|
||||||
|
setAboutDialogOpen(true);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'settings':
|
case 'settings':
|
||||||
setSettingsDialogOpen(true);
|
setSettingsDialogOpen(true);
|
||||||
break;
|
break;
|
||||||
@@ -185,6 +191,7 @@ export const useMenuActions = (
|
|||||||
setSessionCreateDialogOpen,
|
setSessionCreateDialogOpen,
|
||||||
setActiveMainTab,
|
setActiveMainTab,
|
||||||
setSettingsDialogOpen,
|
setSettingsDialogOpen,
|
||||||
|
setAboutDialogOpen,
|
||||||
setThemeMode,
|
setThemeMode,
|
||||||
agents,
|
agents,
|
||||||
onToggleMemoryDebug,
|
onToggleMemoryDebug,
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ interface UIStore {
|
|||||||
isMobile: boolean;
|
isMobile: boolean;
|
||||||
isCommandPaletteOpen: boolean;
|
isCommandPaletteOpen: boolean;
|
||||||
isHelpDialogOpen: boolean;
|
isHelpDialogOpen: boolean;
|
||||||
|
isAboutDialogOpen: boolean;
|
||||||
isSessionCreateDialogOpen: boolean;
|
isSessionCreateDialogOpen: boolean;
|
||||||
isSettingsDialogOpen: boolean;
|
isSettingsDialogOpen: boolean;
|
||||||
sidebarSection: SidebarSection;
|
sidebarSection: SidebarSection;
|
||||||
@@ -58,6 +59,7 @@ interface UIStore {
|
|||||||
setCommandPaletteOpen: (open: boolean) => void;
|
setCommandPaletteOpen: (open: boolean) => void;
|
||||||
toggleHelpDialog: () => void;
|
toggleHelpDialog: () => void;
|
||||||
setHelpDialogOpen: (open: boolean) => void;
|
setHelpDialogOpen: (open: boolean) => void;
|
||||||
|
setAboutDialogOpen: (open: boolean) => void;
|
||||||
setSessionCreateDialogOpen: (open: boolean) => void;
|
setSessionCreateDialogOpen: (open: boolean) => void;
|
||||||
setSettingsDialogOpen: (open: boolean) => void;
|
setSettingsDialogOpen: (open: boolean) => void;
|
||||||
applyTheme: () => void;
|
applyTheme: () => void;
|
||||||
@@ -93,6 +95,7 @@ export const useUIStore = create<UIStore>()(
|
|||||||
isMobile: false,
|
isMobile: false,
|
||||||
isCommandPaletteOpen: false,
|
isCommandPaletteOpen: false,
|
||||||
isHelpDialogOpen: false,
|
isHelpDialogOpen: false,
|
||||||
|
isAboutDialogOpen: false,
|
||||||
isSessionCreateDialogOpen: false,
|
isSessionCreateDialogOpen: false,
|
||||||
isSettingsDialogOpen: false,
|
isSettingsDialogOpen: false,
|
||||||
sidebarSection: 'sessions',
|
sidebarSection: 'sessions',
|
||||||
@@ -192,6 +195,10 @@ export const useUIStore = create<UIStore>()(
|
|||||||
set({ isHelpDialogOpen: open });
|
set({ isHelpDialogOpen: open });
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setAboutDialogOpen: (open) => {
|
||||||
|
set({ isAboutDialogOpen: open });
|
||||||
|
},
|
||||||
|
|
||||||
setSessionCreateDialogOpen: (open) => {
|
setSessionCreateDialogOpen: (open) => {
|
||||||
set({ isSessionCreateDialogOpen: open });
|
set({ isSessionCreateDialogOpen: open });
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,9 +2,11 @@ import { defineConfig } from 'vite';
|
|||||||
import react from '@vitejs/plugin-react';
|
import react from '@vitejs/plugin-react';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { fileURLToPath } from 'node:url';
|
import { fileURLToPath } from 'node:url';
|
||||||
|
import { readFileSync } from 'node:fs';
|
||||||
import { themeStoragePlugin } from '../../vite-theme-plugin';
|
import { themeStoragePlugin } from '../../vite-theme-plugin';
|
||||||
|
|
||||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
const packageJson = JSON.parse(readFileSync(path.resolve(__dirname, 'package.json'), 'utf-8'));
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: path.resolve(__dirname, '.'),
|
root: path.resolve(__dirname, '.'),
|
||||||
@@ -23,6 +25,7 @@ export default defineConfig({
|
|||||||
define: {
|
define: {
|
||||||
'process.env': {},
|
'process.env': {},
|
||||||
global: 'globalThis',
|
global: 'globalThis',
|
||||||
|
__APP_VERSION__: JSON.stringify(packageJson.version),
|
||||||
},
|
},
|
||||||
optimizeDeps: {
|
optimizeDeps: {
|
||||||
include: ['@opencode-ai/sdk'],
|
include: ['@opencode-ai/sdk'],
|
||||||
|
|||||||
Reference in New Issue
Block a user