From 8210da380a8fcc55dc0c44e7ff6b4778fd6561b6 Mon Sep 17 00:00:00 2001 From: lyswhut Date: Sat, 25 May 2024 19:55:02 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=AF=BC=E5=85=A5=E6=AD=8C?= =?UTF-8?q?=E5=8D=95=E6=97=B6=E5=8F=AF=E8=83=BD=E4=BC=9A=E5=AF=BC=E8=87=B4?= =?UTF-8?q?=E6=AD=8C=E5=8D=95=E6=95=B0=E6=8D=AE=E5=AD=98=E5=82=A8=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=88#500=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- publish/changeLog.md | 1 + src/plugins/storage.ts | 79 +++++++++++++------ .../Home/Views/Mylist/MyList/listAction.ts | 3 +- .../Views/Setting/settings/Backup/actions.ts | 6 +- src/utils/log.ts | 7 +- 5 files changed, 65 insertions(+), 31 deletions(-) diff --git a/publish/changeLog.md b/publish/changeLog.md index f341b0a4f..52e58b75c 100644 --- a/publish/changeLog.md +++ b/publish/changeLog.md @@ -5,6 +5,7 @@ ### 修复 - 修复重复的数据初始化调用 +- 修复导入歌单时可能会导致歌单数据存储异常的问题(#500) ### 变更 diff --git a/src/plugins/storage.ts b/src/plugins/storage.ts index 745e4d74f..91fa8851a 100644 --- a/src/plugins/storage.ts +++ b/src/plugins/storage.ts @@ -2,7 +2,9 @@ import AsyncStorage from '@react-native-async-storage/async-storage' import { log } from '@/utils/log' const partKeyPrefix = '@___PART___' +const partKeyArrPrefix = '@___PART_A___' const partKeyPrefixRxp = /^@___PART___/ +const partKeyArrPrefixRxp = /^@___PART_A___/ const keySplit = ',' const limit = 500000 @@ -15,14 +17,14 @@ const buildData = (key: string, value: any, datas: Array<[string, string]>) => { const partKeys = [] for (let i = 0, len = Math.floor(valueStr.length / limit); i <= len; i++) { - let partKey = `${partKeyPrefix}${key}${i}` + let partKey = `${partKeyArrPrefix}${key}${i}` partKeys.push(partKey) datas.push([partKey, valueStr.substring(i * limit, (i + 1) * limit)]) } - datas.push([key, `${partKeyPrefix}${partKeys.join(keySplit)}`]) + datas.push([key, partKeyArrPrefix + JSON.stringify(partKeys)]) } -const handleGetData = async(partKeys: string): Promise => { +const handleGetDataOld = async(partKeys: string): Promise => { const keys = partKeys.replace(partKeyPrefixRxp, '').split(keySplit) return AsyncStorage.multiGet(keys).then(datas => { @@ -30,11 +32,21 @@ const handleGetData = async(partKeys: string): Promise => { }) } +const handleGetData = async(partKeys: string): Promise => { + if (partKeys.startsWith(partKeyPrefix)) return handleGetDataOld(partKeys) + + const keys = JSON.parse(partKeys.replace(partKeyArrPrefixRxp, '')) as string[] + return AsyncStorage.multiGet(keys).then(datas => { + return JSON.parse(datas.map(data => data[1]).join('')) + }) +} + export const saveData = async(key: string, value: any) => { const datas: Array<[string, string]> = [] buildData(key, value, datas) try { + await removeData(key) await AsyncStorage.multiSet(datas) } catch (e: any) { // saving error @@ -52,7 +64,7 @@ export const getData = async(key: string): Promise => { log.error('storage error[getData]:', key, e.message) throw e } - if (value && partKeyPrefixRxp.test(value)) { + if (value && (partKeyPrefixRxp.test(value) || partKeyArrPrefixRxp.test(value))) { return handleGetData(value) } else if (value == null) return value return JSON.parse(value) @@ -67,25 +79,39 @@ export const removeData = async(key: string) => { log.error('storage error[removeData]:', key, e.message) throw e } - if (value && partKeyPrefixRxp.test(value)) { - let partKeys = value.replace(partKeyPrefixRxp, '').split(keySplit) - partKeys.push(key) - try { - await AsyncStorage.multiRemove(partKeys) - } catch (e: any) { - // remove error - log.error('storage error[removeData]:', key, e.message) - throw e - } - } else { - try { - await AsyncStorage.removeItem(key) - } catch (e: any) { - // remove error - log.error('storage error[removeData]:', key, e.message) - throw e + if (value) { + if (partKeyPrefixRxp.test(value)) { + let partKeys = value.replace(partKeyPrefixRxp, '').split(keySplit) + partKeys.push(key) + try { + await AsyncStorage.multiRemove(partKeys) + } catch (e: any) { + // remove error + log.error('storage error[removeData]:', key, e.message) + throw e + } + return + } else if (partKeyArrPrefixRxp.test(value)) { + let partKeys = JSON.parse(value.replace(partKeyArrPrefixRxp, '')) as string[] + partKeys.push(key) + try { + await AsyncStorage.multiRemove(partKeys) + } catch (e: any) { + // remove error + log.error('storage error[removeData]:', key, e.message) + throw e + } + return } } + + try { + await AsyncStorage.removeItem(key) + } catch (e: any) { + // remove error + log.error('storage error[removeData]:', key, e.message) + throw e + } } export const getAllKeys = async() => { @@ -114,7 +140,7 @@ export const getDataMultiple = async(keys: T) => { } const promises: Array>> = [] for (const [, value] of datas) { - if (value && partKeyPrefixRxp.test(value)) { + if (value && (partKeyPrefixRxp.test(value) || partKeyArrPrefixRxp.test(value))) { promises.push(handleGetData(value)) } else { // eslint-disable-next-line @typescript-eslint/no-unsafe-argument @@ -132,6 +158,7 @@ export const saveDataMultiple = async(datas: Array<[string, any]>) => { buildData(key, value, allData) } try { + await removeDataMultiple(datas.map(k => k[0])) await AsyncStorage.multiSet(allData) } catch (e: any) { // save error @@ -147,8 +174,12 @@ export const removeDataMultiple = async(keys: string[]) => { let allKeys = [] for (const [key, value] of datas) { allKeys.push(key) - if (value && partKeyPrefixRxp.test(value)) { - allKeys.push(...value.replace(partKeyPrefixRxp, '').split(keySplit)) + if (value) { + if (partKeyPrefixRxp.test(value)) { + allKeys.push(...value.replace(partKeyPrefixRxp, '').split(keySplit)) + } else if (partKeyArrPrefixRxp.test(value)) { + allKeys.push(...JSON.parse(value.replace(partKeyPrefixRxp, '')) as string[]) + } } } try { diff --git a/src/screens/Home/Views/Mylist/MyList/listAction.ts b/src/screens/Home/Views/Mylist/MyList/listAction.ts index 501afa48f..d2297f39f 100644 --- a/src/screens/Home/Views/Mylist/MyList/listAction.ts +++ b/src/screens/Home/Views/Mylist/MyList/listAction.ts @@ -48,7 +48,8 @@ export const handleImport = (path: string, position: number) => { void readListData(path).then(async listData => { if (listData == null) return void handleImportListPart(listData, position) - }).catch(() => { + }).catch((err) => { + log.error(err) toast(global.i18n.t('setting_backup_part_import_list_tip_error')) }) } diff --git a/src/screens/Home/Views/Setting/settings/Backup/actions.ts b/src/screens/Home/Views/Setting/settings/Backup/actions.ts index 6c602b537..b13459619 100644 --- a/src/screens/Home/Views/Setting/settings/Backup/actions.ts +++ b/src/screens/Home/Views/Setting/settings/Backup/actions.ts @@ -103,7 +103,8 @@ export const handleImportListPart = async(listData: LX.ConfigFile.MyListInfoPart position: Math.max(position, -1), }).then(() => { toast(global.i18n.t('setting_backup_part_import_list_tip_success')) - }).catch(() => { + }).catch((err) => { + log.error(err) toast(global.i18n.t('setting_backup_part_import_list_tip_error')) }) } @@ -160,7 +161,8 @@ export const handleImportList = (path: string) => { void importPlayList(path).then((skipTip) => { if (skipTip) return toast(global.i18n.t('setting_backup_part_import_list_tip_success')) - }).catch(() => { + }).catch((err) => { + log.error(err) toast(global.i18n.t('setting_backup_part_import_list_tip_error')) }) } diff --git a/src/utils/log.ts b/src/utils/log.ts index b00330c46..5fa8661f6 100644 --- a/src/utils/log.ts +++ b/src/utils/log.ts @@ -37,7 +37,7 @@ export const clearLogs = async() => { export const log = { info(...msgs: any[]) { // console.info(...msgs) - const msg = msgs.map(m => typeof m == 'string' ? m : JSON.stringify(m)).join(' ') + const msg = msgs.map(m => typeof m == 'string' ? m : m instanceof Error ? m.stack ?? m.message : JSON.stringify(m)).join(' ') if (msg.startsWith('%c')) return const time = new Date().toLocaleString() if (logTools.tempLog) { @@ -46,15 +46,14 @@ export const log = { }, warn(...msgs: any[]) { // console.warn(...msgs) - const msg = msgs.map(m => typeof m == 'string' ? m : JSON.stringify(m)).join(' ') + const msg = msgs.map(m => typeof m == 'string' ? m : m instanceof Error ? m.stack ?? m.message : JSON.stringify(m)).join(' ') const time = new Date().toLocaleString() if (logTools.tempLog) { logTools.tempLog.push({ type: 'WARN', time, text: msg }) } else logTools.writeLog(`${time} WARN ${msg}`) }, error(...msgs: any[]) { - // console.error...(msgs) - const msg = msgs.map(m => typeof m == 'string' ? m : JSON.stringify(m)).join(' ') + const msg = msgs.map(m => typeof m == 'string' ? m : m instanceof Error ? m.stack ?? m.message : JSON.stringify(m)).join(' ') const time = new Date().toLocaleString() if (logTools.tempLog) { logTools.tempLog.push({ type: 'ERROR', time, text: msg })