136 lines
4.4 KiB
TypeScript
136 lines
4.4 KiB
TypeScript
import { Ionicons } from '@expo/vector-icons'
|
||
import { Block, ConfirmModal, ListEmpty, Text, Toast, VideoBox } from '@share/components'
|
||
import { FlashList } from '@shopify/flash-list'
|
||
import { router, Stack, useFocusEffect } from 'expo-router'
|
||
import { observer } from 'mobx-react-lite'
|
||
import React, { useCallback, useEffect } from 'react'
|
||
|
||
import { bleManager } from '@/ble/managers/bleManager'
|
||
import BannerSection from '@/components/BannerSection'
|
||
import { bleStore, userStore } from '@/stores'
|
||
import { screenWidth } from '@/utils'
|
||
import { buildCdnUrl } from '@/utils/getCDNKey'
|
||
|
||
// ============ 主组件 ============
|
||
const Device = observer(() => {
|
||
const { user, isAuthenticated } = userStore
|
||
|
||
const { isConnected } = bleStore.state
|
||
const { galleryList } = bleStore
|
||
const itemWidth = Math.floor((screenWidth - 12 * 2 - 12 * 2) / 3)
|
||
|
||
useFocusEffect(() => {
|
||
if (!isAuthenticated) {
|
||
router.replace('/')
|
||
router.push('/auth')
|
||
}
|
||
})
|
||
|
||
useEffect(() => {
|
||
if (!isConnected) {
|
||
Toast.show({ title: `设备已断开连接` })
|
||
router.back()
|
||
}
|
||
}, [isConnected])
|
||
|
||
const renderGridItem = useCallback(
|
||
({ item }: { item: any }) => {
|
||
const handleDeleteConfirm = async () => {
|
||
try {
|
||
await bleManager.deleteFile(item)
|
||
bleStore.removeGalleryItem(item)
|
||
Toast.hideModal()
|
||
} catch (error: any) {
|
||
// console.error('Error deleting file:', error)
|
||
// Toast.show({ title: `删除失败: ${error?.message || error}` })
|
||
}
|
||
}
|
||
|
||
const handleDelete = async () => {
|
||
if (!isConnected) {
|
||
Toast.show({ title: `请先连接设备` })
|
||
return
|
||
}
|
||
if (galleryList.length <= 1) {
|
||
Toast.show({ title: `至少保留一个文件` })
|
||
return
|
||
}
|
||
Toast.showModal(
|
||
<ConfirmModal
|
||
title="删除文件"
|
||
content={
|
||
<Text className="text-[14px] font-bold leading-relaxed text-gray-800">确定要删除这个文件吗?</Text>
|
||
}
|
||
onCancel={() => Toast.hideModal()}
|
||
onConfirm={handleDeleteConfirm}
|
||
/>,
|
||
)
|
||
}
|
||
|
||
const url = buildCdnUrl(item)
|
||
if (!url) return null
|
||
|
||
return (
|
||
<Block className="relative">
|
||
<Block
|
||
className={`relative overflow-hidden border-2 ${'shadow-hard-black'} ${'border-black'}`}
|
||
style={{ transform: [{ skewX: '-6deg' }], height: itemWidth, width: itemWidth }}
|
||
>
|
||
<Block className="flex items-center justify-center" style={{ height: itemWidth, width: itemWidth }}>
|
||
<VideoBox style={{ width: itemWidth, height: itemWidth }} url={url} />
|
||
</Block>
|
||
|
||
{/* 删除按钮 */}
|
||
<Block
|
||
className="absolute right-1 top-1 z-20 size-6 items-center justify-center rounded-full border-2 border-black bg-[#e61e25] shadow-hard-black"
|
||
style={{ transform: [{ skewX: '6deg' }] }}
|
||
onClick={() => {
|
||
handleDelete()
|
||
}}
|
||
>
|
||
<Ionicons color="white" name="trash-outline" size={12} />
|
||
</Block>
|
||
</Block>
|
||
</Block>
|
||
)
|
||
},
|
||
[itemWidth],
|
||
)
|
||
|
||
const renderHeader = () => (
|
||
<Block className="flex-row items-center justify-between px-[16px]" style={{ paddingTop: 12, paddingBottom: 12 }}>
|
||
<Block className="ml-[-8px] size-[40px] items-center justify-center" opacity={0.7} onClick={() => router.back()}>
|
||
<Ionicons color="white" name="chevron-back" size={24} />
|
||
</Block>
|
||
<Text className="text-[16px] font-[700] text-white">吧唧管理</Text>
|
||
<Block className="w-[32px]" />
|
||
</Block>
|
||
)
|
||
|
||
return (
|
||
<Block className="relative flex-1">
|
||
<BannerSection />
|
||
<Stack.Screen options={{ headerShown: false }} />
|
||
{renderHeader()}
|
||
|
||
<Block className="z-10 flex-1">
|
||
<FlashList
|
||
contentContainerStyle={{ paddingHorizontal: 12, paddingBottom: 200 }}
|
||
data={galleryList}
|
||
drawDistance={1200}
|
||
// @ts-ignore
|
||
estimatedItemSize={itemWidth}
|
||
getItemType={() => 'row'}
|
||
ItemSeparatorComponent={() => <Block style={{ height: 6 }} />}
|
||
keyExtractor={(item) => item}
|
||
ListEmptyComponent={<ListEmpty />}
|
||
numColumns={3}
|
||
renderItem={renderGridItem}
|
||
/>
|
||
</Block>
|
||
</Block>
|
||
)
|
||
})
|
||
|
||
export default Device
|