feat: context menu on downloaditem

This commit is contained in:
Adrian Castro
2024-03-26 20:52:15 +01:00
parent 37570b3ee0
commit a86b1a0ea3
2 changed files with 73 additions and 29 deletions

View File

@@ -1,8 +1,13 @@
import type { Asset } from "expo-media-library";
import type { NativeSyntheticEvent } from "react-native";
import type { ContextMenuOnPressNativeEvent } from "react-native-context-menu-view";
import React from "react";
import ContextMenu from "react-native-context-menu-view";
import { TouchableOpacity } from "react-native-gesture-handler";
import { Progress, Spinner, Text, View } from "tamagui";
import { useDownloadManager } from "~/hooks/DownloadManagerContext";
export interface DownloadItemProps {
id: string;
filename: string;
@@ -18,6 +23,11 @@ export interface DownloadItemProps {
isHLS?: boolean;
}
enum ContextMenuActions {
Cancel = "Cancel",
Remove = "Remove",
}
const formatBytes = (bytes: number, decimals = 2) => {
if (bytes === 0) return "0 Bytes";
const k = 1024;
@@ -44,6 +54,24 @@ export const DownloadItem: React.FC<DownloadItemProps> = ({
const percentage = progress * 100;
const formattedFileSize = formatBytes(fileSize);
const formattedDownloaded = formatBytes(downloaded);
const { removeDownload, cancelDownload } = useDownloadManager();
const contextMenuActions = [
{
title: ContextMenuActions.Remove,
},
...(!isFinished ? [{ title: ContextMenuActions.Cancel }] : []),
];
const onContextMenuPress = (
e: NativeSyntheticEvent<ContextMenuOnPressNativeEvent>,
) => {
if (e.nativeEvent.name === ContextMenuActions.Cancel) {
void cancelDownload(id);
} else if (e.nativeEvent.name === ContextMenuActions.Remove) {
removeDownload(id);
}
};
const renderStatus = () => {
if (statusText) {
@@ -72,39 +100,50 @@ export const DownloadItem: React.FC<DownloadItemProps> = ({
};
return (
<TouchableOpacity
onPress={() => onPress(asset)}
onLongPress={() => onLongPress(id)}
activeOpacity={0.7}
<ContextMenu
actions={contextMenuActions}
onPress={onContextMenuPress}
previewBackgroundColor="transparent"
>
<View marginBottom={16} borderRadius={8} borderColor="white" padding={16}>
<Text marginBottom={4} fontSize={16}>
{filename}
</Text>
<Progress
value={percentage}
height={10}
backgroundColor="$progressBackground"
>
<Progress.Indicator
animation="bounce"
backgroundColor="$progressFilled"
/>
</Progress>
<TouchableOpacity
onPress={() => onPress(asset)}
onLongPress={() => onLongPress(id)}
activeOpacity={0.7}
>
<View
marginTop={8}
flexDirection="row"
alignItems="center"
justifyContent="space-between"
marginBottom={16}
borderRadius={8}
borderColor="white"
padding={16}
>
<Text fontSize={12} color="gray">
{isHLS
? `${percentage.toFixed()}% - ${downloaded} of ${fileSize} segments`
: `${percentage.toFixed()}% - ${formattedDownloaded} of ${formattedFileSize}`}
<Text marginBottom={4} fontSize={16}>
{filename}
</Text>
{renderStatus()}
<Progress
value={percentage}
height={10}
backgroundColor="$progressBackground"
>
<Progress.Indicator
animation="bounce"
backgroundColor="$progressFilled"
/>
</Progress>
<View
marginTop={8}
flexDirection="row"
alignItems="center"
justifyContent="space-between"
>
<Text fontSize={12} color="gray">
{isHLS
? `${percentage.toFixed()}% - ${downloaded} of ${fileSize} segments`
: `${percentage.toFixed()}% - ${formattedDownloaded} of ${formattedFileSize}`}
</Text>
{renderStatus()}
</View>
</View>
</View>
</TouchableOpacity>
</TouchableOpacity>
</ContextMenu>
);
};

View File

@@ -84,6 +84,11 @@ export const DownloadManagerProvider: React.FC<{ children: ReactNode }> = ({
if (downloadItem?.downloadResumable) {
await downloadItem.downloadResumable.cancelAsync();
}
toastController.show("Download cancelled", {
burntOptions: { preset: "done" },
native: true,
duration: 500,
});
};
const startDownload = async (