新增同步服务地址历史列表功能

This commit is contained in:
lyswhut 2021-12-20 13:00:56 +08:00
parent e8ba013186
commit 69d46ec4bd
12 changed files with 191 additions and 19 deletions

View File

@ -2,6 +2,7 @@
- 同步功能新增对列表位置调整的支持(若你使用同步功能,请务必升级到此版本以上,不然会有问题)
- 新增播放详情页歌词字体大小调整设置,可在详情页右上角的按钮进行调整
- 新增同步服务地址历史列表功能
### 优化

View File

@ -19,6 +19,7 @@ export const storageDataPrefix = {
playInfo: '@play_info',
syncAuthKey: '@sync_auth_key',
syncHost: '@sync_host',
syncHostHistory: '@sync_host_history',
}
export const ITEM_HEIGHT = 60

View File

@ -69,7 +69,7 @@
"loading": "Loading...",
"move_to": "Move to...",
"name": "Name: {{name}}",
"nav__my_list": "My list",
"nav_my_list": "My list",
"parent_dir_name": "Parent directory",
"pause": "Pause",
"play": "Play",
@ -83,7 +83,7 @@
"play_prev": "Previous song",
"play_single": "Disable song switching",
"play_single_loop": "Single loop playback",
"player__setting_lrc_font_size": "Lyric font size setting",
"player_setting_lrc_font_size": "Lyric font size setting",
"quality_high_quality": "HQ",
"quality_lossless": "SQ",
"setting_about": "About LX Music",
@ -169,6 +169,8 @@
"setting_sync_code_input_tip": "Please enter the connection code",
"setting_sync_code_label": "You need to enter the connection code for the first connection",
"setting_sync_enbale": "Enable sync",
"setting_sync_history": "History address",
"setting_sync_history_empty": "Nothing here",
"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",
@ -178,7 +180,6 @@
"setting_version": "Software Update",
"setting_version_show_ver_modal": "Open the update window 🚀",
"singer": "Artist: {{name}}",
"songlist__tags": "Playlist category",
"songlist_hot": "Hot",
"songlist_hot_collect": "Hot Collect",
"songlist_new": "New",
@ -187,6 +188,7 @@
"songlist_open_input_tip": "1. Cross-source opening of the playlist is not supported. Please confirm whether the playlist to be opened corresponds to the current playlist source\n2. If you encounter a playlist link that cannot be opened, feedback is welcome\n3, Kugou source Open with playlist ID is not supported, but Kugou code is supported",
"songlist_recommend": "Recommend",
"songlist_rise": "Rise",
"songlist_tags": "Playlist category",
"source_alias_all": "Aggregated",
"source_alias_bd": "BD Music",
"source_alias_kg": "KG Music",

View File

@ -70,7 +70,7 @@
"loading": "加载中...",
"move_to": "移动到...",
"name": "歌曲名:{{name}}",
"nav__my_list": "我的列表",
"nav_my_list": "我的列表",
"parent_dir_name": "父级目录",
"pause": "暂停",
"play": "播放",
@ -84,7 +84,7 @@
"play_prev": "上一曲",
"play_single": "禁用歌曲切换",
"play_single_loop": "单曲循环播放",
"player__setting_lrc_font_size": "歌词字体大小设置",
"player_setting_lrc_font_size": "歌词字体大小设置",
"quality_high_quality": "高品质",
"quality_lossless": "无损",
"setting_about": "关于洛雪音乐",
@ -170,6 +170,9 @@
"setting_sync_code_input_tip": "请输入连接码",
"setting_sync_code_label": "首次连接需要输入连接码",
"setting_sync_enbale": "启用同步",
"setting_sync_history": "历史地址",
"setting_sync_history_empty": "这里啥也没有😮",
"setting_sync_history_title": "连接历史",
"setting_sync_host_label": "同步服务IP地址",
"setting_sync_host_tip": "请输入同步服务IP地址",
"setting_sync_port_label": "同步服务端口号",
@ -179,7 +182,6 @@
"setting_version": "软件更新",
"setting_version_show_ver_modal": "打开更新窗口 🚀",
"singer": "艺术家:{{name}}",
"songlist__tags": "歌单类别",
"songlist_hot": "最热",
"songlist_hot_collect": "热藏",
"songlist_new": "最新",
@ -188,6 +190,7 @@
"songlist_open_input_tip": "1、不支持跨源打开歌单请确认要打开的歌单与当前歌单源是否对应\n2、若遇到无法打开的歌单链接欢迎反馈\n3、酷狗源不支持用歌单ID打开但支持酷狗码打开",
"songlist_recommend": "推荐",
"songlist_rise": "飙升",
"songlist_tags": "歌单类别",
"source_alias_all": "聚合大会",
"source_alias_bd": "小杜音乐",
"source_alias_kg": "小枸音乐",

