Skip to content

Commit 23706d4

Browse files
committed
useAppsettings hook for message input appearance, cleanup unused stuff
1 parent 8a072c0 commit 23706d4

File tree

3 files changed

+10
-113
lines changed

3 files changed

+10
-113
lines changed

src/app/layout.tsx

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { Metadata } from "next";
2-
import { Geist, Geist_Mono, Inter } from "next/font/google";
2+
import { Geist, Geist_Mono } from "next/font/google";
33
import "./globals.css";
44
import { ThemeProvider } from "@/components/layout/ThemeProvider";
55
import { I18nProvider } from "@/components/layout/I18nProvider";
@@ -16,11 +16,6 @@ const geistMono = Geist_Mono({
1616
subsets: ["latin"],
1717
});
1818

19-
const inter = Inter({
20-
variable: "--font-inter",
21-
subsets: ["latin"],
22-
});
23-
2419
export const metadata: Metadata = {
2520
title: "CodePilot",
2621
description: "A desktop GUI for Claude Code",
@@ -34,7 +29,7 @@ export default function RootLayout({
3429
return (
3530
<html lang="en" suppressHydrationWarning>
3631
<body
37-
className={`${geistSans.variable} ${geistMono.variable} ${inter.variable} antialiased`}
32+
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
3833
>
3934
<ThemeProvider>
4035
<AppearanceProvider>

src/components/chat/MessageInput.tsx

Lines changed: 4 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
} from "@hugeicons/core-free-icons";
2323
import { cn } from '@/lib/utils';
2424
import { useTranslation } from '@/hooks/useTranslation';
25+
import { useAppSettings } from '@/hooks/useAppSettings';
2526
import type { TranslationKey } from '@/i18n';
2627
import {
2728
PromptInput,
@@ -400,53 +401,13 @@ export function MessageInput({
400401
const [aiSearchLoading, setAiSearchLoading] = useState(false);
401402
const aiSearchAbortRef = useRef<AbortController | null>(null);
402403
const aiSearchTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
403-
const [showModeSelector, setShowModeSelector] = useState<boolean | null>(null);
404-
const [showImageAgent, setShowImageAgent] = useState<boolean | null>(null);
405404
const onModeChangeRef = useRef(onModeChange);
406405
onModeChangeRef.current = onModeChange;
407406
const modeRef = useRef(mode);
408407
modeRef.current = mode;
409-
410-
useEffect(() => {
411-
const controller = new AbortController();
412-
let superseded = false;
413-
414-
// Initial fetch
415-
fetch('/api/settings/app', { signal: controller.signal })
416-
.then(res => res.ok ? res.json() : null)
417-
.then(data => {
418-
if (superseded) return;
419-
if (data?.settings) {
420-
const show = data.settings.show_mode_selector !== 'false';
421-
setShowModeSelector(show);
422-
if (!show && modeRef.current !== 'code') onModeChangeRef.current?.('code');
423-
setShowImageAgent(data.settings.show_image_agent !== 'false');
424-
} else {
425-
setShowModeSelector(true);
426-
setShowImageAgent(true);
427-
}
428-
})
429-
.catch(() => {});
430-
431-
// Listen for settings changes from GeneralSection
432-
const handleSettingsChanged = (e: Event) => {
433-
superseded = true;
434-
const detail = (e as CustomEvent).detail;
435-
if (detail?.show_mode_selector !== undefined) {
436-
const show = detail.show_mode_selector !== 'false';
437-
setShowModeSelector(show);
438-
if (!show && modeRef.current !== 'code') onModeChangeRef.current?.('code');
439-
}
440-
if (detail?.show_image_agent !== undefined) {
441-
setShowImageAgent(detail.show_image_agent !== 'false');
442-
}
443-
};
444-
window.addEventListener('settings-changed', handleSettingsChanged);
445-
return () => {
446-
controller.abort();
447-
window.removeEventListener('settings-changed', handleSettingsChanged);
448-
};
449-
}, []);
408+
const { showModeSelector, showImageAgent } = useAppSettings(
409+
(show) => { if (!show && modeRef.current !== 'code') onModeChangeRef.current?.('code'); },
410+
);
450411

451412
// Fetch provider groups from API
452413
const fetchProviderModels = useCallback(() => {

src/components/settings/AppearanceSection.tsx

Lines changed: 4 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use client';
22

3-
import { useState, useCallback, useEffect } from 'react';
43
import { useAppearance } from '@/hooks/useAppearance';
4+
import { useAppSettings } from '@/hooks/useAppSettings';
55
import { useTranslation } from '@/hooks/useTranslation';
66
import {
77
FONT_SIZES,
@@ -20,70 +20,11 @@ const FONT_SIZE_LABELS: Record<FontSizeKey, TranslationKey> = {
2020

2121
export function AppearanceSection() {
2222
const { fontSize, setFontSize } = useAppearance();
23+
const { showModeSelector, showImageAgent, saveShowModeSelector, saveShowImageAgent } = useAppSettings();
2324
const { t } = useTranslation();
24-
const [showModeSelector, setShowModeSelector] = useState(true);
25-
const [showImageAgent, setShowImageAgent] = useState(true);
2625

2726
const fontSizeKeys = Object.keys(FONT_SIZES) as FontSizeKey[];
2827

29-
const fetchAppSettings = useCallback(async () => {
30-
try {
31-
const res = await fetch('/api/settings/app');
32-
if (res.ok) {
33-
const data = await res.json();
34-
const appSettings = data.settings || {};
35-
setShowModeSelector(appSettings.show_mode_selector !== 'false');
36-
setShowImageAgent(appSettings.show_image_agent !== 'false');
37-
}
38-
} catch {
39-
// ignore
40-
}
41-
}, []);
42-
43-
useEffect(() => {
44-
fetchAppSettings();
45-
}, [fetchAppSettings]);
46-
47-
const saveShowImageAgent = async (enabled: boolean) => {
48-
try {
49-
const res = await fetch('/api/settings/app', {
50-
method: 'PUT',
51-
headers: { 'Content-Type': 'application/json' },
52-
body: JSON.stringify({
53-
settings: { show_image_agent: enabled ? 'true' : 'false' },
54-
}),
55-
});
56-
if (res.ok) {
57-
setShowImageAgent(enabled);
58-
window.dispatchEvent(new CustomEvent('settings-changed', {
59-
detail: { show_image_agent: enabled ? 'true' : 'false' },
60-
}));
61-
}
62-
} catch {
63-
// ignore
64-
}
65-
};
66-
67-
const saveShowModeSelector = async (enabled: boolean) => {
68-
try {
69-
const res = await fetch('/api/settings/app', {
70-
method: 'PUT',
71-
headers: { 'Content-Type': 'application/json' },
72-
body: JSON.stringify({
73-
settings: { show_mode_selector: enabled ? 'true' : 'false' },
74-
}),
75-
});
76-
if (res.ok) {
77-
setShowModeSelector(enabled);
78-
window.dispatchEvent(new CustomEvent('settings-changed', {
79-
detail: { show_mode_selector: enabled ? 'true' : 'false' },
80-
}));
81-
}
82-
} catch {
83-
// ignore
84-
}
85-
};
86-
8728
return (
8829
<div className="max-w-3xl space-y-6">
8930
{/* Mode selector toggle */}
@@ -94,7 +35,7 @@ export function AppearanceSection() {
9435
<p className="text-xs text-muted-foreground">{t('settings.showModeSelectorDesc')}</p>
9536
</div>
9637
<Switch
97-
checked={showModeSelector}
38+
checked={showModeSelector ?? false}
9839
onCheckedChange={saveShowModeSelector}
9940
/>
10041
</div>
@@ -108,7 +49,7 @@ export function AppearanceSection() {
10849
<p className="text-xs text-muted-foreground">{t('settings.showImageAgentDesc')}</p>
10950
</div>
11051
<Switch
111-
checked={showImageAgent}
52+
checked={showImageAgent ?? false}
11253
onCheckedChange={saveShowImageAgent}
11354
/>
11455
</div>

0 commit comments

Comments
 (0)