Add Windows support notice modal for Windows users on startup

Shows a modal on first launch for Windows users explaining that Windows
support is actively being improved. Features:
- Inline toggle to enable beta updates for latest bug fixes
- Link to report issues on GitHub (with note that vetted PRs welcome)
- Link to join Discord Windows-specific channel for community support
- Create Debug Package button for easy bug reporting
- Checkbox to suppress the modal for future sessions
- Console debug function: window.__showWindowsWarningModal()
This commit is contained in:
Pedram Amini
2026-02-04 17:33:54 -06:00
parent 21f1bbdec3
commit 60fc0fc5da
6 changed files with 587 additions and 0 deletions

View File

@@ -0,0 +1,250 @@
/**
* Tests for WindowsWarningModal component
*
* Tests the core behavior of the Windows warning dialog:
* - Rendering with correct content
* - Button click handlers
* - Suppress checkbox functionality
* - Debug function exposure
*/
import React from 'react';
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { WindowsWarningModal, exposeWindowsWarningModalDebug } from '../../../renderer/components/WindowsWarningModal';
import { LayerStackProvider } from '../../../renderer/contexts/LayerStackContext';
import type { Theme } from '../../../renderer/types';
// Mock lucide-react
vi.mock('lucide-react', () => ({
X: () => <svg data-testid="x-icon" />,
AlertTriangle: () => <svg data-testid="alert-triangle-icon" />,
Bug: () => <svg data-testid="bug-icon" />,
Wrench: () => <svg data-testid="wrench-icon" />,
ExternalLink: () => <svg data-testid="external-link-icon" />,
Command: () => <svg data-testid="command-icon" />,
Check: () => <svg data-testid="check-icon" />,
MessageCircle: () => <svg data-testid="message-circle-icon" />,
}));
// Create a test theme
const testTheme: Theme = {
id: 'test-theme',
name: 'Test Theme',
mode: 'dark',
colors: {
bgMain: '#1e1e1e',
bgSidebar: '#252526',
bgActivity: '#333333',
textMain: '#d4d4d4',
textDim: '#808080',
accent: '#007acc',
border: '#404040',
error: '#f14c4c',
warning: '#cca700',
success: '#89d185',
info: '#3794ff',
textInverse: '#000000',
accentForeground: '#ffffff',
},
};
// Helper to render with LayerStackProvider
const renderWithLayerStack = (ui: React.ReactElement) => {
return render(<LayerStackProvider>{ui}</LayerStackProvider>);
};
describe('WindowsWarningModal', () => {
const defaultProps = {
theme: testTheme,
isOpen: true,
onClose: vi.fn(),
onSuppressFuture: vi.fn(),
onOpenDebugPackage: vi.fn(),
useBetaChannel: false,
onSetUseBetaChannel: vi.fn(),
};
beforeEach(() => {
vi.clearAllMocks();
// Mock shell.openExternal for this test suite
vi.mocked(window.maestro.shell.openExternal).mockResolvedValue(undefined);
});
afterEach(() => {
vi.restoreAllMocks();
});
describe('rendering', () => {
it('renders when isOpen is true', () => {
renderWithLayerStack(<WindowsWarningModal {...defaultProps} />);
expect(screen.getByText('Windows Support Notice')).toBeInTheDocument();
});
it('does not render when isOpen is false', () => {
renderWithLayerStack(<WindowsWarningModal {...defaultProps} isOpen={false} />);
expect(screen.queryByText('Windows Support Notice')).not.toBeInTheDocument();
});
it('displays recommendations section', () => {
renderWithLayerStack(<WindowsWarningModal {...defaultProps} />);
expect(screen.getByText('Recommendations')).toBeInTheDocument();
expect(screen.getByText('Enable Beta Updates')).toBeInTheDocument();
expect(screen.getByText('Report Issues')).toBeInTheDocument();
expect(screen.getByText('Join Discord')).toBeInTheDocument();
expect(screen.getByText('Create Debug Package')).toBeInTheDocument();
});
it('displays suppress checkbox', () => {
renderWithLayerStack(<WindowsWarningModal {...defaultProps} />);
expect(screen.getByText("Don't show this message again")).toBeInTheDocument();
});
it('displays Got it! button', () => {
renderWithLayerStack(<WindowsWarningModal {...defaultProps} />);
expect(screen.getByRole('button', { name: 'Got it!' })).toBeInTheDocument();
});
});
describe('button handlers', () => {
it('calls onClose when Got it! button is clicked', () => {
const onClose = vi.fn();
renderWithLayerStack(<WindowsWarningModal {...defaultProps} onClose={onClose} />);
fireEvent.click(screen.getByRole('button', { name: 'Got it!' }));
expect(onClose).toHaveBeenCalledTimes(1);
});
it('calls onClose when X button is clicked', () => {
const onClose = vi.fn();
renderWithLayerStack(<WindowsWarningModal {...defaultProps} onClose={onClose} />);
// Find the X icon and click its parent button
const closeButton = screen.getByTestId('x-icon').closest('button');
fireEvent.click(closeButton!);
expect(onClose).toHaveBeenCalledTimes(1);
});
it('calls onSetUseBetaChannel with true when Enable Beta Updates is clicked', () => {
const onSetUseBetaChannel = vi.fn();
renderWithLayerStack(<WindowsWarningModal {...defaultProps} useBetaChannel={false} onSetUseBetaChannel={onSetUseBetaChannel} />);
fireEvent.click(screen.getByText('Enable Beta Updates'));
expect(onSetUseBetaChannel).toHaveBeenCalledWith(true);
});
it('calls onSetUseBetaChannel with false when Beta Updates toggle is clicked while enabled', () => {
const onSetUseBetaChannel = vi.fn();
renderWithLayerStack(<WindowsWarningModal {...defaultProps} useBetaChannel={true} onSetUseBetaChannel={onSetUseBetaChannel} />);
fireEvent.click(screen.getByText('Enable Beta Updates'));
expect(onSetUseBetaChannel).toHaveBeenCalledWith(false);
});
it('opens GitHub issues when Report Issues is clicked', () => {
renderWithLayerStack(<WindowsWarningModal {...defaultProps} />);
fireEvent.click(screen.getByText('Report Issues'));
expect(window.maestro.shell.openExternal).toHaveBeenCalledWith('https://github.com/pedramamini/Maestro/issues');
});
it('opens Discord when Join Discord is clicked', () => {
renderWithLayerStack(<WindowsWarningModal {...defaultProps} />);
fireEvent.click(screen.getByText('Join Discord'));
expect(window.maestro.shell.openExternal).toHaveBeenCalledWith('https://discord.gg/FCAh4EWzfD');
});
it('calls onOpenDebugPackage when Create Debug Package is clicked', () => {
const onOpenDebugPackage = vi.fn();
renderWithLayerStack(<WindowsWarningModal {...defaultProps} onOpenDebugPackage={onOpenDebugPackage} />);
fireEvent.click(screen.getByText('Create Debug Package'));
expect(onOpenDebugPackage).toHaveBeenCalledTimes(1);
});
});
describe('suppress checkbox', () => {
it('checkbox is unchecked by default', () => {
renderWithLayerStack(<WindowsWarningModal {...defaultProps} />);
const checkbox = screen.getByRole('checkbox');
expect(checkbox).not.toBeChecked();
});
it('checkbox can be toggled', () => {
renderWithLayerStack(<WindowsWarningModal {...defaultProps} />);
const checkbox = screen.getByRole('checkbox');
fireEvent.click(checkbox);
expect(checkbox).toBeChecked();
});
it('calls onSuppressFuture with false when closed without checking', () => {
const onSuppressFuture = vi.fn();
renderWithLayerStack(<WindowsWarningModal {...defaultProps} onSuppressFuture={onSuppressFuture} />);
fireEvent.click(screen.getByRole('button', { name: 'Got it!' }));
expect(onSuppressFuture).toHaveBeenCalledWith(false);
});
it('calls onSuppressFuture with true when closed with checkbox checked', () => {
const onSuppressFuture = vi.fn();
renderWithLayerStack(<WindowsWarningModal {...defaultProps} onSuppressFuture={onSuppressFuture} />);
// Check the checkbox first
fireEvent.click(screen.getByRole('checkbox'));
// Then close
fireEvent.click(screen.getByRole('button', { name: 'Got it!' }));
expect(onSuppressFuture).toHaveBeenCalledWith(true);
});
});
describe('focus management', () => {
it('focuses Got it! button on mount', async () => {
renderWithLayerStack(<WindowsWarningModal {...defaultProps} />);
await waitFor(() => {
expect(document.activeElement).toBe(screen.getByRole('button', { name: 'Got it!' }));
});
});
});
describe('accessibility', () => {
it('has correct ARIA attributes on dialog', () => {
renderWithLayerStack(<WindowsWarningModal {...defaultProps} />);
const dialog = screen.getByRole('dialog');
expect(dialog).toHaveAttribute('aria-modal', 'true');
expect(dialog).toHaveAttribute('aria-label', 'Windows Support Notice');
});
it('has tabIndex on dialog for focus', () => {
renderWithLayerStack(<WindowsWarningModal {...defaultProps} />);
expect(screen.getByRole('dialog')).toHaveAttribute('tabIndex', '-1');
});
});
describe('exposeWindowsWarningModalDebug', () => {
it('exposes __showWindowsWarningModal function to window', () => {
const setShowModal = vi.fn();
exposeWindowsWarningModalDebug(setShowModal);
expect((window as any).__showWindowsWarningModal).toBeDefined();
});
it('calls setShowModal with true when __showWindowsWarningModal is invoked', () => {
const setShowModal = vi.fn();
exposeWindowsWarningModalDebug(setShowModal);
(window as any).__showWindowsWarningModal();
expect(setShowModal).toHaveBeenCalledWith(true);
});
});
});

