优化本地文件封面读取,标签编辑添加从文件名解析歌曲、艺术家的功能

This commit is contained in:
lyswhut 2023-12-16 14:52:45 +08:00
parent 4410e0e0b2
commit 9ff9368b74
13 changed files with 108 additions and 29 deletions

View File

@ -64,9 +64,9 @@ public class Utils {
private static void writeToFile(String filePath, String dataString) throws IOException {
File file = new File(filePath);
deletePath(file);
FileOutputStream fileOutputStream = new FileOutputStream(file);
fileOutputStream.write(dataString.getBytes());
fileOutputStream.close();
try (FileOutputStream fileOutputStream = new FileOutputStream(file)){
fileOutputStream.write(dataString.getBytes());
}
}
static class WriteStringToFile implements Callable<Object> {

12
package-lock.json generated
View File

@ -24,7 +24,7 @@
"react-native-exception-handler": "^2.10.10",
"react-native-fast-image": "^8.6.3",
"react-native-fs": "^2.20.0",
"react-native-local-media-metadata": "github:lyswhut/react-native-local-media-metadata#c2b993093ddd141b4b88673baba7cb4d7b565d04",
"react-native-local-media-metadata": "github:lyswhut/react-native-local-media-metadata#ac715cd5bd3e338d313f585bb9cb3075607a4378",
"react-native-navigation": "^7.37.2",
"react-native-pager-view": "^6.2.3",
"react-native-quick-base64": "^2.0.8",
@ -8997,8 +8997,8 @@
},
"node_modules/react-native-local-media-metadata": {
"version": "0.1.0",
"resolved": "git+ssh://git@github.com/lyswhut/react-native-local-media-metadata.git#c2b993093ddd141b4b88673baba7cb4d7b565d04",
"integrity": "sha512-4DjQA97Ec9BPa+KPx6NBMgSQsZERTM+nkCQbLfKq+G/udZAM5+AhjVukZPey14Lp8yUyytSdBt/75jpWJomIpQ==",
"resolved": "git+ssh://git@github.com/lyswhut/react-native-local-media-metadata.git#ac715cd5bd3e338d313f585bb9cb3075607a4378",
"integrity": "sha512-/ElZWRuXfxL/soMVx+yemaeizy3Ec7zSq+T47HKfmXSQWAc7CLQqk/icn5lH4ELapCEBhoTsOsDVIbsZQLTrKg==",
"license": "MIT",
"workspaces": [
"example"
@ -17194,9 +17194,9 @@
}
},
"react-native-local-media-metadata": {
"version": "git+ssh://git@github.com/lyswhut/react-native-local-media-metadata.git#c2b993093ddd141b4b88673baba7cb4d7b565d04",
"integrity": "sha512-4DjQA97Ec9BPa+KPx6NBMgSQsZERTM+nkCQbLfKq+G/udZAM5+AhjVukZPey14Lp8yUyytSdBt/75jpWJomIpQ==",
"from": "react-native-local-media-metadata@github:lyswhut/react-native-local-media-metadata#c2b993093ddd141b4b88673baba7cb4d7b565d04",
"version": "git+ssh://git@github.com/lyswhut/react-native-local-media-metadata.git#ac715cd5bd3e338d313f585bb9cb3075607a4378",
"integrity": "sha512-/ElZWRuXfxL/soMVx+yemaeizy3Ec7zSq+T47HKfmXSQWAc7CLQqk/icn5lH4ELapCEBhoTsOsDVIbsZQLTrKg==",
"from": "react-native-local-media-metadata@github:lyswhut/react-native-local-media-metadata#ac715cd5bd3e338d313f585bb9cb3075607a4378",
"requires": {}
},
"react-native-navigation": {

View File

@ -58,7 +58,7 @@
"react-native-exception-handler": "^2.10.10",
"react-native-fast-image": "^8.6.3",
"react-native-fs": "^2.20.0",
"react-native-local-media-metadata": "github:lyswhut/react-native-local-media-metadata#c2b993093ddd141b4b88673baba7cb4d7b565d04",
"react-native-local-media-metadata": "github:lyswhut/react-native-local-media-metadata#ac715cd5bd3e338d313f585bb9cb3075607a4378",
"react-native-navigation": "^7.37.2",
"react-native-pager-view": "^6.2.3",
"react-native-quick-base64": "^2.0.8",

View File

@ -13,7 +13,7 @@
- 优化播放详情页歌曲封面、控制按钮对各尺寸屏幕的适配,修改横屏下的控制栏按钮布局
- 优化横竖屏界面的暂时判断,现在趋于方屏的屏幕按竖屏的方式显示,横屏下的播放栏添加上一曲切歌按钮
- 添加对wy源某些歌曲有问题的歌词进行修复#370
- 文件选择器允许选择外置存储设备上的路径(/storage
- 文件选择器允许(在旧系统)选择外置存储设备上的路径(`/storage`
- 图片显示改用第三方的图片组件支持gif类型的图片显示尝试解决某些设备上图片过多导致的应用崩溃问题
- 歌曲评论内容过长时自动折叠,需手动展开
- 改进本地音乐在线信息的匹配机制
@ -26,7 +26,7 @@
### 变更
- 在更低版本的安卓上启用跟随系统亮暗主题功能(#317
- 由于歌曲评论的图片太大占用较多资源,评论图片不再直接加载,需要点击后点击图片后再加载
- 由于歌曲评论的图片太大占用较多资源,评论图片不再直接加载,需要点击图片区域后再加载
### 其他

View File

@ -16,7 +16,7 @@ export interface InputItemProps extends InputProps {
export default memo(({ value, label, onChanged, ...props }: InputItemProps) => {
const theme = useTheme()
return (
<View style={styles.container} onStartShouldSetResponder={() => true}>
<View style={styles.container}>
<Text style={styles.label} size={14}>{label}</Text>
<Input
value={value}

View File

@ -5,8 +5,8 @@ import InputItem from './InputItem'
import { useI18n } from '@/lang'
import TextAreaItem from './TextAreaItem'
import PicItem from './PicItem'
import Text from '@/components/common/Text'
import { useTheme } from '@/store/theme/hook'
import ParseName from './ParseName'
export interface Metadata {
name: string // 歌曲名
@ -79,10 +79,13 @@ export default forwardRef<MetadataFormType, {}>((props, ref) => {
return (
<View style={styles.container}>
<View>
<Text size={14}>{global.i18n.t('metadata_edit_modal_file_path')}</Text>
<Text size={14} selectable color={theme['c-primary-font']} style={styles.pathText}>{path}</Text>
</View>
<TextAreaItem
value={path}
label={global.i18n.t('metadata_edit_modal_file_path')}
numberOfLines={3}
scrollEnabled
style={{ ...styles.pathText, color: theme['c-primary-font'] }}
/>
<InputItem
value={data.name}
@ -94,11 +97,17 @@ export default forwardRef<MetadataFormType, {}>((props, ref) => {
label={t('metadata_edit_modal_form_singer')}
onChanged={handleUpdateSinger}
keyboardType="name-phone-pad" />
<ParseName
path={path}
onNameChanged={handleUpdateName}
onSingerChanged={handleUpdateSinger}
/>
<InputItem
value={data.albumName}
label={t('metadata_edit_modal_form_album_name')}
onChanged={handleUpdateAlbumName}
keyboardType="name-phone-pad" />
<PicItem
value={data.pic}
label={t('metadata_edit_modal_form_pic')}
@ -107,6 +116,7 @@ export default forwardRef<MetadataFormType, {}>((props, ref) => {
value={data.lyric}
label={t('metadata_edit_modal_form_lyric')}
onChanged={handleUpdateLyric}
numberOfLines={6}
keyboardType="default" />
</View>
)
@ -121,7 +131,7 @@ const styles = createStyle({
maxWidth: '100%',
},
pathText: {
marginBottom: 10,
height: 60,
},
})

View File

@ -0,0 +1,60 @@
import { memo } from 'react'
import { StyleSheet, View } from 'react-native'
import { useTheme } from '@/store/theme/hook'
import Text from '@/components/common/Text'
import ButtonPrimary from '@/components/common/ButtonPrimary'
import { useI18n } from '@/lang'
export interface ParseNameProps {
path: string
onNameChanged: (text: string) => void
onSingerChanged: (text: string) => void
}
const parsePath = (path: string) => {
return path.substring(path.lastIndexOf('/') + 1, path.lastIndexOf('.')).split('-').map(name => name.trim())
}
export default memo(({ path, onNameChanged, onSingerChanged }: ParseNameProps) => {
const theme = useTheme()
const t = useI18n()
const handleParseNameSinger = () => {
const [name, singer] = parsePath(path)
onNameChanged(name)
if (singer) onSingerChanged(singer)
}
const handleParseSingerName = () => {
const [singer, name] = parsePath(path)
onSingerChanged(singer)
if (name) onNameChanged(name)
}
return (
<View style={styles.container}>
<Text style={styles.label} size={14}>{t('metadata_edit_modal_form_parse_name')}</Text>
<View style={styles.btns}>
<ButtonPrimary style={{ backgroundColor: theme['c-button-background'] }} onPress={handleParseNameSinger}>
<Text color={theme['c-button-font']} size={13}>{t('metadata_edit_modal_form_parse_name_singer')}</Text>
</ButtonPrimary>
<ButtonPrimary style={{ backgroundColor: theme['c-button-background'] }} onPress={handleParseSingerName}>
<Text color={theme['c-button-font']} size={13}>{t('metadata_edit_modal_form_parse_singer_name')}</Text>
</ButtonPrimary>
</View>
</View>
)
})
const styles = StyleSheet.create({
container: {
// paddingLeft: 25,
marginBottom: 15,
},
label: {
marginBottom: 2,
},
btns: {
marginTop: 5,
flexDirection: 'row',
},
})

View File

@ -31,7 +31,7 @@ export default memo(({ value, label, onChanged }: PicItemProps) => {
})
}, [onChanged])
return (
<View style={styles.container} onStartShouldSetResponder={() => true}>
<View style={styles.container}>
<View style={styles.header}>
<Text style={styles.label} size={14}>{label}</Text>
<View style={styles.btns}>

View File

@ -1,6 +1,6 @@
import { memo } from 'react'
import { View } from 'react-native'
import { StyleSheet, View } from 'react-native'
import type { InputProps } from '@/components/common/Input'
import Input from '@/components/common/Input'
import { useTheme } from '@/store/theme/hook'
@ -11,22 +11,21 @@ import { createStyle } from '@/utils/tools'
export interface TextAreaItemProps extends InputProps {
value: string
label: string
onChanged: (text: string) => void
onChanged?: (text: string) => void
}
export default memo(({ value, label, onChanged, ...props }: TextAreaItemProps) => {
export default memo(({ value, label, onChanged, style, ...props }: TextAreaItemProps) => {
const theme = useTheme()
return (
<View style={styles.container} onStartShouldSetResponder={() => true}>
<View style={styles.container}>
<Text style={styles.label} size={14}>{label}</Text>
<Input
value={value}
onChangeText={onChanged}
numberOfLines={6}
scrollEnabled={false}
textAlignVertical='top'
multiline
style={{ ...styles.textarea, backgroundColor: theme['c-primary-input-background'] }}
style={StyleSheet.compose({ ...styles.textarea, backgroundColor: theme['c-primary-input-background'] }, style)}
{...props}
/>
</View>

View File

@ -5,7 +5,7 @@ import Text from '@/components/common/Text'
import { useTheme } from '@/store/theme/hook'
import { createStyle } from '@/utils/tools'
type ButtonProps = BtnProps
export type ButtonProps = BtnProps
export default memo(({ disabled, onPress, children }: ButtonProps) => {
const theme = useTheme()

View File

@ -113,6 +113,9 @@
"metadata_edit_modal_form_album_name": "Album name",
"metadata_edit_modal_form_lyric": "LRC Lyrics",
"metadata_edit_modal_form_name": "Song name",
"metadata_edit_modal_form_parse_name": "Parse song name and artist from file name",
"metadata_edit_modal_form_parse_name_singer": "Name - Artist",
"metadata_edit_modal_form_parse_singer_name": "Artist - Name",
"metadata_edit_modal_form_pic": "Song cover",
"metadata_edit_modal_form_remove_pic": "Remove image",
"metadata_edit_modal_form_select_pic": "Select Image",

View File

@ -113,6 +113,9 @@
"metadata_edit_modal_form_album_name": "专辑名",
"metadata_edit_modal_form_lyric": "LRC 歌词",
"metadata_edit_modal_form_name": "歌曲名",
"metadata_edit_modal_form_parse_name": "从文件名解析歌曲名、艺术家",
"metadata_edit_modal_form_parse_name_singer": "歌曲名 - 艺术家",
"metadata_edit_modal_form_parse_singer_name": "艺术家 - 歌曲名",
"metadata_edit_modal_form_pic": "歌曲封面",
"metadata_edit_modal_form_remove_pic": "移除图片",
"metadata_edit_modal_form_select_pic": "选择图片",

View File

@ -1,10 +1,10 @@
import { scanFiles } from 'react-native-local-media-metadata'
import { temporaryDirectoryPath } from '@/utils/fs'
import { scanFiles, readPic as _readPic } from 'react-native-local-media-metadata'
export {
type MusicMetadata,
type MusicMetadataFull,
readMetadata,
writeMetadata,
readPic,
writePic,
readLyric,
writeLyric,
@ -14,6 +14,10 @@ export const scanAudioFiles = async(dirPath: string): Promise<string[]> => {
return scanFiles(dirPath, ['mp3', 'flac', 'ogg', 'wav'])
}
export const readPic = async(dirPath: string): Promise<string> => {
return _readPic(dirPath, temporaryDirectoryPath + '/local-media-metadata')
}
// export interface MusicMetadata {
// type: 'mp3' | 'flac' | 'ogg' | 'wav'
// bitrate: string