diff --git a/apps/x/apps/renderer/src/components/settings/connected-accounts-settings.tsx b/apps/x/apps/renderer/src/components/settings/connected-accounts-settings.tsx index bf263851..4b9eb802 100644 --- a/apps/x/apps/renderer/src/components/settings/connected-accounts-settings.tsx +++ b/apps/x/apps/renderer/src/components/settings/connected-accounts-settings.tsx @@ -445,14 +445,16 @@ export function ConnectedAccountsSettings({ dialogOpen }: ConnectedAccountsSetti One channel per line. Use channel names or IDs. - + {(c.slackKnowledgeDirty || c.slackKnowledgeSaving) && ( + + )} {c.slackKnowledgeEnabled && c.slackSyncStatuses.filter(s => s.enabled).map(status => (
diff --git a/apps/x/apps/renderer/src/hooks/useConnectors.ts b/apps/x/apps/renderer/src/hooks/useConnectors.ts index b436e583..82869a0c 100644 --- a/apps/x/apps/renderer/src/hooks/useConnectors.ts +++ b/apps/x/apps/renderer/src/hooks/useConnectors.ts @@ -101,6 +101,10 @@ export function useConnectors(active: boolean) { const [slackKnowledgeEnabled, setSlackKnowledgeEnabled] = useState(false) const [slackKnowledgeChannels, setSlackKnowledgeChannels] = useState("") const [slackKnowledgeSaving, setSlackKnowledgeSaving] = useState(false) + // Snapshot of the last-persisted knowledge config, used to detect unsaved + // edits so the Save button only appears when there's something to save. + const [slackKnowledgeSavedEnabled, setSlackKnowledgeSavedEnabled] = useState(false) + const [slackKnowledgeSavedChannels, setSlackKnowledgeSavedChannels] = useState("") const [slackSyncStatuses, setSlackSyncStatuses] = useState([]) // Composio Gmail/Calendar sync was removed. These flags are seeded false @@ -324,6 +328,8 @@ export function useConnectors(active: boolean) { }) setSlackKnowledgeEnabled(false) setSlackKnowledgeChannels("") + setSlackKnowledgeSavedEnabled(false) + setSlackKnowledgeSavedChannels("") toast.success('Slack disabled') } catch (error) { console.error('Failed to update Slack config:', error) @@ -347,18 +353,24 @@ export function useConnectors(active: boolean) { try { const result = await window.ipc.invoke('knowledgeSources:getConfig', null) const slackSource = (result.sources as KnowledgeSourceConfig[]).find(source => source.id === 'slack') - setSlackKnowledgeEnabled(Boolean(slackSource?.enabled)) - setSlackKnowledgeChannels((slackSource?.scopes ?? []) + const enabled = Boolean(slackSource?.enabled) + const channels = (slackSource?.scopes ?? []) .filter(scope => scope.type === 'channel') .map(scope => { const channel = scope.name || scope.id return scope.workspaceUrl ? `${scope.workspaceUrl} ${channel}` : channel }) - .join('\n')) + .join('\n') + setSlackKnowledgeEnabled(enabled) + setSlackKnowledgeChannels(channels) + setSlackKnowledgeSavedEnabled(enabled) + setSlackKnowledgeSavedChannels(channels) } catch (error) { console.error('Failed to load knowledge sources:', error) setSlackKnowledgeEnabled(false) setSlackKnowledgeChannels("") + setSlackKnowledgeSavedEnabled(false) + setSlackKnowledgeSavedChannels("") } }, []) @@ -787,6 +799,11 @@ export function useConnectors(active: boolean) { (status) => Boolean(status?.error) ) + // Whether the knowledge config has unsaved edits — drives Save button visibility. + const slackKnowledgeDirty = + slackKnowledgeEnabled !== slackKnowledgeSavedEnabled || + slackKnowledgeChannels !== slackKnowledgeSavedChannels + return { // OAuth providers providers, @@ -842,6 +859,7 @@ export function useConnectors(active: boolean) { slackKnowledgeChannels, setSlackKnowledgeChannels, slackKnowledgeSaving, + slackKnowledgeDirty, handleSlackEnable, handleSlackImportDesktop, handleSlackQuitAndImport,