| ... | ... | @@ -1,8 +1,9 @@ |
| 1 | 1 | import * as Haptics from "expo-haptics"; |
| 2 | import { isLiquidGlassSupported, LiquidGlassView } from "@callstack/liquid-glass"; |
| 2 | 3 | import { SymbolView } from "../../components/AppSymbol"; |
| 3 | 4 | import { useCallback, useEffect, useRef } from "react"; |
| 4 | | import { ActivityIndicator, Pressable, View } from "react-native"; |
| 5 | | import Animated, { FadeIn, FadeOut } from "react-native-reanimated"; |
| 5 | import { ActivityIndicator, Pressable, StyleSheet, useColorScheme, View } from "react-native"; |
| 6 | import Animated, { FadeIn, FadeOut, LinearTransition } from "react-native-reanimated"; |
| 6 | 7 | import { useSafeAreaInsets } from "react-native-safe-area-context"; |
| 7 | 8 | |
| 8 | 9 | import { AppText as Text } from "../../components/AppText"; |
| ... | ... | @@ -10,6 +11,9 @@ import { tryOpenExternalUrl } from "../../lib/openExternalUrl"; |
| 10 | 11 | import { useThemeColor } from "../../lib/useThemeColor"; |
| 11 | 12 | import type { GitActionProgress } from "../../state/use-vcs-action-state"; |
| 12 | 13 | |
| 14 | const OVERLAY_LAYOUT_TRANSITION = LinearTransition.duration(220); |
| 15 | const AnimatedLiquidGlassView = Animated.createAnimatedComponent(LiquidGlassView); |
| 16 | |
| 13 | 17 | export function GitActionProgressOverlay(props: { |
| 14 | 18 | readonly progress: GitActionProgress; |
| 15 | 19 | readonly onDismiss: () => void; |
| ... | ... | @@ -45,7 +49,7 @@ export function GitActionProgressOverlay(props: { |
| 45 | 49 | |
| 46 | 50 | return ( |
| 47 | 51 | <Animated.View |
| 48 | | entering={FadeIn.duration(200)} |
| 52 | entering={isLiquidGlassSupported ? undefined : FadeIn.duration(200)} |
| 49 | 53 | exiting={FadeOut.duration(150)} |
| 50 | 54 | className="absolute inset-x-3 z-[100]" |
| 51 | 55 | style={{ top: insets.top + 48 }} |
| ... | ... | @@ -61,16 +65,11 @@ export function GitActionProgressOverlay(props: { |
| 61 | 65 | function OverlayContent(props: { readonly progress: GitActionProgress }) { |
| 62 | 66 | const { progress } = props; |
| 63 | 67 | const iconColor = useThemeColor("--color-icon"); |
| 64 | | |
| 65 | | const bgClass = |
| 66 | | progress.phase === "error" |
| 67 | | ? "bg-red-50 dark:bg-red-950/80 border-red-200 dark:border-red-800" |
| 68 | | : "bg-card border-border"; |
| 69 | | |
| 70 | | return ( |
| 71 | | <View |
| 72 | | className={`flex-row items-center gap-2.5 rounded-2xl border px-3.5 py-3 shadow-lg shadow-black/10 ${bgClass}`} |
| 73 | | > |
| 68 | const glassBorder = useThemeColor("--color-header-border"); |
| 69 | const glassTint = useThemeColor("--color-glass-tint"); |
| 70 | const isDarkMode = useColorScheme() === "dark"; |
| 71 | const content = ( |
| 72 | <> |
| 74 | 73 | <OverlayIcon phase={progress.phase} iconColor={iconColor} /> |
| 75 | 74 | |
| 76 | 75 | <View className="flex-1 gap-0.5"> |
| ... | ... | @@ -89,7 +88,56 @@ function OverlayContent(props: { readonly progress: GitActionProgress }) { |
| 89 | 88 | {progress.prUrl ? ( |
| 90 | 89 | <SymbolView name="arrow.up.right" size={13} tintColor={iconColor} type="monochrome" /> |
| 91 | 90 | ) : null} |
| 92 | | </View> |
| 91 | </> |
| 92 | ); |
| 93 | |
| 94 | if (isLiquidGlassSupported) { |
| 95 | return ( |
| 96 | <Animated.View |
| 97 | layout={OVERLAY_LAYOUT_TRANSITION} |
| 98 | style={{ |
| 99 | backgroundColor: glassTint, |
| 100 | borderColor: glassBorder, |
| 101 | borderCurve: "continuous", |
| 102 | borderRadius: 26, |
| 103 | borderWidth: StyleSheet.hairlineWidth, |
| 104 | overflow: "hidden", |
| 105 | }} |
| 106 | > |
| 107 | <AnimatedLiquidGlassView |
| 108 | colorScheme={isDarkMode ? "dark" : "light"} |
| 109 | effect="regular" |
| 110 | interactive |
| 111 | layout={OVERLAY_LAYOUT_TRANSITION} |
| 112 | style={{ |
| 113 | borderCurve: "continuous", |
| 114 | borderRadius: 26, |
| 115 | overflow: "hidden", |
| 116 | }} |
| 117 | > |
| 118 | <Animated.View |
| 119 | entering={FadeIn.delay(60).duration(140)} |
| 120 | className="flex-row items-center gap-2.5 px-3.5 py-3" |
| 121 | > |
| 122 | {content} |
| 123 | </Animated.View> |
| 124 | </AnimatedLiquidGlassView> |
| 125 | </Animated.View> |
| 126 | ); |
| 127 | } |
| 128 | |
| 129 | const bgClass = |
| 130 | progress.phase === "error" |
| 131 | ? "bg-red-50 dark:bg-red-950/80 border-red-200 dark:border-red-800" |
| 132 | : "bg-card border-border"; |
| 133 | |
| 134 | return ( |
| 135 | <Animated.View |
| 136 | layout={OVERLAY_LAYOUT_TRANSITION} |
| 137 | className={`flex-row items-center gap-2.5 rounded-[26px] border border-continuous px-3.5 py-3 shadow-lg shadow-black/10 ${bgClass}`} |
| 138 | > |
| 139 | {content} |
| 140 | </Animated.View> |
| 93 | 141 | ); |
| 94 | 142 | } |
| 95 | 143 | |