|
@@ -155,6 +155,7 @@ import {
|
|
|
isCueSplitItem
|
|
isCueSplitItem
|
|
|
} from '../common/util/CueUtils';
|
|
} from '../common/util/CueUtils';
|
|
|
import { CueComptent } from '../view/CueComptent';
|
|
import { CueComptent } from '../view/CueComptent';
|
|
|
|
|
+import { SearchHistoryUtil } from '../common/util/SearchHistoryUtil';
|
|
|
import { IsoExtractComptent } from '../view/IsoExtractComptent';
|
|
import { IsoExtractComptent } from '../view/IsoExtractComptent';
|
|
|
import PlaylistTable from '../common/util/PlaylistTable';
|
|
import PlaylistTable from '../common/util/PlaylistTable';
|
|
|
import { showAddToPlaylistDialog } from '../dialog/AddToPlaylistDialog';
|
|
import { showAddToPlaylistDialog } from '../dialog/AddToPlaylistDialog';
|
|
@@ -191,6 +192,7 @@ import { CoverThumbCache } from '../common/util/CoverThumbCache';
|
|
|
import { LyricCopySheet } from './LyricCopySheet';
|
|
import { LyricCopySheet } from './LyricCopySheet';
|
|
|
import {
|
|
import {
|
|
|
IsoArchiveAudioEntry,
|
|
IsoArchiveAudioEntry,
|
|
|
|
|
+ IsoExtractFailureDetail,
|
|
|
IsoExtractProgressMessage,
|
|
IsoExtractProgressMessage,
|
|
|
IsoExtractTaskResult,
|
|
IsoExtractTaskResult,
|
|
|
listIsoAudioEntriesTask,
|
|
listIsoAudioEntriesTask,
|
|
@@ -439,6 +441,13 @@ export struct LocalMusic {
|
|
|
private isoExtractProgressTimer: number = 0
|
|
private isoExtractProgressTimer: number = 0
|
|
|
private isoExtractExpectedOutputPaths: Array<string> = []
|
|
private isoExtractExpectedOutputPaths: Array<string> = []
|
|
|
private isoExtractTotalBytes: number = 0
|
|
private isoExtractTotalBytes: number = 0
|
|
|
|
|
+ private isoExtractDisplayedProgress: number = 0
|
|
|
|
|
+ private isoExtractReceivedTaskProgress: boolean = false
|
|
|
|
|
+ private isoExtractTask: taskpool.Task | undefined = undefined
|
|
|
|
|
+ private isoExtractLastActivityTime: number = 0
|
|
|
|
|
+ private readonly isoExtractStallTimeoutMs: number = 15000
|
|
|
|
|
+ private isoExtractCanceled: boolean = false
|
|
|
|
|
+ private isoExtractCancelMessage: string = ''
|
|
|
searchController: SearchController = new SearchController()
|
|
searchController: SearchController = new SearchController()
|
|
|
@State rightTopImage:Resource = $r('sys.symbol.sort')
|
|
@State rightTopImage:Resource = $r('sys.symbol.sort')
|
|
|
@State isEditAudio:boolean = false
|
|
@State isEditAudio:boolean = false
|
|
@@ -992,6 +1001,7 @@ export struct LocalMusic {
|
|
|
this.tipPopup = !this.tipPopup
|
|
this.tipPopup = !this.tipPopup
|
|
|
PreferencesUtil.putSync('isFirstTiped',false)
|
|
PreferencesUtil.putSync('isFirstTiped',false)
|
|
|
}
|
|
}
|
|
|
|
|
+ this.loadSearchHistory()
|
|
|
this.initSetting()
|
|
this.initSetting()
|
|
|
this.syncEqualizerUi();
|
|
this.syncEqualizerUi();
|
|
|
this.UNKONWN = Utility.resourceToString(this.context, $r('app.string.unknown'));
|
|
this.UNKONWN = Utility.resourceToString(this.context, $r('app.string.unknown'));
|
|
@@ -1426,7 +1436,7 @@ export struct LocalMusic {
|
|
|
this.isMemoryLastPlay = PreferencesUtil.getBooleanSync(SettingPage.iS_MEMORY_LAST_PLAY, false)
|
|
this.isMemoryLastPlay = PreferencesUtil.getBooleanSync(SettingPage.iS_MEMORY_LAST_PLAY, false)
|
|
|
this.isShowTitleBar = PreferencesUtil.getBooleanSync(SettingPage.IS_SHOW_TITLTBAR, true)
|
|
this.isShowTitleBar = PreferencesUtil.getBooleanSync(SettingPage.IS_SHOW_TITLTBAR, true)
|
|
|
this.isShowAllBar = PreferencesUtil.getBooleanSync(SettingPage.IS_SHOW_ALLBAR, true)
|
|
this.isShowAllBar = PreferencesUtil.getBooleanSync(SettingPage.IS_SHOW_ALLBAR, true)
|
|
|
- this.twoFingerType = PreferencesUtil.getNumberSync(SettingPage.TWO_FINGER_TYPE, 2)
|
|
|
|
|
|
|
+ this.twoFingerType = PreferencesUtil.getNumberSync(SettingPage.TWO_FINGER_TYPE, 3)
|
|
|
this.isCircleBtn = PreferencesUtil.getBooleanSync(SettingPage.IS_CIRCLE_BTN, true)
|
|
this.isCircleBtn = PreferencesUtil.getBooleanSync(SettingPage.IS_CIRCLE_BTN, true)
|
|
|
this.isShowPlayPageBack = PreferencesUtil.getBooleanSync(SettingPage.IS_SHOW_PLAYPAGE_BACK, true)
|
|
this.isShowPlayPageBack = PreferencesUtil.getBooleanSync(SettingPage.IS_SHOW_PLAYPAGE_BACK, true)
|
|
|
this.isCoverTopBig = PreferencesUtil.getBooleanSync(SettingPage.IS_COVER_TOP_BIG, false)
|
|
this.isCoverTopBig = PreferencesUtil.getBooleanSync(SettingPage.IS_COVER_TOP_BIG, false)
|
|
@@ -1522,16 +1532,16 @@ export struct LocalMusic {
|
|
|
makeWorker() {
|
|
makeWorker() {
|
|
|
setTimeout(() => {
|
|
setTimeout(() => {
|
|
|
if (PreferencesUtil.getBooleanSync('isFirstApp', true)) {
|
|
if (PreferencesUtil.getBooleanSync('isFirstApp', true)) {
|
|
|
- ToastUtil.showToast('请到文件扫描页面导入音乐!')
|
|
|
|
|
|
|
+ // ToastUtil.showToast('请到文件扫描页面导入音乐!')
|
|
|
//发送worker通知扫描文件入库,用户反馈4000多首用这个方法扫描会闪退。
|
|
//发送worker通知扫描文件入库,用户反馈4000多首用这个方法扫描会闪退。
|
|
|
- // workerInstance.postMessage({
|
|
|
|
|
- // code: 1,
|
|
|
|
|
- // data1: this.context,
|
|
|
|
|
- // data2: this.rootPath,
|
|
|
|
|
- // data3: this.lockPath,
|
|
|
|
|
- // data4: PreferencesUtil.getStringSync('COVER_API', ''),
|
|
|
|
|
- // data5: PreferencesUtil.getBooleanSync('autoParseMusicName', true),
|
|
|
|
|
- // });
|
|
|
|
|
|
|
+ workerInstance.postMessage({
|
|
|
|
|
+ code: 1,
|
|
|
|
|
+ data1: this.context,
|
|
|
|
|
+ data2: this.rootPath,
|
|
|
|
|
+ data3: this.lockPath,
|
|
|
|
|
+ data4: PreferencesUtil.getStringSync('COVER_API', ''),
|
|
|
|
|
+ data5: PreferencesUtil.getBooleanSync('autoParseMusicName', true),
|
|
|
|
|
+ });
|
|
|
PreferencesUtil.putSync('isFirstApp', false)
|
|
PreferencesUtil.putSync('isFirstApp', false)
|
|
|
} else {
|
|
} else {
|
|
|
|
|
|
|
@@ -4449,6 +4459,7 @@ export struct LocalMusic {
|
|
|
if(this.modeType==0){
|
|
if(this.modeType==0){
|
|
|
this.modeType =1//如果是首页 切换到媒体库搜索
|
|
this.modeType =1//如果是首页 切换到媒体库搜索
|
|
|
}
|
|
}
|
|
|
|
|
+ this.commitSearchHistory(value)
|
|
|
this.onSearchInput(this.searchText);
|
|
this.onSearchInput(this.searchText);
|
|
|
|
|
|
|
|
})
|
|
})
|
|
@@ -4475,6 +4486,7 @@ export struct LocalMusic {
|
|
|
.zIndex(0)
|
|
.zIndex(0)
|
|
|
.onClick(()=>{
|
|
.onClick(()=>{
|
|
|
this.isSearchMode = true
|
|
this.isSearchMode = true
|
|
|
|
|
+ this.loadSearchHistory()
|
|
|
})
|
|
})
|
|
|
//排序按钮
|
|
//排序按钮
|
|
|
Button({ type: ButtonType.Circle, stateEffect: true }) {
|
|
Button({ type: ButtonType.Circle, stateEffect: true }) {
|
|
@@ -5232,6 +5244,79 @@ export struct LocalMusic {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private deleteComponentId: number = 0
|
|
private deleteComponentId: number = 0
|
|
|
|
|
+
|
|
|
|
|
+ private closeDeleteDialog(afterClose?: () => void): void {
|
|
|
|
|
+ if (this.deleteComponentId > 0) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ this.getUIContext().getPromptAction().closeCustomDialog(this.deleteComponentId)
|
|
|
|
|
+ } catch (_error) {
|
|
|
|
|
+ }
|
|
|
|
|
+ this.deleteComponentId = 0
|
|
|
|
|
+ }
|
|
|
|
|
+ if (afterClose) {
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ afterClose()
|
|
|
|
|
+ }, 16)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private resetDeleteSelectionState(): void {
|
|
|
|
|
+ this.isMultiSelect = false
|
|
|
|
|
+ this.selectedFiles = []
|
|
|
|
|
+ this.isAllSelected = false
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private removeDisplayedLocalItemsByKeys(deletedKeys: Set<string>): void {
|
|
|
|
|
+ for (let index = this.dataSource.dataArray.length - 1; index >= 0; index--) {
|
|
|
|
|
+ const item = this.dataSource.dataArray[index]
|
|
|
|
|
+ if (item && deletedKeys.has(item.filePath)) {
|
|
|
|
|
+ this.dataSource.deleteData(index)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private async removeDeletedLocalItemsLocally(deletedItems: Array<VideoItem>): Promise<void> {
|
|
|
|
|
+ if (ArrayUtil.isEmpty(deletedItems) || this.modeType !== 0) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ const deletedKeys: Set<string> = new Set<string>()
|
|
|
|
|
+ for (let i = 0; i < deletedItems.length; i++) {
|
|
|
|
|
+ const item = deletedItems[i]
|
|
|
|
|
+ if (StrUtil.isNotEmpty(item?.filePath)) {
|
|
|
|
|
+ deletedKeys.add(item.filePath)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (deletedKeys.size <= 0) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const nextVideoLocalList = this.videoLocalList.filter((item: VideoItem) => !deletedKeys.has(item.filePath))
|
|
|
|
|
+ const nextDirList = this.dirList.filter((item: VideoItem) => !deletedKeys.has(item.filePath))
|
|
|
|
|
+ const nextFilteredList = this.filteredList.filter((item: VideoItem) => !deletedKeys.has(item.filePath))
|
|
|
|
|
+ const removedCount = this.videoLocalList.length - nextVideoLocalList.length
|
|
|
|
|
+
|
|
|
|
|
+ this.videoLocalList = nextVideoLocalList
|
|
|
|
|
+ this.dirList = nextDirList
|
|
|
|
|
+ this.filteredList = nextFilteredList
|
|
|
|
|
+ this.removeDisplayedLocalItemsByKeys(deletedKeys)
|
|
|
|
|
+ if (removedCount > 0 && this.totalCount > 0) {
|
|
|
|
|
+ this.totalCount = Math.max(0, this.totalCount - removedCount)
|
|
|
|
|
+ }
|
|
|
|
|
+ this.pageCache.clear()
|
|
|
|
|
+ this.pageHasMoreCache.clear()
|
|
|
|
|
+ this.pageTotalCountCache.clear()
|
|
|
|
|
+ this.setButtonStatus()
|
|
|
|
|
+ this.markAlphaBetDirty()
|
|
|
|
|
+ this.syncLocalSelectionState()
|
|
|
|
|
+
|
|
|
|
|
+ this.addCache(this.currentPath, nextVideoLocalList)
|
|
|
|
|
+ if (this.currentPath === this.rootPath) {
|
|
|
|
|
+ this.addCache(this.currentPath + '_dirList', nextDirList)
|
|
|
|
|
+ }
|
|
|
|
|
+ this.deleteStringCache(this.currentPath + '_hash')
|
|
|
|
|
+ await this.saveCacheToStorage()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
//多选删除文件
|
|
//多选删除文件
|
|
|
showWarnIsDelete(){
|
|
showWarnIsDelete(){
|
|
|
this.getUIContext().getPromptAction().openCustomDialog({
|
|
this.getUIContext().getPromptAction().openCustomDialog({
|
|
@@ -5242,12 +5327,13 @@ export struct LocalMusic {
|
|
|
showInSubWindow:false,
|
|
showInSubWindow:false,
|
|
|
maskColor: Color.Transparent,
|
|
maskColor: Color.Transparent,
|
|
|
dialogTransition: // 设置弹窗内容显示的过渡效果
|
|
dialogTransition: // 设置弹窗内容显示的过渡效果
|
|
|
- TransitionEffect.translate({ x: 0, y: 290, z: 0 })
|
|
|
|
|
- .animation({ duration: 600, curve: Curve.Smooth }),
|
|
|
|
|
|
|
+ TransitionEffect.translate({ x: 0, y: 120, z: 0 })
|
|
|
|
|
+ .combine(TransitionEffect.opacity(0.01))
|
|
|
|
|
+ .animation({ duration: 260, curve: Curve.EaseOut }),
|
|
|
|
|
|
|
|
maskTransition: // 设置蒙层显示的过渡效果
|
|
maskTransition: // 设置蒙层显示的过渡效果
|
|
|
TransitionEffect.opacity(0)
|
|
TransitionEffect.opacity(0)
|
|
|
- .animation({ duration: 600, curve: Curve.Smooth })
|
|
|
|
|
|
|
+ .animation({ duration: 220, curve: Curve.EaseOut })
|
|
|
}).then((dialogId: number) => {
|
|
}).then((dialogId: number) => {
|
|
|
this.deleteComponentId = dialogId
|
|
this.deleteComponentId = dialogId
|
|
|
})
|
|
})
|
|
@@ -5264,24 +5350,22 @@ export struct LocalMusic {
|
|
|
isPlaylistMode: this.modeType == 4,
|
|
isPlaylistMode: this.modeType == 4,
|
|
|
playlistId: this.currentSongListID,
|
|
playlistId: this.currentSongListID,
|
|
|
onCancel:()=>{
|
|
onCancel:()=>{
|
|
|
- this.isMultiSelect = false
|
|
|
|
|
- this.selectedFiles = []
|
|
|
|
|
- this.isAllSelected = false
|
|
|
|
|
- this.getUIContext().getPromptAction().closeCustomDialog(this.deleteComponentId)
|
|
|
|
|
|
|
+ this.closeDeleteDialog(() => {
|
|
|
|
|
+ this.resetDeleteSelectionState()
|
|
|
|
|
+ })
|
|
|
},
|
|
},
|
|
|
onDeleteResult:(result: boolean)=>{
|
|
onDeleteResult:(result: boolean)=>{
|
|
|
- this.isMultiSelect = false
|
|
|
|
|
- this.getUIContext().getPromptAction().closeCustomDialog(this.deleteComponentId)
|
|
|
|
|
- if(result){//如果删除成功,更新数据
|
|
|
|
|
- this.selectedFiles = [];
|
|
|
|
|
- this.isAllSelected = false
|
|
|
|
|
- if (this.modeType == 4) {
|
|
|
|
|
- this.doSongListTask()
|
|
|
|
|
- } else {
|
|
|
|
|
- this.cache.delete(this.currentPath);
|
|
|
|
|
- this.getSortedFiles(this.currentPath, true);
|
|
|
|
|
|
|
+ const deletedItems = [...this.selectedFiles]
|
|
|
|
|
+ this.closeDeleteDialog(() => {
|
|
|
|
|
+ this.resetDeleteSelectionState()
|
|
|
|
|
+ if(result){//如果删除成功,更新数据
|
|
|
|
|
+ if (this.modeType == 4) {
|
|
|
|
|
+ this.doSongListTask()
|
|
|
|
|
+ } else {
|
|
|
|
|
+ void this.removeDeletedLocalItemsLocally(deletedItems)
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
@@ -5895,6 +5979,30 @@ export struct LocalMusic {
|
|
|
@State searchText: string = ''; // 用户输入内容
|
|
@State searchText: string = ''; // 用户输入内容
|
|
|
@State filteredList: Array<VideoItem> = []; // 过滤后的结果
|
|
@State filteredList: Array<VideoItem> = []; // 过滤后的结果
|
|
|
@State isSearchMode: boolean = false
|
|
@State isSearchMode: boolean = false
|
|
|
|
|
+ @State searchHistoryItems: string[] = []
|
|
|
|
|
+ private readonly searchHistoryScope: string = 'local_music'
|
|
|
|
|
+
|
|
|
|
|
+ private loadSearchHistory(): void {
|
|
|
|
|
+ this.searchHistoryItems = SearchHistoryUtil.load(this.searchHistoryScope)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private saveSearchHistory(keyword: string): void {
|
|
|
|
|
+ this.searchHistoryItems = SearchHistoryUtil.save(this.searchHistoryScope, keyword)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private commitSearchHistory(keyword: string): void {
|
|
|
|
|
+ const normalized = keyword.trim()
|
|
|
|
|
+ if (normalized.length === 0) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ this.saveSearchHistory(normalized)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private applySearchHistory(keyword: string): void {
|
|
|
|
|
+ this.searchText = keyword
|
|
|
|
|
+ this.searchController.stopEditing()
|
|
|
|
|
+ void this.onSearchInput(keyword)
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// 实时搜索逻辑(带防抖)
|
|
// 实时搜索逻辑(带防抖)
|
|
|
private async onSearchInput(value: string): Promise<void> {
|
|
private async onSearchInput(value: string): Promise<void> {
|
|
@@ -5904,6 +6012,7 @@ export struct LocalMusic {
|
|
|
|
|
|
|
|
// 清空搜索文本时保持搜索态,只重置为不带关键词的结果列表
|
|
// 清空搜索文本时保持搜索态,只重置为不带关键词的结果列表
|
|
|
if (this.searchText === '') {
|
|
if (this.searchText === '') {
|
|
|
|
|
+ this.loadSearchHistory()
|
|
|
await this.resetAndLoadFirstPage();
|
|
await this.resetAndLoadFirstPage();
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
@@ -5917,6 +6026,47 @@ export struct LocalMusic {
|
|
|
await this.resetAndLoadFirstPage();
|
|
await this.resetAndLoadFirstPage();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ @Builder
|
|
|
|
|
+ private SearchHistoryView(): void {
|
|
|
|
|
+ Column({ space: 10 }) {
|
|
|
|
|
+ Row() {
|
|
|
|
|
+ Text('搜索历史')
|
|
|
|
|
+ .fontSize(14)
|
|
|
|
|
+ .fontWeight(FontWeight.Medium)
|
|
|
|
|
+ .fontColor($r('app.color.text_color'))
|
|
|
|
|
+ Blank()
|
|
|
|
|
+ Button('清空')
|
|
|
|
|
+ .fontSize(12)
|
|
|
|
|
+ .fontColor(this.themeColor)
|
|
|
|
|
+ .backgroundColor(Color.Transparent)
|
|
|
|
|
+ .padding({ left: 8, right: 8, top: 4, bottom: 4 })
|
|
|
|
|
+ .onClick(() => {
|
|
|
|
|
+ SearchHistoryUtil.clear(this.searchHistoryScope)
|
|
|
|
|
+ this.searchHistoryItems = []
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ .width('100%')
|
|
|
|
|
+
|
|
|
|
|
+ Flex({ wrap: FlexWrap.Wrap }) {
|
|
|
|
|
+ ForEach(this.searchHistoryItems, (keyword: string) => {
|
|
|
|
|
+ Button(keyword)
|
|
|
|
|
+ .fontSize(12)
|
|
|
|
|
+ .fontColor($r('app.color.text_color'))
|
|
|
|
|
+ .backgroundColor(this.isDarkMode ? '#222222' : '#F2F3F5')
|
|
|
|
|
+ .borderRadius(16)
|
|
|
|
|
+ .margin({ right: 8, bottom: 8 })
|
|
|
|
|
+ .padding({ left: 12, right: 12, top: 8, bottom: 8 })
|
|
|
|
|
+ .onClick(() => {
|
|
|
|
|
+ this.applySearchHistory(keyword)
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ .width('100%')
|
|
|
|
|
+ }
|
|
|
|
|
+ .width('100%')
|
|
|
|
|
+ .padding({ left: 16, right: 16, top: 10, bottom: 10 })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
@State dragItem: number = -1
|
|
@State dragItem: number = -1
|
|
|
@State scaleItem: number = -1
|
|
@State scaleItem: number = -1
|
|
|
@State neighborItem: number = -1
|
|
@State neighborItem: number = -1
|
|
@@ -7093,7 +7243,7 @@ export struct LocalMusic {
|
|
|
(this.modeType == 0 || this.modeType == 1 || ((this.modeType == 3 || this.modeType == 2) && this.isCanBack)))
|
|
(this.modeType == 0 || this.modeType == 1 || ((this.modeType == 3 || this.modeType == 2) && this.isCanBack)))
|
|
|
&& item.type !== CommonConstants.TYPE_IS_CSJAD &&
|
|
&& item.type !== CommonConstants.TYPE_IS_CSJAD &&
|
|
|
!this.isHistory) ? { end: this.DeleteButton(item, index, item.filePath),
|
|
!this.isHistory) ? { end: this.DeleteButton(item, index, item.filePath),
|
|
|
- start:null,edgeEffect: SwipeEdgeEffect.None } : {}) //左滑
|
|
|
|
|
|
|
+ edgeEffect: SwipeEdgeEffect.None } : {}) //左滑
|
|
|
.onClick(() => {
|
|
.onClick(() => {
|
|
|
if (this.isMultiSelect) {
|
|
if (this.isMultiSelect) {
|
|
|
if (this.isSelectableLocalItem(item)) {
|
|
if (this.isSelectableLocalItem(item)) {
|
|
@@ -7759,10 +7909,12 @@ export struct LocalMusic {
|
|
|
|
|
|
|
|
private async openIsoArchiveDialog(item: VideoItem): Promise<void> {
|
|
private async openIsoArchiveDialog(item: VideoItem): Promise<void> {
|
|
|
if (!item || StrUtil.isEmpty(item.filePath)) {
|
|
if (!item || StrUtil.isEmpty(item.filePath)) {
|
|
|
|
|
+ Logger.error(TAG, `heanup ISO open dialog invalid path=${item ? item.filePath : ''}`)
|
|
|
ToastUtil.showToast('ISO 文件无效')
|
|
ToastUtil.showToast('ISO 文件无效')
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ Logger.info(TAG, `heanup ISO open dialog path=${item.filePath}, name=${item.fileName || item.name}`)
|
|
|
this.closeIsoDialog()
|
|
this.closeIsoDialog()
|
|
|
this.isoSourceFilePath = item.filePath
|
|
this.isoSourceFilePath = item.filePath
|
|
|
this.isoSourceFileName = item.fileName || item.name
|
|
this.isoSourceFileName = item.fileName || item.name
|
|
@@ -7778,14 +7930,16 @@ export struct LocalMusic {
|
|
|
const task = new taskpool.Task(listIsoAudioEntriesTask, item.filePath)
|
|
const task = new taskpool.Task(listIsoAudioEntriesTask, item.filePath)
|
|
|
const entries = await taskpool.execute(task, taskpool.Priority.HIGH) as IsoArchiveAudioEntry[]
|
|
const entries = await taskpool.execute(task, taskpool.Priority.HIGH) as IsoArchiveAudioEntry[]
|
|
|
this.isoAudioEntries = Array.isArray(entries) ? entries : []
|
|
this.isoAudioEntries = Array.isArray(entries) ? entries : []
|
|
|
|
|
+ Logger.info(TAG, `heanup ISO list entries done count=${this.isoAudioEntries.length}, path=${item.filePath}`)
|
|
|
if (ArrayUtil.isEmpty(this.isoAudioEntries)) {
|
|
if (ArrayUtil.isEmpty(this.isoAudioEntries)) {
|
|
|
|
|
+ Logger.error(TAG, `heanup ISO list entries empty path=${item.filePath}`)
|
|
|
ToastUtil.showToast('ISO 内未找到音频文件')
|
|
ToastUtil.showToast('ISO 内未找到音频文件')
|
|
|
this.closeIsoDialog()
|
|
this.closeIsoDialog()
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
- this.selectedIsoAudioPaths = this.isoAudioEntries.map((entry: IsoArchiveAudioEntry) => entry.path)
|
|
|
|
|
|
|
+ this.selectedIsoAudioPaths = []
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
- Logger.error(TAG, `解析 ISO 失败: ${(error as Error).message}`)
|
|
|
|
|
|
|
+ Logger.error(TAG, `heanup 解析 ISO 失败: ${(error as Error).message}`)
|
|
|
ToastUtil.showToast('解析 ISO 失败')
|
|
ToastUtil.showToast('解析 ISO 失败')
|
|
|
this.closeIsoDialog()
|
|
this.closeIsoDialog()
|
|
|
return
|
|
return
|
|
@@ -7810,30 +7964,33 @@ export struct LocalMusic {
|
|
|
}).then((dialogId: number) => {
|
|
}).then((dialogId: number) => {
|
|
|
this.isoComponentId = dialogId
|
|
this.isoComponentId = dialogId
|
|
|
}).catch((error: BusinessError) => {
|
|
}).catch((error: BusinessError) => {
|
|
|
- Logger.error(TAG, `打开 ISO 弹窗失败: ${error.message}`)
|
|
|
|
|
|
|
+ Logger.error(TAG, `heanup 打开 ISO 弹窗失败: ${error.message}`)
|
|
|
this.closeIsoDialog()
|
|
this.closeIsoDialog()
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private toggleIsoEntrySelection(path: string, checked: boolean): void {
|
|
private toggleIsoEntrySelection(path: string, checked: boolean): void {
|
|
|
- const exists = this.selectedIsoAudioPaths.includes(path)
|
|
|
|
|
|
|
+ const selectedPathSet: Set<string> = new Set<string>(this.selectedIsoAudioPaths)
|
|
|
if (checked) {
|
|
if (checked) {
|
|
|
- if (!exists) {
|
|
|
|
|
- this.selectedIsoAudioPaths = [...this.selectedIsoAudioPaths, path]
|
|
|
|
|
- }
|
|
|
|
|
- return
|
|
|
|
|
- }
|
|
|
|
|
- if (exists) {
|
|
|
|
|
- this.selectedIsoAudioPaths = this.selectedIsoAudioPaths.filter(itemPath => itemPath !== path)
|
|
|
|
|
|
|
+ selectedPathSet.add(path)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ selectedPathSet.delete(path)
|
|
|
}
|
|
}
|
|
|
|
|
+ this.selectedIsoAudioPaths = this.isoAudioEntries
|
|
|
|
|
+ .filter((entry: IsoArchiveAudioEntry) => selectedPathSet.has(entry.path))
|
|
|
|
|
+ .map((entry: IsoArchiveAudioEntry) => entry.path)
|
|
|
|
|
+ Logger.info(TAG,
|
|
|
|
|
+ `heanup ISO toggle selection path=${path}, checked=${checked}, total=${this.selectedIsoAudioPaths.length}`)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private toggleIsoEntrySelectAll(): void {
|
|
private toggleIsoEntrySelectAll(): void {
|
|
|
if (this.selectedIsoAudioPaths.length === this.isoAudioEntries.length) {
|
|
if (this.selectedIsoAudioPaths.length === this.isoAudioEntries.length) {
|
|
|
this.selectedIsoAudioPaths = []
|
|
this.selectedIsoAudioPaths = []
|
|
|
|
|
+ Logger.info(TAG, 'heanup ISO toggle select all cleared')
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
this.selectedIsoAudioPaths = this.isoAudioEntries.map((entry: IsoArchiveAudioEntry) => entry.path)
|
|
this.selectedIsoAudioPaths = this.isoAudioEntries.map((entry: IsoArchiveAudioEntry) => entry.path)
|
|
|
|
|
+ Logger.info(TAG, `heanup ISO toggle select all count=${this.selectedIsoAudioPaths.length}`)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private startIsoExtractProgressWatcher(entries: Array<IsoArchiveAudioEntry>): void {
|
|
private startIsoExtractProgressWatcher(entries: Array<IsoArchiveAudioEntry>): void {
|
|
@@ -7843,6 +8000,9 @@ export struct LocalMusic {
|
|
|
const size = entry && entry.size > 0 ? entry.size : 0
|
|
const size = entry && entry.size > 0 ? entry.size : 0
|
|
|
return total + size
|
|
return total + size
|
|
|
}, 0)
|
|
}, 0)
|
|
|
|
|
+ this.isoExtractReceivedTaskProgress = false
|
|
|
|
|
+ this.isoExtractDisplayedProgress = 0
|
|
|
|
|
+ this.isoExtractLastActivityTime = Date.now()
|
|
|
if (this.isoExtractTotalBytes <= 0 || ArrayUtil.isEmpty(this.isoExtractExpectedOutputPaths)) {
|
|
if (this.isoExtractTotalBytes <= 0 || ArrayUtil.isEmpty(this.isoExtractExpectedOutputPaths)) {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
@@ -7858,11 +8018,17 @@ export struct LocalMusic {
|
|
|
}
|
|
}
|
|
|
this.isoExtractExpectedOutputPaths = []
|
|
this.isoExtractExpectedOutputPaths = []
|
|
|
this.isoExtractTotalBytes = 0
|
|
this.isoExtractTotalBytes = 0
|
|
|
|
|
+ this.isoExtractReceivedTaskProgress = false
|
|
|
|
|
+ this.isoExtractLastActivityTime = 0
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private markIsoExtractActivity(): void {
|
|
|
|
|
+ this.isoExtractLastActivityTime = Date.now()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private updateIsoExtractProgressFromFiles(): void {
|
|
private updateIsoExtractProgressFromFiles(): void {
|
|
|
if (!this.loadingProgressDialogId || this.isoExtractTotalBytes <= 0 ||
|
|
if (!this.loadingProgressDialogId || this.isoExtractTotalBytes <= 0 ||
|
|
|
- ArrayUtil.isEmpty(this.isoExtractExpectedOutputPaths)) {
|
|
|
|
|
|
|
+ ArrayUtil.isEmpty(this.isoExtractExpectedOutputPaths) || this.isoExtractReceivedTaskProgress) {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -7889,14 +8055,54 @@ export struct LocalMusic {
|
|
|
if (progress > 99) {
|
|
if (progress > 99) {
|
|
|
progress = 99
|
|
progress = 99
|
|
|
}
|
|
}
|
|
|
|
|
+ this.markIsoExtractActivity()
|
|
|
} else if (existingCount > 0) {
|
|
} else if (existingCount > 0) {
|
|
|
progress = 1
|
|
progress = 1
|
|
|
|
|
+ this.markIsoExtractActivity()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (progress > 0) {
|
|
if (progress > 0) {
|
|
|
- DialogHelper.updateLoading(this.loadingProgressDialogId,
|
|
|
|
|
- `正在提取 ${progress}% (${existingCount}/${this.isoExtractExpectedOutputPaths.length})`, progress)
|
|
|
|
|
|
|
+ this.updateIsoExtractProgressDialog(progress,
|
|
|
|
|
+ `正在提取 ${progress}% (${existingCount}/${this.isoExtractExpectedOutputPaths.length})`)
|
|
|
|
|
+ return
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ if (this.isoExtractTask && this.isoExtractLastActivityTime > 0 &&
|
|
|
|
|
+ Date.now() - this.isoExtractLastActivityTime > this.isoExtractStallTimeoutMs) {
|
|
|
|
|
+ Logger.warn(TAG, `heanup ISO 提取进度长时间无变化: timeout=${this.isoExtractStallTimeoutMs}`)
|
|
|
|
|
+ this.markIsoExtractActivity()
|
|
|
|
|
+ this.updateIsoExtractProgressDialog(1, '准备提取 1%')
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private updateIsoExtractProgressDialog(progress: number, message: string, force: boolean = false): void {
|
|
|
|
|
+ if (!this.loadingProgressDialogId) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ let safeProgress = progress
|
|
|
|
|
+ if (safeProgress < 0) {
|
|
|
|
|
+ safeProgress = 0
|
|
|
|
|
+ }
|
|
|
|
|
+ if (safeProgress > 100) {
|
|
|
|
|
+ safeProgress = 100
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!force && safeProgress < this.isoExtractDisplayedProgress) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ this.isoExtractDisplayedProgress = safeProgress
|
|
|
|
|
+ DialogHelper.updateLoading(this.loadingProgressDialogId, message, safeProgress)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private closeIsoExtractLoadingDialog(): void {
|
|
|
|
|
+ if (!this.loadingProgressDialogId) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ try {
|
|
|
|
|
+ DialogHelper.closeDialog(this.loadingProgressDialogId)
|
|
|
|
|
+ } catch (_error) {
|
|
|
|
|
+ }
|
|
|
|
|
+ this.loadingProgressDialogId = ''
|
|
|
|
|
+ this.isoExtractDisplayedProgress = 0
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private buildIsoExtractExpectedOutputPaths(entries: Array<IsoArchiveAudioEntry>): Array<string> {
|
|
private buildIsoExtractExpectedOutputPaths(entries: Array<IsoArchiveAudioEntry>): Array<string> {
|
|
@@ -7918,7 +8124,7 @@ export struct LocalMusic {
|
|
|
const baseName = extension.length > 0 ? cleanName.substring(0, cleanName.length - extension.length) : cleanName
|
|
const baseName = extension.length > 0 ? cleanName.substring(0, cleanName.length - extension.length) : cleanName
|
|
|
|
|
|
|
|
let candidatePath = `${this.trimIsoOutputTrailingSeparator(destinationDir)}/${cleanName}`
|
|
let candidatePath = `${this.trimIsoOutputTrailingSeparator(destinationDir)}/${cleanName}`
|
|
|
- let suffix = 1
|
|
|
|
|
|
|
+ let suffix = 0
|
|
|
while (occupiedPaths.has(candidatePath) || FileUtil.accessSync(candidatePath)) {
|
|
while (occupiedPaths.has(candidatePath) || FileUtil.accessSync(candidatePath)) {
|
|
|
suffix++
|
|
suffix++
|
|
|
candidatePath = `${this.trimIsoOutputTrailingSeparator(destinationDir)}/${baseName} (${suffix})${extension}`
|
|
candidatePath = `${this.trimIsoOutputTrailingSeparator(destinationDir)}/${baseName} (${suffix})${extension}`
|
|
@@ -7968,6 +8174,27 @@ export struct LocalMusic {
|
|
|
return path
|
|
return path
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private cancelIsoExtraction(reason?: string, closeLoadingDialog: boolean = true): void {
|
|
|
|
|
+ const currentTask = this.isoExtractTask
|
|
|
|
|
+ Logger.info(TAG,
|
|
|
|
|
+ `heanup ISO cancel request reason=${reason || ''}, hasTask=${currentTask ? 'true' : 'false'}, ` +
|
|
|
|
|
+ `closeLoading=${closeLoadingDialog}`)
|
|
|
|
|
+ this.isoExtractCanceled = true
|
|
|
|
|
+ this.isoExtractCancelMessage = reason ? reason : ''
|
|
|
|
|
+ this.isoExtractTask = undefined
|
|
|
|
|
+ if (currentTask) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ taskpool.terminateTask(currentTask)
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ Logger.error(TAG, `heanup 终止 ISO 提取任务失败: ${(error as Error).message}`)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (closeLoadingDialog) {
|
|
|
|
|
+ this.closeIsoExtractLoadingDialog()
|
|
|
|
|
+ }
|
|
|
|
|
+ this.closeIsoDialog()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private async extractSelectedIsoAudioFiles(): Promise<void> {
|
|
private async extractSelectedIsoAudioFiles(): Promise<void> {
|
|
|
if (this.isIsoExtracting) {
|
|
if (this.isIsoExtracting) {
|
|
|
return
|
|
return
|
|
@@ -7976,45 +8203,83 @@ export struct LocalMusic {
|
|
|
ToastUtil.showToast('请先选择要提取的音频文件')
|
|
ToastUtil.showToast('请先选择要提取的音频文件')
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
+ const selectedPathSet: Set<string> = new Set<string>(this.selectedIsoAudioPaths)
|
|
|
const selectedEntries = this.isoAudioEntries
|
|
const selectedEntries = this.isoAudioEntries
|
|
|
- .filter((entry: IsoArchiveAudioEntry) => this.selectedIsoAudioPaths.includes(entry.path))
|
|
|
|
|
|
|
+ .filter((entry: IsoArchiveAudioEntry) => selectedPathSet.has(entry.path))
|
|
|
if (ArrayUtil.isEmpty(selectedEntries)) {
|
|
if (ArrayUtil.isEmpty(selectedEntries)) {
|
|
|
ToastUtil.showToast('未找到要提取的音频文件')
|
|
ToastUtil.showToast('未找到要提取的音频文件')
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
const hasSacdTrack: boolean = selectedEntries.some((entry: IsoArchiveAudioEntry) => entry.entryType === 'sacd_track')
|
|
const hasSacdTrack: boolean = selectedEntries.some((entry: IsoArchiveAudioEntry) => entry.entryType === 'sacd_track')
|
|
|
- const hasDstTrack: boolean = selectedEntries.some((entry: IsoArchiveAudioEntry) =>
|
|
|
|
|
- entry.entryType === 'sacd_track' && entry.frameFormat === 0)
|
|
|
|
|
|
|
|
|
|
this.isIsoExtracting = true
|
|
this.isIsoExtracting = true
|
|
|
|
|
+ this.isoExtractCanceled = false
|
|
|
|
|
+ this.isoExtractCancelMessage = ''
|
|
|
|
|
+ Logger.info(TAG,
|
|
|
|
|
+ `heanup ISO extract start file=${this.isoSourceFilePath}, selected=${selectedEntries.length}, hasSacd=${hasSacdTrack}`)
|
|
|
|
|
+ Logger.info(TAG,
|
|
|
|
|
+ `heanup ISO selected entries: ${selectedEntries.map((entry: IsoArchiveAudioEntry) => entry.path).join(', ')}`)
|
|
|
this.loadingProgressDialogId = DialogHelper.showLoadingProgress({
|
|
this.loadingProgressDialogId = DialogHelper.showLoadingProgress({
|
|
|
progress: 0,
|
|
progress: 0,
|
|
|
- backCancel: false,
|
|
|
|
|
|
|
+ backCancel: true,
|
|
|
autoCancel: false,
|
|
autoCancel: false,
|
|
|
loadColor: this.themeColor,
|
|
loadColor: this.themeColor,
|
|
|
- fontColor: this.themeColor
|
|
|
|
|
|
|
+ fontColor: this.themeColor,
|
|
|
|
|
+ onWillDismiss: (dismissDialogAction: DismissDialogAction) => {
|
|
|
|
|
+ if (dismissDialogAction.reason == DismissReason.PRESS_BACK) {
|
|
|
|
|
+ this.cancelIsoExtraction('已取消 ISO 提取', false)
|
|
|
|
|
+ dismissDialogAction.dismiss()
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
})
|
|
})
|
|
|
|
|
+ this.isoExtractDisplayedProgress = 0
|
|
|
|
|
+ this.updateIsoExtractProgressDialog(1, '准备提取 1%', true)
|
|
|
this.startIsoExtractProgressWatcher(selectedEntries)
|
|
this.startIsoExtractProgressWatcher(selectedEntries)
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
|
|
+ const outputPaths: string[] = this.buildIsoExtractExpectedOutputPaths(selectedEntries)
|
|
|
const payloadJson = JSON.stringify({
|
|
const payloadJson = JSON.stringify({
|
|
|
isoPath: this.isoSourceFilePath,
|
|
isoPath: this.isoSourceFilePath,
|
|
|
destinationDir: this.currentPath,
|
|
destinationDir: this.currentPath,
|
|
|
- entries: selectedEntries
|
|
|
|
|
|
|
+ entries: selectedEntries,
|
|
|
|
|
+ outputPaths
|
|
|
})
|
|
})
|
|
|
const task = new taskpool.Task(extractIsoAudioEntriesTask, payloadJson)
|
|
const task = new taskpool.Task(extractIsoAudioEntriesTask, payloadJson)
|
|
|
|
|
+ this.isoExtractTask = task
|
|
|
task.onReceiveData((progressData: IsoExtractProgressMessage) => {
|
|
task.onReceiveData((progressData: IsoExtractProgressMessage) => {
|
|
|
|
|
+ this.markIsoExtractActivity()
|
|
|
const progress = typeof progressData.progress === 'number' ? Math.floor(progressData.progress) : 0
|
|
const progress = typeof progressData.progress === 'number' ? Math.floor(progressData.progress) : 0
|
|
|
|
|
+ Logger.info(TAG,
|
|
|
|
|
+ `heanup ISO task receive stage=${progressData.stage || ''}, progress=${progress}, name=${progressData.name || ''}`)
|
|
|
|
|
+ if (progress > 1 && !this.isoExtractReceivedTaskProgress) {
|
|
|
|
|
+ this.isoExtractReceivedTaskProgress = true
|
|
|
|
|
+ if (this.isoExtractProgressTimer) {
|
|
|
|
|
+ clearInterval(this.isoExtractProgressTimer)
|
|
|
|
|
+ this.isoExtractProgressTimer = 0
|
|
|
|
|
+ }
|
|
|
|
|
+ Logger.info(TAG, `heanup ISO 提取切换为任务进度: progress=${progress}, stage=${progressData.stage || ''}`)
|
|
|
|
|
+ }
|
|
|
const stageText = progressData.stage === 'prepare' ? '准备提取' :
|
|
const stageText = progressData.stage === 'prepare' ? '准备提取' :
|
|
|
(progressData.stage === 'done' ? '提取完成' : (progressData.stage === 'error' ? '提取异常' : '正在提取'))
|
|
(progressData.stage === 'done' ? '提取完成' : (progressData.stage === 'error' ? '提取异常' : '正在提取'))
|
|
|
const nameText = StrUtil.isNotEmpty(progressData.name) ? ` ${progressData.name}` : ''
|
|
const nameText = StrUtil.isNotEmpty(progressData.name) ? ` ${progressData.name}` : ''
|
|
|
- if (this.loadingProgressDialogId) {
|
|
|
|
|
- DialogHelper.updateLoading(this.loadingProgressDialogId, `${stageText} ${progress}%${nameText}`, progress)
|
|
|
|
|
|
|
+ if (progress > this.isoExtractDisplayedProgress || progressData.stage !== 'extract') {
|
|
|
|
|
+ Logger.info(TAG,
|
|
|
|
|
+ `heanup ISO 提取任务进度: stage=${progressData.stage || ''}, progress=${progress}, ` +
|
|
|
|
|
+ `name=${progressData.name || ''}`)
|
|
|
}
|
|
}
|
|
|
|
|
+ this.updateIsoExtractProgressDialog(progress, `${stageText} ${progress}%${nameText}`)
|
|
|
})
|
|
})
|
|
|
const result = await taskpool.execute(task, taskpool.Priority.HIGH) as IsoExtractTaskResult
|
|
const result = await taskpool.execute(task, taskpool.Priority.HIGH) as IsoExtractTaskResult
|
|
|
|
|
+ this.isoExtractTask = undefined
|
|
|
|
|
+ Logger.info(TAG, `heanup ISO extract task completed canceled=${this.isoExtractCanceled}`)
|
|
|
|
|
+ if (this.isoExtractCanceled) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
const extractedPaths = result?.extractedPaths || []
|
|
const extractedPaths = result?.extractedPaths || []
|
|
|
const failedEntries = result?.failedEntries || []
|
|
const failedEntries = result?.failedEntries || []
|
|
|
|
|
+ const failureDetails = result?.failureDetails || []
|
|
|
|
|
+ Logger.info(TAG,
|
|
|
|
|
+ `heanup ISO extract result extracted=${extractedPaths.length}, failed=${failedEntries.length}, details=${failureDetails.length}`)
|
|
|
if (ArrayUtil.isNotEmpty(extractedPaths)) {
|
|
if (ArrayUtil.isNotEmpty(extractedPaths)) {
|
|
|
await this.importExtractedFilesToCurrentPath(extractedPaths)
|
|
await this.importExtractedFilesToCurrentPath(extractedPaths)
|
|
|
}
|
|
}
|
|
@@ -8024,23 +8289,34 @@ export struct LocalMusic {
|
|
|
ToastUtil.showToast(`提取完成,成功 ${extractedPaths.length} 个,失败 ${failedEntries.length} 个`)
|
|
ToastUtil.showToast(`提取完成,成功 ${extractedPaths.length} 个,失败 ${failedEntries.length} 个`)
|
|
|
} else if (extractedPaths.length > 0) {
|
|
} else if (extractedPaths.length > 0) {
|
|
|
ToastUtil.showToast(`提取完成,已导入 ${extractedPaths.length} 个音频文件`)
|
|
ToastUtil.showToast(`提取完成,已导入 ${extractedPaths.length} 个音频文件`)
|
|
|
- } else if (hasDstTrack) {
|
|
|
|
|
- ToastUtil.showToast('当前 SACD ISO 为 DST 压缩轨道,暂不支持提取')
|
|
|
|
|
|
|
+ } else if (ArrayUtil.isNotEmpty(failureDetails)) {
|
|
|
|
|
+ const firstFailure: IsoExtractFailureDetail = failureDetails[0]
|
|
|
|
|
+ const reasonText = firstFailure.reason && firstFailure.reason.length > 0 ? firstFailure.reason : '提取失败'
|
|
|
|
|
+ ToastUtil.showToast(reasonText)
|
|
|
} else if (hasSacdTrack) {
|
|
} else if (hasSacdTrack) {
|
|
|
ToastUtil.showToast('SACD ISO 轨道提取失败')
|
|
ToastUtil.showToast('SACD ISO 轨道提取失败')
|
|
|
} else {
|
|
} else {
|
|
|
ToastUtil.showToast('提取失败')
|
|
ToastUtil.showToast('提取失败')
|
|
|
}
|
|
}
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
- Logger.error(TAG, `提取 ISO 音频失败: ${(error as Error).message}`)
|
|
|
|
|
|
|
+ this.isoExtractTask = undefined
|
|
|
|
|
+ if (this.isoExtractCanceled) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ Logger.error(TAG, `heanup 提取 ISO 音频失败: ${(error as Error).message}`)
|
|
|
ToastUtil.showToast('提取 ISO 音频失败')
|
|
ToastUtil.showToast('提取 ISO 音频失败')
|
|
|
} finally {
|
|
} finally {
|
|
|
this.stopIsoExtractProgressWatcher()
|
|
this.stopIsoExtractProgressWatcher()
|
|
|
|
|
+ this.isoExtractTask = undefined
|
|
|
this.isIsoExtracting = false
|
|
this.isIsoExtracting = false
|
|
|
- if (this.loadingProgressDialogId) {
|
|
|
|
|
- DialogHelper.closeDialog(this.loadingProgressDialogId)
|
|
|
|
|
- this.loadingProgressDialogId = ''
|
|
|
|
|
|
|
+ Logger.info(TAG,
|
|
|
|
|
+ `heanup ISO extract finally canceled=${this.isoExtractCanceled}, cancelMessage=${this.isoExtractCancelMessage}`)
|
|
|
|
|
+ if (this.isoExtractCanceled && this.isoExtractCancelMessage.length > 0) {
|
|
|
|
|
+ ToastUtil.showToast(this.isoExtractCancelMessage)
|
|
|
}
|
|
}
|
|
|
|
|
+ this.isoExtractCanceled = false
|
|
|
|
|
+ this.isoExtractCancelMessage = ''
|
|
|
|
|
+ this.closeIsoExtractLoadingDialog()
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -8091,6 +8367,7 @@ export struct LocalMusic {
|
|
|
this.isoSourceFilePath = ''
|
|
this.isoSourceFilePath = ''
|
|
|
this.isIsoExtracting = false
|
|
this.isIsoExtracting = false
|
|
|
this.stopIsoExtractProgressWatcher()
|
|
this.stopIsoExtractProgressWatcher()
|
|
|
|
|
+ this.isoExtractTask = undefined
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Builder
|
|
@Builder
|
|
@@ -8112,6 +8389,7 @@ export struct LocalMusic {
|
|
|
},
|
|
},
|
|
|
onCancel: () => {
|
|
onCancel: () => {
|
|
|
if (this.isIsoExtracting) {
|
|
if (this.isIsoExtracting) {
|
|
|
|
|
+ this.cancelIsoExtraction('已取消 ISO 提取')
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
this.closeIsoDialog()
|
|
this.closeIsoDialog()
|
|
@@ -19300,22 +19578,22 @@ export struct LocalMusic {
|
|
|
DeleteButton(item: VideoItem, index: number, filePath: string) {
|
|
DeleteButton(item: VideoItem, index: number, filePath: string) {
|
|
|
Row() {
|
|
Row() {
|
|
|
//加入收藏
|
|
//加入收藏
|
|
|
- Button() {
|
|
|
|
|
- Image(Utility.getIsFav(this.favList, item) ? $r('app.media.add_fac_light2') : $r('app.media.add_fac'))
|
|
|
|
|
- .fillColor(Color.White)
|
|
|
|
|
- .width(20)
|
|
|
|
|
- }
|
|
|
|
|
- .width(40)
|
|
|
|
|
- .height(40)
|
|
|
|
|
- .type(ButtonType.Circle)
|
|
|
|
|
- .backgroundColor(this.themeColor)
|
|
|
|
|
- .margin(5)
|
|
|
|
|
- .visibility(this.supportsLocalAudioActions(item) ? Visibility.Visible : Visibility.None)
|
|
|
|
|
- .onClick(() => {
|
|
|
|
|
- if (item) {
|
|
|
|
|
- this.doFav(item)
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ // Button() {
|
|
|
|
|
+ // Image(Utility.getIsFav(this.favList, item) ? $r('app.media.add_fac_light2') : $r('app.media.add_fac'))
|
|
|
|
|
+ // .fillColor(Color.White)
|
|
|
|
|
+ // .width(20)
|
|
|
|
|
+ // }
|
|
|
|
|
+ // .width(40)
|
|
|
|
|
+ // .height(40)
|
|
|
|
|
+ // .type(ButtonType.Circle)
|
|
|
|
|
+ // .backgroundColor(this.themeColor)
|
|
|
|
|
+ // .margin(5)
|
|
|
|
|
+ // .visibility(this.supportsLocalAudioActions(item) ? Visibility.Visible : Visibility.None)
|
|
|
|
|
+ // .onClick(() => {
|
|
|
|
|
+ // if (item) {
|
|
|
|
|
+ // this.doFav(item)
|
|
|
|
|
+ // }
|
|
|
|
|
+ // })
|
|
|
|
|
|
|
|
//加入下一首播放
|
|
//加入下一首播放
|
|
|
Button() {
|
|
Button() {
|
|
@@ -19386,23 +19664,23 @@ export struct LocalMusic {
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
//重命名
|
|
//重命名
|
|
|
- Button() {
|
|
|
|
|
- Image($r('app.media.rename2'))
|
|
|
|
|
- .fillColor(Color.White)
|
|
|
|
|
- .width(20)
|
|
|
|
|
- }
|
|
|
|
|
- .width(40)
|
|
|
|
|
- .height(40)
|
|
|
|
|
- .type(ButtonType.Circle)
|
|
|
|
|
- .backgroundColor(this.themeColor)
|
|
|
|
|
- .visibility(item.type === CommonConstants.TYPE_IS_DIR ?
|
|
|
|
|
- (item.name === LocalMusic.STR_LOCK_VIDEO || item.name === LocalMusic.STR_FAC_VIDEO ||
|
|
|
|
|
- item.name === LocalMusic.STR_HISTORY_MUSIC ? Visibility.None : Visibility.Visible) : Visibility.Visible)
|
|
|
|
|
- .margin(5)
|
|
|
|
|
- .onClick(() => {
|
|
|
|
|
- this.showReNameDialog(item, index + '', filePath)
|
|
|
|
|
-
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ // Button() {
|
|
|
|
|
+ // Image($r('app.media.rename2'))
|
|
|
|
|
+ // .fillColor(Color.White)
|
|
|
|
|
+ // .width(20)
|
|
|
|
|
+ // }
|
|
|
|
|
+ // .width(40)
|
|
|
|
|
+ // .height(40)
|
|
|
|
|
+ // .type(ButtonType.Circle)
|
|
|
|
|
+ // .backgroundColor(this.themeColor)
|
|
|
|
|
+ // .visibility(item.type === CommonConstants.TYPE_IS_DIR ?
|
|
|
|
|
+ // (item.name === LocalMusic.STR_LOCK_VIDEO || item.name === LocalMusic.STR_FAC_VIDEO ||
|
|
|
|
|
+ // item.name === LocalMusic.STR_HISTORY_MUSIC ? Visibility.None : Visibility.Visible) : Visibility.Visible)
|
|
|
|
|
+ // .margin(5)
|
|
|
|
|
+ // .onClick(() => {
|
|
|
|
|
+ // this.showReNameDialog(item, index + '', filePath)
|
|
|
|
|
+ //
|
|
|
|
|
+ // })
|
|
|
|
|
|
|
|
Button() {
|
|
Button() {
|
|
|
Image($r('app.media.delete2'))
|
|
Image($r('app.media.delete2'))
|
|
@@ -19416,27 +19694,27 @@ export struct LocalMusic {
|
|
|
.visibility(item.type === CommonConstants.TYPE_IS_DIR ?
|
|
.visibility(item.type === CommonConstants.TYPE_IS_DIR ?
|
|
|
(item.name === LocalMusic.STR_LOCK_VIDEO || item.name === LocalMusic.STR_FAC_VIDEO ||
|
|
(item.name === LocalMusic.STR_LOCK_VIDEO || item.name === LocalMusic.STR_FAC_VIDEO ||
|
|
|
item.name === LocalMusic.STR_HISTORY_MUSIC ? Visibility.None : Visibility.Visible) : Visibility.Visible)
|
|
item.name === LocalMusic.STR_HISTORY_MUSIC ? Visibility.None : Visibility.Visible) : Visibility.Visible)
|
|
|
- .margin(5)
|
|
|
|
|
|
|
+ .margin({ left:5,top:5,bottom:5,right:20} )
|
|
|
.onClick(() => {
|
|
.onClick(() => {
|
|
|
this.selectSingleItemForDelete(item)
|
|
this.selectSingleItemForDelete(item)
|
|
|
this.showWarnIsDelete()
|
|
this.showWarnIsDelete()
|
|
|
// this.showWarnIsDeleteFile(item, index + '', filePath)
|
|
// this.showWarnIsDeleteFile(item, index + '', filePath)
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- Button() {
|
|
|
|
|
- Image($r('app.media.share2'))
|
|
|
|
|
- .fillColor(Color.White)
|
|
|
|
|
- .width(20)
|
|
|
|
|
- }
|
|
|
|
|
- .width(40)
|
|
|
|
|
- .height(40)
|
|
|
|
|
- .type(ButtonType.Circle)
|
|
|
|
|
- .backgroundColor(this.themeColor)
|
|
|
|
|
- .margin(5)
|
|
|
|
|
- .visibility(item.type === CommonConstants.TYPE_IS_DIR ? Visibility.None : Visibility.Visible)
|
|
|
|
|
- .onClick(() => {
|
|
|
|
|
- Utility.doShareMusic(item, getContext(this) as common.UIAbilityContext)
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ // Button() {
|
|
|
|
|
+ // Image($r('app.media.share2'))
|
|
|
|
|
+ // .fillColor(Color.White)
|
|
|
|
|
+ // .width(20)
|
|
|
|
|
+ // }
|
|
|
|
|
+ // .width(40)
|
|
|
|
|
+ // .height(40)
|
|
|
|
|
+ // .type(ButtonType.Circle)
|
|
|
|
|
+ // .backgroundColor(this.themeColor)
|
|
|
|
|
+ // .margin(5)
|
|
|
|
|
+ // .visibility(item.type === CommonConstants.TYPE_IS_DIR ? Visibility.None : Visibility.Visible)
|
|
|
|
|
+ // .onClick(() => {
|
|
|
|
|
+ // Utility.doShareMusic(item, getContext(this) as common.UIAbilityContext)
|
|
|
|
|
+ // })
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -19904,11 +20182,6 @@ function cutPopupBuilder(dataBu: BubbleBean) {
|
|
|
.margin({ top: 7, bottom: 7 })
|
|
.margin({ top: 7, bottom: 7 })
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
- .transition(TransitionEffect.asymmetric(TransitionEffect.move(TransitionEdge.BOTTOM)
|
|
|
|
|
- .animation({ duration: 500 }),
|
|
|
|
|
- TransitionEffect.scale({ x: 0, y: 0 })))
|
|
|
|
|
- // .transition(TransitionEffect.asymmetric(TransitionEffect.scale({ x: 1.2, y: 1.2 }).animation({ duration: 500 }),
|
|
|
|
|
- // TransitionEffect.scale({ x: 0, y: 0 }) ))
|
|
|
|
|
.onClick(() => {
|
|
.onClick(() => {
|
|
|
dataBu.onItemClick?.(index)
|
|
dataBu.onItemClick?.(index)
|
|
|
})
|
|
})
|