import { ConstEnv } from "@/constants/ConstEnv"; import Styles from "@/constants/Styles"; import { apiDeleteFileProject, apiGetProjectOne } from "@/lib/api"; import { setUpdateProject } from "@/lib/projectUpdate"; import { useAuthSession } from "@/providers/AuthProvider"; import { useTheme } from "@/providers/ThemeProvider"; import { Ionicons, MaterialCommunityIcons } from "@expo/vector-icons"; import * as FileSystem from 'expo-file-system'; import { startActivityAsync } from 'expo-intent-launcher'; import { useLocalSearchParams } from "expo-router"; import * as Sharing from 'expo-sharing'; import { useEffect, useState } from "react"; import { Alert, Platform, Pressable, View } from "react-native"; import * as mime from 'react-native-mime-types'; import Toast from "react-native-toast-message"; import { useDispatch, useSelector } from "react-redux"; import DrawerBottom from "../drawerBottom"; import MenuItemRow from "../menuItemRow"; import ModalConfirmation from "../ModalConfirmation"; import ModalLoading from "../modalLoading"; import Skeleton from "../skeleton"; import Text from "../Text"; type Props = { id: string name: string extension: string idStorage: string } function getFileIcon(extension: string): keyof typeof MaterialCommunityIcons.glyphMap { const ext = extension.toLowerCase() if (['jpg', 'jpeg', 'png', 'gif', 'webp', 'heic', 'heif'].includes(ext)) return 'image-outline' if (ext === 'pdf') return 'file-pdf-box' if (['mp4', 'mov', 'avi', 'mkv'].includes(ext)) return 'video-outline' if (['doc', 'docx'].includes(ext)) return 'file-word-outline' if (['xls', 'xlsx'].includes(ext)) return 'file-excel-outline' if (['zip', 'rar', '7z'].includes(ext)) return 'zip-box-outline' return 'file-outline' } function getFileColor(extension: string): string { const ext = extension.toLowerCase() if (['jpg', 'jpeg', 'png', 'gif', 'webp', 'heic', 'heif'].includes(ext)) return '#339AF0' if (ext === 'pdf') return '#F03E3E' if (['mp4', 'mov', 'avi', 'mkv'].includes(ext)) return '#AE3EC9' if (['doc', 'docx'].includes(ext)) return '#1C7ED6' if (['xls', 'xlsx'].includes(ext)) return '#2F9E44' if (['zip', 'rar', '7z'].includes(ext)) return '#E8590C' return '#868E96' } export default function SectionFile({ status, member, refreshing }: { status: number | undefined, member: boolean, refreshing?: boolean }) { const { colors } = useTheme(); const entityUser = useSelector((state: any) => state.user) const [isModal, setModal] = useState(false) const { token, decryptToken } = useAuthSession(); const { id } = useLocalSearchParams<{ id: string }>(); const [data, setData] = useState([]); const update = useSelector((state: any) => state.projectUpdate) const dispatch = useDispatch() const [loading, setLoading] = useState(true) const arrSkeleton = Array.from({ length: 4 }) const [selectFile, setSelectFile] = useState(null) const [showDeleteModal, setShowDeleteModal] = useState(false) const [loadingOpen, setLoadingOpen] = useState(false) async function handleLoad(loading: boolean) { try { setLoading(loading) const hasil = await decryptToken(String(token?.current)); const response = await apiGetProjectOne({ user: hasil, cat: "file", id }); setData(response.data); } catch (error) { console.error(error); } finally { setLoading(false) } } useEffect(() => { handleLoad(false) }, [update.file]); useEffect(() => { if (refreshing) handleLoad(false) }, [refreshing]); useEffect(() => { handleLoad(true) }, []); async function handleDelete() { try { const hasil = await decryptToken(String(token?.current)); const response = await apiDeleteFileProject({ user: hasil }, String(selectFile?.id)); if (response.success) { Toast.show({ type: 'small', text1: 'Berhasil menghapus file' }) dispatch(setUpdateProject({ ...update, file: !update.file })) } else { Toast.show({ type: 'small', text1: response.message }) } } catch (error: any) { Toast.show({ type: 'small', text1: error?.response?.data?.message || "Gagal menghapus file" }) } finally { setModal(false) } } const openFile = () => { setModal(false) setLoadingOpen(true) const remoteUrl = ConstEnv.url_storage + '/files/' + selectFile?.idStorage const fileName = selectFile?.name + '.' + selectFile?.extension const localPath = `${FileSystem.documentDirectory}/${fileName}` const mimeType = mime.lookup(fileName) FileSystem.downloadAsync(remoteUrl, localPath).then(async ({ uri }) => { const contentURL = await FileSystem.getContentUriAsync(uri) try { if (Platform.OS === 'android') { await startActivityAsync('android.intent.action.VIEW', { data: contentURL, flags: 1, type: mimeType as string }) } else { Sharing.shareAsync(localPath) } } catch { Alert.alert('INFO', 'Gagal membuka file, tidak ada aplikasi yang dapat membuka file ini') } finally { setLoadingOpen(false) } }) } return ( <> File {loading ? ( {arrSkeleton.map((_, index) => ( ))} ) : data.length > 0 ? ( {data.map((item, index) => { const iconName = getFileIcon(item.extension) const iconColor = getFileColor(item.extension) return ( { setSelectFile(item); setModal(true) }} style={[Styles.fileCard, { backgroundColor: colors.card, borderColor: colors.icon + '18' }]} > {item.name} {item.extension.toUpperCase()} ) })} ) : ( Tidak ada file )} } title="Lihat / Share" onPress={openFile} /> {(!member && (entityUser.role === "user" || entityUser.role === "coadmin")) ? null : ( } title="Hapus" disabled={status === 3} onPress={() => { if (status === 3) return setModal(false) setTimeout(() => setShowDeleteModal(true), 600) }} /> )} { setShowDeleteModal(false); handleDelete() }} onCancel={() => setShowDeleteModal(false)} confirmText="Hapus" cancelText="Batal" /> ) }