|
@@ -4,7 +4,7 @@ import { common } from '@kit.AbilityKit'
|
|
|
import { CommonConstants } from '../common/constants/CommonConstants'
|
|
import { CommonConstants } from '../common/constants/CommonConstants'
|
|
|
import { EventConstants } from '../common/constants/EventConstants'
|
|
import { EventConstants } from '../common/constants/EventConstants'
|
|
|
import MediaTable from '../common/util/MediaTable'
|
|
import MediaTable from '../common/util/MediaTable'
|
|
|
-import { ButtonFancyModifier, ShadowModifier, SymbolGlyphFancyModifier } from '../common/util/AttributeModifierUtil'
|
|
|
|
|
|
|
+import { SymbolGlyphFancyModifier } from '../common/util/AttributeModifierUtil'
|
|
|
import { BreakpointType, BreakpointTypeEnum } from '../common/util/BreakpointSystem'
|
|
import { BreakpointType, BreakpointTypeEnum } from '../common/util/BreakpointSystem'
|
|
|
import Logger from '../common/util/Logger'
|
|
import Logger from '../common/util/Logger'
|
|
|
import { RemoteDriveManager } from '../common/util/RemoteDriveManager'
|
|
import { RemoteDriveManager } from '../common/util/RemoteDriveManager'
|
|
@@ -16,6 +16,8 @@ import { Playlist } from '../viewmodel/Playlist'
|
|
|
import { ConfigTitle } from './ConfigTitle'
|
|
import { ConfigTitle } from './ConfigTitle'
|
|
|
import { PointLightActionButton } from './PointLight/PointLightActionButton'
|
|
import { PointLightActionButton } from './PointLight/PointLightActionButton'
|
|
|
import { PointLightContentButton } from './PointLight/PointLightContentButton'
|
|
import { PointLightContentButton } from './PointLight/PointLightContentButton'
|
|
|
|
|
+import { TitleBarPointLightButton } from './PointLight/TitleBarPointLightButton'
|
|
|
|
|
+import { DeleteComptent } from './DeleteComptent'
|
|
|
import { SettingPage } from '../pages/SettingPage'
|
|
import { SettingPage } from '../pages/SettingPage'
|
|
|
import { FindAlbumDetail } from './FindAlbumDetail'
|
|
import { FindAlbumDetail } from './FindAlbumDetail'
|
|
|
import { PlayingIndicator } from './PlayingIndicator'
|
|
import { PlayingIndicator } from './PlayingIndicator'
|
|
@@ -157,6 +159,7 @@ export struct FindView {
|
|
|
@State private favoriteSectionPageIndex: number = 0
|
|
@State private favoriteSectionPageIndex: number = 0
|
|
|
@State private refreshPullRatio: number = 1
|
|
@State private refreshPullRatio: number = 1
|
|
|
@State private maxRefreshingHeight: number = 100
|
|
@State private maxRefreshingHeight: number = 100
|
|
|
|
|
+ @State private pendingDeleteSongs: VideoItem[] = []
|
|
|
|
|
|
|
|
searchController: SearchController = new SearchController()
|
|
searchController: SearchController = new SearchController()
|
|
|
@StorageProp('currentBreakpoint') @Watch('onDiscoverBreakpointChange') currentBreakpoint: string = BreakpointTypeEnum.MD
|
|
@StorageProp('currentBreakpoint') @Watch('onDiscoverBreakpointChange') currentBreakpoint: string = BreakpointTypeEnum.MD
|
|
@@ -189,6 +192,7 @@ export struct FindView {
|
|
|
private isRemoteBootstrapLoading: boolean = false
|
|
private isRemoteBootstrapLoading: boolean = false
|
|
|
private playlistSongsCache: Map<string, VideoItem[]> = new Map<string, VideoItem[]>()
|
|
private playlistSongsCache: Map<string, VideoItem[]> = new Map<string, VideoItem[]>()
|
|
|
private heartPlaylistCoverTicket: number = 0
|
|
private heartPlaylistCoverTicket: number = 0
|
|
|
|
|
+ private deleteComponentId: number = 0
|
|
|
|
|
|
|
|
aboutToAppear(): void {
|
|
aboutToAppear(): void {
|
|
|
this.initSetting()
|
|
this.initSetting()
|
|
@@ -254,7 +258,7 @@ export struct FindView {
|
|
|
|
|
|
|
|
if (triggeredByRefresh) {
|
|
if (triggeredByRefresh) {
|
|
|
this.isRefreshing = true
|
|
this.isRefreshing = true
|
|
|
- this.refreshText = '正在刷新推荐...'
|
|
|
|
|
|
|
+ this.refreshText = '正在刷新'
|
|
|
} else if (this.isPageLoading) {
|
|
} else if (this.isPageLoading) {
|
|
|
this.refreshText = '加载中...'
|
|
this.refreshText = '加载中...'
|
|
|
}
|
|
}
|
|
@@ -1192,6 +1196,179 @@ export struct FindView {
|
|
|
this.currentAlbumSongs = []
|
|
this.currentAlbumSongs = []
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private canDeleteCurrentAlbumSongs(): boolean {
|
|
|
|
|
+ if (this.currentAlbumSongs.length <= 0) {
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+ return this.currentAlbumSongs.every((item: VideoItem) =>
|
|
|
|
|
+ item.type === CommonConstants.TYPE_LOCAL && StrUtil.isNotEmpty(item.filePath))
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private canFavoriteCurrentAlbumSong(song: VideoItem): boolean {
|
|
|
|
|
+ return StrUtil.isNotEmpty(song.filePath)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private updateAlbumSongFavoriteState(filePath: string, isFav: number): void {
|
|
|
|
|
+ this.currentAlbumSongs.forEach((item: VideoItem) => {
|
|
|
|
|
+ if (item.filePath === filePath) {
|
|
|
|
|
+ item.isFav = isFav
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private async handleAlbumFavoriteSong(song: VideoItem): Promise<void> {
|
|
|
|
|
+ if (!this.mediaTable) {
|
|
|
|
|
+ ToastUtil.showToast('收藏功能暂不可用')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!this.canFavoriteCurrentAlbumSong(song)) {
|
|
|
|
|
+ ToastUtil.showToast('当前歌曲暂不支持收藏')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ const nextFav: number = song.isFav === 1 ? 0 : 1
|
|
|
|
|
+ this.mediaTable.updateIsFavByFilePath(song.filePath, nextFav, async (result: boolean, error?: string) => {
|
|
|
|
|
+ if (!result) {
|
|
|
|
|
+ Logger.warn(TAG, `发现页专辑详情收藏更新失败: ${song.filePath}, error=${error ?? ''}`)
|
|
|
|
|
+ ToastUtil.showToast(nextFav === 1 ? '收藏失败' : '取消收藏失败')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ song.isFav = nextFav
|
|
|
|
|
+ this.updateAlbumSongFavoriteState(song.filePath, nextFav)
|
|
|
|
|
+ await this.loadDiscoveryContent(false)
|
|
|
|
|
+ this.syncCurrentAlbumDetailFromState()
|
|
|
|
|
+ ToastUtil.showToast(nextFav === 1 ? '收藏成功' : '取消收藏成功')
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ 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 filterPlaylistCachesByDeletedKeys(deletedKeys: Set<string>): void {
|
|
|
|
|
+ this.playlistSongsCache.forEach((songs: VideoItem[], key: string) => {
|
|
|
|
|
+ this.playlistSongsCache.set(key, songs.filter((item: VideoItem) => !deletedKeys.has(item.filePath)))
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private syncCurrentAlbumDetailFromState(): void {
|
|
|
|
|
+ if (StrUtil.isEmpty(this.currentAlbumId)) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ if (this.currentAlbumId === 'find-recent-collection') {
|
|
|
|
|
+ this.currentAlbumSongs = this.recentSongsPool.slice()
|
|
|
|
|
+ this.currentAlbumCoverPath = this.pickAlbumCoverSong(this.currentAlbumSongs)?.pixelMapPath ?? ''
|
|
|
|
|
+ } else if (this.currentAlbumId === 'find-favorite-collection') {
|
|
|
|
|
+ this.currentAlbumSongs = this.favoriteSongsPool.slice()
|
|
|
|
|
+ this.currentAlbumCoverPath = this.pickAlbumCoverSong(this.currentAlbumSongs)?.pixelMapPath ?? ''
|
|
|
|
|
+ } else if (this.currentAlbumId.startsWith('find-playlist-')) {
|
|
|
|
|
+ const playlistId = this.currentAlbumId.replace('find-playlist-', '')
|
|
|
|
|
+ const playlist = this.heartPlaylists.find((item: Playlist) => item.id === playlistId)
|
|
|
|
|
+ const songs = this.playlistSongsCache.get(playlistId) ?? []
|
|
|
|
|
+ this.currentAlbumSongs = songs.slice()
|
|
|
|
|
+ if (playlist) {
|
|
|
|
|
+ this.currentAlbumTitle = playlist.name
|
|
|
|
|
+ this.currentAlbumArtist = '心动歌单'
|
|
|
|
|
+ const coverSong = this.pickAlbumCoverSong(songs)
|
|
|
|
|
+ this.currentAlbumCoverPath = StrUtil.isNotEmpty(playlist.coverPath) ? playlist.coverPath as string :
|
|
|
|
|
+ (coverSong?.pixelMapPath ?? '')
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.currentAlbumCoverPath = ''
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ const album = this.featuredAlbumsPool.find((item: FindAlbumGroup) => item.id === this.currentAlbumId) ??
|
|
|
|
|
+ this.cloudAlbumsPool.find((item: FindAlbumGroup) => item.id === this.currentAlbumId)
|
|
|
|
|
+ if (album) {
|
|
|
|
|
+ this.currentAlbumTitle = album.title
|
|
|
|
|
+ this.currentAlbumArtist = album.artist
|
|
|
|
|
+ this.currentAlbumCoverPath = album.coverPath
|
|
|
|
|
+ this.currentAlbumSourceLabel = album.isRemote ? '云端专辑' : '精选专辑'
|
|
|
|
|
+ this.currentAlbumSongs = album.songs.slice()
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.currentAlbumCoverPath = ''
|
|
|
|
|
+ this.currentAlbumSongs = []
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private async handleAlbumDeleteSuccess(deletedItems: VideoItem[]): Promise<void> {
|
|
|
|
|
+ if (deletedItems.length <= 0) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ const deletedKeys: Set<string> = new Set<string>()
|
|
|
|
|
+ deletedItems.forEach((item: VideoItem) => {
|
|
|
|
|
+ if (StrUtil.isNotEmpty(item.filePath)) {
|
|
|
|
|
+ deletedKeys.add(item.filePath)
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ if (deletedKeys.size <= 0) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ this.currentAlbumSongs = this.currentAlbumSongs.filter((item: VideoItem) => !deletedKeys.has(item.filePath))
|
|
|
|
|
+ this.filterPlaylistCachesByDeletedKeys(deletedKeys)
|
|
|
|
|
+ await this.loadDiscoveryContent(false)
|
|
|
|
|
+ this.syncCurrentAlbumDetailFromState()
|
|
|
|
|
+ ToastUtil.showToast('删除成功')
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private openDeleteSongDialog(song: VideoItem): void {
|
|
|
|
|
+ if (song.type !== CommonConstants.TYPE_LOCAL || StrUtil.isEmpty(song.filePath)) {
|
|
|
|
|
+ ToastUtil.showToast('云端歌曲暂不支持删除')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ this.pendingDeleteSongs = [song]
|
|
|
|
|
+ this.getUIContext().getPromptAction().openCustomDialog({
|
|
|
|
|
+ builder: () => {
|
|
|
|
|
+ this.buildDeleteSongDialog()
|
|
|
|
|
+ },
|
|
|
|
|
+ isModal: true,
|
|
|
|
|
+ showInSubWindow: false,
|
|
|
|
|
+ maskColor: Color.Transparent,
|
|
|
|
|
+ dialogTransition: TransitionEffect.translate({ x: 0, y: 120, z: 0 })
|
|
|
|
|
+ .combine(TransitionEffect.opacity(0.01))
|
|
|
|
|
+ .animation({ duration: 260, curve: Curve.EaseOut }),
|
|
|
|
|
+ maskTransition: TransitionEffect.opacity(0)
|
|
|
|
|
+ .animation({ duration: 220, curve: Curve.EaseOut })
|
|
|
|
|
+ }).then((dialogId: number) => {
|
|
|
|
|
+ this.deleteComponentId = dialogId
|
|
|
|
|
+ }).catch((error: BusinessError) => {
|
|
|
|
|
+ Logger.error(TAG, `发现页打开删除弹窗失败: ${error.message}`)
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Builder
|
|
|
|
|
+ private buildDeleteSongDialog() {
|
|
|
|
|
+ DeleteComptent({
|
|
|
|
|
+ selectedFiles: this.pendingDeleteSongs,
|
|
|
|
|
+ onCancel: () => {
|
|
|
|
|
+ this.closeDeleteDialog(() => {
|
|
|
|
|
+ this.pendingDeleteSongs = []
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ onDeleteResult: (result: boolean) => {
|
|
|
|
|
+ const deletedItems = this.pendingDeleteSongs.slice()
|
|
|
|
|
+ this.closeDeleteDialog(() => {
|
|
|
|
|
+ this.pendingDeleteSongs = []
|
|
|
|
|
+ if (result) {
|
|
|
|
|
+ void this.handleAlbumDeleteSuccess(deletedItems)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ ToastUtil.showToast('删除失败')
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private playCurrentAlbum(startIndex: number, songs: VideoItem[] = this.currentAlbumSongs): void {
|
|
private playCurrentAlbum(startIndex: number, songs: VideoItem[] = this.currentAlbumSongs): void {
|
|
|
if (songs.length === 0) {
|
|
if (songs.length === 0) {
|
|
|
ToastUtil.showToast('专辑里还没有歌曲')
|
|
ToastUtil.showToast('专辑里还没有歌曲')
|
|
@@ -1534,9 +1711,9 @@ export struct FindView {
|
|
|
const mimeType = (item.mimeType ?? '').toLowerCase()
|
|
const mimeType = (item.mimeType ?? '').toLowerCase()
|
|
|
const fileName = (item.fileName ?? item.name ?? '').toLowerCase()
|
|
const fileName = (item.fileName ?? item.name ?? '').toLowerCase()
|
|
|
const isLosslessFormat = mimeType.includes('flac') || mimeType.includes('wav') || mimeType.includes('ape') ||
|
|
const isLosslessFormat = mimeType.includes('flac') || mimeType.includes('wav') || mimeType.includes('ape') ||
|
|
|
- mimeType.includes('alac') || mimeType.includes('dsf') || mimeType.includes('dff') ||
|
|
|
|
|
- fileName.endsWith('.flac') || fileName.endsWith('.wav') || fileName.endsWith('.ape') ||
|
|
|
|
|
- fileName.endsWith('.alac') || fileName.endsWith('.dsf') || fileName.endsWith('.dff')
|
|
|
|
|
|
|
+ mimeType.includes('alac') || mimeType.includes('dsf') || mimeType.includes('dff') ||
|
|
|
|
|
+ fileName.endsWith('.flac') || fileName.endsWith('.wav') || fileName.endsWith('.ape') ||
|
|
|
|
|
+ fileName.endsWith('.alac') || fileName.endsWith('.dsf') || fileName.endsWith('.dff')
|
|
|
return isLosslessFormat ? '无损' : ''
|
|
return isLosslessFormat ? '无损' : ''
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1639,21 +1816,39 @@ export struct FindView {
|
|
|
@Builder
|
|
@Builder
|
|
|
private buildTopErrorBanner() {
|
|
private buildTopErrorBanner() {
|
|
|
if (StrUtil.isNotEmpty(this.refreshText)) {
|
|
if (StrUtil.isNotEmpty(this.refreshText)) {
|
|
|
- Row({ space: 6 }) {
|
|
|
|
|
- SymbolGlyph($r('sys.symbol.exclamationmark_circle'))
|
|
|
|
|
- .fontSize(15)
|
|
|
|
|
- .fontColor([$r('app.color.orange')])
|
|
|
|
|
- Text(this.refreshText)
|
|
|
|
|
- .layoutWeight(1)
|
|
|
|
|
- .fontSize(12)
|
|
|
|
|
- .fontColor($r('app.color.orange'))
|
|
|
|
|
- .maxLines(1)
|
|
|
|
|
- .textOverflow({ overflow: TextOverflow.Ellipsis })
|
|
|
|
|
|
|
+ if (this.isRefreshing) {
|
|
|
|
|
+ Row({ space: 8 }) {
|
|
|
|
|
+ LoadingProgress()
|
|
|
|
|
+ .width(14)
|
|
|
|
|
+ .height(14)
|
|
|
|
|
+ .color(this.themeColor)
|
|
|
|
|
+ Text(this.refreshText)
|
|
|
|
|
+ .fontSize(12)
|
|
|
|
|
+ .fontColor(this.getSecondaryTextColor())
|
|
|
|
|
+ .textAlign(TextAlign.Center)
|
|
|
|
|
+ .maxLines(1)
|
|
|
|
|
+ }
|
|
|
|
|
+ .width('100%')
|
|
|
|
|
+ .padding({ left: 12, right: 12, top: 10, bottom: 10 })
|
|
|
|
|
+ .justifyContent(FlexAlign.Center)
|
|
|
|
|
+ .alignItems(VerticalAlign.Center)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Row({ space: 6 }) {
|
|
|
|
|
+ SymbolGlyph($r('sys.symbol.exclamationmark_circle'))
|
|
|
|
|
+ .fontSize(15)
|
|
|
|
|
+ .fontColor([$r('app.color.orange')])
|
|
|
|
|
+ Text(this.refreshText)
|
|
|
|
|
+ .layoutWeight(1)
|
|
|
|
|
+ .fontSize(12)
|
|
|
|
|
+ .fontColor($r('app.color.orange'))
|
|
|
|
|
+ .maxLines(1)
|
|
|
|
|
+ .textOverflow({ overflow: TextOverflow.Ellipsis })
|
|
|
|
|
+ }
|
|
|
|
|
+ .width('100%')
|
|
|
|
|
+ .padding({ left: 12, right: 12, top: 10, bottom: 10 })
|
|
|
|
|
+ .backgroundColor($r('app.color.timeColor_bg'))
|
|
|
|
|
+ .borderRadius(16)
|
|
|
}
|
|
}
|
|
|
- .width('100%')
|
|
|
|
|
- .padding({ left: 12, right: 12, top: 10, bottom: 10 })
|
|
|
|
|
- .backgroundColor($r('app.color.timeColor_bg'))
|
|
|
|
|
- .borderRadius(16)
|
|
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1662,21 +1857,18 @@ export struct FindView {
|
|
|
Column() {
|
|
Column() {
|
|
|
Row({ space: 12 }) {
|
|
Row({ space: 12 }) {
|
|
|
if (!this.isSearchMode && !this.isAlbumMode) {
|
|
if (!this.isSearchMode && !this.isAlbumMode) {
|
|
|
- Button({ type: ButtonType.Circle, stateEffect: true }) {
|
|
|
|
|
- SymbolGlyph($r('sys.symbol.sort'))
|
|
|
|
|
- .attributeModifier(new SymbolGlyphFancyModifier(25, '', ''))
|
|
|
|
|
- }
|
|
|
|
|
- .attributeModifier(new ButtonFancyModifier(40, 40))
|
|
|
|
|
- .clickEffect({ level: ClickEffectLevel.MIDDLE, scale: 0.6 })
|
|
|
|
|
- .animation({ duration: 300, curve: Curve.Ease })
|
|
|
|
|
- .onClick(() => {
|
|
|
|
|
- this.getUIContext().animateTo({ duration: 500 }, () => {
|
|
|
|
|
- this.isShowDrawer = !this.isShowDrawer
|
|
|
|
|
- this.offsetX = 0
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ TitleBarPointLightButton({
|
|
|
|
|
+ iconResource: $r('sys.symbol.sort'),
|
|
|
|
|
+ iconSize: 25,
|
|
|
|
|
+ pointColor: this.themeColor,
|
|
|
|
|
+ clickScale: 0.8,
|
|
|
|
|
+ clickHandler: () => {
|
|
|
|
|
+ this.getUIContext().animateTo({ duration: 500 }, () => {
|
|
|
|
|
+ this.isShowDrawer = !this.isShowDrawer
|
|
|
|
|
+ this.offsetX = 0
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
})
|
|
})
|
|
|
- .attributeModifier(new ShadowModifier())
|
|
|
|
|
- .zIndex(0)
|
|
|
|
|
|
|
|
|
|
Text('发现页')
|
|
Text('发现页')
|
|
|
.margin({ left: 3, right: 10 })
|
|
.margin({ left: 3, right: 10 })
|
|
@@ -1687,22 +1879,19 @@ export struct FindView {
|
|
|
.textOverflow({ overflow: TextOverflow.MARQUEE })
|
|
.textOverflow({ overflow: TextOverflow.MARQUEE })
|
|
|
.layoutWeight(1)
|
|
.layoutWeight(1)
|
|
|
} else {
|
|
} else {
|
|
|
- Button({ type: ButtonType.Circle, stateEffect: true }) {
|
|
|
|
|
- SymbolGlyph($r('sys.symbol.chevron_left'))
|
|
|
|
|
- .attributeModifier(new SymbolGlyphFancyModifier(24, '', ''))
|
|
|
|
|
- }
|
|
|
|
|
- .attributeModifier(new ButtonFancyModifier(40, 40))
|
|
|
|
|
- .clickEffect({ level: ClickEffectLevel.MIDDLE, scale: 0.6 })
|
|
|
|
|
- .animation({ duration: 300, curve: Curve.Ease })
|
|
|
|
|
- .onClick(() => {
|
|
|
|
|
- if (this.isSearchMode) {
|
|
|
|
|
- this.exitSearchMode()
|
|
|
|
|
- return
|
|
|
|
|
|
|
+ TitleBarPointLightButton({
|
|
|
|
|
+ iconResource: $r('sys.symbol.chevron_left'),
|
|
|
|
|
+ iconSize: 24,
|
|
|
|
|
+ pointColor: this.themeColor,
|
|
|
|
|
+ clickScale: 0.8,
|
|
|
|
|
+ clickHandler: () => {
|
|
|
|
|
+ if (this.isSearchMode) {
|
|
|
|
|
+ this.exitSearchMode()
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ this.exitAlbumMode()
|
|
|
}
|
|
}
|
|
|
- this.exitAlbumMode()
|
|
|
|
|
})
|
|
})
|
|
|
- .attributeModifier(new ShadowModifier())
|
|
|
|
|
- .zIndex(0)
|
|
|
|
|
|
|
|
|
|
if (this.isAlbumMode) {
|
|
if (this.isAlbumMode) {
|
|
|
Column({ space: 2 }) {
|
|
Column({ space: 2 }) {
|
|
@@ -1758,22 +1947,19 @@ export struct FindView {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (!this.isSearchMode && !this.isAlbumMode) {
|
|
if (!this.isSearchMode && !this.isAlbumMode) {
|
|
|
- Button({ type: ButtonType.Circle, stateEffect: true }) {
|
|
|
|
|
- SymbolGlyph($r('sys.symbol.magnifyingglass'))
|
|
|
|
|
- .attributeModifier(new SymbolGlyphFancyModifier(25, '', ''))
|
|
|
|
|
- }
|
|
|
|
|
- .attributeModifier(new ButtonFancyModifier(40, 40))
|
|
|
|
|
- .animation({ duration: 300, curve: Curve.Ease })
|
|
|
|
|
- .clickEffect({ level: ClickEffectLevel.MIDDLE, scale: 0.6 })
|
|
|
|
|
- .attributeModifier(new ShadowModifier())
|
|
|
|
|
- .zIndex(0)
|
|
|
|
|
- .onClick(() => {
|
|
|
|
|
- this.isAlbumMode = false
|
|
|
|
|
- this.getUIContext()?.animateTo({ duration: 500 }, () => {
|
|
|
|
|
- this.isSearchMode = true
|
|
|
|
|
- })
|
|
|
|
|
- this.loadSearchHistory()
|
|
|
|
|
- void this.ensureSearchSourceReady()
|
|
|
|
|
|
|
+ TitleBarPointLightButton({
|
|
|
|
|
+ iconResource: $r('sys.symbol.magnifyingglass'),
|
|
|
|
|
+ iconSize: 25,
|
|
|
|
|
+ pointColor: this.themeColor,
|
|
|
|
|
+ clickScale: 0.6,
|
|
|
|
|
+ clickHandler: () => {
|
|
|
|
|
+ this.isAlbumMode = false
|
|
|
|
|
+ this.getUIContext()?.animateTo({ duration: 500 }, () => {
|
|
|
|
|
+ this.isSearchMode = true
|
|
|
|
|
+ })
|
|
|
|
|
+ this.loadSearchHistory()
|
|
|
|
|
+ void this.ensureSearchSourceReady()
|
|
|
|
|
+ }
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -2034,10 +2220,10 @@ export struct FindView {
|
|
|
this.buildSwiperCardContent(item)
|
|
this.buildSwiperCardContent(item)
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
- .width('100%')
|
|
|
|
|
- .onClick(() => {
|
|
|
|
|
- this.handleSwiperTap(index)
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ .width('100%')
|
|
|
|
|
+ .onClick(() => {
|
|
|
|
|
+ this.handleSwiperTap(index)
|
|
|
|
|
+ })
|
|
|
}, getFindSongKey)
|
|
}, getFindSongKey)
|
|
|
}
|
|
}
|
|
|
.width('100%')
|
|
.width('100%')
|
|
@@ -2191,10 +2377,10 @@ export struct FindView {
|
|
|
this.buildCloudSongCardContent(item)
|
|
this.buildCloudSongCardContent(item)
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
- .width('100%')
|
|
|
|
|
- .onClick(() => {
|
|
|
|
|
- this.handleRemoteSongTap(pageIndex * this.getSectionPageSize(this.getDiscoverSectionColumns()) + itemIndex)
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ .width('100%')
|
|
|
|
|
+ .onClick(() => {
|
|
|
|
|
+ this.handleRemoteSongTap(pageIndex * this.getSectionPageSize(this.getDiscoverSectionColumns()) + itemIndex)
|
|
|
|
|
+ })
|
|
|
}
|
|
}
|
|
|
}, getFindSongKey)
|
|
}, getFindSongKey)
|
|
|
}
|
|
}
|
|
@@ -2290,10 +2476,10 @@ export struct FindView {
|
|
|
this.buildAlbumCardContent(album)
|
|
this.buildAlbumCardContent(album)
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
- .width('100%')
|
|
|
|
|
- .onClick(() => {
|
|
|
|
|
- this.openAlbumDetail(album)
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ .width('100%')
|
|
|
|
|
+ .onClick(() => {
|
|
|
|
|
+ this.openAlbumDetail(album)
|
|
|
|
|
+ })
|
|
|
}
|
|
}
|
|
|
}, getFindAlbumKey)
|
|
}, getFindAlbumKey)
|
|
|
}
|
|
}
|
|
@@ -2336,10 +2522,10 @@ export struct FindView {
|
|
|
this.buildAlbumCardContent(album)
|
|
this.buildAlbumCardContent(album)
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
- .width('100%')
|
|
|
|
|
- .onClick(() => {
|
|
|
|
|
- this.openAlbumDetail(album)
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ .width('100%')
|
|
|
|
|
+ .onClick(() => {
|
|
|
|
|
+ this.openAlbumDetail(album)
|
|
|
|
|
+ })
|
|
|
}
|
|
}
|
|
|
}, getFindAlbumKey)
|
|
}, getFindAlbumKey)
|
|
|
}
|
|
}
|
|
@@ -2420,9 +2606,9 @@ export struct FindView {
|
|
|
this.buildHotSongCardContent(item)
|
|
this.buildHotSongCardContent(item)
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
- .onClick(() => {
|
|
|
|
|
- this.handleHotSongTap(index)
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ .onClick(() => {
|
|
|
|
|
+ this.handleHotSongTap(index)
|
|
|
|
|
+ })
|
|
|
}
|
|
}
|
|
|
.margin({
|
|
.margin({
|
|
|
left: index === 0 ? 2 : 0,
|
|
left: index === 0 ? 2 : 0,
|
|
@@ -2502,9 +2688,9 @@ export struct FindView {
|
|
|
this.buildHeartPlaylistCardContent(playlist)
|
|
this.buildHeartPlaylistCardContent(playlist)
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
- .onClick(() => {
|
|
|
|
|
- void this.openPlaylistDetail(playlist)
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ .onClick(() => {
|
|
|
|
|
+ void this.openPlaylistDetail(playlist)
|
|
|
|
|
+ })
|
|
|
}
|
|
}
|
|
|
}, getFindPlaylistKey)
|
|
}, getFindPlaylistKey)
|
|
|
}
|
|
}
|
|
@@ -2534,9 +2720,9 @@ export struct FindView {
|
|
|
this.buildHotSongCardContent(item)
|
|
this.buildHotSongCardContent(item)
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
- .onClick(() => {
|
|
|
|
|
- this.handleCloudMoodSongTap(index)
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ .onClick(() => {
|
|
|
|
|
+ this.handleCloudMoodSongTap(index)
|
|
|
|
|
+ })
|
|
|
}
|
|
}
|
|
|
.margin({
|
|
.margin({
|
|
|
left: index === 0 ? 2 : 0,
|
|
left: index === 0 ? 2 : 0,
|
|
@@ -2618,10 +2804,10 @@ export struct FindView {
|
|
|
this.buildRecentSongCardContent(item)
|
|
this.buildRecentSongCardContent(item)
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
- .width('100%')
|
|
|
|
|
- .onClick(() => {
|
|
|
|
|
- this.handleRecentSongTap(pageIndex * this.getSectionPageSize(this.getDiscoverSectionColumns()) + itemIndex)
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ .width('100%')
|
|
|
|
|
+ .onClick(() => {
|
|
|
|
|
+ this.handleRecentSongTap(pageIndex * this.getSectionPageSize(this.getDiscoverSectionColumns()) + itemIndex)
|
|
|
|
|
+ })
|
|
|
}
|
|
}
|
|
|
}, getFindSongKey)
|
|
}, getFindSongKey)
|
|
|
}
|
|
}
|
|
@@ -2707,10 +2893,10 @@ export struct FindView {
|
|
|
this.buildPopularSongCardContent(item)
|
|
this.buildPopularSongCardContent(item)
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
- .width('100%')
|
|
|
|
|
- .onClick(() => {
|
|
|
|
|
- this.handlePopularSongTap(pageIndex * this.getSectionPageSize(this.getDiscoverSectionColumns()) + itemIndex)
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ .width('100%')
|
|
|
|
|
+ .onClick(() => {
|
|
|
|
|
+ this.handlePopularSongTap(pageIndex * this.getSectionPageSize(this.getDiscoverSectionColumns()) + itemIndex)
|
|
|
|
|
+ })
|
|
|
}
|
|
}
|
|
|
}, getFindSongKey)
|
|
}, getFindSongKey)
|
|
|
}
|
|
}
|
|
@@ -2795,10 +2981,10 @@ export struct FindView {
|
|
|
this.buildFavoriteSongCardContent(item)
|
|
this.buildFavoriteSongCardContent(item)
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
- .width('100%')
|
|
|
|
|
- .onClick(() => {
|
|
|
|
|
- this.handleFavoriteSongTap(pageIndex * this.getSectionPageSize(this.getDiscoverSectionColumns()) + itemIndex)
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ .width('100%')
|
|
|
|
|
+ .onClick(() => {
|
|
|
|
|
+ this.handleFavoriteSongTap(pageIndex * this.getSectionPageSize(this.getDiscoverSectionColumns()) + itemIndex)
|
|
|
|
|
+ })
|
|
|
}
|
|
}
|
|
|
}, getFindSongKey)
|
|
}, getFindSongKey)
|
|
|
}
|
|
}
|
|
@@ -2927,6 +3113,7 @@ export struct FindView {
|
|
|
albumCoverPath: this.currentAlbumCoverPath,
|
|
albumCoverPath: this.currentAlbumCoverPath,
|
|
|
albumSourceLabel: this.currentAlbumSourceLabel,
|
|
albumSourceLabel: this.currentAlbumSourceLabel,
|
|
|
songs: this.currentAlbumSongs,
|
|
songs: this.currentAlbumSongs,
|
|
|
|
|
+ allowDelete: this.canDeleteCurrentAlbumSongs(),
|
|
|
onBack: () => {
|
|
onBack: () => {
|
|
|
this.exitAlbumMode()
|
|
this.exitAlbumMode()
|
|
|
},
|
|
},
|
|
@@ -2941,6 +3128,12 @@ export struct FindView {
|
|
|
},
|
|
},
|
|
|
onSongTap: (index: number, songs?: VideoItem[]) => {
|
|
onSongTap: (index: number, songs?: VideoItem[]) => {
|
|
|
this.handleAlbumSongTap(index, songs)
|
|
this.handleAlbumSongTap(index, songs)
|
|
|
|
|
+ },
|
|
|
|
|
+ onFavoriteSong: (song: VideoItem) => {
|
|
|
|
|
+ void this.handleAlbumFavoriteSong(song)
|
|
|
|
|
+ },
|
|
|
|
|
+ onDeleteSong: (song: VideoItem) => {
|
|
|
|
|
+ this.openDeleteSongDialog(song)
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
} else {
|
|
} else {
|