mirror of
https://github.com/movie-web/native-app.git
synced 2025-09-13 16:53:25 +00:00
feat: downloaditem placeholder
This commit is contained in:
@@ -49,6 +49,7 @@
|
|||||||
"react-native-css-interop": "^0.0.35",
|
"react-native-css-interop": "^0.0.35",
|
||||||
"react-native-gesture-handler": "~2.14.1",
|
"react-native-gesture-handler": "~2.14.1",
|
||||||
"react-native-modal": "^13.0.1",
|
"react-native-modal": "^13.0.1",
|
||||||
|
"react-native-progress": "^5.0.1",
|
||||||
"react-native-quick-base64": "^2.0.8",
|
"react-native-quick-base64": "^2.0.8",
|
||||||
"react-native-quick-crypto": "^0.6.1",
|
"react-native-quick-crypto": "^0.6.1",
|
||||||
"react-native-reanimated": "~3.6.2",
|
"react-native-reanimated": "~3.6.2",
|
||||||
|
@@ -1,10 +1,34 @@
|
|||||||
|
import { ScrollView } from "react-native-gesture-handler";
|
||||||
|
|
||||||
|
import type { DownloadItemProps } from "~/components/DownloadItem";
|
||||||
|
import { DownloadItem } from "~/components/DownloadItem";
|
||||||
import ScreenLayout from "~/components/layout/ScreenLayout";
|
import ScreenLayout from "~/components/layout/ScreenLayout";
|
||||||
import { Text } from "~/components/ui/Text";
|
|
||||||
|
|
||||||
export default function DownloadsScreen() {
|
export default function DownloadsScreen() {
|
||||||
|
const downloads: DownloadItemProps[] = [
|
||||||
|
{
|
||||||
|
filename: "episode.mp4",
|
||||||
|
progress: 0.3,
|
||||||
|
speed: 1.2,
|
||||||
|
fileSize: 500 * 1024 * 1024,
|
||||||
|
downloaded: 150 * 1024 * 1024,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
filename: "episode.m3u8",
|
||||||
|
progress: 0.7,
|
||||||
|
speed: 0.8,
|
||||||
|
fileSize: 200 * 1024 * 1024,
|
||||||
|
downloaded: 140 * 1024 * 1024,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScreenLayout title="Downloads">
|
<ScreenLayout title="Downloads">
|
||||||
<Text>Downloads tab</Text>
|
<ScrollView>
|
||||||
|
{downloads.map((item, index) => (
|
||||||
|
<DownloadItem key={index} {...item} />
|
||||||
|
))}
|
||||||
|
</ScrollView>
|
||||||
</ScreenLayout>
|
</ScreenLayout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
55
apps/expo/src/components/DownloadItem.tsx
Normal file
55
apps/expo/src/components/DownloadItem.tsx
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Text, View } from "react-native";
|
||||||
|
import { Bar as ProgressBar } from "react-native-progress";
|
||||||
|
|
||||||
|
import colors from "@movie-web/tailwind-config/colors";
|
||||||
|
|
||||||
|
export interface DownloadItemProps {
|
||||||
|
filename: string;
|
||||||
|
progress: number;
|
||||||
|
speed: number;
|
||||||
|
fileSize: number;
|
||||||
|
downloaded: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatBytes = (bytes: number, decimals = 2) => {
|
||||||
|
if (bytes === 0) return "0 Bytes";
|
||||||
|
const k = 1024;
|
||||||
|
const dm = decimals < 0 ? 0 : decimals;
|
||||||
|
const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
||||||
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DownloadItem: React.FC<DownloadItemProps> = ({
|
||||||
|
filename,
|
||||||
|
progress,
|
||||||
|
speed,
|
||||||
|
fileSize,
|
||||||
|
downloaded,
|
||||||
|
}) => {
|
||||||
|
const percentage = (progress * 100).toFixed(0);
|
||||||
|
const formattedFileSize = formatBytes(fileSize);
|
||||||
|
const formattedDownloaded = formatBytes(downloaded);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View className="mb-4 rounded-lg border border-gray-300 p-4">
|
||||||
|
<Text className="mb-2 text-lg text-gray-200">{filename}</Text>
|
||||||
|
<ProgressBar
|
||||||
|
progress={progress}
|
||||||
|
width={null}
|
||||||
|
color={colors.primary[400]}
|
||||||
|
unfilledColor={colors.gray[200]}
|
||||||
|
borderWidth={0}
|
||||||
|
height={10}
|
||||||
|
borderRadius={5}
|
||||||
|
/>
|
||||||
|
<View className="mt-2 flex-row items-center justify-between">
|
||||||
|
<Text className="text-sm text-gray-600">
|
||||||
|
{percentage}% - {formattedDownloaded} of {formattedFileSize}
|
||||||
|
</Text>
|
||||||
|
<Text className="text-sm text-gray-600">{speed} MB/s</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
12
pnpm-lock.yaml
generated
12
pnpm-lock.yaml
generated
@@ -119,6 +119,9 @@ importers:
|
|||||||
react-native-modal:
|
react-native-modal:
|
||||||
specifier: ^13.0.1
|
specifier: ^13.0.1
|
||||||
version: 13.0.1(react-native@0.73.2)(react@18.2.0)
|
version: 13.0.1(react-native@0.73.2)(react@18.2.0)
|
||||||
|
react-native-progress:
|
||||||
|
specifier: ^5.0.1
|
||||||
|
version: 5.0.1(react-native-svg@14.1.0)
|
||||||
react-native-quick-base64:
|
react-native-quick-base64:
|
||||||
specifier: ^2.0.8
|
specifier: ^2.0.8
|
||||||
version: 2.0.8(react-native@0.73.2)(react@18.2.0)
|
version: 2.0.8(react-native@0.73.2)(react@18.2.0)
|
||||||
@@ -9253,6 +9256,15 @@ packages:
|
|||||||
react-native-animatable: 1.3.3
|
react-native-animatable: 1.3.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/react-native-progress@5.0.1(react-native-svg@14.1.0):
|
||||||
|
resolution: {integrity: sha512-TYfJ4auAe5vubDma2yfFvt7ktSI+UCfysqJnkdHEcLXqAitRFOozgF/cLgN5VNi/iLdaf3ga1ETi2RF4jVZ/+g==}
|
||||||
|
peerDependencies:
|
||||||
|
react-native-svg: '*'
|
||||||
|
dependencies:
|
||||||
|
prop-types: 15.8.1
|
||||||
|
react-native-svg: 14.1.0(react-native@0.73.2)(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/react-native-quick-base64@2.0.8(react-native@0.73.2)(react@18.2.0):
|
/react-native-quick-base64@2.0.8(react-native@0.73.2)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-2kMlnLSy0qz4NA0KXMGugd3qNB5EAizxZ6ghEVNGIxAOlc9CGvC8miv35wgpFbSKeiaBRfcPfkdTM/5Erb/6SQ==}
|
resolution: {integrity: sha512-2kMlnLSy0qz4NA0KXMGugd3qNB5EAizxZ6ghEVNGIxAOlc9CGvC8miv35wgpFbSKeiaBRfcPfkdTM/5Erb/6SQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
Reference in New Issue
Block a user