|
@@ -129,6 +129,7 @@ import {
|
|
|
isAudioStationType,
|
|
isAudioStationType,
|
|
|
isPlexType,
|
|
isPlexType,
|
|
|
isRemoteCloudType,
|
|
isRemoteCloudType,
|
|
|
|
|
+ mergeCoverWithPriority,
|
|
|
WorkerEditMusicResult,
|
|
WorkerEditMusicResult,
|
|
|
WebDavMetadataUpdatePayload,
|
|
WebDavMetadataUpdatePayload,
|
|
|
isDaoLiYuType
|
|
isDaoLiYuType
|
|
@@ -1100,12 +1101,16 @@ export struct LocalMusic {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (payload.pixelMapPath && payload.pixelMapPath.length > 0) {
|
|
|
|
|
- this.cover = payload.pixelMapPath;
|
|
|
|
|
- if (this.currentSong) {
|
|
|
|
|
- this.currentSong.pixelMapPath = payload.pixelMapPath;
|
|
|
|
|
|
|
+ if (this.currentSong) {
|
|
|
|
|
+ const coverMutated = mergeCoverWithPriority(this.currentSong, payload.pixelMapPath,
|
|
|
|
|
+ payload.isCustomCover ?? 0);
|
|
|
|
|
+ if (coverMutated && this.currentSong.pixelMapPath) {
|
|
|
|
|
+ this.cover = this.currentSong.pixelMapPath;
|
|
|
|
|
+ Logger.info(TAG, `LocalMusic: 封面已更新: ${this.currentSong.pixelMapPath}`);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (payload.md5Str && payload.md5Str.length > 0) {
|
|
|
|
|
+ this.currentSong.md5Str = payload.md5Str;
|
|
|
}
|
|
}
|
|
|
- Logger.info(TAG, `LocalMusic: 封面已更新: ${payload.pixelMapPath}`);
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 同步更新 AppStorage
|
|
// 同步更新 AppStorage
|
|
@@ -1662,6 +1667,8 @@ export struct LocalMusic {
|
|
|
remoteMetadataUpdates.set(target.filePath, {
|
|
remoteMetadataUpdates.set(target.filePath, {
|
|
|
filePath: target.filePath,
|
|
filePath: target.filePath,
|
|
|
pixelMapPath: target.pixelMapPath,
|
|
pixelMapPath: target.pixelMapPath,
|
|
|
|
|
+ isCustomCover: target.isCustomCover,
|
|
|
|
|
+ md5Str: target.md5Str,
|
|
|
name: target.name,
|
|
name: target.name,
|
|
|
artist: target.artist
|
|
artist: target.artist
|
|
|
});
|
|
});
|
|
@@ -1676,8 +1683,8 @@ export struct LocalMusic {
|
|
|
if (payload.artist) {
|
|
if (payload.artist) {
|
|
|
this.artist = payload.artist;
|
|
this.artist = payload.artist;
|
|
|
}
|
|
}
|
|
|
- if (payload.pixelMapPath) {
|
|
|
|
|
- this.cover = payload.pixelMapPath;
|
|
|
|
|
|
|
+ if (payload.pixelMapPath && this.currentSong?.pixelMapPath) {
|
|
|
|
|
+ this.cover = this.currentSong.pixelMapPath;
|
|
|
}
|
|
}
|
|
|
if (payload.lyricContent) {
|
|
if (payload.lyricContent) {
|
|
|
this.applyInlineLyricContent(payload.lyricContent);
|
|
this.applyInlineLyricContent(payload.lyricContent);
|
|
@@ -1806,8 +1813,9 @@ export struct LocalMusic {
|
|
|
this.assignStringMetadata(target, 'duration', payload.duration);
|
|
this.assignStringMetadata(target, 'duration', payload.duration);
|
|
|
this.assignStringMetadata(target, 'sampleRate', payload.sampleRate);
|
|
this.assignStringMetadata(target, 'sampleRate', payload.sampleRate);
|
|
|
this.assignStringMetadata(target, 'mimeType', payload.mimeType);
|
|
this.assignStringMetadata(target, 'mimeType', payload.mimeType);
|
|
|
|
|
+ this.assignStringMetadata(target, 'md5Str', payload.md5Str);
|
|
|
this.assignStringMetadata(target, 'size', payload.size);
|
|
this.assignStringMetadata(target, 'size', payload.size);
|
|
|
- this.assignStringMetadata(target, 'pixelMapPath', payload.pixelMapPath);
|
|
|
|
|
|
|
+ mergeCoverWithPriority(target, payload.pixelMapPath);
|
|
|
this.assignStringMetadata(target, 'lyricContent', payload.lyricContent, true);
|
|
this.assignStringMetadata(target, 'lyricContent', payload.lyricContent, true);
|
|
|
this.assignStringMetadata(target, 'genre', payload.genre);
|
|
this.assignStringMetadata(target, 'genre', payload.genre);
|
|
|
this.assignStringMetadata(target, 'track', payload.track);
|
|
this.assignStringMetadata(target, 'track', payload.track);
|
|
@@ -1837,10 +1845,11 @@ export struct LocalMusic {
|
|
|
this.assignStringMetadata(target, 'bit_rate', source.bit_rate);
|
|
this.assignStringMetadata(target, 'bit_rate', source.bit_rate);
|
|
|
this.assignStringMetadata(target, 'duration', source.duration);
|
|
this.assignStringMetadata(target, 'duration', source.duration);
|
|
|
this.assignStringMetadata(target, 'sampleRate', source.sampleRate);
|
|
this.assignStringMetadata(target, 'sampleRate', source.sampleRate);
|
|
|
|
|
+ this.assignStringMetadata(target, 'md5Str', source.md5Str);
|
|
|
this.assignStringMetadata(target, 'trackCount', source.trackCount);
|
|
this.assignStringMetadata(target, 'trackCount', source.trackCount);
|
|
|
this.assignStringMetadata(target, 'mimeType', source.mimeType);
|
|
this.assignStringMetadata(target, 'mimeType', source.mimeType);
|
|
|
this.assignStringMetadata(target, 'size', source.size);
|
|
this.assignStringMetadata(target, 'size', source.size);
|
|
|
- this.assignStringMetadata(target, 'pixelMapPath', source.pixelMapPath);
|
|
|
|
|
|
|
+ mergeCoverWithPriority(target, source.pixelMapPath, source.isCustomCover ?? 0);
|
|
|
this.assignStringMetadata(target, 'lyricContent', source.lyricContent, true);
|
|
this.assignStringMetadata(target, 'lyricContent', source.lyricContent, true);
|
|
|
this.assignStringMetadata(target, 'genre', source.genre);
|
|
this.assignStringMetadata(target, 'genre', source.genre);
|
|
|
this.assignStringMetadata(target, 'track', source.track);
|
|
this.assignStringMetadata(target, 'track', source.track);
|
|
@@ -3098,16 +3107,20 @@ export struct LocalMusic {
|
|
|
|
|
|
|
|
if (item.filePath == this.currentSong?.filePath) {
|
|
if (item.filePath == this.currentSong?.filePath) {
|
|
|
this.cover = imagePath
|
|
this.cover = imagePath
|
|
|
|
|
+ if (this.currentSong) {
|
|
|
|
|
+ this.currentSong.isCustomCover = 1;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
if (item) {
|
|
if (item) {
|
|
|
item.pixelMapPath = imagePath
|
|
item.pixelMapPath = imagePath
|
|
|
|
|
+ item.isCustomCover = 1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (isRemoteCloudType(item.type)) {
|
|
if (isRemoteCloudType(item.type)) {
|
|
|
return FileUtil.getFilePath(imagePath);
|
|
return FileUtil.getFilePath(imagePath);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- this.table.updatePixelMapPath(item.filePath, imagePath, (success: boolean, error?: string) => {
|
|
|
|
|
|
|
+ this.table.updateCustomCoverPath(item.filePath, imagePath, (success: boolean, error?: string) => {
|
|
|
if (success) {
|
|
if (success) {
|
|
|
this.doUpdateData()
|
|
this.doUpdateData()
|
|
|
console.log("onecold 更新音乐封面成功,数据库已同步");
|
|
console.log("onecold 更新音乐封面成功,数据库已同步");
|
|
@@ -3183,6 +3196,7 @@ export struct LocalMusic {
|
|
|
if (isRemoteCloudType(this.currentSong.type)) {
|
|
if (isRemoteCloudType(this.currentSong.type)) {
|
|
|
this.cover = coverUri;
|
|
this.cover = coverUri;
|
|
|
this.currentSong.pixelMapPath = coverUri;
|
|
this.currentSong.pixelMapPath = coverUri;
|
|
|
|
|
+ this.currentSong.isCustomCover = 1;
|
|
|
this.syncRemoteManagerSong(this.currentSong);
|
|
this.syncRemoteManagerSong(this.currentSong);
|
|
|
await this.persistRemoteMetadataToDb(this.currentSong);
|
|
await this.persistRemoteMetadataToDb(this.currentSong);
|
|
|
this.emitRemoteMetadataUpdated(this.currentSong);
|
|
this.emitRemoteMetadataUpdated(this.currentSong);
|
|
@@ -3211,6 +3225,7 @@ export struct LocalMusic {
|
|
|
|
|
|
|
|
this.cover = coverUri;
|
|
this.cover = coverUri;
|
|
|
this.currentSong.pixelMapPath = coverUri;
|
|
this.currentSong.pixelMapPath = coverUri;
|
|
|
|
|
+ this.currentSong.isCustomCover = 1;
|
|
|
await this.doUpateEditedFields(this.currentSong);
|
|
await this.doUpateEditedFields(this.currentSong);
|
|
|
ToastUtil.showToast('更换封面成功');
|
|
ToastUtil.showToast('更换封面成功');
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
@@ -8942,6 +8957,8 @@ export struct LocalMusic {
|
|
|
const payload: WebDavMetadataUpdatePayload = {
|
|
const payload: WebDavMetadataUpdatePayload = {
|
|
|
filePath: item.filePath,
|
|
filePath: item.filePath,
|
|
|
pixelMapPath: item.pixelMapPath,
|
|
pixelMapPath: item.pixelMapPath,
|
|
|
|
|
+ isCustomCover: item.isCustomCover,
|
|
|
|
|
+ md5Str: item.md5Str,
|
|
|
name: item.name,
|
|
name: item.name,
|
|
|
artist: item.artist
|
|
artist: item.artist
|
|
|
};
|
|
};
|
|
@@ -8959,9 +8976,6 @@ export struct LocalMusic {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
this.mergeVideoItemFromSource(target, item);
|
|
this.mergeVideoItemFromSource(target, item);
|
|
|
- if (StrUtil.isNotEmpty(item.pixelMapPath)) {
|
|
|
|
|
- target.pixelMapPath = item.pixelMapPath;
|
|
|
|
|
- }
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private async saveRemoteSongEdit(item: VideoItem): Promise<void> {
|
|
private async saveRemoteSongEdit(item: VideoItem): Promise<void> {
|
|
@@ -8969,13 +8983,14 @@ export struct LocalMusic {
|
|
|
this.syncEditedFields(item);
|
|
this.syncEditedFields(item);
|
|
|
if (StrUtil.isNotEmpty(this.imagePathStr)) {
|
|
if (StrUtil.isNotEmpty(this.imagePathStr)) {
|
|
|
item.pixelMapPath = this.normalizeEditedCoverPath(this.imagePathStr);
|
|
item.pixelMapPath = this.normalizeEditedCoverPath(this.imagePathStr);
|
|
|
|
|
+ item.isCustomCover = 1;
|
|
|
}
|
|
}
|
|
|
this.name = this.titleStr;
|
|
this.name = this.titleStr;
|
|
|
if (this.currentSong && item.filePath === this.currentSong.filePath) {
|
|
if (this.currentSong && item.filePath === this.currentSong.filePath) {
|
|
|
this.syncEditedFields(this.currentSong);
|
|
this.syncEditedFields(this.currentSong);
|
|
|
if (StrUtil.isNotEmpty(item.pixelMapPath)) {
|
|
if (StrUtil.isNotEmpty(item.pixelMapPath)) {
|
|
|
- this.currentSong.pixelMapPath = item.pixelMapPath;
|
|
|
|
|
- this.cover = item.pixelMapPath;
|
|
|
|
|
|
|
+ mergeCoverWithPriority(this.currentSong, item.pixelMapPath, item.isCustomCover ?? 0);
|
|
|
|
|
+ this.cover = this.currentSong.pixelMapPath || item.pixelMapPath;
|
|
|
}
|
|
}
|
|
|
this.artist = this.currentSong.artist ?? '';
|
|
this.artist = this.currentSong.artist ?? '';
|
|
|
this.currentSong = cloneVideoItem(this.currentSong);
|
|
this.currentSong = cloneVideoItem(this.currentSong);
|
|
@@ -12172,8 +12187,8 @@ export struct LocalMusic {
|
|
|
this.PlayOrPauseButton()
|
|
this.PlayOrPauseButton()
|
|
|
},
|
|
},
|
|
|
isPx: false,
|
|
isPx: false,
|
|
|
- builderHeight: this.isPhoneLan()?40:43,
|
|
|
|
|
- builderWidth: this.isPhoneLan()?40:43,
|
|
|
|
|
|
|
+ builderHeight: this.isPhoneLan()?38:41,
|
|
|
|
|
+ builderWidth: this.isPhoneLan()?38:41,
|
|
|
})
|
|
})
|
|
|
.onClick(() =>{
|
|
.onClick(() =>{
|
|
|
this.playOrPause()
|
|
this.playOrPause()
|
|
@@ -12237,8 +12252,8 @@ export struct LocalMusic {
|
|
|
.style({ strokeWidth: 5, status: ProgressStatus.LOADING })
|
|
.style({ strokeWidth: 5, status: ProgressStatus.LOADING })
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- .width(this.isPhoneLan()?40:43)
|
|
|
|
|
- .height(this.isPhoneLan()?40:43)
|
|
|
|
|
|
|
+ .width(this.isPhoneLan()?38:41)
|
|
|
|
|
+ .height(this.isPhoneLan()?38:41)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -15063,27 +15078,27 @@ export struct LocalMusic {
|
|
|
}
|
|
}
|
|
|
const titleS = title||item?.name || '';
|
|
const titleS = title||item?.name || '';
|
|
|
const artistS = artist||item?.artist || ''; // Use empty string if artist is missing
|
|
const artistS = artist||item?.artist || ''; // Use empty string if artist is missing
|
|
|
- return this.searchCover(item, titleS, artistS); // Await is not needed here as we return the promise directly
|
|
|
|
|
|
|
+ return this.searchCover(item, titleS, artistS, true); // Await is not needed here as we return the promise directly
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
*api搜索封面
|
|
*api搜索封面
|
|
|
*item,根据title和artist
|
|
*item,根据title和artist
|
|
|
*/
|
|
*/
|
|
|
- searchCover(item: VideoItem, title: string, artist: string): Promise<string> {
|
|
|
|
|
|
|
+ searchCover(item: VideoItem, title: string, artist: string, markAsCustomCover: boolean = false): Promise<string> {
|
|
|
return NetAxiosUtil.getLyricCover(title, artist, PreferencesUtil.getStringSync('COVER_API', '')).then(async (res) => {
|
|
return NetAxiosUtil.getLyricCover(title, artist, PreferencesUtil.getStringSync('COVER_API', '')).then(async (res) => {
|
|
|
LogUtil.debug("onecold res =" + res);
|
|
LogUtil.debug("onecold res =" + res);
|
|
|
|
|
|
|
|
if (StrUtil.isNotEmpty(res) && res !== 'unknown' && res !== 'Timeout was reached') {
|
|
if (StrUtil.isNotEmpty(res) && res !== 'unknown' && res !== 'Timeout was reached') {
|
|
|
if (item.filePath == this.currentSong?.filePath) {
|
|
if (item.filePath == this.currentSong?.filePath) {
|
|
|
- this.cover = res;
|
|
|
|
|
if (this.currentSong) {
|
|
if (this.currentSong) {
|
|
|
- this.currentSong.pixelMapPath = res;
|
|
|
|
|
|
|
+ mergeCoverWithPriority(this.currentSong, res, markAsCustomCover ? 1 : 0);
|
|
|
|
|
+ this.cover = this.currentSong.pixelMapPath || res;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (isRemoteCloudType(item.type)) {
|
|
if (isRemoteCloudType(item.type)) {
|
|
|
- item.pixelMapPath = res;
|
|
|
|
|
|
|
+ mergeCoverWithPriority(item, res, markAsCustomCover ? 1 : 0);
|
|
|
this.syncRemoteManagerSong(item);
|
|
this.syncRemoteManagerSong(item);
|
|
|
try {
|
|
try {
|
|
|
await this.persistRemoteMetadataToDb(item);
|
|
await this.persistRemoteMetadataToDb(item);
|
|
@@ -15093,15 +15108,26 @@ export struct LocalMusic {
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
// Update pixel map path but always return res regardless of success
|
|
// Update pixel map path but always return res regardless of success
|
|
|
- this.table.updatePixelMapPath(item.filePath, res, (success: boolean, error?: string) => {
|
|
|
|
|
- if (success) {
|
|
|
|
|
- this.doUpdateData();
|
|
|
|
|
- console.log("onecold 更新音乐封面成功,数据库已同步");
|
|
|
|
|
- } else {
|
|
|
|
|
- console.error("onecold 更新音乐封面数据库失败原因: " + error);
|
|
|
|
|
- }
|
|
|
|
|
- // Note: We don't resolve/reject here because we already returned res
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ if (markAsCustomCover) {
|
|
|
|
|
+ item.isCustomCover = 1;
|
|
|
|
|
+ this.table.updateCustomCoverPath(item.filePath, res, (success: boolean, error?: string) => {
|
|
|
|
|
+ if (success) {
|
|
|
|
|
+ this.doUpdateData();
|
|
|
|
|
+ console.log("onecold 更新音乐封面成功,数据库已同步");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ console.error("onecold 更新音乐封面数据库失败原因: " + error);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.table.updatePixelMapPath(item.filePath, res, (success: boolean, error?: string) => {
|
|
|
|
|
+ if (success) {
|
|
|
|
|
+ this.doUpdateData();
|
|
|
|
|
+ console.log("onecold 更新音乐封面成功,数据库已同步");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ console.error("onecold 更新音乐封面数据库失败原因: " + error);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
LogUtil.debug("onecold this.cover =" + this.cover);
|
|
LogUtil.debug("onecold this.cover =" + this.cover);
|
|
@@ -19207,7 +19233,7 @@ async function replaceLocalMusicCoverTask(
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
return await new Promise<boolean>((resolve) => {
|
|
return await new Promise<boolean>((resolve) => {
|
|
|
- table.updatePixelMapPath(filePath, fileUri.getUriFromPath(sandboxCoverPath),
|
|
|
|
|
|
|
+ table.updateCustomCoverPath(filePath, fileUri.getUriFromPath(sandboxCoverPath),
|
|
|
(success: boolean, _error?: string) => {
|
|
(success: boolean, _error?: string) => {
|
|
|
resolve(success);
|
|
resolve(success);
|
|
|
});
|
|
});
|