Fix compact provider sheet footer
This commit is contained in:
@@ -20,6 +20,7 @@ import {
|
|||||||
useIsolatedBottomSheetVisibility,
|
useIsolatedBottomSheetVisibility,
|
||||||
} from "@/components/ui/isolated-bottom-sheet-modal";
|
} from "@/components/ui/isolated-bottom-sheet-modal";
|
||||||
import { isNative, isWeb } from "@/constants/platform";
|
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,
|
// Horizontal indent token shared by the sheet header (title, back arrow,
|
||||||
// leading icon, search input icon) and any row primitive rendered inside the
|
// leading icon, search input icon) and any row primitive rendered inside the
|
||||||
@@ -458,7 +459,12 @@ export function AdaptiveModalSheet({
|
|||||||
}: AdaptiveModalSheetProps) {
|
}: AdaptiveModalSheetProps) {
|
||||||
const { theme } = useUnistyles();
|
const { theme } = useUnistyles();
|
||||||
const isMobile = useIsCompactFormFactor();
|
const isMobile = useIsCompactFormFactor();
|
||||||
|
const insets = useSafeAreaInsets();
|
||||||
const resolvedSnapPoints = useMemo(() => snapPoints ?? ["65%", "90%"], [snapPoints]);
|
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(
|
const handleIndicatorStyle = useMemo(
|
||||||
() => ({ backgroundColor: theme.colors.surface2 }),
|
() => ({ backgroundColor: theme.colors.surface2 }),
|
||||||
[theme.colors.surface2],
|
[theme.colors.surface2],
|
||||||
@@ -515,7 +521,7 @@ export function AdaptiveModalSheet({
|
|||||||
) : (
|
) : (
|
||||||
<View style={styles.bottomSheetStaticContent}>{children}</View>
|
<View style={styles.bottomSheetStaticContent}>{children}</View>
|
||||||
)}
|
)}
|
||||||
{footer ? <View style={styles.footer}>{footer}</View> : null}
|
{footer ? <View style={footerStyle}>{footer}</View> : null}
|
||||||
</IsolatedBottomSheetModal>
|
</IsolatedBottomSheetModal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -534,7 +540,7 @@ export function AdaptiveModalSheet({
|
|||||||
) : (
|
) : (
|
||||||
<View style={styles.desktopStaticContent}>{children}</View>
|
<View style={styles.desktopStaticContent}>{children}</View>
|
||||||
)}
|
)}
|
||||||
{footer ? <View style={styles.footer}>{footer}</View> : null}
|
{footer ? <View style={footerStyle}>{footer}</View> : null}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import {
|
|||||||
} from "@/components/adaptive-modal-sheet";
|
} from "@/components/adaptive-modal-sheet";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { LoadingSpinner } from "@/components/ui/loading-spinner";
|
import { LoadingSpinner } from "@/components/ui/loading-spinner";
|
||||||
|
import { useIsCompactFormFactor } from "@/constants/layout";
|
||||||
import { isWeb } from "@/constants/platform";
|
import { isWeb } from "@/constants/platform";
|
||||||
import { CODE_SURFACE_DATASET } from "@/styles/code-surface";
|
import { CODE_SURFACE_DATASET } from "@/styles/code-surface";
|
||||||
import { useDaemonConfig } from "@/hooks/use-daemon-config";
|
import { useDaemonConfig } from "@/hooks/use-daemon-config";
|
||||||
@@ -359,6 +360,69 @@ interface ProviderModalBodyProps {
|
|||||||
theme: { iconSize: { md: number }; colors: { foregroundMuted: string } };
|
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) {
|
function ProviderModalBody(props: ProviderModalBodyProps) {
|
||||||
const {
|
const {
|
||||||
discoveredCount,
|
discoveredCount,
|
||||||
@@ -446,6 +510,7 @@ export function ProviderDiagnosticSheet({
|
|||||||
serverId,
|
serverId,
|
||||||
}: ProviderDiagnosticSheetProps) {
|
}: ProviderDiagnosticSheetProps) {
|
||||||
const { theme } = useUnistyles();
|
const { theme } = useUnistyles();
|
||||||
|
const isCompact = useIsCompactFormFactor();
|
||||||
const { entries: snapshotEntries, refresh, isRefreshing } = useProvidersSnapshot(serverId);
|
const { entries: snapshotEntries, refresh, isRefreshing } = useProvidersSnapshot(serverId);
|
||||||
const { config, patchConfig } = useDaemonConfig(serverId);
|
const { config, patchConfig } = useDaemonConfig(serverId);
|
||||||
const [query, setQuery] = useState("");
|
const [query, setQuery] = useState("");
|
||||||
@@ -545,38 +610,20 @@ export function ProviderDiagnosticSheet({
|
|||||||
[providerLabel],
|
[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 (
|
return (
|
||||||
<>
|
<>
|
||||||
<AdaptiveModalSheet
|
<AdaptiveModalSheet
|
||||||
header={sheetHeader}
|
header={sheetHeader}
|
||||||
visible={visible}
|
visible={visible}
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
footer={footer}
|
footer={renderProviderSheetFooter({
|
||||||
|
fetchedAtLabel,
|
||||||
|
isCompact,
|
||||||
|
modelsRefreshing,
|
||||||
|
onOpenAddSheet: handleOpenAddSheet,
|
||||||
|
onOpenDiagSheet: handleOpenDiagSheet,
|
||||||
|
onRefreshModels: handleRefreshModels,
|
||||||
|
})}
|
||||||
snapPoints={MAIN_SNAP_POINTS}
|
snapPoints={MAIN_SNAP_POINTS}
|
||||||
>
|
>
|
||||||
<ProviderModalBody
|
<ProviderModalBody
|
||||||
@@ -692,16 +739,36 @@ const sheetStyles = StyleSheet.create((theme) => ({
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
gap: theme.spacing[3],
|
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: {
|
footerMeta: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
fontSize: theme.fontSize.xs,
|
fontSize: theme.fontSize.xs,
|
||||||
color: theme.colors.foregroundMuted,
|
color: theme.colors.foregroundMuted,
|
||||||
},
|
},
|
||||||
|
compactFooterMeta: {
|
||||||
|
flex: 0,
|
||||||
|
},
|
||||||
footerActions: {
|
footerActions: {
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
gap: theme.spacing[2],
|
gap: theme.spacing[2],
|
||||||
},
|
},
|
||||||
|
compactFooterActions: {
|
||||||
|
gap: theme.spacing[2],
|
||||||
|
},
|
||||||
|
compactFooterButton: {
|
||||||
|
alignSelf: "stretch",
|
||||||
|
},
|
||||||
formGroup: {
|
formGroup: {
|
||||||
gap: theme.spacing[3],
|
gap: theme.spacing[3],
|
||||||
},
|
},
|
||||||
@@ -741,6 +808,7 @@ const sheetStyles = StyleSheet.create((theme) => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
const FORM_INPUT_STYLE = [sheetStyles.formInput, isWeb && { outlineStyle: "none" }];
|
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 MAIN_SNAP_POINTS = ["65%", "92%"];
|
||||||
const ADD_SNAP_POINTS = ["40%"];
|
const ADD_SNAP_POINTS = ["40%"];
|
||||||
|
|||||||
Reference in New Issue
Block a user