diff --git a/app/ui_layer/browser/frontend/src/pages/Chat/ChatPage.tsx b/app/ui_layer/browser/frontend/src/pages/Chat/ChatPage.tsx index 4cd82c8d..85552659 100644 --- a/app/ui_layer/browser/frontend/src/pages/Chat/ChatPage.tsx +++ b/app/ui_layer/browser/frontend/src/pages/Chat/ChatPage.tsx @@ -14,6 +14,12 @@ const DEFAULT_PANEL_WIDTH = 460 const MIN_PANEL_WIDTH = 200 const MAX_PANEL_WIDTH = 800 + +const PANEL_WIDTH_STORAGE_KEY = 'craftbot-chat-panel-width' + +const clampPanelWidth = (width: number) => + Math.min(Math.max(width, MIN_PANEL_WIDTH), MAX_PANEL_WIDTH) + export function ChatPage() { const { actions, @@ -45,9 +51,22 @@ export function ChatPage() { }, [messages]) // Resizable panel state - const [panelWidth, setPanelWidth] = useState(DEFAULT_PANEL_WIDTH) + const [panelWidth, setPanelWidth] = useState(()=> { + const stored = localStorage.getItem(PANEL_WIDTH_STORAGE_KEY) + if(stored == null) { + return DEFAULT_PANEL_WIDTH + } + const width = Number(stored) + if (Number.isNaN(width)) { + return DEFAULT_PANEL_WIDTH + } + return clampPanelWidth(width) + }) + const [isResizing, setIsResizing] = useState(false) const containerRef = useRef(null) + const panelWidthRef = useRef(panelWidth) + // Handle resize drag const handleMouseDown = useCallback((e: React.MouseEvent) => { @@ -55,6 +74,11 @@ export function ChatPage() { setIsResizing(true) }, []) + useEffect(() => { + panelWidthRef.current = panelWidth + + }, [panelWidth]) + useEffect(() => { if (!isResizing) return @@ -62,11 +86,16 @@ export function ChatPage() { if (!containerRef.current) return const containerRect = containerRef.current.getBoundingClientRect() const newWidth = containerRect.right - e.clientX - const clampedWidth = Math.min(Math.max(newWidth, MIN_PANEL_WIDTH), MAX_PANEL_WIDTH) + const clampedWidth = clampPanelWidth(newWidth) setPanelWidth(clampedWidth) } const handleMouseUp = () => { + localStorage.setItem( + PANEL_WIDTH_STORAGE_KEY, + panelWidthRef.current.toString() + ) + setIsResizing(false) } diff --git a/app/ui_layer/browser/frontend/src/pages/LivingUI/LivingUIPage.tsx b/app/ui_layer/browser/frontend/src/pages/LivingUI/LivingUIPage.tsx index 6a5844f7..93e532a4 100644 --- a/app/ui_layer/browser/frontend/src/pages/LivingUI/LivingUIPage.tsx +++ b/app/ui_layer/browser/frontend/src/pages/LivingUI/LivingUIPage.tsx @@ -74,6 +74,7 @@ export function LivingUIPage() { const { theme: appTheme } = useTheme() const dispatch = useAppDispatch() const pendingQuestions = useAppSelector(selectLivingUiPendingQuestions) + const SHOW_CHAT_STORAGE_KEY = 'craftbot-living-ui-show-chat' const [showDeleteModal, setShowDeleteModal] = useState(false) const [showThemeModal, setShowThemeModal] = useState(false) @@ -83,7 +84,14 @@ export function LivingUIPage() { const [livingUICustomColors, setLivingUICustomColors] = useState( () => (projectId ? loadLivingUICustomColors(projectId) : { ...DEFAULT_CUSTOM_COLORS }) ) - const [showChat, setShowChat] = useState(true) + // const [showChat, setShowChat] = useState(true) + const [showChat, setShowChat] = useState(()=> { + const stored = localStorage.getItem(SHOW_CHAT_STORAGE_KEY) + if (stored == null) { + return true + } + return stored === 'true' + }) const [panelWidth, setPanelWidth] = useState(350) const [mobileChatRatio, setMobileChatRatio] = useState(0.4) const [isMobile, setIsMobile] = useState( @@ -93,6 +101,13 @@ export function LivingUIPage() { const iframePlaceholderRef = useRef(null) const contentRef = useRef(null) + useEffect(() => { + localStorage.setItem( + SHOW_CHAT_STORAGE_KEY, + showChat.toString() + ) + }, [showChat]) + // Track viewport width for mobile/desktop layout switch useEffect(() => { const onResize = () => setIsMobile(window.innerWidth <= 768)