Explorar o código

继续完善Grid网格功能的长按菜单功能实现

onecold hai 1 ano
pai
achega
4d745187d5
Modificáronse 1 ficheiros con 194 adicións e 114 borrados
  1. 194 114
      entry/src/main/ets/view/LocalMusic.ets

+ 194 - 114
entry/src/main/ets/view/LocalMusic.ets

@@ -1359,8 +1359,8 @@ export struct LocalMusic {
   //
   // }
 
-  goSelectImage() {
-    if (!this.currentSong) {
+  goSelectImage(item:VideoItem) {
+    if (!item) {
       return
     }
     let selectUris: Array<string> = [];
@@ -1385,12 +1385,14 @@ export struct LocalMusic {
       fileIo.closeSync(file);
       fileIo.closeSync(file2);
 
-      this.cover = imagePath
-      if (this.currentSong) {
-        this.currentSong.pixelMapPath = imagePath
+      if(item.filePath==this.currentSong?.filePath){
+        this.cover = imagePath
+      }
+      if (item) {
+        item.pixelMapPath = imagePath
       }
 
-      this.table.updatePixelMapPath(this.videoUrl, this.cover, (success: boolean, error?: string) => {
+      this.table.updatePixelMapPath(item.filePath, imagePath, (success: boolean, error?: string) => {
         if (success) {
           this.doUpdateData()
 
@@ -2897,7 +2899,8 @@ export struct LocalMusic {
 
   }
 
-  @State longItemFilePath:string=''
+  @State longItemFilePath:string =''
+  @State tempLyricContent:string = ''
   @Builder
   private MusicItemGrid(item: VideoItem, index: number) {
 
@@ -2960,21 +2963,32 @@ export struct LocalMusic {
         .bindPopup(this.longItemFilePath === item.filePath, {
           builder: this.MenuBuilder(item,index,item.filePath),
           placement: Placement.Top,
-          autoCancel: true,
+          // autoCancel: true,
           mask: {color:'#33000000'},
           // popupColor: Color.Yellow,
           enableArrow: false,//是否显示箭头
-          showInSubWindow: true,
+          showInSubWindow: false,
           onStateChange: (e) => {
             if (!e.isVisible) {
               this.longItemFilePath = ''
+              this.tempLyricContent = ''
             }
           }
         })
 
         .gesture(LongPressGesture()
-          .onAction(() => {
+          .onAction(async () => {
+            //如果是专辑和艺术家的首页,不能长按
+            if((this.modeType===2||this.modeType==3)&&!this.isCanBack)
+              return
+            //如果是我的收藏 最近播放等也不能长按
+            if(item.name === LocalMusic.STR_LOCK_VIDEO || item.name === LocalMusic.STR_FAC_VIDEO ||
+              item.name === LocalMusic.STR_HISTORY_MUSIC
+            )
+              return
             this.longItemFilePath = item.filePath
+            this.tempLyricContent = await this.getLyricContent(item)
+            LogUtil.info('长按this.tempLyricContent = '+this.tempLyricContent)
         })
           .onActionEnd((event: GestureEvent) => {
 
@@ -3028,80 +3042,81 @@ export struct LocalMusic {
 
   @Builder
   MenuBuilder(item: VideoItem,index: number,filePath:string) {
-    Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
-      Menu() {
-        MenuItem({
-          symbolStartIcon: new SymbolGlyphModifier(Utility.getIsFav(this.favList,item)?$r('sys.symbol.heart_fill'):$r('sys.symbol.heart')),
-          // startIcon: Utility.getIsFav(this.favList,item)?$r('app.media.add_fac_light2'):$r('app.media.add_fac')
-          content: '收藏' })
-          .onClick(() => {
-            if(item){
-              this.doFav(item)
-            }
-            this.longItemFilePath = ''
+    Scroll(){
+      Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
+        Menu() {
+          MenuItem({
+            symbolStartIcon: new SymbolGlyphModifier(Utility.getIsFav(this.favList,item)?$r('sys.symbol.heart_fill'):$r('sys.symbol.heart')),
+
+            content: Utility.getIsFav(this.favList,item)?'取消收藏':'收藏' })
+            .visibility(item.type === CommonConstants.TYPE_IS_DIR ? Visibility.None : Visibility.Visible)
+            .onClick(() => {
+              if(item){
+                this.doFav(item)
+              }
+              this.longItemFilePath = ''
 
-        })
-        MenuItem({ symbolStartIcon: new SymbolGlyphModifier($r('sys.symbol.forward_end_fill')),
-          content: '下一首播放' })
-          .onClick(() => {
-            this.addToNextPlay(item);
-            this.longItemFilePath = ''
-        })
+            })
+          MenuItem({ symbolStartIcon: new SymbolGlyphModifier($r('sys.symbol.forward_end_fill')),
+            content: '下一首播放' })
+            .visibility(item.type === CommonConstants.TYPE_IS_DIR ? Visibility.None : Visibility.Visible)
+            .onClick(() => {
+              this.addToNextPlay(item);
+              this.longItemFilePath = ''
+            })
 
-        MenuItem({
-          symbolStartIcon: new SymbolGlyphModifier($r('sys.symbol.picture_2')),
-          content: $r('app.string.copy')
-        })
-          .visibility(item.type === CommonConstants.TYPE_IS_DIR ? Visibility.None : Visibility.Visible)
-          .onClick(() => {
-            this.showCopyDialog(false, item, index, filePath + 'copy');
-            this.longItemFilePath = ''
-          })
-        MenuItem({
-          symbolStartIcon: new SymbolGlyphModifier($r('sys.symbol.cut')),
-          content: $r('app.string.cut')
-        })
-          .visibility(item.type === CommonConstants.TYPE_IS_DIR ? Visibility.None : Visibility.Visible)
-          .onClick(() => {
-            this.showCutDialog(false, item, index, filePath);
-            this.longItemFilePath = ''
-          })
-        MenuItem({
-          symbolStartIcon: new SymbolGlyphModifier($r('sys.symbol.rename')),
-          content: $r('app.string.rename')
-        })
-          .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)
-          .onClick(() => {
-            this.showReNameDialog(item, index + '', filePath)
-            this.longItemFilePath = ''
+          MenuItem({ symbolStartIcon: new SymbolGlyphModifier($r('sys.symbol.square_and_pencil')),
+            content: '编辑信息' })
+            .bindSheet($$this.isShowEdit, this.editSheet(item), {
+              height:this.isCoverOpacity()?'95%': '88%',
+              dragBar: true,
+              showClose: true,
+              preferType: this.currentBreakpoint!==BreakpointTypeEnum.SM?SheetType.CENTER:SheetType.BOTTOM,
+              title: { title: '编辑信息' }
+            })
+            .visibility(item.type === CommonConstants.TYPE_IS_DIR ? Visibility.None : Visibility.Visible)
+            .onClick(() => {
+              this.isShowEdit = !this.isShowEdit;
+            })
+
+          MenuItem({
+            symbolStartIcon: new SymbolGlyphModifier($r('sys.symbol.rename')),
+            content: $r('app.string.rename')
           })
-        MenuItem({
-          symbolStartIcon: new SymbolGlyphModifier($r('sys.symbol.trash')),
-          content: $r('app.string.delete')
-        })
-          .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)
-          .onClick(() => {
-            this.showWarnIsDeleteFile(item, index + '', filePath)
-            this.longItemFilePath = ''
+            .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)
+            .onClick(() => {
+              this.showReNameDialog(item, index + '', filePath)
+              this.longItemFilePath = ''
+            })
+          MenuItem({
+            symbolStartIcon: new SymbolGlyphModifier($r('sys.symbol.trash')),
+            content: $r('app.string.delete')
           })
-        MenuItem({
-          symbolStartIcon: new SymbolGlyphModifier($r('sys.symbol.share')),
-          content: $r('app.string.share')
-        })
-          .visibility(item.type === CommonConstants.TYPE_IS_DIR ? Visibility.None : Visibility.Visible)
-          .onClick(() => {
-            Utility.doShareMusic(item, getContext(this) as common.UIAbilityContext)
-            this.longItemFilePath = ''
+            .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)
+            .onClick(() => {
+              this.showWarnIsDeleteFile(item, index + '', filePath)
+              this.longItemFilePath = ''
+            })
+          MenuItem({
+            symbolStartIcon: new SymbolGlyphModifier($r('sys.symbol.share')),
+            content: $r('app.string.share')
           })
-      }.font({ size: 15, weight: FontWeight.Normal })
+            .visibility(item.type === CommonConstants.TYPE_IS_DIR ? Visibility.None : Visibility.Visible)
+            .onClick(() => {
+              Utility.doShareMusic(item, getContext(this) as common.UIAbilityContext)
+              this.longItemFilePath = ''
+            })
+
+        }
+        .font({ size: 15, weight: FontWeight.Normal })
+      }
+      .width(180)
     }
-    .width(180)
     .height('40%')
-
   }
 
 
@@ -3162,7 +3177,7 @@ export struct LocalMusic {
           .animation({ curve: Curve.Sharp, duration: 300 })
 
         }
-        .swipeAction((this.modeType !== 3 && this.modeType !== 2 && item.type !== CommonConstants.TYPE_IS_CSJAD &&
+        .swipeAction((((this.modeType==3||this.modeType==2)&&this.isCanBack) && item.type !== CommonConstants.TYPE_IS_CSJAD &&
           !this.isHistory) ? { end: this.DeleteButton(item, index, item.filePath) } : {}) //左滑
         .onClick(() => {
 
@@ -3612,8 +3627,8 @@ export struct LocalMusic {
   }
 
   //编辑信息
-  doEdit() {
-    if (!this.currentSong) {
+  doEdit(item:VideoItem) {
+    if (!item) {
       return
     }
     if (StrUtil.isEmpty(this.titleStr)) {
@@ -3621,7 +3636,7 @@ export struct LocalMusic {
       return
     }
 
-    this.table.updateMediaInfo(this.videoUrl, this.titleStr, this.artistStr, this.ablumStr,
+    this.table.updateMediaInfo(item.filePath, this.titleStr, this.artistStr, this.ablumStr,
       (success: boolean, error?: string) => {
         this.isShowEdit = false
         if (success) {
@@ -3629,8 +3644,9 @@ export struct LocalMusic {
           ToastUtil.showToast('保存成功')
           this.isShowMoreView = false
           this.name = this.titleStr
-          if (this.currentSong) {
+          if (item.filePath==this.currentSong?.filePath) {
             this.currentSong.name = this.titleStr
+            this.artist = this.artistStr
             this.currentSong.artist = this.artistStr
             this.currentSong.album = this.ablumStr
           }
@@ -3644,9 +3660,17 @@ export struct LocalMusic {
 
 
       });
+    let doChangeLyric = false
+    if(item.filePath==this.currentSong?.filePath){
+      if(this.lyricConStr !== this.lyricContent){
+        doChangeLyric = true
+      }
+    }else if(this.lyricConStr !== this.tempLyricContent){
+      doChangeLyric = true
+    }
 
-    if (this.lyricConStr !== this.lyricContent) {
-      let lyricPath = this.videoUrl.substring(0, this.videoUrl.lastIndexOf('.')) + '.lrc'
+    if (doChangeLyric) {
+      let lyricPath = item.filePath.substring(0, this.videoUrl.lastIndexOf('.')) + '.lrc'
       let jiaMilyricPath = lyricPath.substring(0, lyricPath.lastIndexOf('.')) + '.lrcc'
 
       let isJiaMi = false;
@@ -3667,11 +3691,15 @@ export struct LocalMusic {
 
   }
 
+  updateLyricToDB(){
+
+  }
+
   @Builder
-  editSheet() {
+  editSheet(item:VideoItem) {
     Scroll() {
       Column() {
-        this.editDetail()
+        this.editDetail(item)
       }
     }
     .width('100%')
@@ -3679,14 +3707,14 @@ export struct LocalMusic {
   }
 
   @Builder
-  editDetail() {
+  editDetail(item:VideoItem) {
     Column() {
-      if (this.currentSong) {
+      if (item) {
         Row() {
           Stack() {
 
-            Image(StrUtil.isEmpty(this.currentSong.pixelMapPath) ? $r('app.media.music_red') :
-            this.currentSong.pixelMapPath)
+            Image(StrUtil.isEmpty(item.pixelMapPath) ? $r('app.media.music_red') :
+            item.pixelMapPath)
               .height(33)
               .width(33)
               .borderRadius('100%')
@@ -3698,7 +3726,7 @@ export struct LocalMusic {
 
           Row() {
             Column() {
-              Text(this.currentSong.name)
+              Text(item.name)
                 .fontSize(14)
                 .maxLines(1)
                 .textOverflow({ overflow: TextOverflow.MARQUEE })//超长滚动
@@ -3710,7 +3738,7 @@ export struct LocalMusic {
                 .fontColor($r('app.color.title_bar_bg'))
                 .margin({ left: 10 })
               Row() {
-                Text(this.currentSong.artist)
+                Text(item.artist)
                   .fontSize(11)
                   .maxLines(1)
                   .textOverflow({ overflow: TextOverflow.MARQUEE })//超长滚动
@@ -3737,7 +3765,7 @@ export struct LocalMusic {
               .margin({ right: 5, left: 12 })
               .onClick(async () => {
 
-                this.goSelectImage()
+                this.goSelectImage(item)
 
               })
 
@@ -3750,7 +3778,7 @@ export struct LocalMusic {
               .stateEffect(true)
               .margin({ right: 12, left: 5 })
               .onClick(async () => {
-                this.doSearchCover()
+                this.doSearchCover(item)
 
               })
 
@@ -3770,7 +3798,7 @@ export struct LocalMusic {
             .fontColor($r('app.color.text_color'))
             .margin({ left: 22 })
 
-          TextInput({ text: this.currentSong?.name ? this.currentSong.name : '' })
+          TextInput({ text: item.name })
             .height(40)
             .maxLines(1)
             .fontSize(14)
@@ -3791,7 +3819,7 @@ export struct LocalMusic {
             .fontColor($r('app.color.text_color'))
             .margin({ left: 22 })
 
-          TextInput({ text: this.currentSong?.artist ? this.currentSong.artist : '' })
+          TextInput({ text: item.artist  })
             .height(40)
             .maxLines(1)
             .fontSize(14)
@@ -3811,7 +3839,7 @@ export struct LocalMusic {
             .fontSize(14)
             .fontColor($r('app.color.text_color'))
             .margin({ left: 22 })
-          TextInput({ text: this.currentSong?.album ? this.currentSong.album : '' })
+          TextInput({ text: item.album  })
             .height(40)
             .maxLines(1)
             .fontSize(14)
@@ -3831,7 +3859,7 @@ export struct LocalMusic {
             .fontSize(14)
             .fontColor($r('app.color.text_color'))
             .margin({ left: 22 })
-          TextArea({ text: this.lyricContent ? this.lyricContent : '' })
+          TextArea({ text:item.filePath===this.currentSong?.filePath?  this.lyricContent : this.tempLyricContent })
             .type(TextAreaType.NORMAL)
             .height(275)
             .fontSize(14)
@@ -3858,7 +3886,7 @@ export struct LocalMusic {
             .stateEffect(true)
             .margin({ right: 20, bottom: 20 })
             .onClick(async () => {
-              this.doEdit()
+              this.doEdit(item)
 
             })
 
@@ -5008,6 +5036,56 @@ export struct LocalMusic {
 
   }
 
+  //根据item返回歌词内容
+  async getLyricContent(item: VideoItem): Promise<string> {
+    try {
+      let filePath = item.filePath;
+      let lyricPath = filePath.substring(0, filePath.lastIndexOf('.')) + '.lrc';
+      let jiaMilyricPath = lyricPath.substring(0, lyricPath.lastIndexOf('.')) + '.lrcc';
+      let isJiaMi = false;
+      let realLyricPath = lyricPath;
+
+      if (FileUtil.accessSync(jiaMilyricPath)) {
+        isJiaMi = true;
+        realLyricPath = jiaMilyricPath;
+        console.info("onecold 找到加密本地歌词");
+      } else {
+        console.info("onecold 找到本地歌词");
+      }
+
+      let file = fs.openSync(realLyricPath, fs.OpenMode.READ_WRITE);
+      let arrayBuffer = new ArrayBuffer(4096);
+
+      const readLen = await fs.read(file.fd, arrayBuffer);
+      console.info("read file data succeed");
+
+      let buf = new Uint8Array(arrayBuffer, 0, readLen);
+
+      if (buf.length === 0) {
+        throw new Error("Buffer is empty after reading the file");
+      }
+
+      let detectedEncoding = chardet.detect(buf);
+      console.info("Detected encoding: " + detectedEncoding);
+
+      let textDecoder = new util.TextDecoder(detectedEncoding || 'utf-8');
+      let fileContent = textDecoder.decode(buf);
+      console.info(`onecold The content of file1: ${fileContent}`);
+
+      if (isJiaMi) {
+        fileContent = StrUtil.unit8ArrayToStr(Base64Util.decodeSync(fileContent));
+      }
+      console.info(`onecold The content of file2: ${fileContent}`);
+
+      fs.closeSync(file);
+      return fileContent;
+
+    } catch (error) {
+      console.error('init Lyric failed with err: ' + JSON.stringify(error));
+      return '';
+    }
+  }
+
   async saveDataToFile(content: string, filePath: string, isJiaMi?: boolean) {
     if (StrUtil.isEmpty(filePath)) {
       return
@@ -6231,7 +6309,7 @@ export struct LocalMusic {
                 .onClick(() => {
                   this.isShowDetailMore = !this.isShowDetailMore;
                 })
-            } else if (more.id === 15) { //编辑信息
+            } else if (more.id === 15&&this.currentSong) { //编辑信息
               Image(more.image)
                 .width(24)
                 .height(24)
@@ -6242,10 +6320,7 @@ export struct LocalMusic {
               Text(more.title)
                 .fontSize(16)
                 .fontColor(Color.White)
-                .onClick(() => {
-                  this.doMore(more.id)
-                })
-                .bindSheet($$this.isShowEdit, this.editSheet(), {
+                .bindSheet($$this.isShowEdit, this.editSheet(this.currentSong), {
                   height: this.isCoverOpacity() ? '95%' : '93%',
                   dragBar: true,
                   showClose: true,
@@ -6585,40 +6660,45 @@ export struct LocalMusic {
         break;
 
       case 14: //搜索封面
-        this.doSearchCover()
+        if (this.currentSong !== undefined) {
+          this.doSearchCover(this.currentSong)
+        }
         this.isShowMoreView = false
         break;
     }
 
   }
 
-  doSearchCover(){
+  doSearchCover(item:VideoItem){
     if(PreferencesUtil.getStringSync('COVER_API','')===''){
       ToastUtil.showToast('请到设置界面配置封面服务器地址')
       return
     }
-    if (this.currentSong !== undefined) {
-      let artist = this.currentSong?.artist
+    if (item !== undefined) {
+      let artist = item?.artist
       if (StrUtil.isEmpty(artist) || artist === undefined) {
         artist = ''
       }
-      this.searchCover(this.name, artist)
+      this.searchCover(item,item.name, artist)
     }
   }
 
-  searchCover(title: string, artist: string) {
+  searchCover(item:VideoItem,title: string, artist: string) {
 
 
     NetAxiosUtil.getLyricCover(title, artist, PreferencesUtil.getStringSync('COVER_API','')).then(async (res) => {
 
       LogUtil.debug("onecold res =" + res)
       if (StrUtil.isNotEmpty(res) && res !== 'unknown' && res !== 'Timeout was reached') {
-        this.cover = res
-        if (this.currentSong) {
-          this.currentSong.pixelMapPath = res
+        if(item.filePath==this.currentSong?.filePath){
+          this.cover = res
+          if (this.currentSong) {
+            this.currentSong.pixelMapPath = res
+          }
         }
 
-        this.table.updatePixelMapPath(this.videoUrl, this.cover, (success: boolean, error?: string) => {
+
+        this.table.updatePixelMapPath(item.filePath, res, (success: boolean, error?: string) => {
           if (success) {
             this.doUpdateData()
             console.log(" onecold 更新音乐封面成功,数据库已同步");