mirror of
https://github.com/movie-web/native-app.git
synced 2025-09-13 16:33:26 +00:00
flash text while its in progress
This commit is contained in:
@@ -1,10 +1,9 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Alert, Platform } from "react-native";
|
import { Alert, Platform } from "react-native";
|
||||||
import { ScrollView } from "react-native-gesture-handler";
|
|
||||||
import { useFocusEffect, useRouter } from "expo-router";
|
import { useFocusEffect, useRouter } from "expo-router";
|
||||||
import { MaterialCommunityIcons } from "@expo/vector-icons";
|
import { MaterialCommunityIcons } from "@expo/vector-icons";
|
||||||
import { isDevelopmentProvisioningProfile } from "modules/check-ios-certificate";
|
import { isDevelopmentProvisioningProfile } from "modules/check-ios-certificate";
|
||||||
import { useTheme, YStack } from "tamagui";
|
import { ScrollView, useTheme, YStack } from "tamagui";
|
||||||
|
|
||||||
import type { ScrapeMedia } from "@movie-web/provider-utils";
|
import type { ScrapeMedia } from "@movie-web/provider-utils";
|
||||||
|
|
||||||
@@ -114,7 +113,11 @@ const DownloadsScreen: React.FC = () => {
|
|||||||
test download (hls)
|
test download (hls)
|
||||||
</MWButton>
|
</MWButton>
|
||||||
</YStack>
|
</YStack>
|
||||||
<ScrollView>
|
<ScrollView
|
||||||
|
contentContainerStyle={{
|
||||||
|
gap: "$4",
|
||||||
|
}}
|
||||||
|
>
|
||||||
{downloads.map((item) => (
|
{downloads.map((item) => (
|
||||||
<DownloadItem
|
<DownloadItem
|
||||||
key={item.id}
|
key={item.id}
|
||||||
|
@@ -8,6 +8,7 @@ import { Image, Text, View, XStack, YStack } from "tamagui";
|
|||||||
import type { Download } from "~/contexts/DownloadManagerContext";
|
import type { Download } from "~/contexts/DownloadManagerContext";
|
||||||
import { useDownloadManager } from "~/contexts/DownloadManagerContext";
|
import { useDownloadManager } from "~/contexts/DownloadManagerContext";
|
||||||
import { MWProgress } from "./ui/Progress";
|
import { MWProgress } from "./ui/Progress";
|
||||||
|
import { FlashingText } from "./ui/Text";
|
||||||
|
|
||||||
export interface DownloadItemProps {
|
export interface DownloadItemProps {
|
||||||
item: Download;
|
item: Download;
|
||||||
@@ -62,6 +63,12 @@ export function DownloadItem(props: DownloadItemProps) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isInProgress = !(
|
||||||
|
props.item.status === "finished" ||
|
||||||
|
props.item.status === "error" ||
|
||||||
|
props.item.status === "cancelled"
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContextMenu
|
<ContextMenu
|
||||||
actions={contextMenuActions}
|
actions={contextMenuActions}
|
||||||
@@ -112,9 +119,15 @@ export function DownloadItem(props: DownloadItemProps) {
|
|||||||
: `${percentage.toFixed()}% - ${formattedDownloaded} of ${formattedFileSize}`}
|
: `${percentage.toFixed()}% - ${formattedDownloaded} of ${formattedFileSize}`}
|
||||||
</Text>
|
</Text>
|
||||||
<View style={{ flexDirection: "row", alignItems: "center" }}>
|
<View style={{ flexDirection: "row", alignItems: "center" }}>
|
||||||
<Text fontSize="$2" color="gray">
|
<FlashingText
|
||||||
|
isInProgress={isInProgress}
|
||||||
|
style={{
|
||||||
|
fontSize: 12,
|
||||||
|
color: "gray",
|
||||||
|
}}
|
||||||
|
>
|
||||||
{statusToTextMap[props.item.status]}
|
{statusToTextMap[props.item.status]}
|
||||||
</Text>
|
</FlashingText>
|
||||||
</View>
|
</View>
|
||||||
</XStack>
|
</XStack>
|
||||||
</YStack>
|
</YStack>
|
||||||
|
@@ -23,7 +23,7 @@ export const Header = () => {
|
|||||||
height={64}
|
height={64}
|
||||||
paddingHorizontal="$8"
|
paddingHorizontal="$8"
|
||||||
>
|
>
|
||||||
<View width={144}>
|
<View width={150}>
|
||||||
<Controls>
|
<Controls>
|
||||||
<BackButton />
|
<BackButton />
|
||||||
</Controls>
|
</Controls>
|
||||||
@@ -39,7 +39,7 @@ export const Header = () => {
|
|||||||
: ""}
|
: ""}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
<View alignItems="center" justifyContent="center" width={130}>
|
<View alignItems="center" justifyContent="center" width={150}>
|
||||||
<BrandPill />
|
<BrandPill />
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
36
apps/expo/src/components/ui/Text.tsx
Normal file
36
apps/expo/src/components/ui/Text.tsx
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import type { TextProps } from "react-native";
|
||||||
|
import type { AnimatedProps } from "react-native-reanimated";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
import Animated, {
|
||||||
|
Easing,
|
||||||
|
useAnimatedStyle,
|
||||||
|
useSharedValue,
|
||||||
|
withRepeat,
|
||||||
|
withTiming,
|
||||||
|
} from "react-native-reanimated";
|
||||||
|
|
||||||
|
export const FlashingText = (
|
||||||
|
props: AnimatedProps<TextProps> & {
|
||||||
|
isInProgress: boolean;
|
||||||
|
},
|
||||||
|
) => {
|
||||||
|
const opacity = useSharedValue(0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (props.isInProgress) {
|
||||||
|
opacity.value = withRepeat(
|
||||||
|
withTiming(1, { duration: 1000, easing: Easing.ease }),
|
||||||
|
-1,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
opacity.value = 1;
|
||||||
|
}
|
||||||
|
}, [props.isInProgress, opacity]);
|
||||||
|
|
||||||
|
const style = useAnimatedStyle(() => ({
|
||||||
|
opacity: opacity.value,
|
||||||
|
}));
|
||||||
|
|
||||||
|
return <Animated.Text {...props} style={[props.style, style]} />;
|
||||||
|
};
|
Reference in New Issue
Block a user