View File

@ -387,7 +387,7 @@ export default memo(({ currentList, handleCancelMultiSelect, showListSearchBar }
<Icon style={{ color: theme.secondary30, fontSize: 16 }} name="search-2" />
</TouchableOpacity>
</TouchableOpacity>
<Popup visible={visiblePanel} hide={hidePopup} title={t('nav__my_list')}>
<Popup visible={visiblePanel} hide={hidePopup} title={t('nav_my_list')}>
<List setVisiblePanel={setVisiblePanel} currentList={currentList} handleCancelMultiSelect={handleCancelMultiSelect} />
</Popup>
</View>

View File

@ -0,0 +1,143 @@
import React, { memo, useRef, useState, useEffect, useCallback } from 'react'
import { StyleSheet, View, Text, TouchableOpacity, ScrollView } from 'react-native'
import { useGetter } from '@/store'
// import { gzip, ungzip } from 'pako'
import Icon from '@/components/common/Icon'
import Button from '../components/Button'
import { useTranslation } from '@/plugins/i18n'
import { getSyncHostHistory, removeSyncHostHistory, setSyncHost } from '@/utils/tools'
import Popup from '@/components/common/Popup'
import { BorderWidths } from '@/theme'
const HistoryListItem = ({ item, index, remove, setHostInfo }) => {
const theme = useGetter('common', 'theme')
const handleSetHost = () => {
setHostInfo({
host: item.host,
port: item.port,
})
setSyncHost({
host: item.host,
port: item.port,
})
}
const handleRemove = () => {
remove(index)
}
return (
<View style={{ ...styles.listItem, borderBottomColor: theme.borderColor }}>
<TouchableOpacity style={styles.listName} onPress={handleSetHost}>
<Text numberOfLines={1} style={{ fontSize: 12, color: theme.normal }}>{item.host}</Text>
<Text numberOfLines={1} style={{ fontSize: 12, color: theme.normal20 }}>{item.port}</Text>
</TouchableOpacity>
<TouchableOpacity onPress={handleRemove} style={styles.listMoreBtn}>
<Icon name="remove" style={{ color: theme.normal35 }} size={16} />
</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
setList([...historyList])
})
}
useEffect(() => {
if (!visible) return
getHistory()
}, [visible])
useEffect(() => {
isUnmountedRef.current = false
return () => {
isUnmountedRef.current = true
}
}, [])
const handleRemove = useCallback((index) => {
removeSyncHostHistory(index)
const newList = [...list]
newList.splice(index, 1)
setList(newList)
}, [list])
return (
<ScrollView style={styles.list}>
{
list.length
? list.map((item, index) => <HistoryListItem item={item} index={index} remove={handleRemove} key={`${item.host}:${item.port}`} setHostInfo={setHostInfo} />)
: <Text style={{ ...styles.tipText, color: theme.normal10 }}>{t('setting_sync_history_empty')}</Text>
}
</ScrollView>
)
}
export default memo(({ setHostInfo, isWaiting }) => {
const { t } = useTranslation()
const [visible, setVisible] = useState(false)
const isEnableSync = useGetter('common', 'isEnableSync')
const showPopup = () => {
setVisible(true)
}
const hidePopup = () => {
setVisible(false)
}
return (
<>
<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>
</>
)
})
const styles = StyleSheet.create({
cacheSize: {
marginBottom: 5,
},
btn: {
flexDirection: 'row',
marginLeft: 25,
marginBottom: 15,
},
tipText: {
fontSize: 14,
textAlign: 'center',
marginTop: 15,
},
list: {
flexShrink: 1,
flexGrow: 0,
paddingLeft: 10,
paddingRight: 10,
},
listItem: {
flexDirection: 'row',
alignItems: 'center',
paddingTop: 5,
paddingBottom: 5,
borderBottomWidth: BorderWidths.normal,
},
listName: {
flex: 1,
},
})

View File

