Procházet zdrojové kódy

适配hicar的发现页界面
修复网盘的文件夹返回问题

onecold před 4 měsíci
rodič
revize
4f5e222b5e

+ 49 - 0
entry/src/main/ets/common/util/RemoteDriveManager.ets

@@ -4269,11 +4269,36 @@ export class RemoteDriveManager {
   }
 
   // 进入文件夹
+  public prepareEnterFolder(folder: FileInfo): string | undefined {
+    if (!folder.isDirectory) {
+      Logger.error(TAG, '不是文件夹,无法进入');
+      return undefined;
+    }
+    const targetPath = this.normalizeFullPath(folder.href);
+    if (targetPath === this.currentPath) {
+      Logger.warn(TAG, `忽略重复进入当前目录 target=${targetPath}`);
+      return undefined;
+    }
+    Logger.info(TAG, '预处理进入文件夹:', folder.fileName);
+    Logger.info(TAG, '当前路径:', this.currentPath);
+    Logger.info(TAG, '目标路径:', targetPath);
+    this.registerPathLabel(targetPath, folder.fileName);
+    this.pathHistory.push(this.currentPath);
+    this.currentPath = targetPath;
+    Logger.info(TAG, '预处理后路径历史:', JSON.stringify(this.pathHistory));
+    return targetPath;
+  }
+
   public async enterFolder(folder: FileInfo): Promise<void> {
     if (!folder.isDirectory) {
       Logger.error(TAG, '不是文件夹,无法进入');
       return;
     }
+    const targetPath = this.normalizeFullPath(folder.href);
+    if (targetPath === this.currentPath) {
+      Logger.warn(TAG, `忽略重复进入当前目录 target=${targetPath}`);
+      return;
+    }
 
     Logger.info(TAG, '准备进入文件夹:', folder.fileName);
     Logger.info(TAG, '当前路径:', this.currentPath);
@@ -4282,12 +4307,23 @@ export class RemoteDriveManager {
     // 保存当前路径到历史记录
     this.registerPathLabel(folder.href, folder.fileName);
     this.pathHistory.push(this.currentPath);
+    this.currentPath = targetPath;
     Logger.info(TAG, '路径历史:', JSON.stringify(this.pathHistory));
 
     // 加载文件夹内容
     await this.loadFilesInfoFromAccount(this.currentAccount, folder.href);
   }
 
+  public prepareEnterFolderFromPath(path: string): string {
+    const normalizedTarget = this.normalizeFullPath(path);
+    Logger.info(TAG, '预处理面包屑导航当前路径:', this.currentPath);
+    Logger.info(TAG, '预处理面包屑导航目标路径:', normalizedTarget);
+    this.rebuildPathHistoryForTarget(normalizedTarget);
+    this.currentPath = normalizedTarget;
+    Logger.info(TAG, '预处理面包屑导航路径历史:', JSON.stringify(this.pathHistory));
+    return normalizedTarget;
+  }
+
   public async enterFolderFromPath(path: string): Promise<void> {
     const normalizedTarget = this.normalizeFullPath(path);
 
@@ -4338,6 +4374,19 @@ export class RemoteDriveManager {
 
 
   // 返回上级目录
+  public prepareGoBack(): string | undefined {
+    if (this.pathHistory.length === 0) {
+      Logger.info(TAG, '预处理返回失败: 历史为空');
+      return undefined;
+    }
+    const previousPath = this.pathHistory.pop();
+    if (previousPath !== undefined) {
+      this.currentPath = previousPath;
+    }
+    Logger.info(TAG, `预处理返回到上级目录 previous=${previousPath}, 剩余历史=${JSON.stringify(this.pathHistory)}`);
+    return previousPath;
+  }
+
   public async goBack(): Promise<void> {
     if (this.pathHistory.length === 0) {
       Logger.info(TAG, '已经在根目录,无法返回');

+ 1 - 1
entry/src/main/ets/pages/NewIndex.ets

@@ -666,7 +666,7 @@ struct NewIndex {
         this.pointLightOptions = {
           color: this.themeColor,
           intensity: 1,
-          height: 100
+          height: 60
         }
       } else if (event.type === TouchType.Up || event.type === TouchType.Cancel) {
         this.pointLightOptions = undefined

+ 77 - 6
entry/src/main/ets/pages/WebDavMainPage.ets

@@ -8,7 +8,8 @@ import { CommonConstants } from '../common/constants/CommonConstants';
 import { VideoItem } from '../viewmodel/VideoItem';
 import { GlobalContext } from '../common/util/GlobalContext';
 import { FileInfo } from '../viewmodel/FileInfo';
-import { emitter } from '@kit.BasicServicesKit';
+import { emitter, deviceInfo } from '@kit.BasicServicesKit';
+import { hdsEffect } from '@kit.UIDesignKit';
 import { EventConstants } from '../common/constants/EventConstants';
 import { LazyDataSource } from '../common/util/LazyDataSource';
 import { ArrayUtil, FileUtil, MD5, PreferencesUtil, StrUtil, ToastUtil } from '@pura/harmony-utils';
@@ -142,6 +143,8 @@ export struct WebDavMainPage {
   @StorageProp('isDarkMode') isDarkMode: boolean = false;
   @State currentDirectoryPath: string = '';
   @State breadcrumbs:BreadcrumbItem[] = []//面包屑导航
+  @State private pointLightOptions: hdsEffect.PointLightOptions | undefined = undefined
+  @State private activePointLightItemKey: string = ''
 
   @State visibleFoldersState: FileInfo[] = []; // 改为普通状态变量
   @State isShowFileName: boolean = false//是否显示文件名
@@ -2403,7 +2406,13 @@ export struct WebDavMainPage {
 
   // 进入文件夹
   private enterFolder(folder: FileInfo): void {
-    this.scheduleDirectoryRefresh(folder.href, () => this.webdavManager.enterFolder(folder), '进入文件夹失败')
+    const targetPath = this.webdavManager.prepareEnterFolder(folder)
+    if (!targetPath || !this.selectedAccount) {
+      return
+    }
+    Logger.info(TAG, `进入文件夹: current=${this.currentDirectoryPath}, target=${targetPath}`)
+    this.scheduleDirectoryRefresh(targetPath,
+      () => this.webdavManager.loadFilesInfoFromAccount(this.selectedAccount, targetPath), '进入文件夹失败')
   }
 
   // 检查是否为当前目录的直接子项
@@ -2432,8 +2441,13 @@ export struct WebDavMainPage {
   // 返回上级目录
   private goBack(): void {
     if(this.webdavManager.canGoBack()){
-      const previousPath: string | undefined = this.webdavManager.pathHistory[this.webdavManager.pathHistory.length - 1];
-      this.scheduleDirectoryRefresh(previousPath, () => this.webdavManager.goBack(), '返回失败')
+      const previousPath = this.webdavManager.prepareGoBack()
+      if (!previousPath || !this.selectedAccount) {
+        return
+      }
+      Logger.info(TAG, `返回上级目录: current=${this.currentDirectoryPath}, previous=${previousPath}`)
+      this.scheduleDirectoryRefresh(previousPath,
+        () => this.webdavManager.loadFilesInfoFromAccount(this.selectedAccount, previousPath), '返回失败')
     }else{
       this.getUIContext().animateTo({ duration: 555 }, () => {
         // 动画闭包内控制Image组件的出现和消失
@@ -2674,7 +2688,12 @@ export struct WebDavMainPage {
     if (!crumb) {
       return;
     }
-    this.scheduleDirectoryRefresh(crumb.path, () => this.webdavManager.enterFolderFromPath(crumb.path),
+    if (!this.selectedAccount) {
+      return
+    }
+    const targetPath = this.webdavManager.prepareEnterFolderFromPath(crumb.path)
+    Logger.info(TAG, `面包屑导航: current=${this.currentDirectoryPath}, target=${targetPath}`)
+    this.scheduleDirectoryRefresh(targetPath, () => this.webdavManager.loadFilesInfoFromAccount(this.selectedAccount, targetPath),
       '导航到面包屑路径失败')
   }
 
@@ -3738,6 +3757,36 @@ export struct WebDavMainPage {
     .padding({ left: 12, right: 12, bottom: this.bottomSafeHeight  })
   }
 
+  private getPointLightItemKey(prefix: string, value: string): string {
+    return `${prefix}_${value}`
+  }
+
+  private handlePointLightTouch(itemKey: string, event: TouchEvent): void {
+    if (deviceInfo.sdkApiVersion < 20) {
+      return
+    }
+    if (event.type === TouchType.Down) {
+      this.activePointLightItemKey = itemKey
+      this.pointLightOptions = {
+        color: this.themeColor,
+        intensity: 1,
+        height: 60
+      }
+      return
+    }
+    if ((event.type === TouchType.Up || event.type === TouchType.Cancel) && this.activePointLightItemKey === itemKey) {
+      this.activePointLightItemKey = ''
+      this.pointLightOptions = undefined
+    }
+  }
+
+  private getPointLightOptions(itemKey: string): hdsEffect.PointLightOptions | undefined {
+    if (this.activePointLightItemKey !== itemKey) {
+      return undefined
+    }
+    return this.pointLightOptions
+  }
+
   // 文件夹列表项
   @Builder
   buildFolderItem(folder: FileInfo) {
@@ -3812,11 +3861,22 @@ export struct WebDavMainPage {
     .bindContextMenu(this.FolderLongPressMenuBuilder(folder), ResponseType.LongPress,
       {
         preview: MenuPreviewMode.IMAGE
-      })
+    })
     .bindContextMenu(this.FolderLongPressMenuBuilder(folder), ResponseType.RightClick,
       {
         preview: MenuPreviewMode.IMAGE
       })
+    .onTouch((event: TouchEvent) => {
+      this.handlePointLightTouch(this.getPointLightItemKey('webdav_folder', folder.href), event)
+    })
+    .visualEffect(deviceInfo.sdkApiVersion >= 20
+      ? new hdsEffect.HdsEffectBuilder()
+        .pointLight({
+          options: this.getPointLightOptions(this.getPointLightItemKey('webdav_folder', folder.href)),
+          illuminatedType: hdsEffect.PointLightIlluminatedType.BORDER_CONTENT
+        })
+        .buildEffect()
+      : undefined)
   }
 
   // 歌曲列表项
@@ -3948,6 +4008,17 @@ export struct WebDavMainPage {
       {
         preview: MenuPreviewMode.IMAGE
       })
+    .onTouch((event: TouchEvent) => {
+      this.handlePointLightTouch(this.getPointLightItemKey('webdav_song', song.filePath), event)
+    })
+    .visualEffect(deviceInfo.sdkApiVersion >= 20
+      ? new hdsEffect.HdsEffectBuilder()
+        .pointLight({
+          options: this.getPointLightOptions(this.getPointLightItemKey('webdav_song', song.filePath)),
+          illuminatedType: hdsEffect.PointLightIlluminatedType.BORDER_CONTENT
+        })
+        .buildEffect()
+      : undefined)
   }
 
 

+ 29 - 3
entry/src/main/ets/view/FindView.ets

@@ -4,7 +4,7 @@ import { CommonConstants } from '../common/constants/CommonConstants'
 import { EventConstants } from '../common/constants/EventConstants'
 import MediaTable from '../common/util/MediaTable'
 import { ButtonFancyModifier, ShadowModifier, SymbolGlyphFancyModifier } from '../common/util/AttributeModifierUtil'
-import { BreakpointTypeEnum } from '../common/util/BreakpointSystem'
+import { BreakpointType, BreakpointTypeEnum } from '../common/util/BreakpointSystem'
 import Logger from '../common/util/Logger'
 import { SearchHistoryUtil } from '../common/util/SearchHistoryUtil'
 import { VideoItem } from '../viewmodel/VideoItem'
@@ -1697,7 +1697,6 @@ export struct FindView {
       })
     }
     .width('100%')
-    .borderRadius(24)
     .clip(true)
   }
 
@@ -1722,6 +1721,7 @@ export struct FindView {
       }
       .width('100%')
       .clip(true)
+      .displayCount(this.getTopSwiperDisplayCount())
       .autoPlay(true)
       .interval(3200)
       .loop(true)
@@ -1738,6 +1738,26 @@ export struct FindView {
     }
   }
 
+  private getSwiperDisplayCount(): number {
+    return new BreakpointType<number>({
+      sm: 1,
+      md: 1,
+      lg: 1,
+      xl: 2,
+      xxl: 2
+    }).getValue(this.currentBreakpoint) ?? 1
+  }
+
+  private getTopSwiperDisplayCount(): number {
+    return new BreakpointType<number>({
+      sm: 1,
+      md: 2,
+      lg: 3,
+      xl: 4,
+      xxl: 5
+    }).getValue(this.currentBreakpoint) ?? 1
+  }
+
   @Builder
   private buildActionButtons() {
     Row({ space: 10 }) {
@@ -1862,6 +1882,7 @@ export struct FindView {
       .width('100%')
       .indicator(false)
       .autoPlay(false)
+      .displayCount(this.getSwiperDisplayCount())
       .loop(false)
       .onChange((index: number) => {
         this.cloudSectionPageIndex = index
@@ -1961,6 +1982,7 @@ export struct FindView {
       .indicator(false)
       .autoPlay(false)
       .loop(false)
+      .displayCount(this.getSwiperDisplayCount())
       .onChange((index: number) => {
         this.featuredAlbumPageIndex = index
       })
@@ -2006,6 +2028,7 @@ export struct FindView {
       .indicator(false)
       .autoPlay(false)
       .loop(false)
+      .displayCount(this.getSwiperDisplayCount())
       .onChange((index: number) => {
         this.cloudAlbumPageIndex = index
       })
@@ -2058,7 +2081,7 @@ export struct FindView {
   @Builder
   private buildLocalRandomSection() {
     ConfigTitle({
-      text: '今日曲',
+      text: '今日曲',
       onActionClick: () => {
         this.refreshLocalRandomSongs()
       }
@@ -2209,6 +2232,7 @@ export struct FindView {
       .width('100%')
       .indicator(false)
       .autoPlay(false)
+      .displayCount(this.getSwiperDisplayCount())
       .loop(false)
       .onChange((index: number) => {
         this.recentSectionPageIndex = index
@@ -2298,6 +2322,7 @@ export struct FindView {
       .indicator(false)
       .autoPlay(false)
       .loop(false)
+      .displayCount(this.getSwiperDisplayCount())
       .onChange((index: number) => {
         this.popularSectionPageIndex = index
       })
@@ -2384,6 +2409,7 @@ export struct FindView {
       .width('100%')
       .indicator(false)
       .autoPlay(false)
+      .displayCount(this.getSwiperDisplayCount())
       .loop(false)
       .onChange((index: number) => {
         this.favoriteSectionPageIndex = index

+ 78 - 0
entry/src/main/ets/view/LocalMusic.ets

@@ -635,6 +635,8 @@ export struct LocalMusic {
     position: {},
     globalPosition: {}
   }
+  @State private pointLightOptions: hdsEffect.PointLightOptions | undefined = undefined
+  @State private activePointLightItemKey: string = ''
   @StorageProp('currentColorMode') @Watch('onColorModeChange') currentMode: number =
     ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET;
 
@@ -5736,6 +5738,17 @@ export struct LocalMusic {
     .reuseId('dir_item')
     .visibility(this.isShowDir(item.name) ? Visibility.Visible : Visibility.None)
     .opacity(this.opacityItem) // 绑定透明度
+    .onTouch((event: TouchEvent) => {
+      this.handlePointLightTouch(this.getPointLightItemKey('list_dir', item, index), event)
+    })
+    .visualEffect(deviceInfo.sdkApiVersion >= 20
+      ? new hdsEffect.HdsEffectBuilder()
+        .pointLight({
+          options: this.getPointLightOptions(this.getPointLightItemKey('list_dir', item, index)),
+          illuminatedType: hdsEffect.PointLightIlluminatedType.BORDER_CONTENT
+        })
+        .buildEffect()
+      : undefined)
 
   }
 
@@ -5760,6 +5773,38 @@ export struct LocalMusic {
     }
     return true
   }
+
+  private getPointLightItemKey(prefix: string, item: VideoItem, index?: number): string {
+    const itemPath = StrUtil.isNotEmpty(item.filePath) ? item.filePath : `${item.name}_${index ?? -1}`
+    return `${prefix}_${itemPath}`
+  }
+
+  private handlePointLightTouch(itemKey: string, event: TouchEvent): void {
+    if (deviceInfo.sdkApiVersion < 20) {
+      return
+    }
+    if (event.type === TouchType.Down) {
+      this.activePointLightItemKey = itemKey
+      this.pointLightOptions = {
+        color: this.themeColor,
+        intensity: 1,
+        height: 60
+      }
+      return
+    }
+    if ((event.type === TouchType.Up || event.type === TouchType.Cancel) && this.activePointLightItemKey === itemKey) {
+      this.activePointLightItemKey = ''
+      this.pointLightOptions = undefined
+    }
+  }
+
+  private getPointLightOptions(itemKey: string): hdsEffect.PointLightOptions | undefined {
+    if (this.activePointLightItemKey !== itemKey) {
+      return undefined
+    }
+    return this.pointLightOptions
+  }
+
   @State opacityItem: number = 1; // 控制透明度的状态变量
   @Builder
   private MusicItem(item: VideoItem, index?: number) {
@@ -5919,6 +5964,17 @@ export struct LocalMusic {
     .width('100%')
     .reuseId('file_item')
     .height(this.twoFingerType == 3 ? ITEM_HEIGHT_BIG : this.twoFingerType == 2 ? ITEM_HEIGHT : ITEM_HEIGHT_SMALL)
+    .onTouch((event: TouchEvent) => {
+      this.handlePointLightTouch(this.getPointLightItemKey('list_music', item, index), event)
+    })
+    .visualEffect(deviceInfo.sdkApiVersion >= 20
+      ? new hdsEffect.HdsEffectBuilder()
+        .pointLight({
+          options: this.getPointLightOptions(this.getPointLightItemKey('list_music', item, index)),
+          illuminatedType: hdsEffect.PointLightIlluminatedType.BORDER_CONTENT
+        })
+        .buildEffect()
+      : undefined)
   }
 
   private readonly tabs: string[] = ['文件夹', '媒体库', '艺术家', '专辑']
@@ -6443,6 +6499,17 @@ export struct LocalMusic {
       color: 'on_primary'
     })
     .reuseId('card_item')
+    .onTouch((event: TouchEvent) => {
+      this.handlePointLightTouch(this.getPointLightItemKey('water_music', item, index), event)
+    })
+    .visualEffect(deviceInfo.sdkApiVersion >= 20
+      ? new hdsEffect.HdsEffectBuilder()
+        .pointLight({
+          options: this.getPointLightOptions(this.getPointLightItemKey('water_music', item, index)),
+          illuminatedType: hdsEffect.PointLightIlluminatedType.BORDER_CONTENT
+        })
+        .buildEffect()
+      : undefined)
     .onClick(() => {
       if (this.isMultiSelect) {
         if (this.isSelectableLocalItem(item)) {
@@ -6813,6 +6880,17 @@ export struct LocalMusic {
     .width('100%')
     .padding({ top: 15 })
     .height(this.getGridAllHeight())
+    .onTouch((event: TouchEvent) => {
+      this.handlePointLightTouch(this.getPointLightItemKey('grid_music', item, index), event)
+    })
+    .visualEffect(deviceInfo.sdkApiVersion >= 20
+      ? new hdsEffect.HdsEffectBuilder()
+        .pointLight({
+          options: this.getPointLightOptions(this.getPointLightItemKey('grid_music', item, index)),
+          illuminatedType: hdsEffect.PointLightIlluminatedType.BORDER_CONTENT
+        })
+        .buildEffect()
+      : undefined)
     .onClick(() => {
       if (this.isMultiSelect) {
         if (this.isSelectableLocalItem(item)) {

+ 1 - 1
entry/src/main/ets/view/PointLight/PointLightContentButton.ets

@@ -8,7 +8,7 @@ export struct PointLightContentButton {
   @Prop buttonColor: ResourceColor = Color.Transparent
   @Prop buttonRadius: number = 18
   @Prop pressScale: number = 0.97
-  @Prop pointLightHeight: number = 120
+  @Prop pointLightHeight: number = 100
   @Prop useShadow: boolean = false
   @Prop usePointLight: boolean = true
 

+ 166 - 0
entry/src/main/ets/view/RemoteMusicPage.ets

@@ -19,6 +19,7 @@ import { resolveAudioQualityTag, Utility } from '../common/util/Utility';
 import { Constants } from '../Constants';
 import { EventConstants } from '../common/constants/EventConstants';
 import { emitter } from '@kit.BasicServicesKit';
+import { deviceInfo } from '@kit.BasicServicesKit';
 import { setNavidromePlaylist, appendToNavidromePlaylist, setNavidromeTotalCount } from '../common/util/NavidromePlaylistStore';
 import { registerLoadMoreCallback, unregisterLoadMoreCallback } from '../common/util/NavidromeRandomLoader';
 import { navidromeApi, NavidromeSong } from '../common/network/NavidromeApi';
@@ -36,6 +37,7 @@ import { LazyDataSource } from '../common/util/LazyDataSource';
 import { taskpool } from '@kit.ArkTS';
 import { SearchHistoryUtil } from '../common/util/SearchHistoryUtil';
 import { PlayingIndicator } from './PlayingIndicator';
+import { hdsEffect } from '@kit.UIDesignKit';
 
 const NAVIDROME_PLAYLIST_ID = 'navidrome-playlist';
 const NAVIDROME_SEARCH_LIMIT = 500;
@@ -218,6 +220,8 @@ export struct RemoteMusicPage {
   @State blurValue: number = 0 //背景模糊
   @State bgBrightness: number = 0 //背景亮度
   @State customizeBgPath: string | undefined = '';
+  @State private pointLightOptions: hdsEffect.PointLightOptions | undefined = undefined
+  @State private activePointLightItemKey: string = ''
   @Link mType: number;
   @Link offsetX: number;
   @Link isShowDrawer: boolean;
@@ -3664,6 +3668,36 @@ export struct RemoteMusicPage {
     }
   }
 
+  private getPointLightItemKey(prefix: string, value: string): string {
+    return `${prefix}_${value}`
+  }
+
+  private handlePointLightTouch(itemKey: string, event: TouchEvent): void {
+    if (deviceInfo.sdkApiVersion < 20) {
+      return
+    }
+    if (event.type === TouchType.Down) {
+      this.activePointLightItemKey = itemKey
+      this.pointLightOptions = {
+        color: this.themeColor,
+        intensity: 1,
+        height: 100
+      }
+      return
+    }
+    if ((event.type === TouchType.Up || event.type === TouchType.Cancel) && this.activePointLightItemKey === itemKey) {
+      this.activePointLightItemKey = ''
+      this.pointLightOptions = undefined
+    }
+  }
+
+  private getPointLightOptions(itemKey: string): hdsEffect.PointLightOptions | undefined {
+    if (this.activePointLightItemKey !== itemKey) {
+      return undefined
+    }
+    return this.pointLightOptions
+  }
+
   @Builder
   buildContentView(){
     // 主内容区域
@@ -3777,24 +3811,68 @@ export struct RemoteMusicPage {
           GridItem() {
             this.buildSongItemGrid(item, index)
           }
+          .onTouch((event: TouchEvent) => {
+            this.handlePointLightTouch(this.getPointLightItemKey('remote_grid_song', item.id), event)
+          })
+          .visualEffect(deviceInfo.sdkApiVersion >= 20
+            ? new hdsEffect.HdsEffectBuilder()
+              .pointLight({
+                options: this.getPointLightOptions(this.getPointLightItemKey('remote_grid_song', item.id)),
+                illuminatedType: hdsEffect.PointLightIlluminatedType.BORDER_CONTENT
+              })
+              .buildEffect()
+            : undefined)
         }, (item: VideoItem) => item.id)
       } else if (this.selectedTab === 1) {
         LazyForEach(this.artistDataSource, (artist: NavidromeRestArtist) => {
           GridItem() {
             this.buildArtistItemGrid(artist)
           }
+          .onTouch((event: TouchEvent) => {
+            this.handlePointLightTouch(this.getPointLightItemKey('remote_grid_artist', artist.id), event)
+          })
+          .visualEffect(deviceInfo.sdkApiVersion >= 20
+            ? new hdsEffect.HdsEffectBuilder()
+              .pointLight({
+                options: this.getPointLightOptions(this.getPointLightItemKey('remote_grid_artist', artist.id)),
+                illuminatedType: hdsEffect.PointLightIlluminatedType.BORDER_CONTENT
+              })
+              .buildEffect()
+            : undefined)
         }, (artist: NavidromeRestArtist) => artist.id)
       } else if (this.selectedTab === 2) {
         LazyForEach(this.albumDataSource, (album: NavidromeRestAlbum) => {
           GridItem() {
             this.buildAlbumItemGrid(album)
           }
+          .onTouch((event: TouchEvent) => {
+            this.handlePointLightTouch(this.getPointLightItemKey('remote_grid_album', album.id), event)
+          })
+          .visualEffect(deviceInfo.sdkApiVersion >= 20
+            ? new hdsEffect.HdsEffectBuilder()
+              .pointLight({
+                options: this.getPointLightOptions(this.getPointLightItemKey('remote_grid_album', album.id)),
+                illuminatedType: hdsEffect.PointLightIlluminatedType.BORDER_CONTENT
+              })
+              .buildEffect()
+            : undefined)
         }, (album: NavidromeRestAlbum) => album.id)
       } else if (this.selectedTab === 3) {
         LazyForEach(this.playlistDataSource, (playlist: NavidromeRestPlaylist) => {
           GridItem() {
             this.buildPlaylistItemGrid(playlist)
           }
+          .onTouch((event: TouchEvent) => {
+            this.handlePointLightTouch(this.getPointLightItemKey('remote_grid_playlist', playlist.id), event)
+          })
+          .visualEffect(deviceInfo.sdkApiVersion >= 20
+            ? new hdsEffect.HdsEffectBuilder()
+              .pointLight({
+                options: this.getPointLightOptions(this.getPointLightItemKey('remote_grid_playlist', playlist.id)),
+                illuminatedType: hdsEffect.PointLightIlluminatedType.BORDER_CONTENT
+              })
+              .buildEffect()
+            : undefined)
         }, (playlist: NavidromeRestPlaylist) => playlist.id)
       }
 
@@ -4302,24 +4380,68 @@ export struct RemoteMusicPage {
           ListItem() {
             this.buildSongItem(item, index)
           }
+          .onTouch((event: TouchEvent) => {
+            this.handlePointLightTouch(this.getPointLightItemKey('remote_list_song', item.id), event)
+          })
+          .visualEffect(deviceInfo.sdkApiVersion >= 20
+            ? new hdsEffect.HdsEffectBuilder()
+              .pointLight({
+                options: this.getPointLightOptions(this.getPointLightItemKey('remote_list_song', item.id)),
+                illuminatedType: hdsEffect.PointLightIlluminatedType.BORDER_CONTENT
+              })
+              .buildEffect()
+            : undefined)
         }, (item: VideoItem) => item.id)
       } else if (this.selectedTab === 1) {
         LazyForEach(this.artistDataSource, (artist: NavidromeRestArtist) => {
           ListItem() {
             this.buildArtistItem(artist)
           }
+          .onTouch((event: TouchEvent) => {
+            this.handlePointLightTouch(this.getPointLightItemKey('remote_list_artist', artist.id), event)
+          })
+          .visualEffect(deviceInfo.sdkApiVersion >= 20
+            ? new hdsEffect.HdsEffectBuilder()
+              .pointLight({
+                options: this.getPointLightOptions(this.getPointLightItemKey('remote_list_artist', artist.id)),
+                illuminatedType: hdsEffect.PointLightIlluminatedType.BORDER_CONTENT
+              })
+              .buildEffect()
+            : undefined)
         }, (artist: NavidromeRestArtist) => artist.id)
       } else if (this.selectedTab === 2) {
         LazyForEach(this.albumDataSource, (album: NavidromeRestAlbum) => {
           ListItem() {
             this.buildAlbumItem(album)
           }
+          .onTouch((event: TouchEvent) => {
+            this.handlePointLightTouch(this.getPointLightItemKey('remote_list_album', album.id), event)
+          })
+          .visualEffect(deviceInfo.sdkApiVersion >= 20
+            ? new hdsEffect.HdsEffectBuilder()
+              .pointLight({
+                options: this.getPointLightOptions(this.getPointLightItemKey('remote_list_album', album.id)),
+                illuminatedType: hdsEffect.PointLightIlluminatedType.BORDER_CONTENT
+              })
+              .buildEffect()
+            : undefined)
         }, (album: NavidromeRestAlbum) => album.id)
       } else if (this.selectedTab === 3) {
         LazyForEach(this.playlistDataSource, (playlist: NavidromeRestPlaylist) => {
           ListItem() {
             this.buildPlaylistItem(playlist)
           }
+          .onTouch((event: TouchEvent) => {
+            this.handlePointLightTouch(this.getPointLightItemKey('remote_list_playlist', playlist.id), event)
+          })
+          .visualEffect(deviceInfo.sdkApiVersion >= 20
+            ? new hdsEffect.HdsEffectBuilder()
+              .pointLight({
+                options: this.getPointLightOptions(this.getPointLightItemKey('remote_list_playlist', playlist.id)),
+                illuminatedType: hdsEffect.PointLightIlluminatedType.BORDER_CONTENT
+              })
+              .buildEffect()
+            : undefined)
         }, (playlist: NavidromeRestPlaylist) => playlist.id)
       }
     }
@@ -4462,6 +4584,17 @@ export struct RemoteMusicPage {
               }
               .width('100%')
               .clickEffect({ level: ClickEffectLevel.LIGHT, scale: 0.9 })
+              .onTouch((event: TouchEvent) => {
+                this.handlePointLightTouch(this.getPointLightItemKey('remote_water_song', item.id), event)
+              })
+              .visualEffect(deviceInfo.sdkApiVersion >= 20
+                ? new hdsEffect.HdsEffectBuilder()
+                  .pointLight({
+                    options: this.getPointLightOptions(this.getPointLightItemKey('remote_water_song', item.id)),
+                    illuminatedType: hdsEffect.PointLightIlluminatedType.BORDER_CONTENT
+                  })
+                  .buildEffect()
+                : undefined)
             }, (item: VideoItem) => item.id)
           } else if (this.selectedTab === 1) {
             // 艺术家瀑布流
@@ -4471,6 +4604,17 @@ export struct RemoteMusicPage {
               }
               .width('100%')
               .clickEffect({ level: ClickEffectLevel.LIGHT, scale: 0.9 })
+              .onTouch((event: TouchEvent) => {
+                this.handlePointLightTouch(this.getPointLightItemKey('remote_water_artist', artist.id), event)
+              })
+              .visualEffect(deviceInfo.sdkApiVersion >= 20
+                ? new hdsEffect.HdsEffectBuilder()
+                  .pointLight({
+                    options: this.getPointLightOptions(this.getPointLightItemKey('remote_water_artist', artist.id)),
+                    illuminatedType: hdsEffect.PointLightIlluminatedType.BORDER_CONTENT
+                  })
+                  .buildEffect()
+                : undefined)
             }, (artist: NavidromeRestArtist) => artist.id)
           } else if (this.selectedTab === 2) {
             // 专辑瀑布流
@@ -4480,6 +4624,17 @@ export struct RemoteMusicPage {
               }
               .width('100%')
               .clickEffect({ level: ClickEffectLevel.LIGHT, scale: 0.9 })
+              .onTouch((event: TouchEvent) => {
+                this.handlePointLightTouch(this.getPointLightItemKey('remote_water_album', album.id), event)
+              })
+              .visualEffect(deviceInfo.sdkApiVersion >= 20
+                ? new hdsEffect.HdsEffectBuilder()
+                  .pointLight({
+                    options: this.getPointLightOptions(this.getPointLightItemKey('remote_water_album', album.id)),
+                    illuminatedType: hdsEffect.PointLightIlluminatedType.BORDER_CONTENT
+                  })
+                  .buildEffect()
+                : undefined)
             }, (album: NavidromeRestAlbum) => album.id)
           } else if (this.selectedTab === 3) {
             // 歌单瀑布流
@@ -4489,6 +4644,17 @@ export struct RemoteMusicPage {
               }
               .width('100%')
               .clickEffect({ level: ClickEffectLevel.LIGHT, scale: 0.9 })
+              .onTouch((event: TouchEvent) => {
+                this.handlePointLightTouch(this.getPointLightItemKey('remote_water_playlist', playlist.id), event)
+              })
+              .visualEffect(deviceInfo.sdkApiVersion >= 20
+                ? new hdsEffect.HdsEffectBuilder()
+                  .pointLight({
+                    options: this.getPointLightOptions(this.getPointLightItemKey('remote_water_playlist', playlist.id)),
+                    illuminatedType: hdsEffect.PointLightIlluminatedType.BORDER_CONTENT
+                  })
+                  .buildEffect()
+                : undefined)
             }, (playlist: NavidromeRestPlaylist) => playlist.id)
           }
         }