diff --git a/apps/code/src/renderer/features/inbox/components/InboxEmptyStates.tsx b/apps/code/src/renderer/features/inbox/components/InboxEmptyStates.tsx
index b4685a7e7..1aeddadf3 100644
--- a/apps/code/src/renderer/features/inbox/components/InboxEmptyStates.tsx
+++ b/apps/code/src/renderer/features/inbox/components/InboxEmptyStates.tsx
@@ -64,7 +64,7 @@ export function WarmingUpPane({
color="gray"
onClick={onConfigureSources}
>
- Configure sources
+ Configure inbox
diff --git a/apps/code/src/renderer/features/inbox/components/SignalSourceToggles.tsx b/apps/code/src/renderer/features/inbox/components/SignalSourceToggles.tsx
index f295ed602..db1a72a98 100644
--- a/apps/code/src/renderer/features/inbox/components/SignalSourceToggles.tsx
+++ b/apps/code/src/renderer/features/inbox/components/SignalSourceToggles.tsx
@@ -416,3 +416,52 @@ export function SignalSourceToggles({
);
}
+
+function SignalSourceToggleCardSkeleton() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export function SignalSourceTogglesSkeleton() {
+ return (
+
+
+
+ PostHog data
+
+
+ {Array.from({ length: 3 }).map((_, index) => (
+ // biome-ignore lint/suspicious/noArrayIndexKey: static loading placeholders
+
+ ))}
+
+
+
+
+ External connections
+
+
+ {Array.from({ length: 4 }).map((_, index) => (
+ // biome-ignore lint/suspicious/noArrayIndexKey: static loading placeholders
+
+ ))}
+
+
+
+ );
+}
diff --git a/apps/code/src/renderer/features/inbox/components/list/SignalsToolbar.tsx b/apps/code/src/renderer/features/inbox/components/list/SignalsToolbar.tsx
index 1304ea04d..ad66c46a2 100644
--- a/apps/code/src/renderer/features/inbox/components/list/SignalsToolbar.tsx
+++ b/apps/code/src/renderer/features/inbox/components/list/SignalsToolbar.tsx
@@ -52,7 +52,7 @@ interface SignalsToolbarProps {
effectiveBulkIds?: string[];
/** Called when the select-all checkbox is toggled. Parent owns all state transitions. */
onToggleSelectAll?: (checked: boolean) => void;
- /** Called when the "Configure sources" button is clicked. */
+ /** Called when the "Configure inbox" button is clicked. */
onConfigureSources?: () => void;
/**
* Opens the dismiss flow: exactly one report selected (snooze or permanent suppress, with a reason).
@@ -505,7 +505,7 @@ export function SignalsToolbar({
className="flex shrink-0 cursor-pointer items-center gap-1 border-0 bg-transparent p-0 text-[12px] text-gray-10 transition-colors hover:text-gray-12"
>
- Configure sources
+ Configure inbox
) : null}
diff --git a/apps/code/src/renderer/features/inbox/hooks/useSignalSourceManager.ts b/apps/code/src/renderer/features/inbox/hooks/useSignalSourceManager.ts
index 7d9f0a642..3ab9e5d31 100644
--- a/apps/code/src/renderer/features/inbox/hooks/useSignalSourceManager.ts
+++ b/apps/code/src/renderer/features/inbox/hooks/useSignalSourceManager.ts
@@ -112,7 +112,8 @@ export function useSignalSourceManager() {
useExternalDataSources();
const { data: evaluations } = useEvaluations();
const { data: teamConfig } = useSignalTeamConfig();
- const { data: userAutonomyConfig } = useSignalUserAutonomyConfig();
+ const { data: userAutonomyConfig, isLoading: userAutonomyConfigLoading } =
+ useSignalUserAutonomyConfig();
// Optimistic overrides keyed by source product — only sources actively being
// toggled get an entry, so unrelated sources never see a prop change.
@@ -573,6 +574,7 @@ export function useSignalSourceManager() {
teamConfig,
handleUpdateAutostartPriority,
userAutonomyConfig,
+ userAutonomyConfigLoading,
handleUpdateUserAutonomyPriority,
handleUpdateSlackNotifications,
};
diff --git a/apps/code/src/renderer/features/settings/components/sections/GitHubIntegrationSection.tsx b/apps/code/src/renderer/features/settings/components/sections/GitHubIntegrationSection.tsx
index 7944f0e49..0296e674c 100644
--- a/apps/code/src/renderer/features/settings/components/sections/GitHubIntegrationSection.tsx
+++ b/apps/code/src/renderer/features/settings/components/sections/GitHubIntegrationSection.tsx
@@ -35,8 +35,10 @@ function summarizeReposByOwner(
export function GitHubIntegrationSection({
hasGithubIntegration,
+ isLoading = false,
}: {
hasGithubIntegration: boolean;
+ isLoading?: boolean;
}) {
const { repositories, isLoadingRepos } = useRepositoryIntegration();
const ownerSummary = useMemo(
@@ -58,6 +60,27 @@ export function GitHubIntegrationSection({
projectHasTeamIntegration: hasGithubIntegration,
});
+ if (isLoading) {
+ return (
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+
return (
+
+
+
+
+
+
+ );
+ }
+
if (!hasSlackIntegration) {
return (
- Loading signal source configurations...
-
- );
- }
+ const { hasGithubIntegration, isLoadingIntegrations } =
+ useRepositoryIntegration();
const userPriorityValue =
userAutonomyConfig?.autostart_priority ?? NEVER_VALUE;
@@ -65,40 +62,47 @@ export function SignalSourcesSettings({
improvements.
-
+
-
-
-
- {setupSource ? (
- void handleSetupComplete()}
- onCancel={handleSetupCancel}
- />
- ) : (
-
- void handleToggle(source, enabled)
- }
- disabled={!hasGithubIntegration}
- sourceStates={sourceStates}
- onSetup={handleSetup}
- />
- )}
+ {isLoading ? (
+
+ ) : (
+
+
+
+ {setupSource ? (
+ void handleSetupComplete()}
+ onCancel={handleSetupCancel}
+ />
+ ) : (
+
+ void handleToggle(source, enabled)
+ }
+ disabled={!hasGithubIntegration}
+ sourceStates={sourceStates}
+ onSetup={handleSetup}
+ />
+ )}
+
-
-
+
+ )}
-
- void handleUpdateUserAutonomyPriority(
- value === NEVER_VALUE ? null : value,
- )
- }
- />
+ {userAutonomyConfigLoading ? (
+
+ ) : (
+
+ void handleUpdateUserAutonomyPriority(
+ value === NEVER_VALUE ? null : value,
+ )
+ }
+ />
+ )}
);
diff --git a/apps/code/src/renderer/hooks/useIntegrations.ts b/apps/code/src/renderer/hooks/useIntegrations.ts
index c8761ac3c..6ae0ffe86 100644
--- a/apps/code/src/renderer/hooks/useIntegrations.ts
+++ b/apps/code/src/renderer/hooks/useIntegrations.ts
@@ -656,6 +656,7 @@ export function useRepositoryIntegration() {
repositories,
getIntegrationIdForRepo,
isRepoInIntegration,
+ isLoadingIntegrations: integrationsPending,
isLoadingRepos: integrationsPending || reposPending,
isRefreshingRepos,
refreshRepositories,