Преглед на файлове

修复在歌单播放歌曲的时候,这时候搜索歌曲,如果搜到的歌曲不是歌单里的,点击播放他会播放歌单里的第一首歌,而且再返回的的时候,歌单显示的歌曲是乱的

onecold преди 4 месеца
родител
ревизия
707ef56608

+ 47 - 0
entry/src/main/ets/common/util/PlaylistSearchHelper.ets

@@ -0,0 +1,47 @@
+import { VideoItem } from '../../viewmodel/VideoItem'
+
+function normalizeSearchText(value: string | undefined): string {
+  return value ? value.trim().toLowerCase() : ''
+}
+
+function buildSearchCandidateText(song: VideoItem): string {
+  const rawFragments: Array<string | undefined> = [
+    song.name,
+    song.artist,
+    song.album,
+    song.fileName
+  ]
+  const fragments: string[] = []
+
+  rawFragments.forEach((item: string | undefined): void => {
+    if (item !== undefined && item.length > 0) {
+      fragments.push(item)
+    }
+  })
+
+  return fragments
+    .join('\n')
+    .toLowerCase()
+}
+
+// 歌单搜索只在当前歌单队列里过滤,保持原始歌单顺序不变。
+export function filterPlaylistSongsByKeyword(songs: VideoItem[], keyword: string): VideoItem[] {
+  const normalizedKeyword = normalizeSearchText(keyword)
+  if (normalizedKeyword.length === 0) {
+    return [...songs]
+  }
+
+  return songs.filter((song: VideoItem): boolean => {
+    return buildSearchCandidateText(song).includes(normalizedKeyword)
+  })
+}
+
+// 播放队列定位未命中时必须返回 -1,避免错误回落到队列第一首。
+export function findSongIndexByFilePath(queue: VideoItem[], filePath: string): number {
+  for (let index = 0; index < queue.length; index++) {
+    if (queue[index].filePath === filePath) {
+      return index
+    }
+  }
+  return -1
+}

+ 5 - 0
entry/src/main/ets/common/util/WebDavListRenderHelper.ets

@@ -0,0 +1,5 @@
+export function buildWebDavSongItemRenderKey(filePath: string, index: number, pixelMapPath?: string): string {
+  const safeFilePath: string = filePath && filePath.length > 0 ? filePath : 'unknown'
+  const safeCoverKey: string = pixelMapPath && pixelMapPath.length > 0 ? pixelMapPath : 'no-cover'
+  return `${safeFilePath}_${index}_${safeCoverKey}`
+}

+ 43 - 0
entry/src/main/ets/common/util/WebDavThumbPrefetchHelper.ets

@@ -0,0 +1,43 @@
+export interface WebDavThumbPrefetchRange {
+  start: number;
+  endExclusive: number;
+}
+
+export interface WebDavVisibleThumbPrefetchWindow {
+  hasVisibleSongs: boolean;
+  range: WebDavThumbPrefetchRange;
+}
+
+const EMPTY_WEBDAV_THUMB_RANGE: WebDavThumbPrefetchRange = {
+  start: 0,
+  endExclusive: 0
+}
+
+const EMPTY_WEBDAV_VISIBLE_WINDOW: WebDavVisibleThumbPrefetchWindow = {
+  hasVisibleSongs: false,
+  range: EMPTY_WEBDAV_THUMB_RANGE
+}
+
+// List 的可见索引会把顶部文件夹项也算进去,这里统一换算成歌曲数组范围。
+export function buildWebDavVisibleThumbPrefetchWindow(totalSongCount: number, folderCount: number,
+  visibleListStart: number, visibleListEnd: number): WebDavVisibleThumbPrefetchWindow {
+  if (totalSongCount <= 0) {
+    return EMPTY_WEBDAV_VISIBLE_WINDOW
+  }
+  const safeFolderCount: number = Math.max(folderCount, 0)
+  const safeVisibleStart: number = Math.max(visibleListStart, 0)
+  const safeVisibleEnd: number = Math.max(visibleListEnd, safeVisibleStart)
+  const songStart: number = Math.max(0, safeVisibleStart - safeFolderCount)
+  const songEndInclusive: number = Math.min(totalSongCount - 1, safeVisibleEnd - safeFolderCount)
+  if (songEndInclusive < songStart) {
+    return EMPTY_WEBDAV_VISIBLE_WINDOW
+  }
+  const range: WebDavThumbPrefetchRange = {
+    start: songStart,
+    endExclusive: songEndInclusive + 1
+  }
+  return {
+    hasVisibleSongs: true,
+    range: range
+  }
+}

+ 23 - 1
entry/src/main/ets/view/LocalMusic.ets

@@ -51,6 +51,7 @@ import { CommonConstants } from '../common/constants/CommonConstants';
 import { BaiduConstants } from '../common/constants/BaiduConstants';
 import { EventConstants } from '../common/constants/EventConstants';
 import Logger from '../common/util/Logger';
+import { filterPlaylistSongsByKeyword, findSongIndexByFilePath } from '../common/util/PlaylistSearchHelper';
 import { http } from '@kit.NetworkKit';
 import { photoAccessHelper } from '@kit.MediaLibraryKit';
 import { BusinessError, emitter } from '@kit.BasicServicesKit';
@@ -6309,6 +6310,27 @@ export struct LocalMusic {
 
     Logger.info('heanup LocalMusic', `onSearchInput: keyword="${this.searchText}", mode=${this.modeType}`);
 
+    // 歌单模式不走媒体库分页查询,直接在当前歌单中筛选,避免混入非歌单歌曲并打乱顺序。
+    if (this.modeType === 4) {
+      if (this.searchText === '') {
+        this.loadSearchHistory()
+        this.filteredList = []
+        this.updateListData(this.currentSongList, true, true)
+        Logger.info('heanup LocalMusic', `onSearchInput: restore playlist list, count=${this.currentSongList.length}`)
+        return
+      }
+
+      if (!this.isSearchMode) {
+        this.isSearchMode = true
+      }
+
+      const filteredSongs = filterPlaylistSongsByKeyword(this.currentSongList, this.searchText)
+      this.filteredList = filteredSongs
+      this.updateListData(filteredSongs, true, true)
+      Logger.info('heanup LocalMusic', `onSearchInput: playlist filter applied, keyword="${this.searchText}", count=${filteredSongs.length}`)
+      return
+    }
+
     // 清空搜索文本时保持搜索态,只重置为不带关键词的结果列表
     if (this.searchText === '') {
       this.loadSearchHistory()
@@ -8113,7 +8135,7 @@ export struct LocalMusic {
           }
         }else {
           const globalVideoList = this.buildPlayQueueFromView();
-          this.curIndex = Utility.getCurIndexFromGlobalList(globalVideoList, item.filePath)
+          this.curIndex = findSongIndexByFilePath(globalVideoList, item.filePath)
           if (this.curIndex < 0) {
             globalVideoList.push(item);
             this.curIndex = globalVideoList.length - 1;