View File

@@ -29,6 +29,7 @@ import { AppOverlays } from './components/AppOverlays';
import { PlaygroundPanel } from './components/PlaygroundPanel';
import { DebugWizardModal } from './components/DebugWizardModal';
import { DebugPackageModal } from './components/DebugPackageModal';
import { WindowsWarningModal, exposeWindowsWarningModalDebug } from './components/WindowsWarningModal';
import { GistPublishModal, type GistInfo } from './components/GistPublishModal';
import {
MaestroWizard,
@@ -312,6 +313,9 @@ function MaestroConsoleInner() {
// Debug Package Modal
debugPackageModalOpen,
setDebugPackageModalOpen,
// Windows Warning Modal
windowsWarningModalOpen,
setWindowsWarningModalOpen,
// Confirmation Modal
confirmModalOpen,
setConfirmModalOpen,
@@ -571,6 +575,10 @@ function MaestroConsoleInner() {
// File tab refresh settings
fileTabAutoRefreshEnabled,
// Windows warning suppression
suppressWindowsWarning,
setSuppressWindowsWarning,
} = settings;
// --- KEYBOARD SHORTCUT HELPERS ---
@@ -1392,6 +1400,31 @@ function MaestroConsoleInner() {
});
}, []);
// Show Windows warning modal on startup for Windows users (if not suppressed)
// Also expose a debug function to trigger the modal from console for testing
useEffect(() => {
// Expose debug function regardless of platform (for testing)
exposeWindowsWarningModalDebug(setWindowsWarningModalOpen);
// Only check platform when settings have loaded (so we know suppress preference)
if (!settingsLoaded) return;
// Skip if user has suppressed the warning
if (suppressWindowsWarning) return;
// Check if running on Windows using the power API (has platform info)
window.maestro.power
.getStatus()
.then((status) => {
if (status.platform === 'win32') {
setWindowsWarningModalOpen(true);
}
})
.catch((error) => {
console.error('[App] Failed to detect platform for Windows warning:', error);
});
}, [settingsLoaded, suppressWindowsWarning, setWindowsWarningModalOpen]);
// Load file gist URLs from settings on startup
useEffect(() => {
window.maestro.settings
@@ -13746,6 +13779,17 @@ You are taking over this conversation. Based on the context above, provide a bri
onClose={handleCloseDebugPackage}
/>
{/* --- WINDOWS WARNING MODAL --- */}
<WindowsWarningModal
theme={theme}
isOpen={windowsWarningModalOpen}
onClose={() => setWindowsWarningModalOpen(false)}
onSuppressFuture={setSuppressWindowsWarning}
onOpenDebugPackage={() => setDebugPackageModalOpen(true)}
useBetaChannel={enableBetaUpdates}
onSetUseBetaChannel={setEnableBetaUpdates}
/>
{/* --- CELEBRATION OVERLAYS --- */}
<AppOverlays
theme={theme}

View File

@@ -0,0 +1,254 @@
/**
* WindowsWarningModal - Notifies Windows users about platform-specific considerations
*
* This modal is shown on application startup for Windows users to:
* - Inform them that Windows support is newer and may have more bugs
* - Encourage opting into the beta channel for latest fixes
* - Provide easy access to issue reporting with Debug Package creation
* - Allow users to suppress this message for future sessions
*/
import React, { useState, useRef, useCallback } from 'react';
import { AlertTriangle, Bug, Wrench, ExternalLink, Command, Check, MessageCircle } from 'lucide-react';
import type { Theme } from '../types';
import { MODAL_PRIORITIES } from '../constants/modalPriorities';
import { Modal, ModalFooter } from './ui/Modal';
interface WindowsWarningModalProps {
theme: Theme;
isOpen: boolean;
onClose: () => void;
onSuppressFuture: (suppress: boolean) => void;
onOpenDebugPackage: () => void;
useBetaChannel: boolean;
onSetUseBetaChannel: (enabled: boolean) => void;
}
export function WindowsWarningModal({
theme,
isOpen,
onClose,
onSuppressFuture,
onOpenDebugPackage,
useBetaChannel,
onSetUseBetaChannel,
}: WindowsWarningModalProps) {
const [suppressChecked, setSuppressChecked] = useState(false);
const continueButtonRef = useRef<HTMLButtonElement>(null);
// Handle close with suppress preference
const handleClose = useCallback(() => {
onSuppressFuture(suppressChecked);
onClose();
}, [suppressChecked, onSuppressFuture, onClose]);
// Handle toggling beta channel
const handleToggleBetaChannel = useCallback(() => {
onSetUseBetaChannel(!useBetaChannel);
}, [useBetaChannel, onSetUseBetaChannel]);
// Handle opening debug package modal
const handleOpenDebugPackage = useCallback(() => {
onSuppressFuture(suppressChecked);
onOpenDebugPackage();
onClose();
}, [suppressChecked, onSuppressFuture, onOpenDebugPackage, onClose]);
if (!isOpen) return null;
return (
<Modal
theme={theme}
title="Windows Support Notice"
headerIcon={<AlertTriangle className="w-4 h-4" style={{ color: theme.colors.warning }} />}
priority={MODAL_PRIORITIES.WINDOWS_WARNING}
onClose={handleClose}
width={520}
initialFocusRef={continueButtonRef}
footer={
<ModalFooter
theme={theme}
onCancel={handleClose}
onConfirm={handleClose}
cancelLabel="Cancel"
confirmLabel="Got it!"
confirmButtonRef={continueButtonRef}
showCancel={false}
/>
}
>
<div className="space-y-4">
{/* Main message */}
<div
className="p-4 rounded-lg border-l-4"
style={{
backgroundColor: `${theme.colors.warning}10`,
borderLeftColor: theme.colors.warning,
}}
>
<p className="text-sm leading-relaxed" style={{ color: theme.colors.textMain }}>
Windows support in Maestro is actively being improved. You may encounter more bugs
compared to Mac and Linux versions. We're working on it!
</p>
</div>
{/* Recommendations */}
<div className="space-y-3">
<h3 className="text-xs font-semibold uppercase tracking-wider" style={{ color: theme.colors.textDim }}>
Recommendations
</h3>
{/* Beta channel toggle */}
<button
type="button"
onClick={handleToggleBetaChannel}
className="w-full flex items-start gap-3 p-3 rounded-lg border hover:bg-white/5 transition-colors text-left"
style={{
borderColor: useBetaChannel ? theme.colors.accent : theme.colors.border,
backgroundColor: useBetaChannel ? `${theme.colors.accent}10` : 'transparent',
}}
>
<Wrench className="w-4 h-4 mt-0.5 shrink-0" style={{ color: theme.colors.accent }} />
<div className="flex-1 min-w-0">
<p className="text-sm font-medium" style={{ color: theme.colors.textMain }}>
Enable Beta Updates
</p>
<p className="text-xs mt-0.5" style={{ color: theme.colors.textDim }}>
Get the latest bug fixes sooner by opting into the beta channel.
</p>
</div>
{/* Toggle indicator */}
<div
className="w-10 h-5 rounded-full shrink-0 mt-0.5 transition-colors relative"
style={{
backgroundColor: useBetaChannel ? theme.colors.accent : theme.colors.bgMain,
border: `1px solid ${useBetaChannel ? theme.colors.accent : theme.colors.border}`,
}}
>
<div
className="absolute w-3.5 h-3.5 rounded-full top-0.5 transition-all flex items-center justify-center"
style={{
backgroundColor: useBetaChannel ? theme.colors.accentForeground : theme.colors.textDim,
left: useBetaChannel ? 'calc(100% - 18px)' : '2px',
}}
>
{useBetaChannel && (
<Check className="w-2 h-2" style={{ color: theme.colors.accent }} />
)}
</div>
</div>
</button>
{/* Report issues */}
<button
type="button"
onClick={() => window.maestro.shell.openExternal('https://github.com/pedramamini/Maestro/issues')}
className="w-full flex items-start gap-3 p-3 rounded-lg border hover:bg-white/5 transition-colors text-left"
style={{ borderColor: theme.colors.border }}
>
<Bug className="w-4 h-4 mt-0.5 shrink-0" style={{ color: theme.colors.accent }} />
<div className="flex-1 min-w-0">
<p className="text-sm font-medium" style={{ color: theme.colors.textMain }}>
Report Issues
</p>
<p className="text-xs mt-0.5" style={{ color: theme.colors.textDim }}>
Help improve Windows support by reporting bugs on GitHub. Vetted PRs are welcome!
</p>
</div>
<ExternalLink className="w-3 h-3 shrink-0 mt-1" style={{ color: theme.colors.textDim }} />
</button>
{/* Join Discord */}
<button
type="button"
onClick={() => window.maestro.shell.openExternal('https://discord.gg/FCAh4EWzfD')}
className="w-full flex items-start gap-3 p-3 rounded-lg border hover:bg-white/5 transition-colors text-left"
style={{ borderColor: theme.colors.border }}
>
<MessageCircle className="w-4 h-4 mt-0.5 shrink-0" style={{ color: theme.colors.accent }} />
<div className="flex-1 min-w-0">
<p className="text-sm font-medium" style={{ color: theme.colors.textMain }}>
Join Discord
</p>
<p className="text-xs mt-0.5" style={{ color: theme.colors.textDim }}>
Connect with other users in our Windows-specific channel for tips and support.
</p>
</div>
<ExternalLink className="w-3 h-3 shrink-0 mt-1" style={{ color: theme.colors.textDim }} />
</button>
{/* Create Debug Package */}
<button
type="button"
onClick={handleOpenDebugPackage}
className="w-full flex items-start gap-3 p-3 rounded-lg border hover:bg-white/5 transition-colors text-left"
style={{ borderColor: theme.colors.border }}
>
<Command className="w-4 h-4 mt-0.5 shrink-0" style={{ color: theme.colors.accent }} />
<div className="flex-1 min-w-0">
<p className="text-sm font-medium" style={{ color: theme.colors.textMain }}>
Create Debug Package
</p>
<p className="text-xs mt-0.5" style={{ color: theme.colors.textDim }}>
Accessible anytime via <kbd className="px-1 py-0.5 rounded text-[10px]" style={{ backgroundColor: theme.colors.bgMain }}>Ctrl+K</kbd> "Create Debug Package" or from the main menu.
</p>
</div>
<ExternalLink className="w-3 h-3 shrink-0 mt-1" style={{ color: theme.colors.textDim }} />
</button>
</div>
{/* Suppress checkbox */}
<label
className="flex items-center gap-2 pt-2 cursor-pointer group"
>
<div
className="w-4 h-4 rounded border flex items-center justify-center transition-colors"
style={{
borderColor: suppressChecked ? theme.colors.accent : theme.colors.border,
backgroundColor: suppressChecked ? theme.colors.accent : 'transparent',
}}
>
{suppressChecked && (
<svg className="w-3 h-3" viewBox="0 0 12 12" fill="none">
<path
d="M2 6L5 9L10 3"
stroke={theme.colors.accentForeground}
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
)}
</div>
<input
type="checkbox"
checked={suppressChecked}
onChange={(e) => setSuppressChecked(e.target.checked)}
className="sr-only"
/>
<span
className="text-xs group-hover:opacity-100 transition-opacity"
style={{ color: theme.colors.textDim, opacity: 0.8 }}
>
Don't show this message again
</span>
</label>
</div>
</Modal>
);
}
/**
* Debug function to show the Windows warning modal from the console.
* Usage: window.__showWindowsWarningModal()
*/
export function exposeWindowsWarningModalDebug(
setShowWindowsWarning: (show: boolean) => void
): void {
(window as any).__showWindowsWarningModal = () => {
setShowWindowsWarning(true);
console.log('[WindowsWarningModal] Modal triggered via console command');
};
}
export default WindowsWarningModal;

View File

@@ -179,6 +179,9 @@ export const MODAL_PRIORITIES = {
/** Debug package generation modal */
DEBUG_PACKAGE: 605,
/** Windows warning modal - shown on startup for Windows users */
WINDOWS_WARNING: 615,
/** About/info modal */
ABOUT: 600,

View File

@@ -264,6 +264,10 @@ export interface ModalContextValue {
// Symphony Modal
symphonyModalOpen: boolean;
setSymphonyModalOpen: (open: boolean) => void;
// Windows Warning Modal
windowsWarningModalOpen: boolean;
setWindowsWarningModalOpen: (open: boolean) => void;
}
// Create context with null as default (will throw if used outside provider)
@@ -446,6 +450,9 @@ export function ModalProvider({ children }: ModalProviderProps) {
// Symphony Modal
const [symphonyModalOpen, setSymphonyModalOpen] = useState(false);
// Windows Warning Modal
const [windowsWarningModalOpen, setWindowsWarningModalOpen] = useState(false);
// Convenience methods
const openSettings = useCallback((tab?: SettingsTab) => {
if (tab) setSettingsTab(tab);
@@ -696,6 +703,10 @@ export function ModalProvider({ children }: ModalProviderProps) {
// Symphony Modal
symphonyModalOpen,
setSymphonyModalOpen,
// Windows Warning Modal
windowsWarningModalOpen,
setWindowsWarningModalOpen,
}),
[
// Settings Modal
@@ -811,6 +822,8 @@ export function ModalProvider({ children }: ModalProviderProps) {
tourFromWizard,
// Symphony Modal
symphonyModalOpen,
// Windows Warning Modal
windowsWarningModalOpen,
]
);

View File

@@ -350,6 +350,10 @@ export interface UseSettingsReturn {
// File tab auto-refresh settings
fileTabAutoRefreshEnabled: boolean;
setFileTabAutoRefreshEnabled: (value: boolean) => void;
// Windows warning suppression
suppressWindowsWarning: boolean;
setSuppressWindowsWarning: (value: boolean) => void;
}
export function useSettings(): UseSettingsReturn {
@@ -508,6 +512,9 @@ export function useSettings(): UseSettingsReturn {
// File tab auto-refresh settings
const [fileTabAutoRefreshEnabled, setFileTabAutoRefreshEnabledState] = useState(false); // Default: disabled
// Windows warning suppression
const [suppressWindowsWarning, setSuppressWindowsWarningState] = useState(false); // Default: show warning
// Wrapper functions that persist to electron-store
// PERF: All wrapped in useCallback to prevent re-renders
const setLlmProvider = useCallback((value: LLMProvider) => {
@@ -1322,6 +1329,12 @@ export function useSettings(): UseSettingsReturn {
window.maestro.settings.set('fileTabAutoRefreshEnabled', value);
}, []);
// Windows warning suppression toggle
const setSuppressWindowsWarning = useCallback((value: boolean) => {
setSuppressWindowsWarningState(value);
window.maestro.settings.set('suppressWindowsWarning', value);
}, []);
// Load settings from electron-store
// This function is called on mount and on system resume (after sleep/suspend)
// PERF: Use batch loading to reduce IPC calls from ~60 to 3
@@ -1396,6 +1409,7 @@ export function useSettings(): UseSettingsReturn {
const savedSshRemoteHonorGitignore = allSettings['sshRemoteHonorGitignore'];
const savedAutomaticTabNamingEnabled = allSettings['automaticTabNamingEnabled'];
const savedFileTabAutoRefreshEnabled = allSettings['fileTabAutoRefreshEnabled'];
const savedSuppressWindowsWarning = allSettings['suppressWindowsWarning'];
if (savedEnterToSendAI !== undefined) setEnterToSendAIState(savedEnterToSendAI as boolean);
if (savedEnterToSendTerminal !== undefined)
@@ -1760,6 +1774,11 @@ export function useSettings(): UseSettingsReturn {
if (savedFileTabAutoRefreshEnabled !== undefined) {
setFileTabAutoRefreshEnabledState(savedFileTabAutoRefreshEnabled as boolean);
}
// Windows warning suppression
if (savedSuppressWindowsWarning !== undefined) {
setSuppressWindowsWarningState(savedSuppressWindowsWarning as boolean);
}
} catch (error) {
console.error('[Settings] Failed to load settings:', error);
} finally {
@@ -1938,6 +1957,8 @@ export function useSettings(): UseSettingsReturn {
setAutomaticTabNamingEnabled,
fileTabAutoRefreshEnabled,
setFileTabAutoRefreshEnabled,
suppressWindowsWarning,
setSuppressWindowsWarning,
}),
[
// State values
@@ -2083,6 +2104,8 @@ export function useSettings(): UseSettingsReturn {
setAutomaticTabNamingEnabled,
fileTabAutoRefreshEnabled,
setFileTabAutoRefreshEnabled,
suppressWindowsWarning,
setSuppressWindowsWarning,
]
);
}