diff --git a/frontend-modern/src/components/Settings/Settings.tsx b/frontend-modern/src/components/Settings/Settings.tsx index 4d0b5b1..2cc79a7 100644 --- a/frontend-modern/src/components/Settings/Settings.tsx +++ b/frontend-modern/src/components/Settings/Settings.tsx @@ -39,6 +39,7 @@ import { SettingsSectionNav } from './SettingsSectionNav'; import { SettingsAPI } from '@/api/settings'; import { NodesAPI } from '@/api/nodes'; import { UpdatesAPI } from '@/api/updates'; +import { usePersistentSignal } from '@/hooks/usePersistentSignal'; import { Card } from '@/components/shared/Card'; import { SectionHeader } from '@/components/shared/SectionHeader'; import { Toggle } from '@/components/shared/Toggle'; @@ -596,7 +597,7 @@ const Settings: Component = (props) => { ); const [hasUnsavedChanges, setHasUnsavedChanges] = createSignal(false); - const [sidebarCollapsed, setSidebarCollapsed] = createSignal(true); + const [sidebarCollapsed, setSidebarCollapsed] = usePersistentSignal('settings-sidebar-collapsed', false); const [nodes, setNodes] = createSignal([]); const [discoveredNodes, setDiscoveredNodes] = createSignal([]); const [showNodeModal, setShowNodeModal] = createSignal(false); diff --git a/internal/config/watcher.go b/internal/config/watcher.go index 26920c0..6439288 100644 --- a/internal/config/watcher.go +++ b/internal/config/watcher.go @@ -265,8 +265,17 @@ func (cw *ConfigWatcher) pollForChanges() { // Check .env if stat, err := os.Stat(cw.envPath); err == nil { if stat.ModTime().After(cw.lastModTime) { - log.Info().Msg("Detected .env file change via polling") cw.lastModTime = stat.ModTime() + // Check if content actually changed to prevent restart loops on touch + newHash, err := cw.calculateFileHash(cw.envPath) + if err == nil { + if newHash == cw.lastEnvHash { + log.Debug().Msg("Detected .env file touch but content unchanged (polling), skipping reload") + continue + } + cw.lastEnvHash = newHash + } + log.Info().Msg("Detected .env file change via polling") cw.reloadConfig() } }