diff --git a/packages/app/src/components/combined-model-selector.tsx b/packages/app/src/components/combined-model-selector.tsx
index 99bcbac38..863d30575 100644
--- a/packages/app/src/components/combined-model-selector.tsx
+++ b/packages/app/src/components/combined-model-selector.tsx
@@ -202,6 +202,49 @@ function ModelRow({
[onToggleFavorite, row.modelId, row.provider],
);
+ const leadingSlot = useMemo(
+ () => ,
+ [ProviderIcon, theme.iconSize.sm, theme.colors.foregroundMuted],
+ );
+ const trailingSlot = useMemo(
+ () =>
+ onToggleFavorite && !disabled ? (
+
+ {({ hovered }) => (
+
+ )}
+
+ ) : null,
+ [
+ onToggleFavorite,
+ disabled,
+ handleToggleFavorite,
+ isFavorite,
+ row.provider,
+ row.modelId,
+ theme.colors.palette.amber,
+ theme.colors.foregroundMuted,
+ theme.colors.border,
+ ],
+ );
+
const showDescription = row.description && PROVIDERS_WITH_MODEL_DESCRIPTIONS.has(row.provider);
return (
@@ -212,33 +255,8 @@ function ModelRow({
disabled={disabled}
elevated={elevated}
onPress={onPress}
- leadingSlot={}
- trailingSlot={
- onToggleFavorite && !disabled ? (
-
- {({ hovered }) => (
-
- )}
-
- ) : null
- }
+ leadingSlot={leadingSlot}
+ trailingSlot={trailingSlot}
/>
);
}
@@ -719,6 +737,27 @@ export function CombinedModelSelector({
setView({ kind: "provider", providerId, providerLabel });
}, []);
+ const stickyHeader = useMemo(
+ () =>
+ view.kind === "provider" ? (
+
+ {!singleProviderView ? (
+
+ ) : null}
+
+
+ ) : undefined,
+ [view, singleProviderView, handleBackToAll, searchQuery],
+ );
+
return (
<>
- {!singleProviderView ? (
-
- ) : null}
-
-
- ) : undefined
- }
+ stickyHeader={stickyHeader}
>
{isContentReady ? (
({
nestable ? (NestableDraggableFlatList as any) : DraggableFlatList
) as any;
+ const refreshControl = useMemo(
+ () =>
+ shouldShowRefreshControl ? (
+
+ ) : undefined,
+ [shouldShowRefreshControl, refreshing, onRefresh, theme.colors.foregroundMuted, refreshColors],
+ );
+
return (
({
onRelease={handleRelease}
// @ts-ignore - waitFor is supported by RNGH FlatList but missing from DraggableFlatList types
waitFor={waitFor}
- refreshControl={
- shouldShowRefreshControl ? (
-
- ) : undefined
- }
+ refreshControl={refreshControl}
/>
);
}
diff --git a/packages/app/src/components/provider-diagnostic-sheet.tsx b/packages/app/src/components/provider-diagnostic-sheet.tsx
index 83ed23f2f..4b748bece 100644
--- a/packages/app/src/components/provider-diagnostic-sheet.tsx
+++ b/packages/app/src/components/provider-diagnostic-sheet.tsx
@@ -123,6 +123,35 @@ export function ProviderDiagnosticSheet({
});
}, [fetchDiagnostic, provider, refresh]);
+ const headerActions = useMemo(
+ () => (
+
+ {refreshInFlight ? (
+
+ ) : (
+
+ )}
+
+ ),
+ [
+ handleRefresh,
+ refreshInFlight,
+ refreshButtonStyle,
+ providerLabel,
+ theme.iconSize.sm,
+ theme.colors.foregroundMuted,
+ ],
+ );
+
useEffect(() => {
if (visible) {
fetchDiagnostic();
@@ -176,24 +205,7 @@ export function ProviderDiagnosticSheet({
onClose={onClose}
snapPoints={DIAGNOSTIC_SHEET_SNAP_POINTS}
scrollable={false}
- headerActions={
-
- {refreshInFlight ? (
-
- ) : (
-
- )}
-
- }
+ headerActions={headerActions}
>
Diagnostic
diff --git a/packages/app/src/components/workspace-setup-dialog.tsx b/packages/app/src/components/workspace-setup-dialog.tsx
index 5e8fdcf2d..82340df1e 100644
--- a/packages/app/src/components/workspace-setup-dialog.tsx
+++ b/packages/app/src/components/workspace-setup-dialog.tsx
@@ -272,25 +272,28 @@ export function WorkspaceSetupDialog() {
[composerState, pendingAction],
);
+ const subtitleContent = useMemo(
+ () => (
+
+ {iconSource ? (
+
+ ) : (
+
+ {placeholderInitial}
+
+ )}
+
+ {workspaceTitle}
+
+
+ ),
+ [iconSource, placeholderInitial, workspaceTitle],
+ );
+
if (!pendingWorkspaceSetup || !sourceDirectory) {
return null;
}
- const subtitleContent = (
-
- {iconSource ? (
-
- ) : (
-
- {placeholderInitial}
-
- )}
-
- {workspaceTitle}
-
-
- );
-
return (