Improve git action toast feedback
This commit is contained in:
@@ -47,6 +47,7 @@ export function useToastHost(): {
|
||||
toast: ToastState | null;
|
||||
dismiss: () => void;
|
||||
} {
|
||||
const { theme } = useUnistyles();
|
||||
const [toast, setToast] = useState<ToastState | null>(null);
|
||||
const idRef = useRef(0);
|
||||
|
||||
@@ -84,11 +85,11 @@ export function useToastHost(): {
|
||||
copied: (label?: string) =>
|
||||
show(label ? `Copied ${label}` : "Copied", {
|
||||
variant: "success",
|
||||
icon: <CheckCircle2 size={18} />,
|
||||
icon: <CheckCircle2 size={18} color={theme.colors.foreground} />,
|
||||
}),
|
||||
error: (message: string) => show(message, { variant: "error", durationMs: 3200 }),
|
||||
}),
|
||||
[show],
|
||||
[show, theme.colors.foreground],
|
||||
);
|
||||
|
||||
const dismiss = useCallback(() => {
|
||||
@@ -113,6 +114,8 @@ export function ToastViewport({
|
||||
const opacity = useRef(new Animated.Value(0)).current;
|
||||
const translateY = useRef(new Animated.Value(-8)).current;
|
||||
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
const dismissDeadlineRef = useRef<number | null>(null);
|
||||
const remainingDurationRef = useRef(0);
|
||||
|
||||
const clearTimer = useCallback(() => {
|
||||
if (timeoutRef.current) {
|
||||
@@ -143,9 +146,39 @@ export function ToastViewport({
|
||||
});
|
||||
}, [clearTimer, onDismiss, opacity, translateY]);
|
||||
|
||||
const scheduleDismiss = useCallback(
|
||||
(durationMs: number) => {
|
||||
clearTimer();
|
||||
const nextDurationMs = Math.max(0, durationMs);
|
||||
remainingDurationRef.current = nextDurationMs;
|
||||
dismissDeadlineRef.current = Date.now() + nextDurationMs;
|
||||
timeoutRef.current = setTimeout(() => {
|
||||
animateOut();
|
||||
}, nextDurationMs);
|
||||
},
|
||||
[animateOut, clearTimer],
|
||||
);
|
||||
|
||||
const pauseDismiss = useCallback(() => {
|
||||
if (dismissDeadlineRef.current !== null) {
|
||||
remainingDurationRef.current = Math.max(0, dismissDeadlineRef.current - Date.now());
|
||||
}
|
||||
dismissDeadlineRef.current = null;
|
||||
clearTimer();
|
||||
}, [clearTimer]);
|
||||
|
||||
const resumeDismiss = useCallback(() => {
|
||||
if (!toast) {
|
||||
return;
|
||||
}
|
||||
scheduleDismiss(remainingDurationRef.current || toast.durationMs);
|
||||
}, [scheduleDismiss, toast]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!toast) {
|
||||
clearTimer();
|
||||
dismissDeadlineRef.current = null;
|
||||
remainingDurationRef.current = 0;
|
||||
opacity.setValue(0);
|
||||
translateY.setValue(-8);
|
||||
return;
|
||||
@@ -170,14 +203,13 @@ export function ToastViewport({
|
||||
}),
|
||||
]).start();
|
||||
|
||||
timeoutRef.current = setTimeout(() => {
|
||||
animateOut();
|
||||
}, toast.durationMs);
|
||||
remainingDurationRef.current = toast.durationMs;
|
||||
scheduleDismiss(toast.durationMs);
|
||||
|
||||
return () => {
|
||||
clearTimer();
|
||||
};
|
||||
}, [animateOut, clearTimer, opacity, toast, translateY]);
|
||||
}, [clearTimer, opacity, scheduleDismiss, toast, translateY]);
|
||||
|
||||
if (!toast) {
|
||||
return null;
|
||||
@@ -202,6 +234,8 @@ export function ToastViewport({
|
||||
<View style={styles.container} pointerEvents="box-none">
|
||||
<Animated.View
|
||||
testID={toast.testID ?? "app-toast"}
|
||||
onPointerEnter={pauseDismiss}
|
||||
onPointerLeave={resumeDismiss}
|
||||
style={[
|
||||
styles.toast,
|
||||
toast.variant === "success" ? styles.toastSuccess : null,
|
||||
@@ -219,7 +253,6 @@ export function ToastViewport({
|
||||
<Text
|
||||
testID="app-toast-message"
|
||||
style={[styles.message, toast.variant === "error" ? styles.messageError : null]}
|
||||
numberOfLines={2}
|
||||
>
|
||||
{toast.content}
|
||||
</Text>
|
||||
@@ -255,7 +288,7 @@ const styles = StyleSheet.create((theme) => ({
|
||||
alignItems: "center",
|
||||
gap: theme.spacing[2],
|
||||
backgroundColor: theme.colors.surface0,
|
||||
borderRadius: theme.borderRadius.full,
|
||||
borderRadius: theme.borderRadius["2xl"],
|
||||
borderWidth: theme.borderWidth[1],
|
||||
borderColor: theme.colors.border,
|
||||
paddingVertical: theme.spacing[2],
|
||||
|
||||
Reference in New Issue
Block a user