添加同步历史列表

This commit is contained in:
lyswhut 2023-02-20 17:58:24 +08:00
parent 59cc117143
commit 90a0f548c2
5 changed files with 115 additions and 75 deletions

View File

@ -254,6 +254,7 @@
"setting_sync_enbale": "Enable sync",
"setting_sync_history": "History address",
"setting_sync_history_empty": "Nothing here",
"setting_sync_history_title": "Connection history",
"setting_sync_host_label": "Synchronization service IP address",
"setting_sync_host_tip": "Please enter the synchronization service IP address",
"setting_sync_port_label": "Synchronization service port number",

View File

@ -1,4 +1,4 @@
import ChoosePath, { ChoosePathType } from '@/components/common/ChoosePath'
import ChoosePath, { type ChoosePathType } from '@/components/common/ChoosePath'
import { LXM_FILE_EXT_RXP } from '@/config/constant'
import React, { forwardRef, useImperativeHandle, useRef, useState } from 'react'
import { InteractionManager } from 'react-native'

View File

@ -1,97 +1,142 @@
import React, { memo, useRef, useState, useEffect, useCallback } from 'react'
import React, { memo, useRef, useState, useCallback, useImperativeHandle, forwardRef } from 'react'
import { View, TouchableOpacity, ScrollView } from 'react-native'
// import { gzip, ungzip } from 'pako'
import { Icon } from '@/components/common/Icon'
import Button from '../components/Button'
import { useTranslation } from '@/plugins/i18n'
import { createStyle, getSyncHostHistory, removeSyncHostHistory, setSyncHost } from '@/utils/tools'
import Popup from '@/components/common/Popup'
import { getSyncHostHistory, removeSyncHostHistory, setSyncHost } from '@/utils/data'
import Popup, { type PopupType } from '@/components/common/Popup'
import { BorderWidths } from '@/theme'
import Text from '@/components/common/Text'
import { useTheme } from '@/store/theme/hook'
import { useI18n } from '@/lang'
import { useSettingValue } from '@/store/setting/hook'
import { createStyle } from '@/utils/tools'
const HistoryListItem = ({ item, index, remove, setHostInfo }) => {
const theme = useGetter('common', 'theme')
type SyncHistoryItem = Awaited<ReturnType<typeof getSyncHostHistory>>[number]
const HistoryListItem = ({ item, index, onRemove, onSelect }: {
item: SyncHistoryItem
index: number
onRemove: (index: number) => void
onSelect: (index: number) => void
}) => {
const theme = useTheme()
const handleSetHost = () => {
setHostInfo({
host: item.host,
port: item.port,
})
setSyncHost({
host: item.host,
port: item.port,
})
onSelect(index)
// setHostInfo({
// host: item.host,
// port: item.port,
// })
// setSyncHost({
// host: item.host,
// port: item.port,
// })
}
const handleRemove = () => {
remove(index)
onRemove(index)
}
return (
<View style={{ ...styles.listItem, borderBottomColor: theme.borderColor }}>
<View style={{ ...styles.listItem, borderBottomColor: theme['c-border-background'] }}>
<TouchableOpacity style={styles.listName} onPress={handleSetHost}>
<Text numberOfLines={1}>{item.host}</Text>
<Text color={theme['c-font-label']} numberOfLines={1}>{item.port}</Text>
</TouchableOpacity>
<TouchableOpacity onPress={handleRemove} style={styles.listMoreBtn}>
<Icon name="remove" style={{ color: theme.normal35 }} size={16} />
<TouchableOpacity onPress={handleRemove} style={styles.listBtn}>
<Icon name="remove" color={theme['c-font-label']} size={12} />
</TouchableOpacity>
</View>
)
}
const HistoryList = ({ visible, setHostInfo }) => {
const [list, setList] = useState([])
const isUnmountedRef = useRef(true)
const theme = useGetter('common', 'theme')
const { t } = useTranslation()
const getHistory = () => {
getSyncHostHistory().then(historyList => {
if (isUnmountedRef.current) return
interface HistoryListProps {
onSelect: (item: SyncHistoryItem) => void
}
interface HistoryListType {
show: () => void
}
const HistoryList = forwardRef<HistoryListType, HistoryListProps>(({ onSelect }, ref) => {
const popupRef = useRef<PopupType>(null)
const [visible, setVisible] = useState(false)
const [list, setList] = useState<SyncHistoryItem[]>([])
// const isUnmountedRef = useRef(true)
const theme = useTheme()
const t = useI18n()
const handleShow = () => {
popupRef.current?.setVisible(true)
requestAnimationFrame(() => {
void getSyncHostHistory().then(historyList => {
setList([...historyList])
})
})
}
useEffect(() => {
if (!visible) return
getHistory()
}, [visible])
useEffect(() => {
isUnmountedRef.current = false
return () => {
isUnmountedRef.current = true
useImperativeHandle(ref, () => ({
show() {
if (visible) handleShow()
else {
setVisible(true)
requestAnimationFrame(() => {
handleShow()
})
}
}, [])
},
}))
const handleRemove = useCallback((index) => {
removeSyncHostHistory(index)
const handleSelect = useCallback((index: number) => {
popupRef.current?.setVisible(false)
onSelect(list[index])
}, [list, onSelect])
const handleRemove = useCallback((index: number) => {
void removeSyncHostHistory(index)
const newList = [...list]
newList.splice(index, 1)
setList(newList)
}, [list])
return (
visible
? (
<Popup ref={popupRef} title={t('setting_sync_history_title')}>
<ScrollView style={styles.list}>
{
list.length
? list.map((item, index) => <HistoryListItem item={item} index={index} remove={handleRemove} key={`${item.host}:${item.port}`} setHostInfo={setHostInfo} />)
? list.map((item, index) => (
<HistoryListItem
item={item}
index={index}
onRemove={handleRemove}
key={`${item.host}:${item.port}`}
onSelect={handleSelect}
/>
))
: <Text style={styles.tipText} color={theme['c-font-label']}>{t('setting_sync_history_empty')}</Text>
}
</ScrollView>
</Popup>
)
}
: null
)
})
export default memo(({ setHostInfo, isWaiting }) => {
const { t } = useTranslation()
const [visible, setVisible] = useState(false)
const isEnableSync = useGetter('common', 'isEnableSync')
export default memo(({ setHostInfo, isWaiting }: {
setHostInfo: (hostInfo: { host: string, port: string }) => void
isWaiting: boolean
}) => {
const t = useI18n()
const isEnableSync = useSettingValue('sync.enable')
const listRef = useRef<HistoryListType>(null)
const showPopup = () => {
setVisible(true)
listRef.current?.show()
}
const hidePopup = () => {
setVisible(false)
const handleSelect = (item: SyncHistoryItem) => {
setHostInfo(item)
void setSyncHost(item)
}
return (
@ -99,21 +144,12 @@ export default memo(({ setHostInfo, isWaiting }) => {
<View style={styles.btn}>
<Button disabled={isWaiting || isEnableSync} onPress={showPopup}>{t('setting_sync_history')}</Button>
</View>
<Popup
visible={visible}
hide={hidePopup}
title={t('setting_sync_history_title')}
>
<HistoryList visible={visible} setHostInfo={setHostInfo} />
</Popup>
<HistoryList ref={listRef} onSelect={handleSelect} />
</>
)
})
const styles = createStyle({
cacheSize: {
marginBottom: 5,
},
btn: {
flexDirection: 'row',
marginLeft: 25,
@ -126,17 +162,20 @@ const styles = createStyle({
list: {
flexShrink: 1,
flexGrow: 0,
paddingLeft: 10,
paddingRight: 10,
paddingLeft: 15,
paddingRight: 15,
},
listItem: {
flexDirection: 'row',
alignItems: 'center',
paddingTop: 5,
paddingBottom: 5,
paddingTop: 8,
paddingBottom: 8,
borderBottomWidth: BorderWidths.normal,
},
listName: {
flex: 1,
},
listBtn: {
padding: 5,
},
})

View File

@ -2,7 +2,7 @@ import React, { memo, useState } from 'react'
import Section from '../components/Section'
import IsEnable from './IsEnable'
// import History from './History'
import History from './History'
import { useI18n } from '@/lang'
// import SyncHost from './SyncHost'
@ -15,7 +15,7 @@ export default memo(() => {
return (
<Section title={t('setting_sync')}>
<IsEnable hostInfo={hostInfo} setHostInfo={setHostInfo} isWaiting={isWaiting} setIsWaiting={setIsWaiting} />
{/* <History setHostInfo={setHostInfo} isWaiting={isWaiting} /> */}
<History setHostInfo={setHostInfo} isWaiting={isWaiting} />
</Section>
)
})

2
src/types/sync.d.ts vendored
View File

@ -1,4 +1,4 @@
import { io } from 'socket.io-client'
import { type io } from 'socket.io-client'
declare global {
namespace LX {