@ -8,7 +8,7 @@ import ConfirmAlert from '@/components/common/ConfirmAlert'
import Input from '@/components/common/Input'
import { useTranslation } from '@/plugins/i18n'
import { connect, disconnect, SYNC_CODE } from '@/plugins/sync'
import { getSyncHost, setSyncHost, toast } from '@/utils/tools'
import { getSyncHost, setSyncHost, toast, addSyncHostHistory } from '@/utils/tools'
import InputItem from '../components/InputItem'
import { getWIFIIPV4Address } from '@/utils/utils'
@ -66,13 +66,11 @@ const PortInput = memo(({ setPort, port, disabled }) => {
})
export default memo(() => {
export default memo(({ hostInfo, setHostInfo, isWaiting, setIsWaiting }) => {
const { t } = useTranslation()
const setIsEnableSync = useDispatch('common', 'setIsEnableSync')
const syncStatus = useGetter('common', 'syncStatus')
const isEnableSync = useGetter('common', 'isEnableSync')
const [isWaiting, setIsWaiting] = useState(global.isSyncEnableing)
const [hostInfo, setHostInfo] = useState({ host: '', port: '' })
const isUnmountedRef = useRef(true)
const theme = useGetter('common', 'theme')
const [address, setAddress] = useState('')
@ -110,13 +108,15 @@ export default memo(() => {
const handleSetEnableSync = useCallback(flag => {
setIsEnableSync(flag)
if (flag) addSyncHostHistory(hostInfo.host, hostInfo.port)
global.isSyncEnableing = true
setIsWaiting(true)
;(flag ? connect() : disconnect()).finally(() => {
global.isSyncEnableing = false
setIsWaiting(false)
})
}, [setIsEnableSync])
}, [hostInfo, setIsEnableSync, setIsWaiting])
const setHost = useCallback(host => {

View File

@ -1,17 +1,21 @@
import React, { memo } from 'react'
import React, { memo, useState } from 'react'
import Section from '../components/Section'
import IsEnable from './IsEnable'
import History from './History'
// import SyncHost from './SyncHost'
import { useTranslation } from '@/plugins/i18n'
export default memo(() => {
const { t } = useTranslation()
const [hostInfo, setHostInfo] = useState({ host: '', port: '' })
const [isWaiting, setIsWaiting] = useState(global.isSyncEnableing)
return (
<Section title={t('setting_sync')}>
<IsEnable />
{/* <SyncHost /> */}
<IsEnable hostInfo={hostInfo} setHostInfo={setHostInfo} isWaiting={isWaiting} setIsWaiting={setIsWaiting} />
<History setHostInfo={setHostInfo} isWaiting={isWaiting} />
</Section>
)
})

View File

@ -81,7 +81,7 @@ export default memo(() => {
<Popup
visible={visiblePanel}
hide={() => setVisiblePanel(false)}
title={t('songlist__tags')}
title={t('songlist_tags')}
>
<Tags setVisiblePanel={setVisiblePanel} />
</Popup>

View File

@ -64,7 +64,7 @@ const Setting = ({ visible, hide }) => {
visible={visible}
hide={hide}
position='left'
title={t('player__setting_lrc_font_size')}
title={t('player_setting_lrc_font_size')}
>
<LrcFontSize />
</Popup>

View File

@ -62,7 +62,7 @@ const Setting = ({ visible, hide }) => {
<Popup
visible={visible}
hide={hide}
title={t('player__setting_lrc_font_size')}
title={t('player_setting_lrc_font_size')}
>
<LrcFontSize />
</Popup>

View File

@ -10,6 +10,7 @@ const playInfoStorageKey = storageDataPrefix.playInfo
const listPositionPrefix = storageDataPrefix.listPosition
const syncAuthKeyPrefix = storageDataPrefix.syncAuthKey
const syncHostPrefix = storageDataPrefix.syncHost
const syncHostHistoryPrefix = storageDataPrefix.syncHostHistory
const listPrefix = storageDataPrefix.list
const listSortPrefix = storageDataPrefix.listSort
const defaultListKey = listPrefix + 'default'
@ -232,7 +233,6 @@ export const getSyncHost = async() => {
}
return { ...syncHostInfo }
}
export const setSyncHost = async({ host, port }) => {
// let hostInfo = await getData(syncHostPrefix) || {}
// hostInfo.host = host
@ -241,6 +241,24 @@ export const setSyncHost = async({ host, port }) => {
syncHostInfo.port = port
await setData(syncHostPrefix, syncHostInfo)
}
let syncHostHistory
export const getSyncHostHistory = async() => {
if (syncHostHistory === undefined) {
syncHostHistory = await getData(syncHostHistoryPrefix) || []
}
return syncHostHistory
}
export const addSyncHostHistory = async(host, port) => {
let syncHostHistory = await getSyncHostHistory()
if (syncHostHistory.some(h => h.host == host && h.port == port)) return
syncHostHistory.unshift({ host, port })
if (syncHostHistory.length > 20) syncHostHistory = syncHostHistory.slice(0, 20) // 最多存储20个
await setData(syncHostHistoryPrefix, syncHostHistory)
}
export const removeSyncHostHistory = async index => {
syncHostHistory.splice(index, 1)
await setData(syncHostHistoryPrefix, syncHostHistory)
}
export const exitApp = BackHandler.exitApp