Fix compact provider sheet footer

This commit is contained in:
Mohamed Boudra
2026-06-04 08:46:47 +07:00
parent 801140abb2
commit f3b7dac768
2 changed files with 102 additions and 28 deletions

View File

@@ -20,6 +20,7 @@ import {
useIsolatedBottomSheetVisibility,
} from "@/components/ui/isolated-bottom-sheet-modal";
import { isNative, isWeb } from "@/constants/platform";
import { useSafeAreaInsets } from "react-native-safe-area-context";
// Horizontal indent token shared by the sheet header (title, back arrow,
// leading icon, search input icon) and any row primitive rendered inside the
@@ -458,7 +459,12 @@ export function AdaptiveModalSheet({
}: AdaptiveModalSheetProps) {
const { theme } = useUnistyles();
const isMobile = useIsCompactFormFactor();
const insets = useSafeAreaInsets();
const resolvedSnapPoints = useMemo(() => snapPoints ?? ["65%", "90%"], [snapPoints]);
const footerStyle = useMemo(
() => [styles.footer, isMobile ? { paddingBottom: theme.spacing[3] + insets.bottom } : null],
[insets.bottom, isMobile, theme.spacing],
);
const handleIndicatorStyle = useMemo(
() => ({ backgroundColor: theme.colors.surface2 }),
[theme.colors.surface2],
@@ -515,7 +521,7 @@ export function AdaptiveModalSheet({
) : (
<View style={styles.bottomSheetStaticContent}>{children}</View>
)}
{footer ? <View style={styles.footer}>{footer}</View> : null}
{footer ? <View style={footerStyle}>{footer}</View> : null}
</IsolatedBottomSheetModal>
);
}
@@ -534,7 +540,7 @@ export function AdaptiveModalSheet({
) : (
<View style={styles.desktopStaticContent}>{children}</View>
)}
{footer ? <View style={styles.footer}>{footer}</View> : null}
{footer ? <View style={footerStyle}>{footer}</View> : null}
</>
);

View File

@@ -16,6 +16,7 @@ import {
} from "@/components/adaptive-modal-sheet";
import { Button } from "@/components/ui/button";
import { LoadingSpinner } from "@/components/ui/loading-spinner";
import { useIsCompactFormFactor } from "@/constants/layout";
import { isWeb } from "@/constants/platform";
import { CODE_SURFACE_DATASET } from "@/styles/code-surface";
import { useDaemonConfig } from "@/hooks/use-daemon-config";
@@ -359,6 +360,69 @@ interface ProviderModalBodyProps {
theme: { iconSize: { md: number }; colors: { foregroundMuted: string } };
}
interface ProviderSheetFooterInput {
fetchedAtLabel: string | null;
isCompact: boolean;
modelsRefreshing: boolean;
onOpenAddSheet: () => void;
onOpenDiagSheet: () => void;
onRefreshModels: () => void;
}
function renderProviderSheetFooter({
fetchedAtLabel,
isCompact,
modelsRefreshing,
onOpenAddSheet,
onOpenDiagSheet,
onRefreshModels,
}: ProviderSheetFooterInput) {
const contentStyle = isCompact ? sheetStyles.compactFooterContent : sheetStyles.footerContent;
const actionsStyle = isCompact ? sheetStyles.compactFooterActions : sheetStyles.footerActions;
const buttonStyle = isCompact ? sheetStyles.compactFooterButton : null;
const metaStyle = isCompact ? COMPACT_FOOTER_META_STYLE : sheetStyles.footerMeta;
return (
<View style={contentStyle}>
{fetchedAtLabel || !isCompact ? (
<Text style={metaStyle} numberOfLines={1}>
{fetchedAtLabel ? `Updated ${fetchedAtLabel}` : ""}
</Text>
) : null}
<View style={actionsStyle}>
<Button
variant="secondary"
size="sm"
leftIcon={Plus}
onPress={onOpenAddSheet}
style={buttonStyle}
>
Add model
</Button>
<Button
variant="secondary"
size="sm"
leftIcon={FileText}
onPress={onOpenDiagSheet}
style={buttonStyle}
>
Diagnostic
</Button>
<Button
variant="default"
size="sm"
leftIcon={modelsRefreshing ? undefined : RotateCw}
onPress={onRefreshModels}
disabled={modelsRefreshing}
style={buttonStyle}
>
{modelsRefreshing ? "Refreshing…" : "Refresh"}
</Button>
</View>
</View>
);
}
function ProviderModalBody(props: ProviderModalBodyProps) {
const {
discoveredCount,
@@ -446,6 +510,7 @@ export function ProviderDiagnosticSheet({
serverId,
}: ProviderDiagnosticSheetProps) {
const { theme } = useUnistyles();
const isCompact = useIsCompactFormFactor();
const { entries: snapshotEntries, refresh, isRefreshing } = useProvidersSnapshot(serverId);
const { config, patchConfig } = useDaemonConfig(serverId);
const [query, setQuery] = useState("");
@@ -545,38 +610,20 @@ export function ProviderDiagnosticSheet({
[providerLabel],
);
const footer = (
<>
<Text style={sheetStyles.footerMeta} numberOfLines={1}>
{fetchedAtLabel ? `Updated ${fetchedAtLabel}` : ""}
</Text>
<View style={sheetStyles.footerActions}>
<Button variant="secondary" size="sm" leftIcon={Plus} onPress={handleOpenAddSheet}>
Add model
</Button>
<Button variant="secondary" size="sm" leftIcon={FileText} onPress={handleOpenDiagSheet}>
Diagnostic
</Button>
<Button
variant="default"
size="sm"
leftIcon={modelsRefreshing ? undefined : RotateCw}
onPress={handleRefreshModels}
disabled={modelsRefreshing}
>
{modelsRefreshing ? "Refreshing…" : "Refresh"}
</Button>
</View>
</>
);
return (
<>
<AdaptiveModalSheet
header={sheetHeader}
visible={visible}
onClose={onClose}
footer={footer}
footer={renderProviderSheetFooter({
fetchedAtLabel,
isCompact,
modelsRefreshing,
onOpenAddSheet: handleOpenAddSheet,
onOpenDiagSheet: handleOpenDiagSheet,
onRefreshModels: handleRefreshModels,
})}
snapPoints={MAIN_SNAP_POINTS}
>
<ProviderModalBody
@@ -692,16 +739,36 @@ const sheetStyles = StyleSheet.create((theme) => ({
alignItems: "center",
gap: theme.spacing[3],
},
footerContent: {
flex: 1,
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
gap: theme.spacing[2],
},
compactFooterContent: {
flex: 1,
gap: theme.spacing[2],
},
footerMeta: {
flex: 1,
fontSize: theme.fontSize.xs,
color: theme.colors.foregroundMuted,
},
compactFooterMeta: {
flex: 0,
},
footerActions: {
flexDirection: "row",
alignItems: "center",
gap: theme.spacing[2],
},
compactFooterActions: {
gap: theme.spacing[2],
},
compactFooterButton: {
alignSelf: "stretch",
},
formGroup: {
gap: theme.spacing[3],
},
@@ -741,6 +808,7 @@ const sheetStyles = StyleSheet.create((theme) => ({
}));
const FORM_INPUT_STYLE = [sheetStyles.formInput, isWeb && { outlineStyle: "none" }];
const COMPACT_FOOTER_META_STYLE = [sheetStyles.footerMeta, sheetStyles.compactFooterMeta];
const MAIN_SNAP_POINTS = ["65%", "92%"];
const ADD_SNAP_POINTS = ["40%"];