mirror of
https://github.com/ikun0014/lx-music-mobile.git
synced 2025-07-03 16:52:10 +08:00
新增同步服务地址历史列表功能
This commit is contained in:
parent
e8ba013186
commit
69d46ec4bd
@ -2,6 +2,7 @@
|
||||
|
||||
- 同步功能新增对列表位置调整的支持(若你使用同步功能,请务必升级到此版本以上,不然会有问题)
|
||||
- 新增播放详情页歌词字体大小调整设置,可在详情页右上角的按钮进行调整
|
||||
- 新增同步服务地址历史列表功能
|
||||
|
||||
### 优化
|
||||
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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": "小枸音乐",
|
||||
|
@ -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>
|
||||
|
143
src/screens/Home/Setting/Sync/History.js
Normal file
143
src/screens/Home/Setting/Sync/History.js
Normal 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,
|
||||
},
|
||||
})
|
@ -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 => {
|
||||
|
@ -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>
|
||||
)
|
||||
})
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user