import * as Haptics from "expo-haptics"; import { isLiquidGlassSupported, LiquidGlassView } from "@callstack/liquid-glass"; import { SymbolView } from "../../components/AppSymbol"; import { useCallback, useEffect, useRef } from "react"; import { ActivityIndicator, Pressable, StyleSheet, useColorScheme, View } from "react-native"; import Animated, { FadeIn, FadeOut, LinearTransition } from "react-native-reanimated"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import { AppText as Text } from "../../components/AppText"; import { tryOpenExternalUrl } from "../../lib/openExternalUrl"; import { useThemeColor } from "../../lib/useThemeColor"; import type { GitActionProgress } from "../../state/use-vcs-action-state"; const OVERLAY_LAYOUT_TRANSITION = LinearTransition.duration(220); const AnimatedLiquidGlassView = Animated.createAnimatedComponent(LiquidGlassView); export function GitActionProgressOverlay(props: { readonly progress: GitActionProgress; readonly onDismiss: () => void; }) { const { progress, onDismiss } = props; const insets = useSafeAreaInsets(); const prevPhaseRef = useRef(progress.phase); useEffect(() => { const prev = prevPhaseRef.current; prevPhaseRef.current = progress.phase; if (prev === "running" && progress.phase === "success") { Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success); } else if (prev === "running" && progress.phase === "error") { Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error); } }, [progress.phase]); const handlePress = useCallback(() => { if (progress.prUrl) { void tryOpenExternalUrl(progress.prUrl, "pull-request"); return; } if (progress.phase === "success" || progress.phase === "error") { onDismiss(); } }, [onDismiss, progress.phase, progress.prUrl]); if (progress.phase === "idle") { return null; } return ( ); } function OverlayContent(props: { readonly progress: GitActionProgress }) { const { progress } = props; const iconColor = useThemeColor("--color-icon"); const glassBorder = useThemeColor("--color-header-border"); const glassTint = useThemeColor("--color-glass-tint"); const isDarkMode = useColorScheme() === "dark"; const content = ( <> {progress.label ? ( {progress.label} ) : null} {progress.description ? ( {progress.description} ) : null} {progress.prUrl ? ( ) : null} ); if (isLiquidGlassSupported) { return ( {content} ); } const bgClass = progress.phase === "error" ? "bg-red-50 dark:bg-red-950/80 border-red-200 dark:border-red-800" : "bg-card border-border"; return ( {content} ); } function OverlayIcon(props: { readonly phase: GitActionProgress["phase"]; readonly iconColor: ReturnType; }) { switch (props.phase) { case "running": return ; case "success": return ( ); case "error": return ( ); default: return null; } }