mirror of
https://github.com/browseros-ai/BrowserOS.git
synced 2026-05-13 23:53:25 +00:00
feat: customisation page (#178)
* feat: v1 prefs page * feat: customisation updates
This commit is contained in:
@@ -2,6 +2,7 @@ import type { FC } from 'react'
|
||||
import { HashRouter, Navigate, Route, Routes } from 'react-router'
|
||||
import { AISettingsPage } from './ai-settings/AISettingsPage'
|
||||
import { ConnectMCP } from './connect-mcp/ConnectMCP'
|
||||
import { CustomizationPage } from './customization/CustomizationPage'
|
||||
import { DashboardLayout } from './layout/DashboardLayout'
|
||||
import { LlmHubPage } from './llm-hub/LlmHubPage'
|
||||
import { MCPSettingsPage } from './mcp-settings/MCPSettingsPage'
|
||||
@@ -18,6 +19,7 @@ export const App: FC = () => {
|
||||
<Route path="search" element={null} />
|
||||
<Route path="connect-mcp" element={<ConnectMCP />} />
|
||||
<Route path="mcp" element={<MCPSettingsPage />} />
|
||||
<Route path="customization" element={<CustomizationPage />} />
|
||||
<Route
|
||||
path="onboarding"
|
||||
element={<AISettingsPage key="onboarding" />}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { Palette } from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
|
||||
export const CustomizationHeader: FC = () => {
|
||||
return (
|
||||
<div className="rounded-xl border border-border bg-card p-6 shadow-sm transition-all hover:shadow-md">
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="flex h-12 w-12 shrink-0 items-center justify-center rounded-xl bg-[var(--accent-orange)]/10">
|
||||
<Palette className="h-6 w-6 text-[var(--accent-orange)]" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h2 className="mb-1 font-semibold text-xl">Customization</h2>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
Personalize your toolbar and browser interface
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import type { FC } from 'react'
|
||||
import { CustomizationHeader } from './CustomizationHeader'
|
||||
import { ToolbarSettingsCard } from './ToolbarSettingsCard'
|
||||
|
||||
export const CustomizationPage: FC = () => {
|
||||
return (
|
||||
<div className="fade-in slide-in-from-bottom-5 animate-in space-y-6 duration-500">
|
||||
<CustomizationHeader />
|
||||
<ToolbarSettingsCard />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
import { type FC, useEffect, useState } from 'react'
|
||||
import { toast } from 'sonner'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { Switch } from '@/components/ui/switch'
|
||||
import { getBrowserOSAdapter } from '@/lib/browseros/adapter'
|
||||
import { BROWSEROS_PREFS } from '@/lib/browseros/prefs'
|
||||
|
||||
export const ToolbarSettingsCard: FC = () => {
|
||||
const [showLlmChat, setShowLlmChat] = useState(true)
|
||||
const [showLlmHub, setShowLlmHub] = useState(true)
|
||||
const [showToolbarLabels, setShowToolbarLabels] = useState(true)
|
||||
const [isLoading, setIsLoading] = useState(true)
|
||||
|
||||
useEffect(() => {
|
||||
const loadPrefs = async () => {
|
||||
try {
|
||||
const adapter = getBrowserOSAdapter()
|
||||
const [chatPref, hubPref, labelsPref] = await Promise.all([
|
||||
adapter.getPref(BROWSEROS_PREFS.SHOW_LLM_CHAT),
|
||||
adapter.getPref(BROWSEROS_PREFS.SHOW_LLM_HUB),
|
||||
adapter.getPref(BROWSEROS_PREFS.SHOW_TOOLBAR_LABELS),
|
||||
])
|
||||
setShowLlmChat(chatPref?.value !== false)
|
||||
setShowLlmHub(hubPref?.value !== false)
|
||||
setShowToolbarLabels(labelsPref?.value !== false)
|
||||
} catch {
|
||||
// API not available - use defaults
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
loadPrefs()
|
||||
}, [])
|
||||
|
||||
const handleToggle = async (
|
||||
prefKey: string,
|
||||
value: boolean,
|
||||
setter: (v: boolean) => void,
|
||||
) => {
|
||||
try {
|
||||
const adapter = getBrowserOSAdapter()
|
||||
await adapter.setPref(prefKey, value)
|
||||
setter(value)
|
||||
} catch {
|
||||
toast.error('Failed to update setting')
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="rounded-xl border border-border bg-card p-6 shadow-sm transition-all hover:shadow-md">
|
||||
<h3 className="mb-4 font-semibold text-lg">Toolbar Settings</h3>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="space-y-0.5">
|
||||
<Label htmlFor="show-llm-chat" className="font-medium text-sm">
|
||||
Show Chat Button
|
||||
</Label>
|
||||
<p className="text-muted-foreground text-xs">
|
||||
Display the Chat button in the browser toolbar
|
||||
</p>
|
||||
</div>
|
||||
<Switch
|
||||
id="show-llm-chat"
|
||||
checked={showLlmChat}
|
||||
onCheckedChange={(checked) =>
|
||||
handleToggle(
|
||||
BROWSEROS_PREFS.SHOW_LLM_CHAT,
|
||||
checked,
|
||||
setShowLlmChat,
|
||||
)
|
||||
}
|
||||
disabled={isLoading}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="space-y-0.5">
|
||||
<Label htmlFor="show-llm-hub" className="font-medium text-sm">
|
||||
Show Hub Button
|
||||
</Label>
|
||||
<p className="text-muted-foreground text-xs">
|
||||
Display the Hub button in the browser toolbar
|
||||
</p>
|
||||
</div>
|
||||
<Switch
|
||||
id="show-llm-hub"
|
||||
checked={showLlmHub}
|
||||
onCheckedChange={(checked) =>
|
||||
handleToggle(BROWSEROS_PREFS.SHOW_LLM_HUB, checked, setShowLlmHub)
|
||||
}
|
||||
disabled={isLoading}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between border-border border-t pt-4">
|
||||
<div className="space-y-0.5">
|
||||
<Label
|
||||
htmlFor="show-toolbar-labels"
|
||||
className="font-medium text-sm"
|
||||
>
|
||||
Show Button Labels
|
||||
</Label>
|
||||
<p className="text-muted-foreground text-xs">
|
||||
Display text labels next to toolbar button icons
|
||||
</p>
|
||||
</div>
|
||||
<Switch
|
||||
id="show-toolbar-labels"
|
||||
checked={showToolbarLabels}
|
||||
onCheckedChange={(checked) =>
|
||||
handleToggle(
|
||||
BROWSEROS_PREFS.SHOW_TOOLBAR_LABELS,
|
||||
checked,
|
||||
setShowToolbarLabels,
|
||||
)
|
||||
}
|
||||
disabled={isLoading}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
type LucideIcon,
|
||||
Menu,
|
||||
MessageSquare,
|
||||
Palette,
|
||||
PlugZap,
|
||||
RotateCcw,
|
||||
Search,
|
||||
@@ -65,6 +66,12 @@ const navigationItems: NavItem[] = [
|
||||
icon: Server,
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
name: 'Customization',
|
||||
to: '/customization',
|
||||
icon: Palette,
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
name: 'Revisit Onboarding',
|
||||
to: chrome.runtime.getURL('onboarding.html'),
|
||||
|
||||
@@ -6,4 +6,7 @@ export const BROWSEROS_PREFS = {
|
||||
THIRD_PARTY_LLM_PROVIDERS: 'browseros.third_party_llm.providers',
|
||||
ALLOW_REMOTE_MCP: 'browseros.server.allow_remote_in_mcp',
|
||||
RESTART_SERVER: 'browseros.server.restart_requested',
|
||||
SHOW_LLM_CHAT: 'browseros.show_llm_chat',
|
||||
SHOW_LLM_HUB: 'browseros.show_llm_hub',
|
||||
SHOW_TOOLBAR_LABELS: 'browseros.show_toolbar_labels',
|
||||
} as const
|
||||
|
||||
Reference in New Issue
Block a user