From 4a30c53eda091cc0d1d41ef03e1fe2e4d2e3b6f9 Mon Sep 17 00:00:00 2001 From: wangyu Date: Thu, 19 Mar 2026 19:01:16 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E8=A7=86=E9=A2=91=E8=BD=AC?= =?UTF-8?q?=E6=96=87=E5=AD=97=EF=BC=8C=E9=9F=B3=E9=A2=91=E8=BD=AC=E6=96=87?= =?UTF-8?q?=E5=AD=97=EF=BC=8C=E9=9F=B3=E9=A2=91=E6=92=AD=E6=94=BE=E5=99=A8?= =?UTF-8?q?(=E5=BE=85=E5=AE=8C=E5=96=84)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- entry/src/main/ets/common/RouterUrls.ets | 22 +- .../src/main/ets/dialog/AudioPlayerDialog.ets | 271 ++++++++++ entry/src/main/ets/dialog/BindPhoneDialog.ets | 8 +- entry/src/main/ets/entity/ConfigEntity.ets | 3 + ...PermissionEntity.ets => VipAuthEntity.ets} | 2 +- ...obalManager.ets => EventReportManager.ets} | 2 +- .../main/ets/manager/UserConfigManager.ets | 13 + entry/src/main/ets/pages/guide/GuidePage.ets | 6 +- entry/src/main/ets/pages/login/LoginPage.ets | 10 +- entry/src/main/ets/pages/main/MainPage.ets | 6 +- .../src/main/ets/pages/main/home/HomePage.ets | 10 +- .../pages/main/home/link/TakeMaterialPage.ets | 26 +- .../main/home/material/MaterialDetailPage.ets | 12 +- .../pages/main/home/tools/AddAudioPage.ets | 331 ------------- .../main/home/tools/AddWatermarkPage.ets | 70 ++- .../pages/main/home/tools/AudioToTextPage.ets | 423 +++++++++++++++- .../pages/main/home/tools/ClipVideoPage.ets | 468 ------------------ .../pages/main/home/tools/ImageMergePage.ets | 72 ++- .../pages/main/home/tools/MD5ResetPage.ets | 125 ++++- .../pages/main/home/tools/RemoveAudioPage.ets | 65 ++- .../main/home/tools/RemoveWatermarkPage.ets | 76 ++- .../pages/main/home/tools/VideoMirrorPage.ets | 322 ------------ .../main/home/tools/VideoReversePage.ets | 297 ----------- .../main/home/tools/VideoToAudioPage.ets | 218 ++++++-- .../pages/main/home/tools/VideoToTextPage.ets | 125 +++-- .../ets/pages/main/home/wx/WxVideoPage.ets | 26 +- .../src/main/ets/pages/main/mine/MinePage.ets | 15 +- .../pages/main/mine/diamond/DiamondPage.ets | 10 +- .../main/mine/record/AudioRecordPage.ets | 6 +- .../main/mine/record/ImageRecordPage.ets | 26 +- .../main/mine/record/VideoRecordPage.ets | 27 +- .../pages/main/mine/setting/SettingsPage.ets | 12 +- .../mine/setting/account/BindAccountPage.ets | 4 +- .../setting/account/ManageAccountPage.ets | 4 +- .../main/ets/pages/main/mine/vip/VipPage.ets | 24 +- .../src/main/ets/pages/splash/SplashPage.ets | 4 +- entry/src/main/ets/view/RecordItemView.ets | 33 +- .../src/main/ets/viewModel/AuthViewModel.ets | 6 +- .../main/ets/viewModel/FeedbackViewModel.ets | 1 + .../ets/viewModel/TakeMaterialViewModel.ets | 6 +- .../ets/viewModel/UserSettingsViewModel.ets | 1 + .../main/ets/viewModel/WxVideoViewModel.ets | 6 +- .../resources/base/media/ic_add_audio.png | Bin 7139 -> 0 bytes .../resources/base/media/ic_add_audio.webp | Bin 0 -> 2110 bytes .../resources/base/media/ic_audio_pause.webp | Bin 0 -> 460 bytes .../resources/base/media/ic_audio_pause2.webp | Bin 0 -> 1414 bytes .../resources/base/media/ic_audio_play.webp | Bin 0 -> 746 bytes .../resources/base/media/ic_audio_play2.webp | Bin 0 -> 1434 bytes .../base/media/ic_last_audio_disable.webp | Bin 0 -> 676 bytes .../base/media/ic_last_audio_enable.webp | Bin 0 -> 622 bytes .../resources/base/media/ic_share_audio.webp | Bin 0 -> 1048 bytes .../resources/base/profile/main_pages.json | 4 - 52 files changed, 1473 insertions(+), 1725 deletions(-) create mode 100644 entry/src/main/ets/dialog/AudioPlayerDialog.ets rename entry/src/main/ets/entity/{VipPermissionEntity.ets => VipAuthEntity.ets} (88%) rename entry/src/main/ets/manager/{EventReportGlobalManager.ets => EventReportManager.ets} (85%) delete mode 100644 entry/src/main/ets/pages/main/home/tools/AddAudioPage.ets delete mode 100644 entry/src/main/ets/pages/main/home/tools/ClipVideoPage.ets delete mode 100644 entry/src/main/ets/pages/main/home/tools/VideoMirrorPage.ets delete mode 100644 entry/src/main/ets/pages/main/home/tools/VideoReversePage.ets delete mode 100644 entry/src/main/resources/base/media/ic_add_audio.png create mode 100644 entry/src/main/resources/base/media/ic_add_audio.webp create mode 100644 entry/src/main/resources/base/media/ic_audio_pause.webp create mode 100644 entry/src/main/resources/base/media/ic_audio_pause2.webp create mode 100644 entry/src/main/resources/base/media/ic_audio_play.webp create mode 100644 entry/src/main/resources/base/media/ic_audio_play2.webp create mode 100644 entry/src/main/resources/base/media/ic_last_audio_disable.webp create mode 100644 entry/src/main/resources/base/media/ic_last_audio_enable.webp create mode 100644 entry/src/main/resources/base/media/ic_share_audio.webp diff --git a/entry/src/main/ets/common/RouterUrls.ets b/entry/src/main/ets/common/RouterUrls.ets index 1ef6ac0..9a2c752 100644 --- a/entry/src/main/ets/common/RouterUrls.ets +++ b/entry/src/main/ets/common/RouterUrls.ets @@ -55,30 +55,10 @@ export class RouterUrls { static readonly MD5_RESET_PAGE = "pages/main/home/tools/MD5ResetPage" /** - * 视频倒放页 - */ - static readonly VIDEO_REVERSE_PAGE = "pages/main/home/tools/VideoReversePage" - - /** - * 视频裁剪页 - */ - static readonly VIDEO_MIRROR_PAGE = "pages/main/home/tools/VideoMirrorPage" - - /** - * 视频裁剪页 - */ - static readonly CLIP_VIDEO_PAGE = "pages/main/home/tools/ClipVideoPage" - - /** - * 去除音乐页 + * 视频去原声页 */ static readonly REMOVE_AUDIO_PAGE = "pages/main/home/tools/RemoveAudioPage" - /** - * 添加音乐页 - */ - static readonly ADD_AUDIO_PAGE = "pages/main/home/tools/AddAudioPage" - /** * 视频转音频页 */ diff --git a/entry/src/main/ets/dialog/AudioPlayerDialog.ets b/entry/src/main/ets/dialog/AudioPlayerDialog.ets new file mode 100644 index 0000000..afc7db1 --- /dev/null +++ b/entry/src/main/ets/dialog/AudioPlayerDialog.ets @@ -0,0 +1,271 @@ +import { media } from "@kit.MediaKit"; +import { fileIo } from "@kit.CoreFileKit"; +import { avSessionManager } from "../manager/AVSessionManager"; +import { MediaRecordEntity } from "../entity/MediaRecordEntity"; +import { MediaManager } from "../manager/MediaManager"; + +@CustomDialog +export struct AudioPlayerDialog { + controller: CustomDialogController; + + @State index: number = 0 + + @State uri?: string = undefined + @State title?: string = undefined + @State currentTime: number = 0 + @State durationTime: number = 0 + @State isPlaying: boolean = false + @State mediaList: Array = []; + + private avPlayer?: media.AVPlayer; + + aboutToAppear(): void { + this.initPlayer() + this.initParams() + } + + aboutToDisappear(): void { + if (this.avPlayer) { + this.avPlayer.release() + } + } + + async initPlayer() { + this.avPlayer = await media.createAVPlayer() + // 创建状态机变化回调函数 + this.setAVPlayerCallback() + } + + async initParams() { + this.mediaList = await MediaManager.getAudioList() + if (this.mediaList.length > this.index) { + this.uri = this.mediaList[this.index].uri + this.title = this.mediaList[this.index].name + if (this.uri) { + // 打开相应的资源文件地址获取fd + let file = await fileIo.open(this.uri!!) + this.avPlayer!!.url = 'fd://' + file.fd + } + } + } + + formatTime(time: number): string { + let minute: number = 0 + let second: number = 0 + if (time > 60) { + minute = Math.trunc(time / 60) + second = time % 60 + if (minute < 10) { + if (second < 10) { + return `0${minute}:0${second}` + } else { + return `0${minute}:${second}` + } + } else { + if (second < 10) { + return `${minute}:0${second}` + } else { + return `${minute}:${second}` + } + } + } else { + second = time + if (second < 10) { + return `00:0${second}` + } else { + return `00:${second}` + } + } + } + + // 注册avplayer回调函数 + setAVPlayerCallback() { + this.avPlayer!!.on('error', (err) => { + console.error(`播放器发生错误,错误码:${err.code}, 错误信息:${err.message}`); + // 调用reset重置资源,触发idle状态 + this.isPlaying = false + this.avPlayer!!.reset(); + avSessionManager.deactivate() + }) + // 状态机变化回调函数 + this.avPlayer!!.on('stateChange', async (state, reason) => { + switch (state) { + case 'initialized': + console.info('资源初始化完成'); + // 资源初始化完成,开始准备文件 + this.avPlayer!!.prepare(); + break; + case 'prepared': + console.info('资源准备完成'); + // 资源准备完成,开始准备文件 + this.durationTime = Math.trunc(this.avPlayer!!.duration / 1000) + this.currentTime = this.avPlayer!!.currentTime; + + await avSessionManager.activate() + this.avPlayer!!.play(); + break; + case 'completed': + console.info('播放完成'); + this.isPlaying = false + this.avPlayer!!.off('bufferingUpdate') + AppStorage.setOrCreate('currentTime', this.durationTime); + avSessionManager.deactivate() + break; + case 'playing': + console.info('播放开始'); + this.isPlaying = true + break; + case 'released': + case 'stopped': + case 'error': + case 'paused': + console.info('播放暂停'); + this.isPlaying = false + avSessionManager.deactivate() + break; + } + }) + // 时间上报监听函数 + this.avPlayer!!.on('timeUpdate', (time: number) => { + this.currentTime = Math.trunc(time / 1000); + }); + } + + build() { + RelativeContainer() { + Image($r('app.media.ic_close_dialog')).width(20).height(20) + .alignRules({ + right: {anchor: '__container__', align: HorizontalAlign.End} + }) + .margin({top: 12, right: 12}) + .onClick(() => { + this.controller.close() + }) + .id('iv_close') + + Text(this.title).fontColor($r('app.color.color_212226')).fontSize(16) + .alignRules({ + top: {anchor: 'iv_close', align: VerticalAlign.Bottom} + }) + .margin({left: 16, top: 6}) + .id('tv_name') + + Row() { + Text(this.formatTime(this.currentTime)).width(35).fontColor($r('app.color.color_212226')).fontSize(12) + Slider({ + value: this.currentTime, + min: 0, + max: this.durationTime + }) + .blockColor(Color.White) + .trackColor($r('app.color.color_60ffffff')) + .onChange((value: number, mode: SliderChangeMode) => { + this.avPlayer!!.seek(value * 1000, 2); // 设置视频播放的进度跳转到value处 + this.currentTime = value; + }) + .layoutWeight(1) + Text(this.formatTime(this.durationTime)).width(35).fontColor($r('app.color.color_212226')).fontSize(12) + } + .alignRules({ + top: {anchor: 'tv_name', align: VerticalAlign.Bottom} + }) + .width('100%') + .padding({left:16, right: 16}) + .margin({top: 20}) + .id('row_progress') + + Row() { + Image(this.index > 0 ? $r('app.media.ic_last_audio_enable') : $r('app.media.ic_last_audio_disable')).width(20).height(20) + .onClick(async () => { + if (this.index > 0) { + await this.avPlayer!!.stop() + this.index-- + this.uri = this.mediaList[this.index].uri + this.title = this.mediaList[this.index].name + if (this.uri) { + // 打开相应的资源文件地址获取fd + let file = await fileIo.open(this.uri!!) + this.avPlayer!!.url = 'fd://' + file.fd + } + } + }) + .visibility(Visibility.None) + + Image(this.isPlaying ? $r('app.media.ic_audio_pause') : $r('app.media.ic_audio_play')).width(30).height(30) + .margin({left: 50, right: 50}) + .onClick(async () => { + if (this.isPlaying) { + this.avPlayer!!.pause() + } else { + await avSessionManager.activate() + this.avPlayer!!.play() + } + }) + + Image(this.index < this.mediaList.length - 1 ? $r('app.media.ic_last_audio_enable') : $r('app.media.ic_last_audio_disable')).width(20).height(20) + .rotate({angle: 180}) + .onClick(async () => { + if (this.index < this.mediaList.length - 1) { + await this.avPlayer!!.stop() + this.index++ + this.uri = this.mediaList[this.index].uri + this.title = this.mediaList[this.index].name + if (this.uri) { + // 打开相应的资源文件地址获取fd + let file = await fileIo.open(this.uri!!) + this.avPlayer!!.url = 'fd://' + file.fd + } + } + }) + .visibility(Visibility.None) + } + .width('100%') + .justifyContent(FlexAlign.Center) + .alignRules({ + top: {anchor: 'row_progress', align: VerticalAlign.Bottom} + }) + .margin({top: 26}) + .id('row_controller') + + Row() { + Button({ type: ButtonType.Capsule, stateEffect: true }) { + Row() { + Image($r('app.media.ic_share_audio')).width(20).height(20) + Text('分享').fontColor($r('app.color.color_466afd')).fontSize(15).fontWeight(FontWeight.Medium) + } + } + .height(46) + .layoutWeight(1) + .borderWidth(1) + .borderColor($r('app.color.color_466afd')) + .backgroundColor(Color.Transparent) + .onClick(() => { + }) + + Blank().width(9) + + Button({ type: ButtonType.Capsule, stateEffect: true }) { + Row() { + Image($r('app.media.ic_delete_material')).width(20).height(20) + Text('删除').fontColor(Color.White).fontSize(15).fontWeight(FontWeight.Medium) + } + } + .height(46) + .layoutWeight(1) + .backgroundColor($r('app.color.color_466afd')) + .onClick(() => { + + }) + } + .alignRules({ + top: {anchor: 'row_controller', align: VerticalAlign.Bottom} + }) + .padding({left: 16, top: 9, right: 16, bottom: 30}) + .margin({top: 38}) + .backgroundColor(Color.White) + } + .width('100%') + .height('auto') + .backgroundColor($r('app.color.window_background')) + } +} \ No newline at end of file diff --git a/entry/src/main/ets/dialog/BindPhoneDialog.ets b/entry/src/main/ets/dialog/BindPhoneDialog.ets index 4350b8d..c33de68 100644 --- a/entry/src/main/ets/dialog/BindPhoneDialog.ets +++ b/entry/src/main/ets/dialog/BindPhoneDialog.ets @@ -12,10 +12,10 @@ export struct BindPhoneDialog { success: () => void = () => {} - phone: string = ''; - code: string = ''; - timestamp: string = ''; - intervalId: number = -1; + private phone: string = ''; + private code: string = ''; + private timestamp: string = ''; + private intervalId: number = -1; @State countDownTime: number = 0; diff --git a/entry/src/main/ets/entity/ConfigEntity.ets b/entry/src/main/ets/entity/ConfigEntity.ets index e8264f6..80a353d 100644 --- a/entry/src/main/ets/entity/ConfigEntity.ets +++ b/entry/src/main/ets/entity/ConfigEntity.ets @@ -59,4 +59,7 @@ export class ConfigEntity { @Expose({ name: 'client.challenge.enable' }) challengeEnable?: boolean = true; //0元挑战 + + @Expose({ name: 'client.AI.startEnd' }) + aiAuthEnable: boolean = true; //ai功能是否需要鉴权 } \ No newline at end of file diff --git a/entry/src/main/ets/entity/VipPermissionEntity.ets b/entry/src/main/ets/entity/VipAuthEntity.ets similarity index 88% rename from entry/src/main/ets/entity/VipPermissionEntity.ets rename to entry/src/main/ets/entity/VipAuthEntity.ets index a4e8cf3..154bde6 100644 --- a/entry/src/main/ets/entity/VipPermissionEntity.ets +++ b/entry/src/main/ets/entity/VipAuthEntity.ets @@ -1,4 +1,4 @@ -export class VipPermissionEntity { +export class VipAuthEntity { auth: boolean = false auth_ad: boolean = false scene: string = '' diff --git a/entry/src/main/ets/manager/EventReportGlobalManager.ets b/entry/src/main/ets/manager/EventReportManager.ets similarity index 85% rename from entry/src/main/ets/manager/EventReportGlobalManager.ets rename to entry/src/main/ets/manager/EventReportManager.ets index 4af6d5d..eb6cf24 100644 --- a/entry/src/main/ets/manager/EventReportGlobalManager.ets +++ b/entry/src/main/ets/manager/EventReportManager.ets @@ -1,6 +1,6 @@ import { apiService } from "../net/ApiService" -export class EventReportGlobalManager { +export class EventReportManager { static async eventReport(key: string, value: string = '', extra: string = '') { try { apiService.eventReport(key, value, extra) diff --git a/entry/src/main/ets/manager/UserConfigManager.ets b/entry/src/main/ets/manager/UserConfigManager.ets index 86e510c..0bceeed 100644 --- a/entry/src/main/ets/manager/UserConfigManager.ets +++ b/entry/src/main/ets/manager/UserConfigManager.ets @@ -78,6 +78,7 @@ class UserConfigManager { this.saveDomainMap(config.config.domainMap); this.saveCopyContainsList(config.config.copyContainsList); this.saveHomeBanner(config.config.homeBanners); + this.saveAiAuthEnable(config.config.aiAuthEnable); } } @@ -379,6 +380,18 @@ class UserConfigManager { } return new Array(); } + + /** + * ai功能是否需要鉴权 + * @param enable + */ + saveAiAuthEnable(enable: boolean) { + PrefUtils.put("ai_auth_enable", enable) + } + + isAiAuthEnable(): boolean { + return PrefUtils.getBoolean('ai_auth_enable', true) + } } export const ConfigManager = new UserConfigManager() \ No newline at end of file diff --git a/entry/src/main/ets/pages/guide/GuidePage.ets b/entry/src/main/ets/pages/guide/GuidePage.ets index f70b829..38f55ca 100644 --- a/entry/src/main/ets/pages/guide/GuidePage.ets +++ b/entry/src/main/ets/pages/guide/GuidePage.ets @@ -4,7 +4,7 @@ import systemDateTime from '@ohos.systemDateTime'; import { router } from '@kit.ArkUI'; import { AppUtil } from '@pura/harmony-utils'; import { ConfigManager } from '../../manager/UserConfigManager'; -import { EventReportGlobalManager } from '../../manager/EventReportGlobalManager'; +import { EventReportManager } from '../../manager/EventReportManager'; import { EventConstants } from '../../common/EventConstants'; @Entry @@ -23,7 +23,7 @@ struct GuidePage { @Local showHomePage: boolean = true aboutToAppear(): void { - EventReportGlobalManager.eventReport(EventConstants.GUIDE_LAUNCH) + EventReportManager.eventReport(EventConstants.GUIDE_LAUNCH) } build() { @@ -59,7 +59,7 @@ struct GuidePage { .indicator(false) .onChange((index: number) => { this.currentIndex = index; - EventReportGlobalManager.eventReport(EventConstants.GUIDE_OPPORTUNITY_SCROLL, `${index + 1}`) + EventReportManager.eventReport(EventConstants.GUIDE_OPPORTUNITY_SCROLL, `${index + 1}`) }) .onGestureSwipe((index: number, extraInfo: SwiperAnimationEvent) => { if (index === this.child.length - 1 && extraInfo.currentOffset < -60) { diff --git a/entry/src/main/ets/pages/login/LoginPage.ets b/entry/src/main/ets/pages/login/LoginPage.ets index 55200ad..51c0d9b 100644 --- a/entry/src/main/ets/pages/login/LoginPage.ets +++ b/entry/src/main/ets/pages/login/LoginPage.ets @@ -18,7 +18,7 @@ import { ErrCode, SendAuthResp } from '@tencent/wechat_open_sdk'; import BuildProfile from 'BuildProfile'; import { LoadingDialog } from '../../dialog/LoadingDialog'; import { EventConstants } from '../../common/EventConstants'; -import { EventReportGlobalManager } from '../../manager/EventReportGlobalManager'; +import { EventReportManager } from '../../manager/EventReportManager'; @Entry @ComponentV2 @@ -71,7 +71,7 @@ struct LoginPage { @Monitor('viewModel.phoneLoginEntity') onPhoneLogin(monitor: IMonitor) { const loginEntity = monitor.value()?.now as LoginEntity; - EventReportGlobalManager.eventReport(EventConstants.LOGIN, 'phone', this.phone) + EventReportManager.eventReport(EventConstants.LOGIN, 'phone', this.phone) LoginManager.saveToken(loginEntity.token); LoginManager.saveLastLoginType('phone') ConfigManager.userConfig() @@ -87,7 +87,7 @@ struct LoginPage { @Monitor('viewModel.wxLoginEntity') onWxLogin(monitor: IMonitor) { const loginEntity = monitor.value()?.now as LoginEntity; - EventReportGlobalManager.eventReport(EventConstants.LOGIN, 'weixin') + EventReportManager.eventReport(EventConstants.LOGIN, 'weixin') LoginManager.saveToken(loginEntity.token); LoginManager.saveLastLoginType('weixin') ConfigManager.userConfig() @@ -127,7 +127,7 @@ struct LoginPage { return; } this.viewModel.sendCode(this.phone); - EventReportGlobalManager.eventReport(EventConstants.GET_CODE, "code_login", this.phone) + EventReportManager.eventReport(EventConstants.GET_CODE, "code_login", this.phone) } toMainPage() { @@ -177,7 +177,7 @@ struct LoginPage { if (systemDateTime.getTime() - this.clickTime < 1500) { (this.getUIContext().getHostContext() as common.UIAbilityContext).terminateSelf(); } else { - EventReportGlobalManager.eventReport(EventConstants.EXIT_APP, 'login') + EventReportManager.eventReport(EventConstants.EXIT_APP, 'login') this.clickTime = systemDateTime.getTime(); ToastUtils.show('双击退出应用'); } diff --git a/entry/src/main/ets/pages/main/MainPage.ets b/entry/src/main/ets/pages/main/MainPage.ets index 03994f6..9d93662 100644 --- a/entry/src/main/ets/pages/main/MainPage.ets +++ b/entry/src/main/ets/pages/main/MainPage.ets @@ -11,7 +11,7 @@ import { SimpleTipDialog } from '../../dialog/SimpleTipDialog'; import { RouterUrls } from '../../common/RouterUrls'; import { TipDialog } from '../../dialog/TipDialog'; import { ConfigManager } from '../../manager/UserConfigManager'; -import { EventReportGlobalManager } from '../../manager/EventReportGlobalManager'; +import { EventReportManager } from '../../manager/EventReportManager'; import { PasteboardUtils } from '../../utils/PasteboardUtils'; import { MaterialPage } from './material/MaterialPage'; import { ToolsPage } from './mine/tool/ToolsPage'; @@ -133,7 +133,7 @@ struct MainPage { AppUtil.getContext().eventHub.emit(EventConstants.MineRefreshEvent); } this.showLoginTip(); - EventReportGlobalManager.eventReport(EventConstants.HOME_BOTTOM_TAB_CHECK, this.titles[index], '') + EventReportManager.eventReport(EventConstants.HOME_BOTTOM_TAB_CHECK, this.titles[index], '') }) .padding({ bottom: 20 }) .backgroundColor(Color.White) @@ -172,7 +172,7 @@ struct MainPage { if (systemDateTime.getTime() - this.clickTime < 1500) { AppUtil.getContext().terminateSelf(); } else { - EventReportGlobalManager.eventReport(EventConstants.EXIT_APP, 'main') + EventReportManager.eventReport(EventConstants.EXIT_APP, 'main') this.clickTime = systemDateTime.getTime(); ToastUtils.show('双击退出应用'); } diff --git a/entry/src/main/ets/pages/main/home/HomePage.ets b/entry/src/main/ets/pages/main/home/HomePage.ets index c9b1906..7345419 100644 --- a/entry/src/main/ets/pages/main/home/HomePage.ets +++ b/entry/src/main/ets/pages/main/home/HomePage.ets @@ -9,7 +9,7 @@ import { ConfigManager } from '../../../manager/UserConfigManager'; import { LoginManager } from '../../../manager/LoginGlobalManager'; import { RouterUrls } from '../../../common/RouterUrls'; import { TipDialog } from '../../../dialog/TipDialog'; -import { EventReportGlobalManager } from '../../../manager/EventReportGlobalManager'; +import { EventReportManager } from '../../../manager/EventReportManager'; import { Constants } from '../../../common/Constants'; import { MaterialEntity } from '../../../entity/MaterialEntity'; import { DownSamplingStrategy, ImageKnifeComponent, ImageKnifeOption } from '@ohos/imageknifepro'; @@ -139,7 +139,7 @@ export struct HomePage { case 'vip': { if (LoginManager.getUserInfo()?.vip !== 3) { this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIP_PAGE, params: {origin: 'banner'}}) - EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'banner') + EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'banner') } break; } @@ -253,7 +253,7 @@ export struct HomePage { .onClick(() => { // let info = AppUtil.getSignatureInfoSync() this.getUIContext().getRouter().pushUrl({url: RouterUrls.TAKE_MATERIAL_PAGE}) - EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_LINK_EXTRACT) + EventReportManager.eventReport(EventConstants.JUMP_TO_LINK_EXTRACT) }) Column() { @@ -281,7 +281,7 @@ export struct HomePage { .id('layout_wx_video') .onClick(() => { this.getUIContext().getRouter().pushUrl({url: RouterUrls.WX_VIDEO_PAGE, params: { isPlayback: false }}) - EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_WECHAT_VIDEO) + EventReportManager.eventReport(EventConstants.JUMP_TO_WECHAT_VIDEO) }) Column() { @@ -310,7 +310,7 @@ export struct HomePage { TipDialog.show(this.getUIContext(), {title: '提示', content: '仅限微信直播回放视频提取,是否前往?', callback: { confirm: () => { this.getUIContext().getRouter().pushUrl({url: RouterUrls.WX_VIDEO_PAGE, params: { isPlayback: true }}) - EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_WECHAT_PLAYBACK) + EventReportManager.eventReport(EventConstants.JUMP_TO_WECHAT_PLAYBACK) } }}) }) diff --git a/entry/src/main/ets/pages/main/home/link/TakeMaterialPage.ets b/entry/src/main/ets/pages/main/home/link/TakeMaterialPage.ets index d1c56bc..a181aa4 100644 --- a/entry/src/main/ets/pages/main/home/link/TakeMaterialPage.ets +++ b/entry/src/main/ets/pages/main/home/link/TakeMaterialPage.ets @@ -10,7 +10,7 @@ import { TextMaterial, VideoMaterial } from '../../../../entity/MaterialInfoEntity'; -import { VipPermissionEntity } from '../../../../entity/VipPermissionEntity'; +import { VipAuthEntity } from '../../../../entity/VipAuthEntity'; import { LoginManager } from '../../../../manager/LoginGlobalManager'; import { ToastUtils } from '../../../../utils/ToastUtils'; import { TakeMaterialViewModel } from '../../../../viewModel/TakeMaterialViewModel'; @@ -26,7 +26,7 @@ import { SaveUtils } from '../../../../utils/SaveUtils'; import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog'; import { EventConstants } from '../../../../common/EventConstants'; import { SimpleTipDialog } from '../../../../dialog/SimpleTipDialog'; -import { EventReportGlobalManager } from '../../../../manager/EventReportGlobalManager'; +import { EventReportManager } from '../../../../manager/EventReportManager'; import { PasteboardUtils } from '../../../../utils/PasteboardUtils'; import { TipDialog } from '../../../../dialog/TipDialog'; import { PrefUtils } from '../../../../utils/PrefUtils'; @@ -97,9 +97,9 @@ struct TakeMaterialPage { } } - @Monitor('viewModel.permissionInfo') + @Monitor('viewModel.authInfo') onPermissionInfoChange(monitor: IMonitor) { - const info = monitor.value()?.now as VipPermissionEntity; + const info = monitor.value()?.now as VipAuthEntity; if (info.auth) { if (!LoginManager.isLogin()) { this.getUIContext().getRouter().pushUrl({url: RouterUrls.LOGIN_PAGE, params: {from: 1}}, router.RouterMode.Single) @@ -109,7 +109,7 @@ struct TakeMaterialPage { } else { if (!info.auth_ad) { this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIP_PAGE, params: {origin: 'download_material'}}) - EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'download_material') + EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'download_material') return; } } @@ -120,7 +120,7 @@ struct TakeMaterialPage { const errorCode = monitor.value()?.now as number; if (errorCode === 12002 || errorCode === 12003 || errorCode === 12004) { this.getUIContext().getRouter().pushUrl({url: RouterUrls.RECHARGE_DIAMOND_PAGE}); - EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'download_material') + EventReportManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'download_material') ToastUtils.show('M币已用完') } } @@ -344,7 +344,7 @@ struct TakeMaterialPage { DownloadDialog.show(this.getUIContext(), { status: status, totalSize: 0, progress: 0, totalCount: this.selectedList.length, index: this.downloadIndex, callback: { confirm: () => { if (this.downloadStatus === DownloadStatus.COMPLETED) { - EventReportGlobalManager.eventReport(EventConstants.DIALOG_GO_TO_VIEW, this.titles[this.currentIndex]) + EventReportManager.eventReport(EventConstants.DIALOG_GO_TO_VIEW, this.titles[this.currentIndex]) AppUtil.getContext().eventHub.emit(EventConstants.JumpToRecordEvent, this.currentIndex) this.getUIContext().getRouter().back() } else { @@ -355,10 +355,10 @@ struct TakeMaterialPage { if (this.downloadStatus !== DownloadStatus.COMPLETED) { if (this.mediaDownloader) { this.mediaDownloader.cancel() - EventReportGlobalManager.eventReport(EventConstants.CANCEL_DOWNLOAD_VIDEO, this.selectedList[this.downloadIndex].url) + EventReportManager.eventReport(EventConstants.CANCEL_DOWNLOAD_VIDEO, this.selectedList[this.downloadIndex].url) } } else { - EventReportGlobalManager.eventReport(EventConstants.DIALOG_CONFIRM_SAVE_FILE, this.titles[this.currentIndex]) + EventReportManager.eventReport(EventConstants.DIALOG_CONFIRM_SAVE_FILE, this.titles[this.currentIndex]) } } } }) @@ -449,11 +449,11 @@ struct TakeMaterialPage { reportErrorEvent(media: MediaEntity, message: string) { if (media instanceof VideoMaterial) { - EventReportGlobalManager.eventReport(EventConstants.ERROR_CLIENT_DOWNLOAD_VIDEO, media.url, message) + EventReportManager.eventReport(EventConstants.ERROR_CLIENT_DOWNLOAD_VIDEO, media.url, message) } else if (media instanceof ImageMaterial) { - EventReportGlobalManager.eventReport(EventConstants.ERROR_CLIENT_DOWNLOAD_IMG, media.url, message) + EventReportManager.eventReport(EventConstants.ERROR_CLIENT_DOWNLOAD_IMG, media.url, message) } else if (media instanceof AudioMaterial) { - EventReportGlobalManager.eventReport(EventConstants.ERROR_CLIENT_DOWNLOAD_AUDIO, media.url, message) + EventReportManager.eventReport(EventConstants.ERROR_CLIENT_DOWNLOAD_AUDIO, media.url, message) } } @@ -501,7 +501,7 @@ struct TakeMaterialPage { .onClick(() => { if (StrUtil.isNotEmpty(this.inputText)) { this.parseUrl(this.inputText) - EventReportGlobalManager.eventReport(EventConstants.GET_MATERIAL, "material-button", this.inputText) + EventReportManager.eventReport(EventConstants.GET_MATERIAL, "material-button", this.inputText) } else { ToastUtils.show('请输入链接地址') } diff --git a/entry/src/main/ets/pages/main/home/material/MaterialDetailPage.ets b/entry/src/main/ets/pages/main/home/material/MaterialDetailPage.ets index 17d2b03..61f83b9 100644 --- a/entry/src/main/ets/pages/main/home/material/MaterialDetailPage.ets +++ b/entry/src/main/ets/pages/main/home/material/MaterialDetailPage.ets @@ -8,10 +8,10 @@ import { BusinessError, request, systemDateTime } from '@kit.BasicServicesKit'; import { ToastUtils } from '../../../../utils/ToastUtils'; import { SaveUtils } from '../../../../utils/SaveUtils'; import { AuthViewModel } from '../../../../viewModel/AuthViewModel'; -import { VipPermissionEntity } from '../../../../entity/VipPermissionEntity'; +import { VipAuthEntity } from '../../../../entity/VipAuthEntity'; import { LoginManager } from '../../../../manager/LoginGlobalManager'; import { RouterUrls } from '../../../../common/RouterUrls'; -import { EventReportGlobalManager } from '../../../../manager/EventReportGlobalManager'; +import { EventReportManager } from '../../../../manager/EventReportManager'; import { EventConstants } from '../../../../common/EventConstants'; import { LoadingDialog } from '../../../../dialog/LoadingDialog'; import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog'; @@ -27,9 +27,9 @@ struct MaterialDetailPage { private viewModel: AuthViewModel = new AuthViewModel(this.getUIContext()) private imageSize: media.PixelMapParams = {} - @Monitor('viewModel.permissionInfo') + @Monitor('viewModel.authInfo') onPermissionInfoChange(monitor: IMonitor) { - const info = monitor.value()?.now as VipPermissionEntity; + const info = monitor.value()?.now as VipAuthEntity; if (info.auth) { if (!LoginManager.isLogin()) { this.getUIContext().getRouter().pushUrl({url: RouterUrls.LOGIN_PAGE, params: {from: 1}}, router.RouterMode.Single) @@ -39,7 +39,7 @@ struct MaterialDetailPage { } else { if (!info.auth_ad) { this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIP_PAGE, params: {origin: 'download_material'}}) - EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'download_material') + EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'download_material') return; } } @@ -50,7 +50,7 @@ struct MaterialDetailPage { const errorCode = monitor.value()?.now as number; if (errorCode === 12002 || errorCode === 12003 || errorCode === 12004) { this.getUIContext().getRouter().pushUrl({url: RouterUrls.RECHARGE_DIAMOND_PAGE}); - EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'download_material') + EventReportManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'download_material') ToastUtils.show('M币已用完') } } diff --git a/entry/src/main/ets/pages/main/home/tools/AddAudioPage.ets b/entry/src/main/ets/pages/main/home/tools/AddAudioPage.ets deleted file mode 100644 index 0677cef..0000000 --- a/entry/src/main/ets/pages/main/home/tools/AddAudioPage.ets +++ /dev/null @@ -1,331 +0,0 @@ -import { PhotoHelper, PickerUtil } from '@pura/picker_utils' -import { TitleBar } from '../../../../view/TitleBar' -import { photoAccessHelper } from '@kit.MediaLibraryKit' -import { BusinessError, systemDateTime } from '@kit.BasicServicesKit' -import { AppUtil, FileUtil } from '@pura/harmony-utils' -import { ToastUtils } from '../../../../utils/ToastUtils' -import { fileIo, picker } from '@kit.CoreFileKit' -import { SaveUtils } from '../../../../utils/SaveUtils' -import { MP4Parser } from '@ohos/mp4parser' -import { LoadingDialog } from '../../../../dialog/LoadingDialog' -import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog' -import { EventConstants } from '../../../../common/EventConstants' -import { TipDialog } from '../../../../dialog/TipDialog' -import { avSessionManager } from '../../../../manager/AVSessionManager' - -@Entry -@ComponentV2 -struct AddAudioPage { - private controller: VideoController = new VideoController() - @Local videoUri?: string - @Local audioUri?: string - @Local currentTime: number = 0 - @Local durationTime: number = 0 - @Local isPlaying: boolean = false - @Local isSuccess: boolean = false - - mirrorVideo() { - LoadingDialog.show(this.getUIContext()) - this.isSuccess = false - let cacheVideoPath = FileUtil.getCacheDirPath() + FileUtil.separator + `cache_${systemDateTime.getTime()}.mp4` - if (FileUtil.accessSync(cacheVideoPath)) { - FileUtil.unlinkSync(cacheVideoPath) - } - let videoFile = FileUtil.openSync(this.videoUri!!, fileIo.OpenMode.READ_ONLY) - // 复制视频文件到缓存目录下 - FileUtil.copyFileSync(videoFile.fd, cacheVideoPath) - FileUtil.closeSync(videoFile) - - let cacheAudioPath = FileUtil.getCacheDirPath() + FileUtil.separator + `cache_${systemDateTime.getTime()}.mp3` - if (FileUtil.accessSync(cacheAudioPath)) { - FileUtil.unlinkSync(cacheAudioPath) - } - let audioFile = FileUtil.openSync(this.audioUri!!, fileIo.OpenMode.READ_ONLY) - // 复制音频文件到缓存目录下 - FileUtil.copyFileSync(audioFile.fd, cacheAudioPath) - FileUtil.closeSync(audioFile) - - let outputPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp4` - let cmd = `ffmpeg -i ${cacheVideoPath} -stream_loop -1 -i ${cacheAudioPath} -c:v copy -c:a aac -shortest -map 0:v -map 1:a ${outputPath}` - MP4Parser.ffmpegCmd(cmd, { - callBackResult: (code: number) => { - if (code === 0) { - this.videoUri = FileUtil.getUriFromPath(outputPath) - this.isSuccess = true - this.isPlaying = false - ToastUtils.show('处理成功') - } else { - ToastUtils.show('处理失败') - } - LoadingDialog.dismiss() - } - }) - } - - selectVideo() { - PhotoHelper.selectEasy({ - MIMEType: photoAccessHelper.PhotoViewMIMETypes.VIDEO_TYPE, - maxSelectNumber: 1, - isPhotoTakingSupported: false, - isEditSupported: false, - isOriginalSupported: false - }) - .then((uris) => { - if (uris.length != 0) { - this.isSuccess = false - this.videoUri = uris[0] - } - }) - } - - selectAudio() { - /*PickerUtil.selectAudio({maxSelectNumber: 1}) - .then((uris) => { - if (uris.length != 0) { - this.audioUri = uris[0] - } - })*/ - PickerUtil.selectDocument({maxSelectNumber: 1, fileSuffixFilters: ['.mp3']}) - .then((uris) => { - if (uris.length != 0) { - this.audioUri = uris[0] - } - }) - } - - showDownloadDialog() { - DownloadDialog.show(this.getUIContext(), { status: DownloadStatus.COMPLETED, totalSize: 0, progress: 0, totalCount: 1, index: 0, callback: { - confirm: () => { - AppUtil.getContext().eventHub.emit(EventConstants.JumpToRecordEvent, 0) - this.getUIContext().getRouter().back() - } - } }) - } - - formatTime(time: number): string { - let minute: number = 0 - let second: number = 0 - if (time > 60) { - minute = Math.trunc(time / 60) - second = time % 60 - if (minute < 10) { - if (second < 10) { - return `0${minute}:0${second}` - } else { - return `0${minute}:${second}` - } - } else { - if (second < 10) { - return `${minute}:0${second}` - } else { - return `${minute}:${second}` - } - } - } else { - second = time - if (second < 10) { - return `00:0${second}` - } else { - return `00:${second}` - } - } - } - - onBackPress(): boolean | void { - if (this.isSuccess) { - TipDialog.show(this.getUIContext(), {title:'温馨提示', content:'视频尚未保存,是否确定退出?', callback: { - confirm: () => { - this.getUIContext().getRouter().back() - } - }}) - return true - } - return false - } - - build() { - Column() { - TitleBar({ title: '加音乐' }) - - Column() { - Row() { - Text('上传视频').fontColor($r('app.color.color_90ffffff')).fontSize(16).fontWeight(FontWeight.Medium) - Text('(仅支持mp4格式)').fontColor($r('app.color.color_50ffffff')).fontSize(12) - }.alignSelf(ItemAlign.Start) - - RelativeContainer() { - Stack() { - Image($r('app.media.ic_add_video')).width(44).height(44) - } - .width(140) - .height(140) - .borderRadius(10) - .backgroundColor($r('app.color.color_333333')) - .alignRules({ - start: { anchor: '__container__', align: HorizontalAlign.Start }, - top: { anchor: '__container__', align: VerticalAlign.Top }, - end: { anchor: '__container__', align: HorizontalAlign.End }, - bottom: { anchor: '__container__', align: VerticalAlign.Bottom } - }) - .onClick(() => { - this.selectVideo() - }) - } - .height(220) - .margin({ top: 12 }) - .borderRadius(8) - .backgroundColor($r('app.color.color_222222')) - }.margin({ left: 16, top: 16, right: 16 }) - .visibility(this.videoUri ? Visibility.None : Visibility.Visible) - - Column() { - RelativeContainer() { - Video({ - src: this.videoUri, // 设置视频源 - controller: this.controller, //设置视频控制器,可以控制视频的播放状态 - posterOptions: { showFirstFrame: true } - }) - .width('100%') - .height('100%') - .backgroundColor($r('app.color.window_background')) - .controls(false) // 设置是否显示默认控制条 - .autoPlay(false) // 设置是否自动播放 - .loop(false) // 设置是否循环播放 - .objectFit(ImageFit.Contain) // 设置视频填充模式 - .onPrepared((event) => { - if (event) { - this.durationTime = event.duration - } - }) - .onUpdate((event) => { - if (event) { - this.currentTime = event.time - } - }) - .onStart(() => { - this.isPlaying = true - }) - .onPause(() => { - this.isPlaying = false - avSessionManager.deactivate() - }) - .onStop(() => { - this.isPlaying = false - avSessionManager.deactivate() - }) - .onFinish(() => { - this.isPlaying = false - avSessionManager.deactivate() - }) - .onError(() => { - this.isPlaying = false - avSessionManager.deactivate() - }) - .onDisAppear(() => { - avSessionManager.deactivate() - }) - - Image($r('app.media.ic_play_video')) - .width(50) - .height(50) - .visibility(this.isPlaying ? Visibility.None : Visibility.Visible) - .onClick(async () => { - await avSessionManager.activate() - this.controller.start() - }) - .alignRules({ - left: { anchor: '__container__', align: HorizontalAlign.Start }, - top: { anchor: '__container__', align: VerticalAlign.Top }, - right: { anchor: '__container__', align: HorizontalAlign.End }, - bottom: { anchor: '__container__', align: VerticalAlign.Bottom }, - }) - - Row() { - Image(this.isPlaying ? $r('app.media.ic_player_controls_pause') : $r('app.media.ic_player_controls_play')) - .width(20) - .height(20) - .margin({ right: 20 }) - .onClick(async () => { - if (this.isPlaying) { - this.controller.pause() - } else { - await avSessionManager.activate() - this.controller.start() - } - }) - Text(this.formatTime(this.currentTime)).width(35).fontColor(Color.White).fontSize(12) - Slider({ - value: this.currentTime, - min: 0, - max: this.durationTime - }) - .blockColor(Color.White) - .trackColor($r('app.color.color_60ffffff')) - .onChange((value: number, mode: SliderChangeMode) => { - this.controller.setCurrentTime(value); // 设置视频播放的进度跳转到value处 - }) - .layoutWeight(1) - Text(this.formatTime(this.durationTime)).width(35).fontColor(Color.White).fontSize(12) - } - .opacity(0.8) - .width("100%") - .padding({ left: 30, right: 30 }) - .alignRules({ - bottom: { anchor: '__container__', align: VerticalAlign.Bottom } - }) - } - .layoutWeight(1) - - Image($r('app.media.ic_add_audio')).width(50).height(50).margin({top: 20}) - .onClick(() => { - this.selectAudio() - }) - Text('音频').fontColor($r('app.color.color_90ffffff')).fontSize(14).margin({top: 10}) - - Row() { - Text(this.isSuccess ? '重新上传' : '取消').fontColor($r('app.color.color_90ffffff')).fontSize(17).margin({ left: 16 }) - .onClick(() => { - this.controller.stop() - if (this.isSuccess) { - this.selectVideo() - } else { - this.getUIContext().getRouter().back() - } - }) - Blank().layoutWeight(1) - Text(this.isSuccess ? '保存' : '确定').fontColor($r("app.color.color_466afd")).fontSize(17).margin({ right: 16 }) - .onClick(() => { - this.controller.stop() - if (this.isSuccess) { - SaveUtils.saveImageVideoToAlbumDialog([this.videoUri!!]) - .then((saved) => { - if (saved) { - this.videoUri = undefined - this.showDownloadDialog() - } else { - ToastUtils.show('保存失败') - } - }) - .catch((e: BusinessError) => { - ToastUtils.show('保存失败:' + e.message) - }) - - } else { - if (this.audioUri) { - this.mirrorVideo() - } else { - ToastUtils.show('请上传音频') - } - } - }) - } - .margin({ top: 50, bottom: 30 }) - } - .layoutWeight(1) - .visibility(this.videoUri ? Visibility.Visible : Visibility.None) - } - .width('100%') - .height('100%') - .backgroundColor($r('app.color.window_background')) - } -} \ No newline at end of file diff --git a/entry/src/main/ets/pages/main/home/tools/AddWatermarkPage.ets b/entry/src/main/ets/pages/main/home/tools/AddWatermarkPage.ets index 619734b..459962d 100644 --- a/entry/src/main/ets/pages/main/home/tools/AddWatermarkPage.ets +++ b/entry/src/main/ets/pages/main/home/tools/AddWatermarkPage.ets @@ -18,10 +18,21 @@ import { WaterMarkerView } from '../../../../view/WaterMarkerView' import { EditTextDialog } from '../../../../dialog/EditTextDialog' import { image } from '@kit.ImageKit' import { avSessionManager } from '../../../../manager/AVSessionManager' +import { AuthViewModel } from '../../../../viewModel/AuthViewModel' +import { LoginManager } from '../../../../manager/LoginGlobalManager' +import { VipAuthEntity } from '../../../../entity/VipAuthEntity' +import { RouterUrls } from '../../../../common/RouterUrls' +import { router } from '@kit.ArkUI' +import { EventReportManager } from '../../../../manager/EventReportManager' @Entry @ComponentV2 struct AddWatermarkPage { + private viewModel: AuthViewModel = new AuthViewModel(this.getUIContext()) + private controller: VideoController = new VideoController() + private videoSize: media.PixelMapParams = { width: 0, height: 0 } + private rect: RectPosition = { x: 0, y: 0, width: 0, height: 0 } + @Local uri?: string @Local currentTime: number = 0 @Local durationTime: number = 0 @@ -33,9 +44,49 @@ struct AddWatermarkPage { @Local textContent: string = '' @Local imagePath: string = '' - private controller: VideoController = new VideoController() - private videoSize: media.PixelMapParams = { width: 0, height: 0 } - private rect: RectPosition = { x: 0, y: 0, width: 0, height: 0 } + @Monitor('viewModel.authInfo') + onPermissionInfoChange(monitor: IMonitor) { + const info = monitor.value()?.now as VipAuthEntity; + if (info.auth) { + if (!LoginManager.isLogin()) { + this.getUIContext().getRouter().pushUrl({url: RouterUrls.LOGIN_PAGE, params: {from: 1}}, router.RouterMode.Single) + return; + } + this.doSave() + } else { + if (!info.auth_ad) { + this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIP_PAGE, params: {origin: 'addWatermark'}}) + EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'addWatermark') + return; + } + } + } + + @Monitor('viewModel.errorCode') + onErrorCodeChange(monitor: IMonitor) { + const errorCode = monitor.value()?.now as number; + if (errorCode === 12002 || errorCode === 12003 || errorCode === 12004) { + this.getUIContext().getRouter().pushUrl({url: RouterUrls.RECHARGE_DIAMOND_PAGE}); + EventReportManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'addWatermark') + ToastUtils.show('M币已用完') + } + } + + doSave() { + SaveUtils.saveImageVideoToAlbumDialog([this.uri!!]) + .then((saved) => { + if (saved) { + this.uri = undefined + this.isSuccess = false + this.showDownloadDialog() + } else { + ToastUtils.show('保存失败') + } + }) + .catch((e: BusinessError) => { + ToastUtils.show('保存失败:' + e.message) + }) + } addWatermark() { LoadingDialog.show(this.getUIContext()) @@ -430,18 +481,7 @@ struct AddWatermarkPage { .backgroundColor($r('app.color.color_466afd')) .onClick(() => { this.controller.stop() - SaveUtils.saveImageVideoToAlbumDialog([this.uri!!]) - .then((saved) => { - if (saved) { - this.uri = undefined - this.showDownloadDialog() - } else { - ToastUtils.show('保存失败') - } - }) - .catch((e: BusinessError) => { - ToastUtils.show('保存失败:' + e.message) - }) + this.viewModel.checkVip() }) } .visibility(this.isSuccess ? Visibility.Visible : Visibility.None) diff --git a/entry/src/main/ets/pages/main/home/tools/AudioToTextPage.ets b/entry/src/main/ets/pages/main/home/tools/AudioToTextPage.ets index 0d40db3..193d732 100644 --- a/entry/src/main/ets/pages/main/home/tools/AudioToTextPage.ets +++ b/entry/src/main/ets/pages/main/home/tools/AudioToTextPage.ets @@ -1,6 +1,427 @@ -@ComponentV2 +import { PickerUtil } from '@pura/picker_utils' +import { TitleBar } from '../../../../view/TitleBar' +import { BusinessError, systemDateTime } from '@kit.BasicServicesKit' +import { AppUtil, FileUtil, JSONUtil, PasteboardUtil } from '@pura/harmony-utils' +import { ToastUtils } from '../../../../utils/ToastUtils' +import { fileIo } from '@kit.CoreFileKit' +import { LoadingDialog } from '../../../../dialog/LoadingDialog' +import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog' +import { EventConstants } from '../../../../common/EventConstants' +import { TipDialog } from '../../../../dialog/TipDialog' +import { avSessionManager } from '../../../../manager/AVSessionManager' +import { MP4Parser } from '@ohos/mp4parser' +import { QCloud } from 'qcloudfileflash' +import { Constants } from '../../../../common/Constants' +import { VoiceRecognizeResultEntity } from '../../../../entity/VoiceRecognizeResultEntity' +import { AuthViewModel } from '../../../../viewModel/AuthViewModel' +import { VipAuthEntity } from '../../../../entity/VipAuthEntity' +import { LoginManager } from '../../../../manager/LoginGlobalManager' +import { RouterUrls } from '../../../../common/RouterUrls' +import { router } from '@kit.ArkUI' +import { EventReportManager } from '../../../../manager/EventReportManager' +import { ConfigManager } from '../../../../manager/UserConfigManager' +import { media } from '@kit.MediaKit' + @Entry +@ComponentV2 struct AudioToTextPage { + private viewModel: AuthViewModel = new AuthViewModel(this.getUIContext()) + private controller: VideoController = new VideoController() + private avPlayer?: media.AVPlayer = undefined + + @Local resultText?: string + @Local audioUri?: string + @Local currentTime: number = 0 + @Local durationTime: number = 0 + @Local isPlaying: boolean = false + @Local isSuccess: boolean = false + + @Monitor('viewModel.authInfo') + onPermissionInfoChange(monitor: IMonitor) { + const info = monitor.value()?.now as VipAuthEntity; + if (info.auth) { + if (!LoginManager.isLogin()) { + this.getUIContext().getRouter().pushUrl({url: RouterUrls.LOGIN_PAGE, params: {from: 1}}, router.RouterMode.Single) + return; + } + this.doSave() + } else { + if (!info.auth_ad) { + this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIP_PAGE, params: {origin: 'videoToText'}}) + EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'videoToText') + return; + } + } + } + + @Monitor('viewModel.errorCode') + onErrorCodeChange(monitor: IMonitor) { + const errorCode = monitor.value()?.now as number; + if (errorCode === 12002 || errorCode === 12003 || errorCode === 12004) { + this.getUIContext().getRouter().pushUrl({url: RouterUrls.RECHARGE_DIAMOND_PAGE}); + EventReportManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'videoToText') + ToastUtils.show('M币已用完') + } + } + + aboutToAppear(): void { + this.initPlayer() + } + + onPageHide(): void { + if (this.avPlayer) { + this.avPlayer.pause() + } + } + + aboutToDisappear(): void { + if (this.avPlayer) { + this.avPlayer.release() + } + } + + async initPlayer() { + this.avPlayer = await media.createAVPlayer(); + // 创建状态机变化回调函数 + this.setAVPlayerCallback(); + } + + doSave() { + if (this.resultText) { + PasteboardUtil.setDataTextSync(this.resultText) + this.isSuccess = false + ToastUtils.show('复制成功') + } + } + + copyAudio() { + LoadingDialog.show(this.getUIContext()) + this.isSuccess = false + let cachePath = FileUtil.getCacheDirPath() + FileUtil.separator + `cache_${systemDateTime.getTime()}.mp3` + if (FileUtil.accessSync(cachePath)) { + FileUtil.unlinkSync(cachePath) + } + let file = FileUtil.openSync(this.audioUri!!, fileIo.OpenMode.READ_ONLY) + // 复制文件到缓存目录下 + FileUtil.copyFileSync(file.fd, cachePath) + FileUtil.closeSync(file) + + this.recognizeAudio(cachePath) + .then((result) => { + if (result !== null) { + this.resultText = result.flash_result[0].text + this.isSuccess = true + this.isPlaying = false + ToastUtils.show('处理成功') + } else { + ToastUtils.show('处理失败') + } + LoadingDialog.dismiss() + }) + .catch((e: BusinessError) => { + console.log(e.message) + ToastUtils.show('处理失败') + LoadingDialog.dismiss() + }) + } + + async recognizeAudio(uri: string): Promise { + let builder = new QCloud.FileFlash.Builder() + builder.appID = Constants.QCLOUD_APP_ID + builder.secretID = Constants.QCLOUD_SECRET_ID + builder.secretKey = Constants.QCLOUD_SECRET_KEY + // builder.token = this._token + builder.setApiParam(QCloud.FileFlash.kEngineType, '16k_zh') + builder.setApiParam(QCloud.FileFlash.kVoiceFormat, 'mp3') + builder.setApiParam(QCloud.FileFlash.kFilterDirty, 0) + builder.setApiParam(QCloud.FileFlash.kFilterModal, 0) + builder.setApiParam(QCloud.FileFlash.kFilterPunc, 0) + builder.setApiParam(QCloud.FileFlash.kConvertNumMode, 1) + builder.setApiParam(QCloud.FileFlash.kWordInfo, 0) + builder.setApiParam(QCloud.FileFlash.kSpeakerDiarization, 1) + try { + let file = FileUtil.openSync(uri, fileIo.OpenMode.READ_ONLY) + const stat = FileUtil.lstatSync(uri) + const buffer = new ArrayBuffer(stat.size) + FileUtil.readSync(file.fd, buffer) + FileUtil.closeSync(file) + let result = await builder.build(buffer).task + let voiceResult = JSONUtil.jsonToBean(result, VoiceRecognizeResultEntity) + return Promise.resolve(voiceResult) + } catch (e) { + console.error(e) + return Promise.reject(e) + } + } + + selectAudio() { + PickerUtil.selectDocument({maxSelectNumber: 1, fileSuffixFilters: ['.mp3']}) + .then(async (uris) => { + if (uris.length != 0) { + this.isSuccess = false + this.audioUri = uris[0] + this.resultText = undefined + // 打开相应的资源文件地址获取fd + let file = await fileIo.open(this.audioUri) + this.avPlayer!!.url = 'fd://' + file.fd + } + }) + } + + showDownloadDialog() { + DownloadDialog.show(this.getUIContext(), { status: DownloadStatus.COMPLETED, totalSize: 0, progress: 0, totalCount: 1, index: 0, callback: { + confirm: () => { + AppUtil.getContext().eventHub.emit(EventConstants.JumpToRecordEvent, 0) + this.getUIContext().getRouter().back() + } + } }) + } + + // 注册avplayer回调函数 + setAVPlayerCallback() { + this.avPlayer!!.on('error', (err) => { + console.error(`播放器发生错误,错误码:${err.code}, 错误信息:${err.message}`); + // 调用reset重置资源,触发idle状态 + this.isPlaying = false + this.avPlayer!!.reset(); + avSessionManager.deactivate() + }) + // 状态机变化回调函数 + this.avPlayer!!.on('stateChange', async (state, reason) => { + switch (state) { + case 'initialized': + console.info('资源初始化完成'); + // 资源初始化完成,开始准备文件 + this.avPlayer!!.prepare(); + break; + case 'prepared': + console.info('资源准备完成'); + // 资源准备完成,开始准备文件 + this.durationTime = Math.trunc(this.avPlayer!!.duration / 1000) + this.currentTime = this.avPlayer!!.currentTime; + break; + case 'completed': + console.info('播放完成'); + this.isPlaying = false + this.avPlayer!!.off('bufferingUpdate') + AppStorage.setOrCreate('currentTime', this.durationTime); + avSessionManager.deactivate() + break; + case 'playing': + console.info('播放开始'); + this.isPlaying = true + break; + case 'released': + case 'stopped': + case 'error': + case 'paused': + console.info('播放暂停'); + this.isPlaying = false + avSessionManager.deactivate() + break; + } + }) + // 时间上报监听函数 + this.avPlayer!!.on('timeUpdate', (time: number) => { + this.currentTime = Math.trunc(time / 1000); + }); + } + + formatTime(time: number): string { + let minute: number = 0 + let second: number = 0 + if (time > 60) { + minute = Math.trunc(time / 60) + second = time % 60 + if (minute < 10) { + if (second < 10) { + return `0${minute}:0${second}` + } else { + return `0${minute}:${second}` + } + } else { + if (second < 10) { + return `${minute}:0${second}` + } else { + return `${minute}:${second}` + } + } + } else { + second = time + if (second < 10) { + return `00:0${second}` + } else { + return `00:${second}` + } + } + } + + onBackPress(): boolean | void { + if (this.isSuccess) { + TipDialog.show(this.getUIContext(), {title:'温馨提示', content:'文本尚未复制,是否确定退出?', callback: { + confirm: () => { + this.getUIContext().getRouter().back() + } + }}) + return true + } + return false + } + build() { + Column() { + TitleBar({ title: '语音转文字' }) + + Stack() { + Stack() { + Column() { + Image($r('app.media.ic_add_audio')).width(40).height(40) + Text('请上传音频').fontColor($r('app.color.color_466afd')).fontSize(15).fontWeight(FontWeight.Medium).margin({ top: 8}) + } + } + .width('100%') + .aspectRatio(1) + .borderRadius(20) + .backgroundColor(Color.White) + .shadow({radius: 10, color: '#1a9399a1'}) + .onClick(() => { + this.selectAudio() + }) + } + .width('100%') + .height('auto') + .padding({left: 32, right: 32}) + .margin({top: 40}) + .visibility(this.audioUri ? Visibility.None : Visibility.Visible) + + Row() { + Image(this.isPlaying ? $r('app.media.ic_audio_pause2') : $r('app.media.ic_audio_play2')) + .width(40) + .height(40) + .margin({ right: 16 }) + .onClick(async () => { + if (this.isPlaying) { + this.avPlayer!!.pause() + } else { + await avSessionManager.activate() + this.avPlayer!!.play() + } + }) + Text(this.formatTime(this.currentTime)).width(45).fontColor($r('app.color.color_999999')).fontSize(16) + Slider({ + value: this.currentTime, + min: 0, + max: this.durationTime + }) + .blockColor(Color.White) + .trackColor($r('app.color.color_eeeeee')) + .onChange((value: number, mode: SliderChangeMode) => { + this.avPlayer!!.seek(value * 1000, 2); // 设置视频播放的进度跳转到value处 + this.currentTime = value; + }) + .layoutWeight(1) + Text(this.formatTime(this.durationTime)).width(45).fontColor($r('app.color.color_999999')).fontSize(16) + } + .height(60) + .borderRadius(30) + .borderWidth(1) + .borderColor('#DADEE5') + .backgroundColor(Color.White) + .margin({left: 12, top: 40, right: 12}) + .padding({left: 16, right: 16}) + .visibility(this.audioUri ? Visibility.Visible : Visibility.None) + + Stack({alignContent: Alignment.Top}) { + Column() { + Row() { + Image($r('app.media.ic_star')).width(22).height(22) + Text('文本结果').fontColor($r('app.color.color_212226')).fontSize(15).fontWeight(FontWeight.Medium).margin({left: 4}) + } + Divider().strokeWidth(1).color($r('app.color.color_eeeeee')).margin({top: 12}) + Scroll() { + Text(this.resultText).width('100%').fontColor($r('app.color.color_212226')).fontSize(14).margin({top: 12}) + } + .layoutWeight(1) + .align(Alignment.TopStart) + .scrollBar(BarState.Off) + } + .width('100%') + .height('100%') + .alignItems(HorizontalAlign.Start) + .borderRadius(10) + .borderWidth(1) + .borderColor('#DADEE5') + .backgroundColor(Color.White) + .padding(12) + } + .layoutWeight(1) + .margin({top: 30, bottom: 20}) + .padding({left: 16, right: 16}) + .visibility(this.resultText ? Visibility.Visible : Visibility.None) + + Blank().layoutWeight(1).visibility(this.resultText ? Visibility.None : Visibility.Visible) + + Stack() { + Button('确认处理', { type: ButtonType.Capsule, stateEffect: true }) + .width('100%') + .height(46) + .fontColor(Color.White) + .fontSize(15) + .fontWeight(FontWeight.Medium) + .backgroundColor($r('app.color.color_466afd')) + .onClick(() => { + if (this.audioUri) { + this.copyAudio() + } else { + ToastUtils.show('请上传音频') + } + }) + .visibility(!this.resultText ? Visibility.Visible : Visibility.None) + + Row() { + Button({ type: ButtonType.Capsule, stateEffect: true }) { + Row() { + Image($r('app.media.ic_reupload')).width(20).height(20) + Text('重新上传').fontColor($r('app.color.color_466afd')).fontSize(15).fontWeight(FontWeight.Medium) + } + } + .height(46) + .layoutWeight(1) + .borderWidth(1) + .borderColor($r('app.color.color_466afd')) + .backgroundColor(Color.Transparent) + .onClick(() => { + this.controller.stop() + this.selectAudio() + }) + + Blank().width(9) + + Button({ type: ButtonType.Capsule, stateEffect: true }) { + Row() { + Image($r('app.media.ic_copy_text')).width(20).height(20) + Text('复制文本').fontColor(Color.White).fontSize(15).fontWeight(FontWeight.Medium) + } + } + .height(46) + .layoutWeight(1) + .backgroundColor($r('app.color.color_466afd')) + .onClick(() => { + this.controller.stop() + if (ConfigManager.isAiAuthEnable() && this.durationTime > 60) { + this.viewModel.checkVip() + } else { + this.doSave() + } + }) + } + .visibility(this.resultText ? Visibility.Visible : Visibility.None) + } + .padding({left: 16, top: 9, right: 16, bottom: 30 }) + .backgroundColor(Color.White) + } + .width('100%') + .height('100%') + .backgroundColor($r('app.color.window_background')) } } \ No newline at end of file diff --git a/entry/src/main/ets/pages/main/home/tools/ClipVideoPage.ets b/entry/src/main/ets/pages/main/home/tools/ClipVideoPage.ets deleted file mode 100644 index 3f9844c..0000000 --- a/entry/src/main/ets/pages/main/home/tools/ClipVideoPage.ets +++ /dev/null @@ -1,468 +0,0 @@ -import { PhotoHelper } from '@pura/picker_utils' -import { TitleBar } from '../../../../view/TitleBar' -import { photoAccessHelper } from '@kit.MediaLibraryKit' -import { BusinessError, systemDateTime } from '@kit.BasicServicesKit' -import { AppUtil, DisplayUtil, FileUtil } from '@pura/harmony-utils' -import { ToastUtils } from '../../../../utils/ToastUtils' -import { fileIo } from '@kit.CoreFileKit' -import { SaveUtils } from '../../../../utils/SaveUtils' -import { LoadingDialog } from '../../../../dialog/LoadingDialog' -import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog' -import { EventConstants } from '../../../../common/EventConstants' -import { RectCropView, RectPosition } from '../../../../view/RectCropView' -import { media } from '@kit.MediaKit' -import { MediaUtils } from '../../../../utils/MediaUtils' -import { MP4Parser } from '@ohos/mp4parser' -import { TipDialog } from '../../../../dialog/TipDialog' -import { avSessionManager } from '../../../../manager/AVSessionManager' - -@Entry -@ComponentV2 -struct ClipVideoPage { - @Local uri?: string - @Local currentTime: number = 0 - @Local durationTime: number = 0 - @Local isPlaying: boolean = false - @Local isSuccess: boolean = false - @Local playerSize: media.PixelMapParams = { width: 0, height: 0 } - @Local currentIndex: number = 0 - - private controller: VideoController = new VideoController() - private rectArray : Array = ['自由', '1:1', '4:3', '3:4', '16:9', '9:16'] - private videoSize: media.PixelMapParams = { width: 0, height: 0 } - private rect: RectPosition = { x: 0, y: 0, width: 0, height: 0 } - - clipVideo() { - LoadingDialog.show(this.getUIContext()) - this.isSuccess = false - let cacheVideoPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp4` - if (FileUtil.accessSync(cacheVideoPath)) { - FileUtil.unlinkSync(cacheVideoPath) - } - - let file = FileUtil.openSync(this.uri!!, fileIo.OpenMode.READ_ONLY) - // 复制文件到缓存目录下 - FileUtil.copyFileSync(file.fd, cacheVideoPath) - FileUtil.closeSync(file) - - let clipWidth: number = 0 - let clipHeight: number = 0 - if (this.currentIndex === 0) { - clipWidth = (vp2px(this.rect.width * this.videoSize.width!!) / this.playerSize.width!!) - clipHeight = (vp2px(this.rect.height * this.videoSize.height!!) / this.playerSize.height!!) - } else { - const ratio = (DisplayUtil.getWidth() - 180) / this.videoSize.width!! - let originPlayerSize: media.PixelMapParams = {width: Math.ceil(this.videoSize.width!! * ratio), height: Math.ceil(this.videoSize.height!! * ratio)} - clipWidth = (this.playerSize.width!! * this.videoSize.width!!) / originPlayerSize.width!! - clipHeight = (this.playerSize.height!! * this.videoSize.height!!) / originPlayerSize.height!! - } - - let clipX: number = 0 - let clipY: number = 0 - if (this.currentIndex === 0) { - clipX = (vp2px(this.rect.x) * this.videoSize.width!!) / this.playerSize.width!! - clipY = (vp2px(this.rect.y) * this.videoSize.width!!) / this.playerSize.height!! - } else { - const ratio = (DisplayUtil.getWidth() - 180) / this.videoSize.width!! - let originPlayerSize: media.PixelMapParams = {width: Math.ceil(this.videoSize.width!! * ratio), height: Math.ceil(this.videoSize.height!! * ratio)} - clipX = clipWidth === originPlayerSize.width ? 0 : (originPlayerSize.width!! - this.playerSize.width!!) / 2 * (this.videoSize.width!!) / originPlayerSize.width!! - clipY = clipHeight === originPlayerSize.height ? 0 : (originPlayerSize.height!! - this.playerSize.height!!) / 2 * (this.videoSize.height!!) / originPlayerSize.height!! - } - - let outputPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp4` - let cmd = `ffmpeg -i ${cacheVideoPath} -vf \"crop=${Math.ceil(clipWidth)}:${Math.ceil(clipHeight)}:${Math.ceil(clipX)}:${Math.ceil(clipY)}\" -c:v h264 -pix_fmt yuv420p -y ${outputPath}` - MP4Parser.ffmpegCmd(cmd, { - callBackResult: (code: number) => { - if (code === 0) { - this.uri = FileUtil.getUriFromPath(outputPath) - MediaUtils.getVideoSize(this.uri) - .then((size) => { - this.videoSize = size - if (size.width && size.height) { - const ratio = (DisplayUtil.getWidth() - 180) / size.width - this.playerSize = {width: Math.ceil(size.width * ratio), height: Math.ceil(size.height * ratio)} - } - }) - this.isSuccess = true - this.isPlaying = false - ToastUtils.show('处理成功') - } else { - ToastUtils.show('处理失败') - } - LoadingDialog.dismiss() - } - }) - } - - setVideoRatio() { - if (this.videoSize.width && this.videoSize.height) { - const ratio = (DisplayUtil.getWidth() - 180) / this.videoSize.width - let originPlayerSize: media.PixelMapParams = {width: Math.ceil(this.videoSize.width * ratio), height: Math.ceil(this.videoSize.height * ratio)} - - if (originPlayerSize.width && originPlayerSize.height) { - switch (this.currentIndex) { - case 0: { - this.playerSize = originPlayerSize - break - } - - case 1: { - if (originPlayerSize.width >= originPlayerSize.height) { - this.playerSize = {width: originPlayerSize.height, height: originPlayerSize.height} - } else { - this.playerSize = {width: originPlayerSize.width, height: originPlayerSize.width} - } - break - } - - case 2: { - if (originPlayerSize.width / originPlayerSize.height >= 4 / 3) { - this.playerSize = {width: Math.ceil((originPlayerSize.height!!) / 3 * 4), height: originPlayerSize.height} - } else { - this.playerSize = {width: originPlayerSize.width, height: Math.ceil((originPlayerSize.width!!) / 4 * 3)} - } - break - } - - case 3: { - if (originPlayerSize.width / originPlayerSize.height <= 3 / 4) { - this.playerSize = {width: originPlayerSize.width, height: Math.ceil((originPlayerSize.width!!) / 3 * 4)} - } else { - this.playerSize = {width: Math.ceil((originPlayerSize.height!!) / 4 * 3), height: originPlayerSize.height} - } - break - } - - case 4: { - if (originPlayerSize.width / originPlayerSize.height >= 16 / 9) { - this.playerSize = {width: Math.ceil((originPlayerSize.height!!) / 9 * 16), height: originPlayerSize.height} - } else { - this.playerSize = {width: originPlayerSize.width, height: Math.ceil((originPlayerSize.width!!) / 16 * 9)} - } - break - } - - case 5: { - if (originPlayerSize.width / originPlayerSize.height <= 9 / 16) { - this.playerSize = {width: originPlayerSize.width, height: Math.ceil((originPlayerSize.width!!) / 9 * 16)} - } else { - this.playerSize = {width: Math.ceil((originPlayerSize.height!!) / 16 * 9), height: originPlayerSize.height} - } - break - } - } - } - } - } - - selectVideo() { - PhotoHelper.selectEasy({ - MIMEType: photoAccessHelper.PhotoViewMIMETypes.VIDEO_TYPE, - maxSelectNumber: 1, - isPhotoTakingSupported: false, - isEditSupported: false, - isOriginalSupported: false - }) - .then((uris) => { - if (uris.length != 0) { - this.isSuccess = false - this.uri = uris[0] - this.currentIndex = 0 - - MediaUtils.getVideoSize(this.uri) - .then((size) => { - this.videoSize = size - if (size.width && size.height) { - const ratio = (DisplayUtil.getWidth() - 180) / size.width - this.playerSize = {width: Math.ceil(size.width * ratio), height: Math.ceil(size.height * ratio)} - } - }) - } - }) - } - - showDownloadDialog() { - DownloadDialog.show(this.getUIContext(), { - status: DownloadStatus.COMPLETED, - totalSize: 0, - progress: 0, - totalCount: 1, - index: 0, - callback: { - confirm: () => { - AppUtil.getContext().eventHub.emit(EventConstants.JumpToRecordEvent, 0) - this.getUIContext().getRouter().back() - } - } - }) - } - - formatTime(time: number): string { - let minute: number = 0 - let second: number = 0 - if (time > 60) { - minute = Math.trunc(time / 60) - second = time % 60 - if (minute < 10) { - if (second < 10) { - return `0${minute}:0${second}` - } else { - return `0${minute}:${second}` - } - } else { - if (second < 10) { - return `${minute}:0${second}` - } else { - return `${minute}:${second}` - } - } - } else { - second = time - if (second < 10) { - return `00:0${second}` - } else { - return `00:${second}` - } - } - } - - onBackPress(): boolean | void { - if (this.isSuccess) { - TipDialog.show(this.getUIContext(), {title:'温馨提示', content:'视频尚未保存,是否确定退出?', callback: { - confirm: () => { - this.getUIContext().getRouter().back() - } - }}) - return true - } - return false - } - - build() { - Column() { - TitleBar({ title: '视频裁剪' }) - - Column() { - Row() { - Text('上传视频').fontColor($r('app.color.color_90ffffff')).fontSize(16).fontWeight(FontWeight.Medium) - Text('(仅支持mp4格式)').fontColor($r('app.color.color_50ffffff')).fontSize(12) - }.alignSelf(ItemAlign.Start) - - RelativeContainer() { - Stack() { - Image($r('app.media.ic_add_video')).width(44).height(44) - } - .width(140) - .height(140) - .borderRadius(10) - .backgroundColor($r('app.color.color_333333')) - .alignRules({ - start: { anchor: '__container__', align: HorizontalAlign.Start }, - top: { anchor: '__container__', align: VerticalAlign.Top }, - end: { anchor: '__container__', align: HorizontalAlign.End }, - bottom: { anchor: '__container__', align: VerticalAlign.Bottom } - }) - .onClick(() => { - this.selectVideo() - }) - } - .height(220) - .margin({ top: 12 }) - .borderRadius(8) - .backgroundColor($r('app.color.color_222222')) - }.margin({ left: 16, top: 16, right: 16 }) - .visibility(this.uri ? Visibility.None : Visibility.Visible) - - Column() { - RelativeContainer() { - Video({ - src: this.uri, // 设置视频源 - controller: this.controller, //设置视频控制器,可以控制视频的播放状态 - posterOptions: { showFirstFrame: true } - }) - .id('video') - .width(this.playerSize ? px2vp(this.playerSize.width) : '100%') - .height(this.playerSize ? px2vp(this.playerSize.height) : '100%') - .backgroundColor($r('app.color.window_background')) - .controls(false) // 设置是否显示默认控制条 - .autoPlay(false) // 设置是否自动播放 - .loop(false) // 设置是否循环播放 - .objectFit(ImageFit.Cover) // 设置视频填充模式 - .alignRules({ - left: { anchor: '__container__', align: HorizontalAlign.Start }, - top: { anchor: '__container__', align: VerticalAlign.Top }, - right: { anchor: '__container__', align: HorizontalAlign.End }, - bottom: { anchor: '__container__', align: VerticalAlign.Bottom } - }) - .onPrepared((event) => { - if (event) { - this.durationTime = event.duration - } - }) - .onUpdate((event) => { - if (event) { - this.currentTime = event.time - } - }) - .onStart(() => { - this.isPlaying = true - }) - .onPause(() => { - this.isPlaying = false - avSessionManager.deactivate() - }) - .onStop(() => { - this.isPlaying = false - avSessionManager.deactivate() - }) - .onFinish(() => { - this.isPlaying = false - avSessionManager.deactivate() - }) - .onError(() => { - this.isPlaying = false - avSessionManager.deactivate() - }) - .onDisAppear(() => { - avSessionManager.deactivate() - }) - - Image($r('app.media.ic_play_video')) - .width(50) - .height(50) - .visibility(this.isPlaying ? Visibility.None : Visibility.Visible) - .onClick(async () => { - await avSessionManager.activate() - this.controller.start() - }) - .alignRules({ - left: { anchor: 'video', align: HorizontalAlign.Start }, - top: { anchor: 'video', align: VerticalAlign.Top }, - right: { anchor: 'video', align: HorizontalAlign.End }, - bottom: { anchor: 'video', align: VerticalAlign.Bottom } - }) - - Row() { - Image(this.isPlaying ? $r('app.media.ic_player_controls_pause') : $r('app.media.ic_player_controls_play')) - .width(20) - .height(20) - .margin({ right: 20 }) - .onClick(async () => { - if (this.isPlaying) { - this.controller.pause() - } else { - await avSessionManager.activate() - this.controller.start() - } - }) - Text(this.formatTime(this.currentTime)).width(35).fontColor(Color.White).fontSize(12) - Slider({ - value: this.currentTime, - min: 0, - max: this.durationTime - }) - .blockColor(Color.White) - .trackColor($r('app.color.color_60ffffff')) - .onChange((value: number, mode: SliderChangeMode) => { - this.controller.setCurrentTime(value); // 设置视频播放的进度跳转到value处 - }) - .layoutWeight(1) - Text(this.formatTime(this.durationTime)).width(35).fontColor(Color.White).fontSize(12) - } - .opacity(0.8) - .width(this.playerSize ? px2vp(this.playerSize.width) : "100%") - .alignRules({ - left: { anchor: 'video', align: HorizontalAlign.Start }, - right: { anchor: 'video', align: HorizontalAlign.End }, - bottom: { anchor: 'video', align: VerticalAlign.Bottom } - }) - - RectCropView({ - onRectChange: (rect) => { - this.rect = rect - } - }) - .width(this.playerSize ? px2vp(this.playerSize.width) : '100%') - .height(this.playerSize ? px2vp(this.playerSize.height) : '100%') - .alignRules({ - left: { anchor: 'video', align: HorizontalAlign.Start }, - top: { anchor: 'video', align: VerticalAlign.Top }, - right: { anchor: 'video', align: HorizontalAlign.End }, - bottom: { anchor: 'video', align: VerticalAlign.Bottom } - }) - .visibility(this.uri && this.currentIndex === 0 && !this.isSuccess ? Visibility.Visible : Visibility.None) - } - .layoutWeight(1) - - Grid() { - ForEach(this.rectArray, (item: string, index) => { - GridItem() { - Text(item).width(50).height(50) - .textAlign(TextAlign.Center) - .fontColor(Color.White) - .borderRadius(4) - .borderWidth(1.5) - .borderColor(this.currentIndex === index ? '#D33952' : Color.Transparent) - .backgroundColor('#282828') - .onClick(() => { - this.currentIndex = index - this.controller.stop() - this.setVideoRatio() - }) - } - .width('100%') - }) - } - .height(50) - .columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr') - .layoutDirection(GridDirection.Row) - .visibility(this.uri && !this.isSuccess ? Visibility.Visible : Visibility.None) - - Row() { - Text(this.isSuccess ? '重新上传' : '取消').fontColor($r('app.color.color_90ffffff')) - .fontSize(17) - .margin({ left: 16 }) - .onClick(() => { - this.controller.stop() - if (this.isSuccess) { - this.selectVideo() - } else { - this.getUIContext().getRouter().back() - } - }) - Blank().layoutWeight(1) - Text(this.isSuccess ? '保存' : '确定') - .fontColor($r("app.color.color_466afd")) - .fontSize(17) - .margin({ right: 16 }) - .onClick(() => { - this.controller.stop() - if (this.isSuccess) { - SaveUtils.saveImageVideoToAlbumDialog([this.uri!!]) - .then((saved) => { - if (saved) { - this.uri = undefined - this.showDownloadDialog() - } else { - ToastUtils.show('保存失败') - } - }) - .catch((e: BusinessError) => { - ToastUtils.show('保存失败:' + e.message) - }) - - } else { - this.clipVideo() - } - }) - } - .margin({ top: 20, bottom: 30 }) - } - .layoutWeight(1) - .visibility(this.uri ? Visibility.Visible : Visibility.None) - } - .width('100%') - .height('100%') - .backgroundColor($r('app.color.window_background')) - } -} \ No newline at end of file diff --git a/entry/src/main/ets/pages/main/home/tools/ImageMergePage.ets b/entry/src/main/ets/pages/main/home/tools/ImageMergePage.ets index 80cc73b..b94018d 100644 --- a/entry/src/main/ets/pages/main/home/tools/ImageMergePage.ets +++ b/entry/src/main/ets/pages/main/home/tools/ImageMergePage.ets @@ -13,16 +13,70 @@ import { TipDialog } from '../../../../dialog/TipDialog' import { image } from '@kit.ImageKit' import { ImageUtils } from '../../../../utils/ImageUtils' import { Luban } from '@ark/luban' +import { AuthViewModel } from '../../../../viewModel/AuthViewModel' +import { VipAuthEntity } from '../../../../entity/VipAuthEntity' +import { LoginManager } from '../../../../manager/LoginGlobalManager' +import { RouterUrls } from '../../../../common/RouterUrls' +import { router } from '@kit.ArkUI' +import { EventReportManager } from '../../../../manager/EventReportManager' @Entry @ComponentV2 struct ImageMergePage { + private viewModel: AuthViewModel = new AuthViewModel(this.getUIContext()) + private selectedImages: Array = [] + @Local pixelMap?: image.PixelMap = undefined @Local selectedImage?: string = undefined @Local imageUris: Array = [] @Local isSuccess: boolean = false - private selectedImages: Array = [] + @Monitor('viewModel.authInfo') + onPermissionInfoChange(monitor: IMonitor) { + const info = monitor.value()?.now as VipAuthEntity; + if (info.auth) { + if (!LoginManager.isLogin()) { + this.getUIContext().getRouter().pushUrl({url: RouterUrls.LOGIN_PAGE, params: {from: 1}}, router.RouterMode.Single) + return; + } + this.doSave() + } else { + if (!info.auth_ad) { + this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIP_PAGE, params: {origin: 'imageMerge'}}) + EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'imageMerge') + return; + } + } + } + + @Monitor('viewModel.errorCode') + onErrorCodeChange(monitor: IMonitor) { + const errorCode = monitor.value()?.now as number; + if (errorCode === 12002 || errorCode === 12003 || errorCode === 12004) { + this.getUIContext().getRouter().pushUrl({url: RouterUrls.RECHARGE_DIAMOND_PAGE}); + EventReportManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'imageMerge') + ToastUtils.show('M币已用完') + } + } + + doSave() { + SaveUtils.savePixelMapToAlbum(this.pixelMap!!) + .then((saved) => { + if (saved) { + this.pixelMap = undefined + this.selectedImage = undefined + this.imageUris = [] + this.selectedImages = [] + this.isSuccess = false + this.showDownloadDialog() + } else { + ToastUtils.show('保存失败') + } + }) + .catch((e: BusinessError) => { + ToastUtils.show('保存失败:' + e.message) + }) + } async mergeImage() { LoadingDialog.show(this.getUIContext()) @@ -293,21 +347,7 @@ struct ImageMergePage { .layoutWeight(1) .backgroundColor($r('app.color.color_466afd')) .onClick(() => { - SaveUtils.savePixelMapToAlbum(this.pixelMap!!) - .then((saved) => { - if (saved) { - this.pixelMap = undefined - this.selectedImage = undefined - this.imageUris = [] - this.selectedImages = [] - this.showDownloadDialog() - } else { - ToastUtils.show('保存失败') - } - }) - .catch((e: BusinessError) => { - ToastUtils.show('保存失败:' + e.message) - }) + this.viewModel.checkVip() }) } .visibility(this.isSuccess ? Visibility.Visible : Visibility.None) diff --git a/entry/src/main/ets/pages/main/home/tools/MD5ResetPage.ets b/entry/src/main/ets/pages/main/home/tools/MD5ResetPage.ets index e76d08d..bbff3ec 100644 --- a/entry/src/main/ets/pages/main/home/tools/MD5ResetPage.ets +++ b/entry/src/main/ets/pages/main/home/tools/MD5ResetPage.ets @@ -2,26 +2,84 @@ import { PhotoHelper } from '@pura/picker_utils' import { TitleBar } from '../../../../view/TitleBar' import { photoAccessHelper } from '@kit.MediaLibraryKit' import { BusinessError, systemDateTime } from '@kit.BasicServicesKit' -import { AppUtil, FileUtil } from '@pura/harmony-utils' +import { AppUtil, FileUtil, MD5 } from '@pura/harmony-utils' import { ToastUtils } from '../../../../utils/ToastUtils' -import { fileIo } from '@kit.CoreFileKit' +import { fileIo, ReadOptions } from '@kit.CoreFileKit' import { SaveUtils } from '../../../../utils/SaveUtils' import { LoadingDialog } from '../../../../dialog/LoadingDialog' import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog' import { EventConstants } from '../../../../common/EventConstants' import { TipDialog } from '../../../../dialog/TipDialog' import { avSessionManager } from '../../../../manager/AVSessionManager' +import { AuthViewModel } from '../../../../viewModel/AuthViewModel' +import { VipAuthEntity as VipAuthEntity } from '../../../../entity/VipAuthEntity' +import { LoginManager } from '../../../../manager/LoginGlobalManager' +import { RouterUrls } from '../../../../common/RouterUrls' +import { router } from '@kit.ArkUI' +import { EventReportManager } from '../../../../manager/EventReportManager' +import { cryptoFramework } from '@kit.CryptoArchitectureKit' +import { buffer } from '@kit.ArkTS' @Entry @ComponentV2 struct MD5ResetPage { + private viewModel: AuthViewModel = new AuthViewModel(this.getUIContext()) private controller: VideoController = new VideoController() + + @Local oldMd5?: string + @Local newMd5?: string @Local uri?: string @Local currentTime: number = 0 @Local durationTime: number = 0 @Local isPlaying: boolean = false @Local isSuccess: boolean = false + @Monitor('viewModel.authInfo') + onPermissionInfoChange(monitor: IMonitor) { + const info = monitor.value()?.now as VipAuthEntity; + if (info.auth) { + if (!LoginManager.isLogin()) { + this.getUIContext().getRouter().pushUrl({url: RouterUrls.LOGIN_PAGE, params: {from: 1}}, router.RouterMode.Single) + return; + } + this.doSave() + } else { + if (!info.auth_ad) { + this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIP_PAGE, params: {origin: 'md5Reset'}}) + EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'md5Reset') + return; + } + } + } + + @Monitor('viewModel.errorCode') + onErrorCodeChange(monitor: IMonitor) { + const errorCode = monitor.value()?.now as number; + if (errorCode === 12002 || errorCode === 12003 || errorCode === 12004) { + this.getUIContext().getRouter().pushUrl({url: RouterUrls.RECHARGE_DIAMOND_PAGE}); + EventReportManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'md5Reset') + ToastUtils.show('M币已用完') + } + } + + doSave() { + SaveUtils.saveImageVideoToAlbumDialog([this.uri!!]) + .then((saved) => { + if (saved) { + this.uri = undefined + this.oldMd5 = undefined + this.newMd5 = undefined + this.isSuccess = false + this.showDownloadDialog() + } else { + ToastUtils.show('保存失败') + } + }) + .catch((e: BusinessError) => { + ToastUtils.show('保存失败:' + e.message) + }) + } + modifyMD5() { LoadingDialog.show(this.getUIContext()) this.isSuccess = false @@ -35,10 +93,16 @@ struct MD5ResetPage { FileUtil.copyFileSync(file.fd, outputPath) FileUtil.closeSync(file) + //在新文件追加空格 + let newFile = FileUtil.openSync(outputPath, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.APPEND) + FileUtil.writeSync(newFile.fd, buffer.from(' ').buffer) + FileUtil.closeSync(newFile) + if (FileUtil.accessSync(outputPath)) { this.uri = FileUtil.getUriFromPath(outputPath) this.isSuccess = true this.isPlaying = false + this.newMd5 = this.fileMD5(outputPath) ToastUtils.show('处理成功') } else { ToastUtils.show('处理失败') @@ -58,10 +122,40 @@ struct MD5ResetPage { if (uris.length != 0) { this.isSuccess = false this.uri = uris[0] + this.oldMd5 = this.fileMD5(this.uri) + this.newMd5 = undefined } }) } + /** + * 获取文件的MD5值 + */ + fileMD5(uri: string): string { + // 定义摘要类型 + let md = cryptoFramework.createMd('MD5'); + // 打开文件 + let file = fileIo.openSync(uri, fileIo.OpenMode.READ_ONLY); + let fileBufferSize = 4096; + let readSize = 0; + let fileBuffer = new ArrayBuffer(fileBufferSize); + let readOptions: ReadOptions = { + offset: readSize, + length: fileBufferSize + }; + let readLength = fileIo.readSync(file.fd, fileBuffer, readOptions); + while (readLength > 0) { + // 更新摘要数据 + md.updateSync({ data: new Uint8Array(fileBuffer.slice(0, readLength)) }); + readSize += readLength; + readOptions.offset = readSize; + readLength = fileIo.readSync(file.fd, fileBuffer, readOptions); + } + // 计算摘要 + let mdResult = md.digestSync(); + return buffer.from(mdResult.data).toString('hex'); +} + showDownloadDialog() { DownloadDialog.show(this.getUIContext(), { status: DownloadStatus.COMPLETED, totalSize: 0, progress: 0, totalCount: 1, index: 0, callback: { confirm: () => { @@ -244,6 +338,20 @@ struct MD5ResetPage { .padding({left: 32, right: 32}) .margin({top: 40}) + Text('旧-MD5:' + this.oldMd5) + .textAlign(TextAlign.Center) + .fontColor($r('app.color.color_212226')) + .fontSize(15) + .margin({top: 30}) + .visibility(this.oldMd5 ? Visibility.Visible : Visibility.None) + + Text('新-MD5:' + this.newMd5) + .textAlign(TextAlign.Center) + .fontColor($r('app.color.color_212226')) + .fontSize(15) + .margin({top: 15}) + .visibility(this.newMd5 ? Visibility.Visible : Visibility.None) + Blank().layoutWeight(1) Stack() { @@ -293,18 +401,7 @@ struct MD5ResetPage { .backgroundColor($r('app.color.color_466afd')) .onClick(() => { this.controller.stop() - SaveUtils.saveImageVideoToAlbumDialog([this.uri!!]) - .then((saved) => { - if (saved) { - this.uri = undefined - this.showDownloadDialog() - } else { - ToastUtils.show('保存失败') - } - }) - .catch((e: BusinessError) => { - ToastUtils.show('保存失败:' + e.message) - }) + this.viewModel.checkVip() }) } .visibility(this.isSuccess ? Visibility.Visible : Visibility.None) diff --git a/entry/src/main/ets/pages/main/home/tools/RemoveAudioPage.ets b/entry/src/main/ets/pages/main/home/tools/RemoveAudioPage.ets index 78d8a14..15135b7 100644 --- a/entry/src/main/ets/pages/main/home/tools/RemoveAudioPage.ets +++ b/entry/src/main/ets/pages/main/home/tools/RemoveAudioPage.ets @@ -12,17 +12,69 @@ import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialo import { EventConstants } from '../../../../common/EventConstants' import { TipDialog } from '../../../../dialog/TipDialog' import { avSessionManager } from '../../../../manager/AVSessionManager' +import { AuthViewModel } from '../../../../viewModel/AuthViewModel' +import { VipAuthEntity } from '../../../../entity/VipAuthEntity' +import { LoginManager } from '../../../../manager/LoginGlobalManager' +import { RouterUrls } from '../../../../common/RouterUrls' +import { router } from '@kit.ArkUI' +import { EventReportManager } from '../../../../manager/EventReportManager' @Entry @ComponentV2 struct RemoveAudioPage { + private viewModel: AuthViewModel = new AuthViewModel(this.getUIContext()) private controller: VideoController = new VideoController() + @Local uri?: string @Local currentTime: number = 0 @Local durationTime: number = 0 @Local isPlaying: boolean = false @Local isSuccess: boolean = false + @Monitor('viewModel.authInfo') + onPermissionInfoChange(monitor: IMonitor) { + const info = monitor.value()?.now as VipAuthEntity; + if (info.auth) { + if (!LoginManager.isLogin()) { + this.getUIContext().getRouter().pushUrl({url: RouterUrls.LOGIN_PAGE, params: {from: 1}}, router.RouterMode.Single) + return; + } + this.doSave() + } else { + if (!info.auth_ad) { + this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIP_PAGE, params: {origin: 'removeAudio'}}) + EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'removeAudio') + return; + } + } + } + + @Monitor('viewModel.errorCode') + onErrorCodeChange(monitor: IMonitor) { + const errorCode = monitor.value()?.now as number; + if (errorCode === 12002 || errorCode === 12003 || errorCode === 12004) { + this.getUIContext().getRouter().pushUrl({url: RouterUrls.RECHARGE_DIAMOND_PAGE}); + EventReportManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'removeAudio') + ToastUtils.show('M币已用完') + } + } + + doSave() { + SaveUtils.saveImageVideoToAlbumDialog([this.uri!!]) + .then((saved) => { + if (saved) { + this.uri = undefined + this.isSuccess = false + this.showDownloadDialog() + } else { + ToastUtils.show('保存失败') + } + }) + .catch((e: BusinessError) => { + ToastUtils.show('保存失败:' + e.message) + }) + } + removeAudio() { LoadingDialog.show(this.getUIContext()) this.isSuccess = false @@ -299,18 +351,7 @@ struct RemoveAudioPage { .backgroundColor($r('app.color.color_466afd')) .onClick(() => { this.controller.stop() - SaveUtils.saveImageVideoToAlbumDialog([this.uri!!]) - .then((saved) => { - if (saved) { - this.uri = undefined - this.showDownloadDialog() - } else { - ToastUtils.show('保存失败') - } - }) - .catch((e: BusinessError) => { - ToastUtils.show('保存失败:' + e.message) - }) + this.viewModel.checkVip() }) } .visibility(this.isSuccess ? Visibility.Visible : Visibility.None) diff --git a/entry/src/main/ets/pages/main/home/tools/RemoveWatermarkPage.ets b/entry/src/main/ets/pages/main/home/tools/RemoveWatermarkPage.ets index d41a99b..d982776 100644 --- a/entry/src/main/ets/pages/main/home/tools/RemoveWatermarkPage.ets +++ b/entry/src/main/ets/pages/main/home/tools/RemoveWatermarkPage.ets @@ -2,7 +2,7 @@ import { PhotoHelper } from '@pura/picker_utils' import { TitleBar } from '../../../../view/TitleBar' import { photoAccessHelper } from '@kit.MediaLibraryKit' import { BusinessError, systemDateTime } from '@kit.BasicServicesKit' -import { AppUtil, DisplayUtil, FileUtil, ImageUtil, StrUtil } from '@pura/harmony-utils' +import { AppUtil, DisplayUtil, FileUtil } from '@pura/harmony-utils' import { ToastUtils } from '../../../../utils/ToastUtils' import { fileIo } from '@kit.CoreFileKit' import { SaveUtils } from '../../../../utils/SaveUtils' @@ -14,27 +14,74 @@ import { media } from '@kit.MediaKit' import { MediaUtils } from '../../../../utils/MediaUtils' import { MP4Parser } from '@ohos/mp4parser' import { TipDialog } from '../../../../dialog/TipDialog' -import { WaterMarkerView } from '../../../../view/WaterMarkerView' -import { EditTextDialog } from '../../../../dialog/EditTextDialog' -import { image } from '@kit.ImageKit' import { avSessionManager } from '../../../../manager/AVSessionManager' import { SelectBoundsView } from '../../../../view/SelectBoundsView' +import { AuthViewModel } from '../../../../viewModel/AuthViewModel' +import { LoginManager } from '../../../../manager/LoginGlobalManager' +import { VipAuthEntity } from '../../../../entity/VipAuthEntity' +import { RouterUrls } from '../../../../common/RouterUrls' +import { router } from '@kit.ArkUI' +import { EventReportManager } from '../../../../manager/EventReportManager' @Entry @ComponentV2 struct RemoveWatermarkPage { + private viewModel: AuthViewModel = new AuthViewModel(this.getUIContext()) + private controller: VideoController = new VideoController() + private videoSize: media.PixelMapParams = { width: 0, height: 0 } + private rect: RectPosition = { x: 0, y: 0, width: 0, height: 0 } + @Local uri?: string @Local currentTime: number = 0 @Local durationTime: number = 0 @Local isPlaying: boolean = false @Local isSuccess: boolean = false @Local playerSize: media.PixelMapParams = { width: 0, height: 0 } - @Local showBound: boolean = false - private controller: VideoController = new VideoController() - private videoSize: media.PixelMapParams = { width: 0, height: 0 } - private rect: RectPosition = { x: 0, y: 0, width: 0, height: 0 } + @Monitor('viewModel.authInfo') + onPermissionInfoChange(monitor: IMonitor) { + const info = monitor.value()?.now as VipAuthEntity; + if (info.auth) { + if (!LoginManager.isLogin()) { + this.getUIContext().getRouter().pushUrl({url: RouterUrls.LOGIN_PAGE, params: {from: 1}}, router.RouterMode.Single) + return; + } + this.doSave() + } else { + if (!info.auth_ad) { + this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIP_PAGE, params: {origin: 'removeWatermark'}}) + EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'removeWatermark') + return; + } + } + } + + @Monitor('viewModel.errorCode') + onErrorCodeChange(monitor: IMonitor) { + const errorCode = monitor.value()?.now as number; + if (errorCode === 12002 || errorCode === 12003 || errorCode === 12004) { + this.getUIContext().getRouter().pushUrl({url: RouterUrls.RECHARGE_DIAMOND_PAGE}); + EventReportManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'removeWatermark') + ToastUtils.show('M币已用完') + } + } + + doSave() { + SaveUtils.saveImageVideoToAlbumDialog([this.uri!!]) + .then((saved) => { + if (saved) { + this.uri = undefined + this.isSuccess = false + this.showDownloadDialog() + } else { + ToastUtils.show('保存失败') + } + }) + .catch((e: BusinessError) => { + ToastUtils.show('保存失败:' + e.message) + }) + } addWatermark() { LoadingDialog.show(this.getUIContext()) @@ -375,18 +422,7 @@ struct RemoveWatermarkPage { .backgroundColor($r('app.color.color_466afd')) .onClick(() => { this.controller.stop() - SaveUtils.saveImageVideoToAlbumDialog([this.uri!!]) - .then((saved) => { - if (saved) { - this.uri = undefined - this.showDownloadDialog() - } else { - ToastUtils.show('保存失败') - } - }) - .catch((e: BusinessError) => { - ToastUtils.show('保存失败:' + e.message) - }) + this.viewModel.checkVip() }) } .visibility(this.isSuccess ? Visibility.Visible : Visibility.None) diff --git a/entry/src/main/ets/pages/main/home/tools/VideoMirrorPage.ets b/entry/src/main/ets/pages/main/home/tools/VideoMirrorPage.ets deleted file mode 100644 index 345a10d..0000000 --- a/entry/src/main/ets/pages/main/home/tools/VideoMirrorPage.ets +++ /dev/null @@ -1,322 +0,0 @@ -import { PhotoHelper } from '@pura/picker_utils' -import { TitleBar } from '../../../../view/TitleBar' -import { photoAccessHelper } from '@kit.MediaLibraryKit' -import { BusinessError, systemDateTime } from '@kit.BasicServicesKit' -import { AppUtil, FileUtil } from '@pura/harmony-utils' -import { ToastUtils } from '../../../../utils/ToastUtils' -import { fileIo } from '@kit.CoreFileKit' -import { SaveUtils } from '../../../../utils/SaveUtils' -import { LoadingDialog } from '../../../../dialog/LoadingDialog' -import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog' -import { EventConstants } from '../../../../common/EventConstants' -import { MP4Parser } from '@ohos/mp4parser' -import { TipDialog } from '../../../../dialog/TipDialog' -import { avSessionManager } from '../../../../manager/AVSessionManager' - -@Entry -@ComponentV2 -struct VideoMirrorPage { - private controller: VideoController = new VideoController() - @Local uri?: string - @Local currentTime: number = 0 - @Local durationTime: number = 0 - @Local isPlaying: boolean = false - @Local isSuccess: boolean = false - - private orientation: number = 0 - - mirrorVideo() { - LoadingDialog.show(this.getUIContext()) - this.isSuccess = false - let cacheVideoPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp4` - if (FileUtil.accessSync(cacheVideoPath)) { - FileUtil.unlinkSync(cacheVideoPath) - } - - let file = FileUtil.openSync(this.uri!!, fileIo.OpenMode.READ_ONLY) - // 复制文件到缓存目录下 - FileUtil.copyFileSync(file.fd, cacheVideoPath) - FileUtil.closeSync(file) - - let outputPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp4` - let cmd = `ffmpeg -i ${cacheVideoPath} -vf ${this.orientation === 1 ? "hflip" : "vflip"} -c:v h264 -pix_fmt yuv420p -y ${outputPath}` - MP4Parser.ffmpegCmd(cmd, { - callBackResult: (code: number) => { - if (code === 0) { - this.uri = FileUtil.getUriFromPath(outputPath) - this.isSuccess = true - this.isPlaying = false - ToastUtils.show('处理成功') - } else { - ToastUtils.show('处理失败') - } - LoadingDialog.dismiss() - } - }) - } - - selectVideo() { - PhotoHelper.selectEasy({ - MIMEType: photoAccessHelper.PhotoViewMIMETypes.VIDEO_TYPE, - maxSelectNumber: 1, - isPhotoTakingSupported: false, - isEditSupported: false, - isOriginalSupported: false - }) - .then((uris) => { - if (uris.length != 0) { - this.isSuccess = false - this.uri = uris[0] - } - }) - } - - showDownloadDialog() { - DownloadDialog.show(this.getUIContext(), { status: DownloadStatus.COMPLETED, totalSize: 0, progress: 0, totalCount: 1, index: 0, callback: { - confirm: () => { - AppUtil.getContext().eventHub.emit(EventConstants.JumpToRecordEvent, 0) - this.getUIContext().getRouter().back() - } - } }) - } - - formatTime(time: number): string { - let minute: number = 0 - let second: number = 0 - if (time > 60) { - minute = Math.trunc(time / 60) - second = time % 60 - if (minute < 10) { - if (second < 10) { - return `0${minute}:0${second}` - } else { - return `0${minute}:${second}` - } - } else { - if (second < 10) { - return `${minute}:0${second}` - } else { - return `${minute}:${second}` - } - } - } else { - second = time - if (second < 10) { - return `00:0${second}` - } else { - return `00:${second}` - } - } - } - - onBackPress(): boolean | void { - if (this.isSuccess) { - TipDialog.show(this.getUIContext(), {title:'温馨提示', content:'视频尚未保存,是否确定退出?', callback: { - confirm: () => { - this.getUIContext().getRouter().back() - } - }}) - return true - } - return false - } - - build() { - Column() { - TitleBar({ title: '视频镜像' }) - - Column() { - Row() { - Text('上传视频').fontColor($r('app.color.color_90ffffff')).fontSize(16).fontWeight(FontWeight.Medium) - Text('(仅支持mp4格式)').fontColor($r('app.color.color_50ffffff')).fontSize(12) - }.alignSelf(ItemAlign.Start) - - RelativeContainer() { - Stack() { - Image($r('app.media.ic_add_video')).width(44).height(44) - } - .width(140) - .height(140) - .borderRadius(10) - .backgroundColor($r('app.color.color_333333')) - .alignRules({ - start: { anchor: '__container__', align: HorizontalAlign.Start }, - top: { anchor: '__container__', align: VerticalAlign.Top }, - end: { anchor: '__container__', align: HorizontalAlign.End }, - bottom: { anchor: '__container__', align: VerticalAlign.Bottom } - }) - .onClick(() => { - this.selectVideo() - }) - } - .height(220) - .margin({ top: 12 }) - .borderRadius(8) - .backgroundColor($r('app.color.color_222222')) - }.margin({ left: 16, top: 16, right: 16 }) - .visibility(this.uri ? Visibility.None : Visibility.Visible) - - Column() { - RelativeContainer() { - Video({ - src: this.uri, // 设置视频源 - controller: this.controller, //设置视频控制器,可以控制视频的播放状态 - posterOptions: { showFirstFrame: true } - }) - .width('100%') - .height('100%') - .backgroundColor($r('app.color.window_background')) - .controls(false) // 设置是否显示默认控制条 - .autoPlay(false) // 设置是否自动播放 - .loop(false) // 设置是否循环播放 - .objectFit(ImageFit.Contain) // 设置视频填充模式 - .onPrepared((event) => { - if (event) { - this.durationTime = event.duration - } - }) - .onUpdate((event) => { - if (event) { - this.currentTime = event.time - } - }) - .onStart(() => { - this.isPlaying = true - }) - .onPause(() => { - this.isPlaying = false - avSessionManager.deactivate() - }) - .onStop(() => { - this.isPlaying = false - avSessionManager.deactivate() - }) - .onFinish(() => { - this.isPlaying = false - avSessionManager.deactivate() - }) - .onError(() => { - this.isPlaying = false - avSessionManager.deactivate() - }) - .onDisAppear(() => { - avSessionManager.deactivate() - }) - - Image($r('app.media.ic_play_video')) - .width(50) - .height(50) - .visibility(this.isPlaying ? Visibility.None : Visibility.Visible) - .onClick(async () => { - await avSessionManager.activate() - this.controller.start() - }) - .alignRules({ - left: { anchor: '__container__', align: HorizontalAlign.Start }, - top: { anchor: '__container__', align: VerticalAlign.Top }, - right: { anchor: '__container__', align: HorizontalAlign.End }, - bottom: { anchor: '__container__', align: VerticalAlign.Bottom }, - }) - - Row() { - Image(this.isPlaying ? $r('app.media.ic_player_controls_pause') : $r('app.media.ic_player_controls_play')) - .width(20) - .height(20) - .margin({ right: 20 }) - .onClick(async () => { - if (this.isPlaying) { - this.controller.pause() - } else { - await avSessionManager.activate() - this.controller.start() - } - }) - Text(this.formatTime(this.currentTime)).width(35).fontColor(Color.White).fontSize(12) - Slider({ - value: this.currentTime, - min: 0, - max: this.durationTime - }) - .blockColor(Color.White) - .trackColor($r('app.color.color_60ffffff')) - .onChange((value: number, mode: SliderChangeMode) => { - this.controller.setCurrentTime(value); // 设置视频播放的进度跳转到value处 - }) - .layoutWeight(1) - Text(this.formatTime(this.durationTime)).width(35).fontColor(Color.White).fontSize(12) - } - .opacity(0.8) - .width("100%") - .padding({ left: 30, right: 30 }) - .alignRules({ - bottom: { anchor: '__container__', align: VerticalAlign.Bottom } - }) - } - .layoutWeight(1) - - Row() { - Column(){ - Image($r('app.media.ic_mirror_h')).width(50).height(50) - Text('水平').fontColor($r('app.color.color_90ffffff')).fontSize(14).margin({ top: 8 }) - } - .onClick(() => { - this.orientation = 1 - this.controller.stop() - this.mirrorVideo() - }) - Column(){ - Image($r('app.media.ic_mirror_v')).width(50).height(50) - Text('垂直').fontColor($r('app.color.color_90ffffff')).fontSize(14).margin({ top: 8 }) - } - .margin({ left: 50 }) - .onClick(() => { - this.orientation = 2 - this.controller.stop() - this.mirrorVideo() - }) - .visibility(Visibility.None) - } - .margin({ top: 20 }) - - Row() { - Text(this.isSuccess ? '重新上传' : '取消').fontColor($r('app.color.color_90ffffff')).fontSize(17).margin({ left: 16 }) - .onClick(() => { - this.controller.stop() - if (this.isSuccess) { - this.selectVideo() - } else { - this.getUIContext().getRouter().back() - } - }) - Blank().layoutWeight(1) - Text('保存').fontColor($r("app.color.color_466afd")).fontSize(17).margin({ right: 16 }) - .onClick(() => { - this.controller.stop() - if (this.orientation !== 0) { - SaveUtils.saveImageVideoToAlbumDialog([this.uri!!]) - .then((saved) => { - if (saved) { - this.uri = undefined - this.showDownloadDialog() - } else { - ToastUtils.show('保存失败') - } - }) - .catch((e: BusinessError) => { - ToastUtils.show('保存失败:' + e.message) - }) - } else { - ToastUtils.show('请选择镜像方向') - } - }) - } - .margin({ top: 20, bottom: 30 }) - } - .layoutWeight(1) - .visibility(this.uri ? Visibility.Visible : Visibility.None) - } - .width('100%') - .height('100%') - .backgroundColor($r('app.color.window_background')) - } -} \ No newline at end of file diff --git a/entry/src/main/ets/pages/main/home/tools/VideoReversePage.ets b/entry/src/main/ets/pages/main/home/tools/VideoReversePage.ets deleted file mode 100644 index 71922a1..0000000 --- a/entry/src/main/ets/pages/main/home/tools/VideoReversePage.ets +++ /dev/null @@ -1,297 +0,0 @@ -import { PhotoHelper } from '@pura/picker_utils' -import { TitleBar } from '../../../../view/TitleBar' -import { photoAccessHelper } from '@kit.MediaLibraryKit' -import { BusinessError, systemDateTime } from '@kit.BasicServicesKit' -import { AppUtil, FileUtil } from '@pura/harmony-utils' -import { ToastUtils } from '../../../../utils/ToastUtils' -import { fileIo } from '@kit.CoreFileKit' -import { SaveUtils } from '../../../../utils/SaveUtils' -import { LoadingDialog } from '../../../../dialog/LoadingDialog' -import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog' -import { EventConstants } from '../../../../common/EventConstants' -import { MP4Parser } from '@ohos/mp4parser' -import { TipDialog } from '../../../../dialog/TipDialog' -import { avSessionManager } from '../../../../manager/AVSessionManager' - -@Entry -@ComponentV2 -struct VideoReversePage { - private controller: VideoController = new VideoController() - @Local uri?: string - @Local currentTime: number = 0 - @Local durationTime: number = 0 - @Local isPlaying: boolean = false - @Local isSuccess: boolean = false - - videoReverse() { - LoadingDialog.show(this.getUIContext()) - this.isSuccess = false - let cacheVideoPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp4` - if (FileUtil.accessSync(cacheVideoPath)) { - FileUtil.unlinkSync(cacheVideoPath) - } - - let file = FileUtil.openSync(this.uri!!, fileIo.OpenMode.READ_ONLY) - // 复制文件到缓存目录下 - FileUtil.copyFileSync(file.fd, cacheVideoPath) - FileUtil.closeSync(file) - - let outputPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp4` - let cmd = `ffmpeg -i ${cacheVideoPath} -vf reverse -af areverse -c:v h264 -pix_fmt yuv420p -y ${outputPath}` - MP4Parser.ffmpegCmd(cmd, { - callBackResult: (code: number) => { - if (code === 0) { - this.uri = FileUtil.getUriFromPath(outputPath) - this.isSuccess = true - this.isPlaying = false - ToastUtils.show('处理成功') - } else { - ToastUtils.show('处理失败') - } - LoadingDialog.dismiss() - } - }) - } - - selectVideo() { - PhotoHelper.selectEasy({ - MIMEType: photoAccessHelper.PhotoViewMIMETypes.VIDEO_TYPE, - maxSelectNumber: 1, - isPhotoTakingSupported: false, - isEditSupported: false, - isOriginalSupported: false - }) - .then((uris) => { - if (uris.length != 0) { - this.isSuccess = false - this.uri = uris[0] - } - }) - } - - showDownloadDialog() { - DownloadDialog.show(this.getUIContext(), { status: DownloadStatus.COMPLETED, totalSize: 0, progress: 0, totalCount: 1, index: 0, callback: { - confirm: () => { - AppUtil.getContext().eventHub.emit(EventConstants.JumpToRecordEvent, 0) - this.getUIContext().getRouter().back() - } - } }) - } - - formatTime(time: number): string { - let minute: number = 0 - let second: number = 0 - if (time > 60) { - minute = Math.trunc(time / 60) - second = time % 60 - if (minute < 10) { - if (second < 10) { - return `0${minute}:0${second}` - } else { - return `0${minute}:${second}` - } - } else { - if (second < 10) { - return `${minute}:0${second}` - } else { - return `${minute}:${second}` - } - } - } else { - second = time - if (second < 10) { - return `00:0${second}` - } else { - return `00:${second}` - } - } - } - - onBackPress(): boolean | void { - if (this.isSuccess) { - TipDialog.show(this.getUIContext(), {title:'温馨提示', content:'视频尚未保存,是否确定退出?', callback: { - confirm: () => { - this.getUIContext().getRouter().back() - } - }}) - return true - } - return false - } - - build() { - Column() { - TitleBar({ title: '视频倒放' }) - - Column() { - Row() { - Text('上传视频').fontColor($r('app.color.color_90ffffff')).fontSize(16).fontWeight(FontWeight.Medium) - Text('(仅支持mp4格式)').fontColor($r('app.color.color_50ffffff')).fontSize(12) - }.alignSelf(ItemAlign.Start) - - RelativeContainer() { - Stack() { - Image($r('app.media.ic_add_video')).width(44).height(44) - } - .width(140) - .height(140) - .borderRadius(10) - .backgroundColor($r('app.color.color_333333')) - .alignRules({ - start: { anchor: '__container__', align: HorizontalAlign.Start }, - top: { anchor: '__container__', align: VerticalAlign.Top }, - end: { anchor: '__container__', align: HorizontalAlign.End }, - bottom: { anchor: '__container__', align: VerticalAlign.Bottom } - }) - .onClick(() => { - this.selectVideo() - }) - } - .height(220) - .margin({ top: 12 }) - .borderRadius(8) - .backgroundColor($r('app.color.color_222222')) - }.margin({ left: 16, top: 16, right: 16 }) - .visibility(this.uri ? Visibility.None : Visibility.Visible) - - Column() { - RelativeContainer() { - Video({ - src: this.uri, // 设置视频源 - controller: this.controller, //设置视频控制器,可以控制视频的播放状态 - posterOptions: { showFirstFrame: true } - }) - .width('100%') - .height('100%') - .backgroundColor($r('app.color.window_background')) - .controls(false) // 设置是否显示默认控制条 - .autoPlay(false) // 设置是否自动播放 - .loop(false) // 设置是否循环播放 - .objectFit(ImageFit.Contain) // 设置视频填充模式 - .onPrepared((event) => { - if (event) { - this.durationTime = event.duration - } - }) - .onUpdate((event) => { - if (event) { - this.currentTime = event.time - } - }) - .onStart(() => { - this.isPlaying = true - }) - .onPause(() => { - this.isPlaying = false - avSessionManager.deactivate() - }) - .onStop(() => { - this.isPlaying = false - avSessionManager.deactivate() - }) - .onFinish(() => { - this.isPlaying = false - avSessionManager.deactivate() - }) - .onError(() => { - this.isPlaying = false - avSessionManager.deactivate() - }) - .onDisAppear(() => { - avSessionManager.deactivate() - }) - - Image($r('app.media.ic_play_video')) - .width(50) - .height(50) - .visibility(this.isPlaying ? Visibility.None : Visibility.Visible) - .onClick(async () => { - await avSessionManager.activate() - this.controller.start() - }) - .alignRules({ - left: { anchor: '__container__', align: HorizontalAlign.Start }, - top: { anchor: '__container__', align: VerticalAlign.Top }, - right: { anchor: '__container__', align: HorizontalAlign.End }, - bottom: { anchor: '__container__', align: VerticalAlign.Bottom }, - }) - - Row() { - Image(this.isPlaying ? $r('app.media.ic_player_controls_pause') : $r('app.media.ic_player_controls_play')) - .width(20) - .height(20) - .margin({ right: 20 }) - .onClick(async () => { - if (this.isPlaying) { - this.controller.pause() - } else { - await avSessionManager.activate() - this.controller.start() - } - }) - Text(this.formatTime(this.currentTime)).width(35).fontColor(Color.White).fontSize(12) - Slider({ - value: this.currentTime, - min: 0, - max: this.durationTime - }) - .blockColor(Color.White) - .trackColor($r('app.color.color_60ffffff')) - .onChange((value: number, mode: SliderChangeMode) => { - this.controller.setCurrentTime(value); // 设置视频播放的进度跳转到value处 - }) - .layoutWeight(1) - Text(this.formatTime(this.durationTime)).width(35).fontColor(Color.White).fontSize(12) - } - .opacity(0.8) - .width("100%") - .padding({ left: 30, right: 30 }) - .alignRules({ - bottom: { anchor: '__container__', align: VerticalAlign.Bottom } - }) - } - .layoutWeight(1) - - Row() { - Text(this.isSuccess ? '重新上传' : '取消').fontColor($r('app.color.color_90ffffff')).fontSize(17).margin({ left: 16 }) - .onClick(() => { - this.controller.stop() - if (this.isSuccess) { - this.selectVideo() - } else { - this.getUIContext().getRouter().back() - } - }) - Blank().layoutWeight(1) - Text(this.isSuccess ? '保存' : '确定').fontColor($r("app.color.color_466afd")).fontSize(17).margin({ right: 16 }) - .onClick(() => { - this.controller.stop() - if (this.isSuccess) { - SaveUtils.saveImageVideoToAlbumDialog([this.uri!!]) - .then((saved) => { - if (saved) { - this.uri = undefined - this.showDownloadDialog() - } else { - ToastUtils.show('保存失败') - } - }) - .catch((e: BusinessError) => { - ToastUtils.show('保存失败:' + e.message) - }) - - } else { - this.videoReverse() - } - }) - } - .margin({ top: 140, bottom: 30 }) - } - .layoutWeight(1) - .visibility(this.uri ? Visibility.Visible : Visibility.None) - } - .width('100%') - .height('100%') - .backgroundColor($r('app.color.window_background')) - } -} \ No newline at end of file diff --git a/entry/src/main/ets/pages/main/home/tools/VideoToAudioPage.ets b/entry/src/main/ets/pages/main/home/tools/VideoToAudioPage.ets index 49ca687..1a6f354 100644 --- a/entry/src/main/ets/pages/main/home/tools/VideoToAudioPage.ets +++ b/entry/src/main/ets/pages/main/home/tools/VideoToAudioPage.ets @@ -11,18 +11,97 @@ import { LoadingDialog } from '../../../../dialog/LoadingDialog' import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog' import { EventConstants } from '../../../../common/EventConstants' import { avSessionManager } from '../../../../manager/AVSessionManager' +import { AuthViewModel } from '../../../../viewModel/AuthViewModel' +import { LoginManager } from '../../../../manager/LoginGlobalManager' +import { VipAuthEntity } from '../../../../entity/VipAuthEntity' +import { RouterUrls } from '../../../../common/RouterUrls' +import { router } from '@kit.ArkUI' +import { EventReportManager } from '../../../../manager/EventReportManager' +import { media } from '@kit.MediaKit' @Entry @ComponentV2 struct VideoToAudioPage { + private viewModel: AuthViewModel = new AuthViewModel(this.getUIContext()) private controller: VideoController = new VideoController() + private avPlayer?: media.AVPlayer = undefined + @Local videoUri?: string @Local audioUri?: string - @Local currentTime: number = 0 - @Local durationTime: number = 0 - @Local isPlaying: boolean = false + @Local videoCurrentTime: number = 0 + @Local audioCurrentTime: number = 0 + @Local videoDurationTime: number = 0 + @Local audioDurationTime: number = 0 + @Local isVideoPlaying: boolean = false + @Local isAudioPlaying: boolean = false @Local isSuccess: boolean = false + @Monitor('viewModel.authInfo') + onPermissionInfoChange(monitor: IMonitor) { + const info = monitor.value()?.now as VipAuthEntity; + if (info.auth) { + if (!LoginManager.isLogin()) { + this.getUIContext().getRouter().pushUrl({url: RouterUrls.LOGIN_PAGE, params: {from: 1}}, router.RouterMode.Single) + return; + } + this.doSave() + } else { + if (!info.auth_ad) { + this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIP_PAGE, params: {origin: 'videoToAudio'}}) + EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'videoToAudio') + return; + } + } + } + + @Monitor('viewModel.errorCode') + onErrorCodeChange(monitor: IMonitor) { + const errorCode = monitor.value()?.now as number; + if (errorCode === 12002 || errorCode === 12003 || errorCode === 12004) { + this.getUIContext().getRouter().pushUrl({url: RouterUrls.RECHARGE_DIAMOND_PAGE}); + EventReportManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'videoToAudio') + ToastUtils.show('M币已用完') + } + } + + aboutToAppear(): void { + this.initPlayer() + } + + onPageHide(): void { + if (this.avPlayer) { + this.avPlayer.pause() + } + } + + aboutToDisappear(): void { + if (this.avPlayer) { + this.avPlayer.release() + } + } + + async initPlayer() { + this.avPlayer = await media.createAVPlayer(); + // 创建状态机变化回调函数 + this.setAVPlayerCallback(); + } + + doSave() { + SaveUtils.saveAudioToMusic([this.audioUri!!]) + .then((saved) => { + if (saved) { + this.videoUri = undefined + this.isSuccess = false + this.showDownloadDialog() + } else { + ToastUtils.show('保存失败') + } + }) + .catch((e: BusinessError) => { + ToastUtils.show('保存失败:' + e.message) + }) + } + videoToAudio() { LoadingDialog.show(this.getUIContext()) this.isSuccess = false @@ -42,7 +121,10 @@ struct VideoToAudioPage { if (code === 0) { this.audioUri = outputPath this.isSuccess = true - this.isPlaying = false + this.isVideoPlaying = false + // 打开相应的资源文件地址获取fd + let file = fileIo.openSync(this.audioUri) + this.avPlayer!!.url = 'fd://' + file.fd ToastUtils.show('处理成功') } else { ToastUtils.show('处理失败') @@ -78,6 +160,56 @@ struct VideoToAudioPage { } }) } + // 注册avplayer回调函数 + setAVPlayerCallback() { + this.avPlayer!!.on('error', (err) => { + console.error(`播放器发生错误,错误码:${err.code}, 错误信息:${err.message}`); + // 调用reset重置资源,触发idle状态 + this.isAudioPlaying = false + this.avPlayer!!.reset(); + avSessionManager.deactivate() + }) + // 状态机变化回调函数 + this.avPlayer!!.on('stateChange', async (state, reason) => { + switch (state) { + case 'initialized': + console.info('资源初始化完成'); + // 资源初始化完成,开始准备文件 + this.avPlayer!!.prepare(); + break; + case 'prepared': + console.info('资源准备完成'); + // 资源准备完成,开始准备文件 + this.audioDurationTime = Math.trunc(this.avPlayer!!.duration / 1000) + this.audioCurrentTime = this.avPlayer!!.currentTime; + break; + case 'completed': + console.info('播放完成'); + this.isAudioPlaying = false + this.avPlayer!!.off('bufferingUpdate') + AppStorage.setOrCreate('currentTime', this.videoDurationTime); + avSessionManager.deactivate() + break; + case 'playing': + console.info('播放开始'); + this.isAudioPlaying = true + break; + case 'released': + case 'stopped': + case 'error': + case 'paused': + console.info('播放暂停'); + this.isAudioPlaying = false + avSessionManager.deactivate() + break; + } + }) + // 时间上报监听函数 + this.avPlayer!!.on('timeUpdate', (time: number) => { + this.audioCurrentTime = Math.trunc(time / 1000); + }); + } + formatTime(time: number): string { let minute: number = 0 let second: number = 0 @@ -142,31 +274,31 @@ struct VideoToAudioPage { .objectFit(ImageFit.Contain) // 设置视频填充模式 .onPrepared((event) => { if (event) { - this.durationTime = event.duration + this.videoDurationTime = event.duration } }) .onUpdate((event) => { if (event) { - this.currentTime = event.time + this.videoCurrentTime = event.time } }) .onStart(() => { - this.isPlaying = true + this.isVideoPlaying = true }) .onPause(() => { - this.isPlaying = false + this.isVideoPlaying = false avSessionManager.deactivate() }) .onStop(() => { - this.isPlaying = false + this.isVideoPlaying = false avSessionManager.deactivate() }) .onFinish(() => { - this.isPlaying = false + this.isVideoPlaying = false avSessionManager.deactivate() }) .onError(() => { - this.isPlaying = false + this.isVideoPlaying = false avSessionManager.deactivate() }) .onDisAppear(() => { @@ -176,7 +308,7 @@ struct VideoToAudioPage { Image($r('app.media.ic_play_video')) .width(50) .height(50) - .visibility(this.isPlaying ? Visibility.None : Visibility.Visible) + .visibility(this.isVideoPlaying ? Visibility.None : Visibility.Visible) .onClick(async () => { await avSessionManager.activate() this.controller.start() @@ -189,23 +321,23 @@ struct VideoToAudioPage { }) Row() { - Image(this.isPlaying ? $r('app.media.ic_player_controls_pause') : $r('app.media.ic_player_controls_play')) + Image(this.isVideoPlaying ? $r('app.media.ic_player_controls_pause') : $r('app.media.ic_player_controls_play')) .width(20) .height(20) .margin({ right: 20 }) .onClick(async () => { - if (this.isPlaying) { + if (this.isVideoPlaying) { this.controller.pause() } else { await avSessionManager.activate() this.controller.start() } }) - Text(this.formatTime(this.currentTime)).width(35).fontColor(Color.White).fontSize(12) + Text(this.formatTime(this.videoCurrentTime)).width(35).fontColor(Color.White).fontSize(12) Slider({ - value: this.currentTime, + value: this.videoCurrentTime, min: 0, - max: this.durationTime + max: this.videoDurationTime }) .blockColor(Color.White) .trackColor($r('app.color.color_60ffffff')) @@ -213,7 +345,7 @@ struct VideoToAudioPage { this.controller.setCurrentTime(value); // 设置视频播放的进度跳转到value处 }) .layoutWeight(1) - Text(this.formatTime(this.durationTime)).width(35).fontColor(Color.White).fontSize(12) + Text(this.formatTime(this.videoDurationTime)).width(35).fontColor(Color.White).fontSize(12) } .opacity(0.8) .width("100%") @@ -239,6 +371,43 @@ struct VideoToAudioPage { .padding({left: 32, right: 32}) .margin({top: 40}) + Row() { + Image(this.isAudioPlaying ? $r('app.media.ic_audio_pause2') : $r('app.media.ic_audio_play2')) + .width(40) + .height(40) + .margin({ right: 16 }) + .onClick(async () => { + if (this.isAudioPlaying) { + this.avPlayer!!.pause() + } else { + await avSessionManager.activate() + this.avPlayer!!.play() + } + }) + Text(this.formatTime(this.audioCurrentTime)).width(45).fontColor($r('app.color.color_999999')).fontSize(16) + Slider({ + value: this.audioCurrentTime, + min: 0, + max: this.audioDurationTime + }) + .blockColor(Color.White) + .trackColor($r('app.color.color_eeeeee')) + .onChange((value: number, mode: SliderChangeMode) => { + this.avPlayer!!.seek(value * 1000, 2); // 设置视频播放的进度跳转到value处 + this.audioCurrentTime = value; + }) + .layoutWeight(1) + Text(this.formatTime(this.audioDurationTime)).width(45).fontColor($r('app.color.color_999999')).fontSize(16) + } + .height(60) + .borderRadius(30) + .borderWidth(1) + .borderColor('#DADEE5') + .backgroundColor(Color.White) + .margin({left: 12, top: 40, right: 12}) + .padding({left: 16, right: 16}) + .visibility(this.audioUri ? Visibility.Visible : Visibility.None) + Blank().layoutWeight(1) Stack() { @@ -288,18 +457,7 @@ struct VideoToAudioPage { .backgroundColor($r('app.color.color_466afd')) .onClick(() => { this.controller.stop() - SaveUtils.saveAudioToMusic([this.audioUri!!]) - .then((saved) => { - if (saved) { - this.videoUri = undefined - this.showDownloadDialog() - } else { - ToastUtils.show('保存失败') - } - }) - .catch((e: BusinessError) => { - ToastUtils.show('保存失败:' + e.message) - }) + this.viewModel.checkVip() }) } .visibility(this.isSuccess ? Visibility.Visible : Visibility.None) diff --git a/entry/src/main/ets/pages/main/home/tools/VideoToTextPage.ets b/entry/src/main/ets/pages/main/home/tools/VideoToTextPage.ets index 99cee31..389c116 100644 --- a/entry/src/main/ets/pages/main/home/tools/VideoToTextPage.ets +++ b/entry/src/main/ets/pages/main/home/tools/VideoToTextPage.ets @@ -2,10 +2,9 @@ import { PhotoHelper } from '@pura/picker_utils' import { TitleBar } from '../../../../view/TitleBar' import { photoAccessHelper } from '@kit.MediaLibraryKit' import { BusinessError, systemDateTime } from '@kit.BasicServicesKit' -import { AppUtil, FileUtil } from '@pura/harmony-utils' +import { AppUtil, FileUtil, JSONUtil, PasteboardUtil } from '@pura/harmony-utils' import { ToastUtils } from '../../../../utils/ToastUtils' import { fileIo } from '@kit.CoreFileKit' -import { SaveUtils } from '../../../../utils/SaveUtils' import { LoadingDialog } from '../../../../dialog/LoadingDialog' import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog' import { EventConstants } from '../../../../common/EventConstants' @@ -15,12 +14,20 @@ import { MP4Parser } from '@ohos/mp4parser' import { QCloud } from 'qcloudfileflash' import { Constants } from '../../../../common/Constants' import { VoiceRecognizeResultEntity } from '../../../../entity/VoiceRecognizeResultEntity' -import { plainToInstance } from 'class-transformer' +import { AuthViewModel } from '../../../../viewModel/AuthViewModel' +import { VipAuthEntity } from '../../../../entity/VipAuthEntity' +import { LoginManager } from '../../../../manager/LoginGlobalManager' +import { RouterUrls } from '../../../../common/RouterUrls' +import { router } from '@kit.ArkUI' +import { EventReportManager } from '../../../../manager/EventReportManager' +import { ConfigManager } from '../../../../manager/UserConfigManager' @Entry @ComponentV2 struct VideoToTextPage { + private viewModel: AuthViewModel = new AuthViewModel(this.getUIContext()) private controller: VideoController = new VideoController() + @Local resultText?: string @Local videoUri?: string @Local currentTime: number = 0 @@ -28,6 +35,42 @@ struct VideoToTextPage { @Local isPlaying: boolean = false @Local isSuccess: boolean = false + @Monitor('viewModel.authInfo') + onPermissionInfoChange(monitor: IMonitor) { + const info = monitor.value()?.now as VipAuthEntity; + if (info.auth) { + if (!LoginManager.isLogin()) { + this.getUIContext().getRouter().pushUrl({url: RouterUrls.LOGIN_PAGE, params: {from: 1}}, router.RouterMode.Single) + return; + } + this.doSave() + } else { + if (!info.auth_ad) { + this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIP_PAGE, params: {origin: 'videoToText'}}) + EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'videoToText') + return; + } + } + } + + @Monitor('viewModel.errorCode') + onErrorCodeChange(monitor: IMonitor) { + const errorCode = monitor.value()?.now as number; + if (errorCode === 12002 || errorCode === 12003 || errorCode === 12004) { + this.getUIContext().getRouter().pushUrl({url: RouterUrls.RECHARGE_DIAMOND_PAGE}); + EventReportManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'videoToText') + ToastUtils.show('M币已用完') + } + } + + doSave() { + if (this.resultText) { + PasteboardUtil.setDataTextSync(this.resultText) + this.isSuccess = false + ToastUtils.show('复制成功') + } + } + videoToAudio() { LoadingDialog.show(this.getUIContext()) this.isSuccess = false @@ -46,11 +89,15 @@ struct VideoToTextPage { callBackResult: (code: number) => { if (code === 0) { this.recognizeAudio(outputPath) - .then((result: VoiceRecognizeResultEntity) => { - this.resultText = result.flash_result[0].text - this.isSuccess = true - this.isPlaying = false - ToastUtils.show('处理成功') + .then((result) => { + if (result !== null) { + this.resultText = result.flash_result[0].text + this.isSuccess = true + this.isPlaying = false + ToastUtils.show('处理成功') + } else { + ToastUtils.show('处理失败') + } LoadingDialog.dismiss() }) .catch((e: BusinessError) => { @@ -66,7 +113,7 @@ struct VideoToTextPage { }) } - async recognizeAudio(uri: string): Promise { + async recognizeAudio(uri: string): Promise { let builder = new QCloud.FileFlash.Builder() builder.appID = Constants.QCLOUD_APP_ID builder.secretID = Constants.QCLOUD_SECRET_ID @@ -87,7 +134,7 @@ struct VideoToTextPage { FileUtil.readSync(file.fd, buffer) FileUtil.closeSync(file) let result = await builder.build(buffer).task - const voiceResult = plainToInstance(VoiceRecognizeResultEntity, result) + let voiceResult = JSONUtil.jsonToBean(result, VoiceRecognizeResultEntity) return Promise.resolve(voiceResult) } catch (e) { console.error(e) @@ -107,6 +154,7 @@ struct VideoToTextPage { if (uris.length != 0) { this.isSuccess = false this.videoUri = uris[0] + this.resultText = undefined } }) } @@ -151,7 +199,7 @@ struct VideoToTextPage { onBackPress(): boolean | void { if (this.isSuccess) { - TipDialog.show(this.getUIContext(), {title:'温馨提示', content:'文本尚未保存,是否确定退出?', callback: { + TipDialog.show(this.getUIContext(), {title:'温馨提示', content:'文本尚未复制,是否确定退出?', callback: { confirm: () => { this.getUIContext().getRouter().back() } @@ -293,22 +341,32 @@ struct VideoToTextPage { .padding({left: 32, right: 32}) .margin({top: 40}) - Column() { - Row() { - Image($r('app.media.ic_star')).width(22).height(22) - Text('文本结果').fontColor($r('app.color.color_212226')).fontSize(15).fontWeight(FontWeight.Medium).margin({left: 4}) + Stack({alignContent: Alignment.Top}) { + Column() { + Row() { + Image($r('app.media.ic_star')).width(22).height(22) + Text('文本结果').fontColor($r('app.color.color_212226')).fontSize(15).fontWeight(FontWeight.Medium).margin({left: 4}) + } + Divider().strokeWidth(1).color($r('app.color.color_eeeeee')).margin({top: 12}) + Scroll() { + Text(this.resultText).width('100%').fontColor($r('app.color.color_212226')).fontSize(14).margin({top: 12}) + } + .layoutWeight(1) + .align(Alignment.TopStart) + .scrollBar(BarState.Off) } - Divider().strokeWidth(1).color($r('app.color.color_eeeeee')).margin({top: 12}) - Text(this.resultText).width('100%').height('auto').fontColor($r('app.color.color_212226')).fontSize(14).margin({top: 14}) + .width('100%') + .height('100%') + .alignItems(HorizontalAlign.Start) + .borderRadius(10) + .borderWidth(1) + .borderColor('#DADEE5') + .backgroundColor(Color.White) + .padding(12) } - .width('90%') .layoutWeight(1) - .borderRadius(10) - .borderWidth(1) - .borderColor('#DADEE5') - .backgroundColor(Color.White) .margin({top: 30, bottom: 20}) - .padding(12) + .padding({left: 16, right: 16}) .visibility(this.resultText ? Visibility.Visible : Visibility.None) Blank().layoutWeight(1).visibility(this.resultText ? Visibility.None : Visibility.Visible) @@ -328,7 +386,7 @@ struct VideoToTextPage { ToastUtils.show('请上传视频') } }) - .visibility(!this.isSuccess ? Visibility.Visible : Visibility.None) + .visibility(!this.resultText ? Visibility.Visible : Visibility.None) Row() { Button({ type: ButtonType.Capsule, stateEffect: true }) { @@ -360,21 +418,14 @@ struct VideoToTextPage { .backgroundColor($r('app.color.color_466afd')) .onClick(() => { this.controller.stop() - SaveUtils.saveImageVideoToAlbumDialog([this.videoUri!!]) - .then((saved) => { - if (saved) { - this.videoUri = undefined - this.showDownloadDialog() - } else { - ToastUtils.show('保存失败') - } - }) - .catch((e: BusinessError) => { - ToastUtils.show('保存失败:' + e.message) - }) + if (ConfigManager.isAiAuthEnable() && this.durationTime > 60) { + this.viewModel.checkVip() + } else { + this.doSave() + } }) } - .visibility(this.isSuccess ? Visibility.Visible : Visibility.None) + .visibility(this.resultText ? Visibility.Visible : Visibility.None) } .padding({left: 16, top: 9, right: 16, bottom: 30 }) .backgroundColor(Color.White) diff --git a/entry/src/main/ets/pages/main/home/wx/WxVideoPage.ets b/entry/src/main/ets/pages/main/home/wx/WxVideoPage.ets index 670117e..f7751e3 100644 --- a/entry/src/main/ets/pages/main/home/wx/WxVideoPage.ets +++ b/entry/src/main/ets/pages/main/home/wx/WxVideoPage.ets @@ -5,7 +5,7 @@ import { EventConstants } from '../../../../common/EventConstants'; import { RouterUrls } from '../../../../common/RouterUrls'; import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog'; import { ImageMaterial, MaterialInfoEntity, MediaEntity, VideoMaterial } from '../../../../entity/MaterialInfoEntity'; -import { VipPermissionEntity } from '../../../../entity/VipPermissionEntity'; +import { VipAuthEntity } from '../../../../entity/VipAuthEntity'; import { LoginManager } from '../../../../manager/LoginGlobalManager'; import { ShareManager } from '../../../../manager/ShareManager'; import { ConfigManager } from '../../../../manager/UserConfigManager'; @@ -24,7 +24,7 @@ import { ErrCode, SendAuthResp } from '@tencent/wechat_open_sdk'; import { LoadingDialog } from '../../../../dialog/LoadingDialog'; import BuildProfile from 'BuildProfile'; import { Constants } from '../../../../common/Constants'; -import { EventReportGlobalManager } from '../../../../manager/EventReportGlobalManager'; +import { EventReportManager } from '../../../../manager/EventReportManager'; import { TipDialog } from '../../../../dialog/TipDialog'; import { SimpleTipDialog } from '../../../../dialog/SimpleTipDialog'; import { JoinWxGroupCourseDialog } from '../../../../dialog/JoinWxGroupCourseDialog'; @@ -87,9 +87,9 @@ struct WxVideoPage { this.isRefreshing = false } - @Monitor('viewModel.permissionInfo') + @Monitor('viewModel.authInfo') onPermissionInfoChange(monitor: IMonitor) { - const info = monitor.value()?.now as VipPermissionEntity; + const info = monitor.value()?.now as VipAuthEntity; if (info.auth) { if (!LoginManager.isLogin()) { this.getUIContext() @@ -103,7 +103,7 @@ struct WxVideoPage { this.getUIContext() .getRouter() .pushUrl({ url: RouterUrls.VIP_PAGE, params: { origin: 'download_wechat_video' } }) - EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'download_wechat_video') + EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'download_wechat_video') return; } } @@ -114,7 +114,7 @@ struct WxVideoPage { const errorCode = monitor.value()?.now as number; if (errorCode === 12002 || errorCode === 12003 || errorCode === 12004) { this.getUIContext().getRouter().pushUrl({ url: RouterUrls.RECHARGE_DIAMOND_PAGE }); - EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'download_wechat_video') + EventReportManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'download_wechat_video') ToastUtils.show('M币已用完') } } @@ -328,7 +328,7 @@ struct WxVideoPage { callback: { confirm: () => { if (this.downloadStatus === DownloadStatus.COMPLETED) { - EventReportGlobalManager.eventReport(EventConstants.DIALOG_GO_TO_VIEW, this.titles[this.currentIndex]) + EventReportManager.eventReport(EventConstants.DIALOG_GO_TO_VIEW, this.titles[this.currentIndex]) AppUtil.getContext().eventHub.emit(EventConstants.JumpToRecordEvent, this.currentIndex) this.getUIContext().getRouter().back() } else { @@ -339,11 +339,11 @@ struct WxVideoPage { if (this.downloadStatus !== DownloadStatus.COMPLETED) { if (this.mediaDownloader) { this.mediaDownloader.cancel() - EventReportGlobalManager.eventReport(EventConstants.CANCEL_DOWNLOAD_VIDEO, + EventReportManager.eventReport(EventConstants.CANCEL_DOWNLOAD_VIDEO, this.selectedList[this.downloadIndex].url) } } else { - EventReportGlobalManager.eventReport(EventConstants.DIALOG_CONFIRM_SAVE_FILE, + EventReportManager.eventReport(EventConstants.DIALOG_CONFIRM_SAVE_FILE, this.titles[this.currentIndex]) } } @@ -469,7 +469,7 @@ struct WxVideoPage { req.transaction = ''; await WXApi.sendReq(AppUtil.getContext(), req) - EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_SHARE_WX_PLAYBACK, '前往微信分享直播回放') + EventReportManager.eventReport(EventConstants.JUMP_TO_SHARE_WX_PLAYBACK, '前往微信分享直播回放') LoadingDialog.dismiss(); } @@ -501,7 +501,7 @@ struct WxVideoPage { return; } this.viewModel.wxServiceInfo() - EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_SHARE_WX_VIDEO, "前往微信分享视频号", '') + EventReportManager.eventReport(EventConstants.JUMP_TO_SHARE_WX_VIDEO, "前往微信分享视频号", '') } /** @@ -517,9 +517,9 @@ struct WxVideoPage { reportErrorEvent(media: MediaEntity, message: string) { if (media instanceof VideoMaterial) { - EventReportGlobalManager.eventReport(EventConstants.ERROR_CLIENT_DOWNLOAD_VIDEO, media.url, message) + EventReportManager.eventReport(EventConstants.ERROR_CLIENT_DOWNLOAD_VIDEO, media.url, message) } else if (media instanceof ImageMaterial) { - EventReportGlobalManager.eventReport(EventConstants.ERROR_CLIENT_DOWNLOAD_IMG, media.url, message) + EventReportManager.eventReport(EventConstants.ERROR_CLIENT_DOWNLOAD_IMG, media.url, message) } } diff --git a/entry/src/main/ets/pages/main/mine/MinePage.ets b/entry/src/main/ets/pages/main/mine/MinePage.ets index 5455897..f603e95 100644 --- a/entry/src/main/ets/pages/main/mine/MinePage.ets +++ b/entry/src/main/ets/pages/main/mine/MinePage.ets @@ -10,7 +10,7 @@ import { fileIo, storageStatistics } from '@kit.CoreFileKit'; import { BusinessError } from '@kit.BasicServicesKit'; import { LoadingDialog } from '../../../dialog/LoadingDialog'; import { DiamondDetailEntity } from '../../../entity/DiamondDetailEntity'; -import { EventReportGlobalManager } from '../../../manager/EventReportGlobalManager'; +import { EventReportManager } from '../../../manager/EventReportManager'; import { WxServiceEntity } from '../../../entity/WxServiceEntity'; import { WXApi } from '../../../utils/wechat/WXApiEventHandlerImpl'; import * as WxOpenSdk from '@tencent/wechat_open_sdk'; @@ -107,7 +107,7 @@ export struct MinePage { .onClick(() => { if (!LoginManager.isLogin()) { this.getUIContext().getRouter().pushUrl({ url: RouterUrls.LOGIN_PAGE, params: { from : 1 }}, router.RouterMode.Single) - EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_LOGIN, 'center') + EventReportManager.eventReport(EventConstants.JUMP_TO_LOGIN, 'center') } else { this.getUIContext().getRouter().pushUrl({ url: RouterUrls.USER_SETTINGS_PAGE }) } @@ -193,7 +193,7 @@ export struct MinePage { Image($r('app.media.ic_mine_setting')).width(26).height(26) .onClick(() => { this.getUIContext().getRouter().pushUrl({url: RouterUrls.SETTING_PAGE}); - EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_SYSTEM_SETTING) + EventReportManager.eventReport(EventConstants.JUMP_TO_SYSTEM_SETTING) }) } .alignRules({ @@ -267,7 +267,7 @@ export struct MinePage { .id('btn_to_vip') .onClick(() => { this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIP_PAGE, params: {origin: 'center'}}) - EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'center') + EventReportManager.eventReport(EventConstants.JUMP_TO_MEMBER_RECHARGE, 'center') }) } .width('100%') @@ -305,17 +305,17 @@ export struct MinePage { switch (item.alias) { case 'history': { this.getUIContext().getRouter().pushUrl({url: RouterUrls.DOWNLOAD_HISTORY_PAGE}); - EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_DOWNLOAD_HISTORY, 'center') + EventReportManager.eventReport(EventConstants.JUMP_TO_DOWNLOAD_HISTORY, 'center') break } case 'diamond': { this.getUIContext().getRouter().pushUrl({url: RouterUrls.RECHARGE_DIAMOND_PAGE}); - EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'center') + EventReportManager.eventReport(EventConstants.JUMP_TO_RECHARGE_DIAMOND, 'center') break } case 'feedback': { this.getUIContext().getRouter().pushUrl({url: RouterUrls.FEEDBACK_PAGE}); - EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_FEEDBACK, 'center') + EventReportManager.eventReport(EventConstants.JUMP_TO_FEEDBACK, 'center') break } case 'service': { @@ -405,6 +405,7 @@ export struct MinePage { }) .visibility(this.currentIndex === 2 ? Visibility.Visible : Visibility.None) } + .layoutWeight(1) } .width('100%') .height('100%') diff --git a/entry/src/main/ets/pages/main/mine/diamond/DiamondPage.ets b/entry/src/main/ets/pages/main/mine/diamond/DiamondPage.ets index cfc3a8e..68b550d 100644 --- a/entry/src/main/ets/pages/main/mine/diamond/DiamondPage.ets +++ b/entry/src/main/ets/pages/main/mine/diamond/DiamondPage.ets @@ -16,7 +16,7 @@ import { LoadingDialog } from '../../../../dialog/LoadingDialog'; import { DiamondDetailEntity } from '../../../../entity/DiamondDetailEntity'; import { DiamondItemView } from '../../../../view/DiamondItemView'; import { DiamondRuleDialog } from '../../../../dialog/DiamondRuleDialog'; -import { EventReportGlobalManager } from '../../../../manager/EventReportGlobalManager'; +import { EventReportManager } from '../../../../manager/EventReportManager'; import { EventConstants } from '../../../../common/EventConstants'; import { OrderEntity } from '../../../../entity/OrderEntity'; import { TipDialog } from '../../../../dialog/TipDialog'; @@ -49,7 +49,7 @@ struct DiamondPage { this.viewModel.getOrderInfo(this.orderEntity!!.orderId) } else { ToastUtils.show(JSON.parse(payResult).errStr); - EventReportGlobalManager.eventReport( + EventReportManager.eventReport( EventConstants.PAY_CANCEL, `weixin:${this.origin}`, `{type:\"diamond\", orderId:${this.orderEntity?.orderId}, meal:${JSON.stringify(this.diamondInfo)}}` ) @@ -107,7 +107,7 @@ struct DiamondPage { const orderEntity = monitor.value()?.now as OrderEntity; if (orderEntity.status == "2") { ToastUtils.show('支付成功'); - EventReportGlobalManager.eventReport( + EventReportManager.eventReport( EventConstants.PAY_SUCCESS, `alipay:${this.origin}`, `{type:\"diamond\", orderId:${this.orderEntity?.orderId}, meal:${JSON.stringify(this.diamondInfo)}}` ) @@ -173,13 +173,13 @@ struct DiamondPage { this.viewModel.getOrderInfo(this.orderEntity!!.orderId) } else if (resultStatus === '6001') { ToastUtils.show('支付取消'); - EventReportGlobalManager.eventReport( + EventReportManager.eventReport( EventConstants.PAY_CANCEL, `alipay:${this.origin}`, `{type:\"diamond\", orderId:${this.orderEntity?.orderId}, meal:${JSON.stringify(this.diamondInfo)}}` ) } else { ToastUtils.show('支付失败'); - EventReportGlobalManager.eventReport( + EventReportManager.eventReport( EventConstants.ERROR_CLIENT_ALIPAY_ERR, `{orderId:${this.orderEntity?.orderId}, meal:${JSON.stringify(this.diamondInfo)}}`, resultStatus ) diff --git a/entry/src/main/ets/pages/main/mine/record/AudioRecordPage.ets b/entry/src/main/ets/pages/main/mine/record/AudioRecordPage.ets index d103d75..79581e5 100644 --- a/entry/src/main/ets/pages/main/mine/record/AudioRecordPage.ets +++ b/entry/src/main/ets/pages/main/mine/record/AudioRecordPage.ets @@ -64,10 +64,10 @@ export struct AudioRecordPage { build() { Stack() { Column() { - List() { + List({space: 10}) { ForEach(this.mediaList, (item: MediaRecordEntity, index) => { ListItem() { - AudioRecordItemView({ media: item }) + AudioRecordItemView({ media: item, index: index }) } .swipeAction({ end: this.itemEnd(item) @@ -79,7 +79,7 @@ export struct AudioRecordPage { .width('auto') .layoutWeight(1) .scrollBar(BarState.Off) - .margin({ left: 16, right: 16, bottom: 15 }) + .margin({ left: 16, right: 16 }) } EmptyView({ diff --git a/entry/src/main/ets/pages/main/mine/record/ImageRecordPage.ets b/entry/src/main/ets/pages/main/mine/record/ImageRecordPage.ets index da33394..8bfad2d 100644 --- a/entry/src/main/ets/pages/main/mine/record/ImageRecordPage.ets +++ b/entry/src/main/ets/pages/main/mine/record/ImageRecordPage.ets @@ -75,21 +75,19 @@ export struct ImageRecordPage { build() { Stack() { - Column() { - Grid() { - ForEach(this.mediaList, (item: MediaRecordEntity, index) => { - GridItem() { - ImageRecordItemView({ media: item, rowCount: this.rowCount }) - } - }) - } - .scrollBar(BarState.Off) - .columnsTemplate(this.rowCount === 1 ? '1fr' : this.rowCount === 2 ? '1fr 1fr' : '1fr 1fr 1fr') - .rowsGap(10) - .columnsGap(10) - .margin({ left: 16, right: 16, bottom: 15 }) - .layoutWeight(1) + Grid() { + ForEach(this.mediaList, (item: MediaRecordEntity, index) => { + GridItem() { + ImageRecordItemView({ media: item, rowCount: this.rowCount }) + } + }) } + .height('100%') + .scrollBar(BarState.Off) + .columnsTemplate(this.rowCount === 1 ? '1fr' : this.rowCount === 2 ? '1fr 1fr' : '1fr 1fr 1fr') + .rowsGap(10) + .columnsGap(10) + .margin({ left: 16, right: 16 }) EmptyView({ status: this.mediaList.length > 0 ? PageStatus.GONE : PageStatus.NO_DATA, diff --git a/entry/src/main/ets/pages/main/mine/record/VideoRecordPage.ets b/entry/src/main/ets/pages/main/mine/record/VideoRecordPage.ets index b65ee18..9776832 100644 --- a/entry/src/main/ets/pages/main/mine/record/VideoRecordPage.ets +++ b/entry/src/main/ets/pages/main/mine/record/VideoRecordPage.ets @@ -75,21 +75,19 @@ export struct VideoRecordPage { build() { Stack() { - Column() { - Grid() { - ForEach(this.mediaList, (item: MediaRecordEntity, index) => { - GridItem() { - VideoRecordItemView({ media: item, rowCount: this.rowCount }) - } - }) - } - .scrollBar(BarState.Off) - .columnsTemplate(this.rowCount === 1 ? '1fr' : this.rowCount === 2 ? '1fr 1fr' : '1fr 1fr 1fr') - .rowsGap(10) - .columnsGap(10) - .margin({ left: 16, right: 16, bottom: 15 }) - .layoutWeight(1) + Grid() { + ForEach(this.mediaList, (item: MediaRecordEntity, index) => { + GridItem() { + VideoRecordItemView({ media: item, rowCount: this.rowCount }) + } + }) } + .height('100%') + .scrollBar(BarState.Off) + .columnsTemplate(this.rowCount === 1 ? '1fr' : this.rowCount === 2 ? '1fr 1fr' : '1fr 1fr 1fr') + .rowsGap(10) + .columnsGap(10) + .margin({ left: 16, right: 16 }) EmptyView({ status: this.mediaList.length > 0 ? PageStatus.GONE : PageStatus.NO_DATA, @@ -97,5 +95,6 @@ export struct VideoRecordPage { noDataText: '暂无数据' }) } + .height('100%') } } \ No newline at end of file diff --git a/entry/src/main/ets/pages/main/mine/setting/SettingsPage.ets b/entry/src/main/ets/pages/main/mine/setting/SettingsPage.ets index af1b315..af90770 100644 --- a/entry/src/main/ets/pages/main/mine/setting/SettingsPage.ets +++ b/entry/src/main/ets/pages/main/mine/setting/SettingsPage.ets @@ -9,7 +9,7 @@ import { TextItemChildView } from '../../../../view/TextItemChildView' import { TitleBar } from '../../../../view/TitleBar' import { SettingsViewModel } from '../../../../viewModel/SettingsViewModel' import { router } from '@kit.ArkUI' -import { EventReportGlobalManager } from '../../../../manager/EventReportGlobalManager' +import { EventReportManager } from '../../../../manager/EventReportManager' import { fileIo, storageStatistics } from '@kit.CoreFileKit' import { BusinessError } from '@kit.BasicServicesKit' import { LoadingDialog } from '../../../../dialog/LoadingDialog' @@ -24,14 +24,14 @@ struct SettingsPage { @Monitor('viewModel.destroy') onDestroy(monitor: IMonitor) { - EventReportGlobalManager.eventReport(EventConstants.CANCEL_ACCOUNT) + EventReportManager.eventReport(EventConstants.CANCEL_ACCOUNT) this.logout(); ToastUtils.show('账户已注销'); } @Monitor('viewModel.logout') onLogout(monitor: IMonitor) { - EventReportGlobalManager.eventReport(EventConstants.EXIT_LOGIN) + EventReportManager.eventReport(EventConstants.EXIT_LOGIN) this.logout(); } @@ -93,13 +93,13 @@ struct SettingsPage { .backgroundColor(Color.White) .onClick(() => { this.getUIContext().getRouter().pushUrl({url: RouterUrls.BIND_ACCOUNT_PAGE}); - EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_ACCOUNT_BIND) + EventReportManager.eventReport(EventConstants.JUMP_TO_ACCOUNT_BIND) }) TextItemChildView({ text: '账号管理' }).height(60).padding({ left: 16, right: 16 }) .backgroundColor(Color.White) .onClick(() => { this.getUIContext().getRouter().pushUrl({url: RouterUrls.MANAGE_ACCOUNT_PAGE}); - EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_ACCOUNT_MANAGE) + EventReportManager.eventReport(EventConstants.JUMP_TO_ACCOUNT_MANAGE) }) Divider().strokeWidth(10).color($r('app.color.color_eff2f7')) TextItemChildView({ text: '清除缓存', rightText: FileUtil.getFormatFileSize(this.cacheSize) }).height(60) @@ -118,7 +118,7 @@ struct SettingsPage { .backgroundColor(Color.White) .onClick(() => { this.getUIContext().getRouter().pushUrl({url: RouterUrls.ABOUT_PAGE}); - EventReportGlobalManager.eventReport(EventConstants.JUMP_TO_ABOUT_US) + EventReportManager.eventReport(EventConstants.JUMP_TO_ABOUT_US) }) TextItemChildView({ text: '注销账号' }).height(60).padding({ left: 16, right: 16 }) .backgroundColor(Color.White) diff --git a/entry/src/main/ets/pages/main/mine/setting/account/BindAccountPage.ets b/entry/src/main/ets/pages/main/mine/setting/account/BindAccountPage.ets index b0b9979..6e82458 100644 --- a/entry/src/main/ets/pages/main/mine/setting/account/BindAccountPage.ets +++ b/entry/src/main/ets/pages/main/mine/setting/account/BindAccountPage.ets @@ -13,7 +13,7 @@ import { BindPhoneDialog } from '../../../../../dialog/BindPhoneDialog'; import { LevelMode } from '@kit.ArkUI'; import { EventConstants } from '../../../../../common/EventConstants'; import { LoadingDialog } from '../../../../../dialog/LoadingDialog'; -import { EventReportGlobalManager } from '../../../../../manager/EventReportGlobalManager'; +import { EventReportManager } from '../../../../../manager/EventReportManager'; @Entry @ComponentV2 @@ -48,7 +48,7 @@ struct BindAccountPage { onBindInfoChange(monitor: IMonitor) { ToastUtils.show('绑定成功'); this.refreshData(); - EventReportGlobalManager.eventReport(EventConstants.ACCOUNT_BIND) + EventReportManager.eventReport(EventConstants.ACCOUNT_BIND) } @Monitor('viewModel.unbindInfo') diff --git a/entry/src/main/ets/pages/main/mine/setting/account/ManageAccountPage.ets b/entry/src/main/ets/pages/main/mine/setting/account/ManageAccountPage.ets index c37f8ca..362125a 100644 --- a/entry/src/main/ets/pages/main/mine/setting/account/ManageAccountPage.ets +++ b/entry/src/main/ets/pages/main/mine/setting/account/ManageAccountPage.ets @@ -4,7 +4,7 @@ import { LoadingDialog } from '../../../../../dialog/LoadingDialog'; import { TipDialog } from '../../../../../dialog/TipDialog'; import { AccountEntity } from '../../../../../entity/AccountEntity'; import { LoginEntity } from '../../../../../entity/LoginEntity'; -import { EventReportGlobalManager } from '../../../../../manager/EventReportGlobalManager'; +import { EventReportManager } from '../../../../../manager/EventReportManager'; import { LoginManager } from '../../../../../manager/LoginGlobalManager'; import { ConfigManager } from '../../../../../manager/UserConfigManager'; import { ToastUtils } from '../../../../../utils/ToastUtils'; @@ -94,7 +94,7 @@ struct ManageAccountPage { confirm: () => { LoginManager.saveToken(''); this.viewModel.changeAccount(item.user_id); - EventReportGlobalManager.eventReport(EventConstants.SWITCH_ACCOUNT,item.user_id) + EventReportManager.eventReport(EventConstants.SWITCH_ACCOUNT,item.user_id) } }}) }) diff --git a/entry/src/main/ets/pages/main/mine/vip/VipPage.ets b/entry/src/main/ets/pages/main/mine/vip/VipPage.ets index b8c2d06..2c86903 100644 --- a/entry/src/main/ets/pages/main/mine/vip/VipPage.ets +++ b/entry/src/main/ets/pages/main/mine/vip/VipPage.ets @@ -16,7 +16,7 @@ import { VipViewModel } from '../../../../viewModel/VipViewModel'; import { BusinessError, systemDateTime } from '@kit.BasicServicesKit'; import router from '@ohos.router'; import { EventConstants } from '../../../../common/EventConstants'; -import { EventReportGlobalManager } from '../../../../manager/EventReportGlobalManager'; +import { EventReportManager } from '../../../../manager/EventReportManager'; import { SimpleTipDialog } from '../../../../dialog/SimpleTipDialog'; import { OrderEntity } from '../../../../entity/OrderEntity'; import { TipDialog } from '../../../../dialog/TipDialog'; @@ -52,7 +52,7 @@ struct VipPage { this.viewModel.getOrderInfo(this.orderEntity!!.orderId) } else { ToastUtils.show(JSON.parse(payResult).errStr); - EventReportGlobalManager.eventReport( + EventReportManager.eventReport( EventConstants.ERROR_CLIENT_WXPAY_ERR, `{isGuide:${this.isGuide}, orderId:${this.orderEntity?.orderId}, meal:${JSON.stringify(this.vipMeal)}}`, JSON.parse(payResult).errStr @@ -106,7 +106,7 @@ struct VipPage { const orderEntity = monitor.value()?.now as OrderEntity; if (orderEntity.status == "2") { ToastUtils.show('支付成功'); - EventReportGlobalManager.eventReport( + EventReportManager.eventReport( EventConstants.PAY_SUCCESS, 'alipay', `{isGuide:${this.isGuide}, orderId:${this.orderEntity?.orderId}, meal:${JSON.stringify(this.vipMeal)}}` ) @@ -179,13 +179,13 @@ struct VipPage { this.viewModel.getOrderInfo(this.orderEntity!!.orderId) } else if (resultStatus === '6001') { ToastUtils.show('支付取消'); - EventReportGlobalManager.eventReport( + EventReportManager.eventReport( EventConstants.PAY_CANCEL, 'alipay', `{isGuide:${this.isGuide}, orderId:${this.orderEntity?.orderId}, meal:${JSON.stringify(this.vipMeal)}}` ) } else { ToastUtils.show('支付失败'); - EventReportGlobalManager.eventReport( + EventReportManager.eventReport( EventConstants.ERROR_CLIENT_ALIPAY_ERR, `{orderId:${this.orderEntity?.orderId}, meal:${JSON.stringify(this.vipMeal)}}`, resultStatus ) @@ -240,7 +240,7 @@ struct VipPage { onBackPress(): boolean | void { if (this.isGuide) { - EventReportGlobalManager.eventReport(EventConstants.GUIDE_SKIP, "back", this.pageDuration()) + EventReportManager.eventReport(EventConstants.GUIDE_SKIP, "back", this.pageDuration()) this.getUIContext().getRouter().replaceUrl({ url: RouterUrls.MAIN_PAGE }, router.RouterMode.Single) return true; } @@ -274,7 +274,7 @@ struct VipPage { this.vipMeal = item; this.totalPrice = NumberUtil.toNumber(item.price); this.releasePayType(); - EventReportGlobalManager.eventReport(EventConstants.GOODS_SELECT, `${this.origin}:${item.goods_name}`, JSON.stringify(item)) + EventReportManager.eventReport(EventConstants.GOODS_SELECT, `${this.origin}:${item.goods_name}`, JSON.stringify(item)) }) }) } @@ -377,7 +377,7 @@ struct VipPage { .visibility(this.vipMeal?.pay_type.includes('weixin') ? Visibility.Visible : Visibility.None) .onClick(() => { this.payType = 0; - EventReportGlobalManager.eventReport(EventConstants.PAY_SELECT, 'weixin', this.origin) + EventReportManager.eventReport(EventConstants.PAY_SELECT, 'weixin', this.origin) }) Divider().color($r('app.color.color_10ffffff')).strokeWidth(1) @@ -395,7 +395,7 @@ struct VipPage { .visibility(this.vipMeal?.pay_type.includes('alipay') ? Visibility.Visible : Visibility.None) .onClick(() => { this.payType = 1; - EventReportGlobalManager.eventReport(EventConstants.PAY_SELECT, "alipay", this.origin) + EventReportManager.eventReport(EventConstants.PAY_SELECT, "alipay", this.origin) }) Divider().color($r('app.color.color_10ffffff')).strokeWidth(1) @@ -481,12 +481,12 @@ struct VipPage { confirm: () => { this.isAgree = true this.createOrder(); - EventReportGlobalManager.eventReport(EventConstants.PAY_PAY, this.payType === 0 ? 'weixin' : 'alipay', JSON.stringify(this.vipMeal)) + EventReportManager.eventReport(EventConstants.PAY_PAY, this.payType === 0 ? 'weixin' : 'alipay', JSON.stringify(this.vipMeal)) } }}) } else { this.createOrder(); - EventReportGlobalManager.eventReport(EventConstants.PAY_PAY, this.payType === 0 ? 'weixin' : 'alipay', JSON.stringify(this.vipMeal)) + EventReportManager.eventReport(EventConstants.PAY_PAY, this.payType === 0 ? 'weixin' : 'alipay', JSON.stringify(this.vipMeal)) } } }) @@ -507,7 +507,7 @@ struct VipPage { isDark: true, onBackClick: () => { if (this.isGuide) { - EventReportGlobalManager.eventReport(EventConstants.GUIDE_SKIP, "icon", this.pageDuration()) + EventReportManager.eventReport(EventConstants.GUIDE_SKIP, "icon", this.pageDuration()) } this.doBack(); } diff --git a/entry/src/main/ets/pages/splash/SplashPage.ets b/entry/src/main/ets/pages/splash/SplashPage.ets index 8363d50..af9e070 100644 --- a/entry/src/main/ets/pages/splash/SplashPage.ets +++ b/entry/src/main/ets/pages/splash/SplashPage.ets @@ -6,7 +6,7 @@ import { LevelMode, router } from '@kit.ArkUI'; import { LoginManager } from '../../manager/LoginGlobalManager'; import { LoadingDialog } from '../../dialog/LoadingDialog'; import { AppUtil, StrUtil } from '@pura/harmony-utils'; -import { EventReportGlobalManager } from '../../manager/EventReportGlobalManager'; +import { EventReportManager } from '../../manager/EventReportManager'; import { EventConstants } from '../../common/EventConstants'; import { GyConfig, GyManager } from '@getui/gysdk'; import { hilog } from '@kit.PerformanceAnalysisKit'; @@ -51,7 +51,7 @@ struct SplashPage { this.privacyDialogController = new CustomDialogController({ builder: PrivacyPolicyDialog({ confirm: () => { - EventReportGlobalManager.eventReport(EventConstants.APP_LAUNCH, '', '') + EventReportManager.eventReport(EventConstants.APP_LAUNCH, '', '') LoadingDialog.show(this.getUIContext()); ConfigManager.saveIsAgreePrivacy(true); ConfigManager.getOaid() diff --git a/entry/src/main/ets/view/RecordItemView.ets b/entry/src/main/ets/view/RecordItemView.ets index bd10562..ab925fb 100644 --- a/entry/src/main/ets/view/RecordItemView.ets +++ b/entry/src/main/ets/view/RecordItemView.ets @@ -1,6 +1,6 @@ import { RouterUrls } from '../common/RouterUrls'; import { MediaRecordEntity } from '../entity/MediaRecordEntity'; -import { router } from '@kit.ArkUI'; +import { LevelMode, router } from '@kit.ArkUI'; import { AppUtil, DateUtil, DisplayUtil, StrUtil } from '@pura/harmony-utils'; import { ShareManager } from '../manager/ShareManager'; import { Want } from '@kit.AbilityKit'; @@ -10,6 +10,7 @@ import { WantUtils } from '../utils/WantUtils'; import { media } from '@kit.MediaKit'; import { fileIo } from '@kit.CoreFileKit'; import { image } from '@kit.ImageKit'; +import { AudioPlayerDialog } from '../dialog/AudioPlayerDialog'; @ComponentV2 export struct VideoRecordItemView { @@ -158,6 +159,29 @@ export struct ImageRecordItemView { @ComponentV2 export struct AudioRecordItemView { @Param media?: MediaRecordEntity = undefined; + @Param index: number = 0; + + private audioPlayerDialogController?: CustomDialogController | null; + + aboutToDisappear() { + this.audioPlayerDialogController = null + } + + showBindPhoneDialog(index: number) { + this.audioPlayerDialogController = new CustomDialogController({ + builder: AudioPlayerDialog({ + index: index + }), + width: '100%', + cornerRadius: { topLeft: 16, topRight: 16 }, + autoCancel: false, + maskColor: '#CC000000', + levelMode: LevelMode.EMBEDDED, + backgroundBlurStyle: BlurStyle.NONE, + alignment: DialogAlignment.Bottom + }) + this.audioPlayerDialogController.open(); + } formatTime(time: number): string { let minute: number = 0 @@ -235,12 +259,7 @@ export struct AudioRecordItemView { .height(74) .padding({left: 14, right: 14}) .onClick(() => { - this.getUIContext() - .getRouter() - .pushUrl({ - url: RouterUrls.AUDIO_PLAYER_PAGE, - params: { title: this.media?.name, uri: this.media?.uri, showActions: true } - }, router.RouterMode.Single) + this.showBindPhoneDialog(this.index) }) } } \ No newline at end of file diff --git a/entry/src/main/ets/viewModel/AuthViewModel.ets b/entry/src/main/ets/viewModel/AuthViewModel.ets index 696ec41..94b2e4d 100644 --- a/entry/src/main/ets/viewModel/AuthViewModel.ets +++ b/entry/src/main/ets/viewModel/AuthViewModel.ets @@ -1,12 +1,12 @@ import { plainToInstance } from "class-transformer"; -import { VipPermissionEntity } from "../entity/VipPermissionEntity"; +import { VipAuthEntity } from "../entity/VipAuthEntity"; import { apiService } from "../net/ApiService"; import { ToastUtils } from "../utils/ToastUtils"; import { BaseViewModel } from "./BaseViewModel"; @ObservedV2 export class AuthViewModel extends BaseViewModel { - @Trace permissionInfo?: VipPermissionEntity + @Trace authInfo?: VipAuthEntity @Trace errorCode: number = 0; async checkVip() { @@ -14,7 +14,7 @@ export class AuthViewModel extends BaseViewModel { try { const result = await apiService.checkPermission('download'); if (result.isSuccess()) { - this.permissionInfo = plainToInstance(VipPermissionEntity, result.data); + this.authInfo = plainToInstance(VipAuthEntity, result.data); } else { this.errorCode = result.code ToastUtils.show(result.message, true); diff --git a/entry/src/main/ets/viewModel/FeedbackViewModel.ets b/entry/src/main/ets/viewModel/FeedbackViewModel.ets index ef4bc32..3670acb 100644 --- a/entry/src/main/ets/viewModel/FeedbackViewModel.ets +++ b/entry/src/main/ets/viewModel/FeedbackViewModel.ets @@ -60,6 +60,7 @@ export class FeedbackViewModel extends BaseViewModel { FileUtil.readSync(file2.fd, buffer); FileUtil.fsyncSync(file2.fd); FileUtil.closeSync(file2.fd); + FileUtil.closeSync(file); const base64Str = Base64Util.encodeToStrSync(new Uint8Array(buffer)) diff --git a/entry/src/main/ets/viewModel/TakeMaterialViewModel.ets b/entry/src/main/ets/viewModel/TakeMaterialViewModel.ets index ce6fcf2..d0e624f 100644 --- a/entry/src/main/ets/viewModel/TakeMaterialViewModel.ets +++ b/entry/src/main/ets/viewModel/TakeMaterialViewModel.ets @@ -1,6 +1,6 @@ import { plainToInstance } from 'class-transformer'; import { MaterialInfoEntity } from '../entity/MaterialInfoEntity'; -import { VipPermissionEntity } from '../entity/VipPermissionEntity'; +import { VipAuthEntity } from '../entity/VipAuthEntity'; import { apiService } from '../net/ApiService'; import { ToastUtils } from '../utils/ToastUtils'; import { BaseViewModel } from './BaseViewModel'; @@ -9,7 +9,7 @@ import { BaseViewModel } from './BaseViewModel'; export class TakeMaterialViewModel extends BaseViewModel { @Trace materialInfo?: MaterialInfoEntity; @Trace analysisInfo?: MaterialInfoEntity; - @Trace permissionInfo?: VipPermissionEntity; + @Trace permissionInfo?: VipAuthEntity; @Trace errorCode: number = 0; private intervalId = 0 @@ -74,7 +74,7 @@ export class TakeMaterialViewModel extends BaseViewModel { try { const result = await apiService.checkPermission('download'); if (result.isSuccess()) { - this.permissionInfo = plainToInstance(VipPermissionEntity, result.data); + this.permissionInfo = plainToInstance(VipAuthEntity, result.data); } else { this.errorCode = result.code ToastUtils.show(result.message, true); diff --git a/entry/src/main/ets/viewModel/UserSettingsViewModel.ets b/entry/src/main/ets/viewModel/UserSettingsViewModel.ets index bfa9427..a972479 100644 --- a/entry/src/main/ets/viewModel/UserSettingsViewModel.ets +++ b/entry/src/main/ets/viewModel/UserSettingsViewModel.ets @@ -63,6 +63,7 @@ export class UserSettingsViewModel extends BaseViewModel { FileUtil.readSync(file2.fd, buffer); FileUtil.fsyncSync(file2.fd); FileUtil.closeSync(file2.fd); + FileUtil.closeSync(file); const base64Str = Base64Util.encodeToStrSync(new Uint8Array(buffer)) diff --git a/entry/src/main/ets/viewModel/WxVideoViewModel.ets b/entry/src/main/ets/viewModel/WxVideoViewModel.ets index be11175..9aa8471 100644 --- a/entry/src/main/ets/viewModel/WxVideoViewModel.ets +++ b/entry/src/main/ets/viewModel/WxVideoViewModel.ets @@ -1,5 +1,5 @@ import { plainToInstance } from 'class-transformer'; -import { VipPermissionEntity } from '../entity/VipPermissionEntity'; +import { VipAuthEntity } from '../entity/VipAuthEntity'; import { WxVideoEntity } from '../entity/WxVideoEntity'; import { WxVideoServiceEntity } from '../entity/WxVideoServiceEntity'; import { apiService } from '../net/ApiService'; @@ -10,7 +10,7 @@ import { BaseViewModel } from './BaseViewModel'; export class WxVideoViewModel extends BaseViewModel { @Trace wxVideo?: WxVideoEntity; @Trace deleteVideo?: object; - @Trace permissionInfo?: VipPermissionEntity; + @Trace permissionInfo?: VipAuthEntity; @Trace errorCode: number = 0; @Trace wxService?: WxVideoServiceEntity @Trace wxUserinfo?: object @@ -63,7 +63,7 @@ export class WxVideoViewModel extends BaseViewModel { try { const result = await apiService.checkPermission('download'); if (result.isSuccess()) { - this.permissionInfo = plainToInstance(VipPermissionEntity, result.data); + this.permissionInfo = plainToInstance(VipAuthEntity, result.data); } else { this.errorCode = result.code ToastUtils.show(result.message, true); diff --git a/entry/src/main/resources/base/media/ic_add_audio.png b/entry/src/main/resources/base/media/ic_add_audio.png deleted file mode 100644 index 1e8323287462151c665f0be2246c8458ebb0b282..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7139 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 literal 0 HcmV?d00001 diff --git a/entry/src/main/resources/base/media/ic_audio_pause.webp b/entry/src/main/resources/base/media/ic_audio_pause.webp new file mode 100644 index 0000000000000000000000000000000000000000..ef2bddcbd02cec01e3fc6eca6ec52eb0bfb81f52 GIT binary patch literal 460 zcmV;-0WA*3GGNCQACm#~6Tr!PEY?(tpe7!eZyU*#2|6htMe=0)Q& z?FMJag=g>mv>ZoXRm^piPnX@`mFsQjrptMFEo8fGr)!fNp8I6F*0#1}JenynKHxa| zm=evSjLwu=_#A#gnRY~AL2`ADh9hMtp<+psrusb9oRDng-+w>gU_o+qU~D*2h7zDl zDtr#VAaz0HqoKry9EUN*Jj&Q^+jYqeu-+%@Y->vfTu1o|H+Ti+x1n2+hu0vr=7pm& z?FMJag=axGEk~hO1<48#gd!^VDh~iwP&gp40000`2>_h|Dp~+q06vjEnn$IhqM5C8!F_|6S|kNr=cgAwI}fQ3rMvgp{7$&ZqInJQ=;^LR$WI^dy5rsYz4ukb{A*8VF;J>AU&P*@RTb%2f6E1e zeA{PovD{doInFVeDt3TJU{@rnedGdB{;?*D+WIMw{n=8bP`W#T?yjpypqNL2@X=K6 zrgo14k_(C!Nr2LZqD={)aiHkXfW$DMC>SQRsUUf(Wna+rB3pE5a*Ac2 zCckV5qKyGng9%lWIaTvDRcnVT$EC{ksPaOpLb^PvJeMlhp~_iPwVqQopHMX!P&F{9 zGRi(pe!1w-s`Y!qVW@hhJ&<`T%ZbJ)Z)<$8H0C#_{7b9U^4a zEq>c7ivpBBetiX^W#a(1V9X%uoXs)gb`BzEm5-Qxtgz?+YCrM%S%dqwc3ACNaA&o9 z#Oc^o?*)o^#OP=$aDSz{!)Mo3Kt{Fo6Puqc6(p^F(Jw;Th$?K6;Fsm}cP`Ln75@-w~nHEv&fI)hlU2bLSgCv>fc3}UM_ty5f1mZ3qM znOZkr>ZxJ=nu<)0RH(kXY6!$?n!Isx6A97ZfW0OC9I*$ zx;hq;V?-lyKcA}viQ|b59#`-G*pC19GGG7LkJ0?w@%6?C&H)M%JSB&MqFDdOKQA%3 znqWffumAXe-+*orL$t;m)MYdB&s4LcONhyg1=*;oTVAi8RHhU5GNyg2x1ohuZ-9T0 zpO0?z{yW(vVUR~3k2NCl>) z9#?^o5KRPIb?7`9K0(WsUE&W8@$RxL-T+Sk(XwhTk6z@5G^H+5&E5D4nP|4yb8vgs zs29ez-)(XH;7+0LFOPGcvnJY4O>ChZ=6Y=1o7iOe)K_DG&ag;3_X|@L zRCCfpoP~9V`;%SUrh^m zHztS{jJ;(#E8yWsH(Ic5P1IQdmwR~7!rQH(w1DdkuC(xEUK}l0Pgkg{fHwmJ6jre9 zEzw!Qet$460J~B(TDCJ?-B*!iyQvv|udrriG7{ys(DY1s7hITzRb$ zTJOtf8B0A_J)06Cq)z6$2&dN@BE^IbVLQ>zMM!N(R)v!7Zf`|QYC7wVd`&pL=;bfw zHJ9ahks_QP&5ROLo9SAmi*S0gI#A4RnhTxXg_CVVtR|f94RjSpG{dKzMVfGWGc-UP zw8f0GMT&5GIVVaSw}q~ixC^Iu>x0FiTjG3oZ{cL!oT>^X`=b%=;_%I6>?=@&)8|ov zicqo~D-e#&@M?adkh)OmCM+K};oXin;d!)C_VeA{h3Je%9m>>%X~zAZ*dLBig{w>7 zmp?jEsta4Us?&Dh`GjC$tY@~b@{#`o0aj2rAjkj!05AvuodGIZ09pV(kv^J8C8MID zDypck5(#Ml)wzom^0AG3_L&~#k-2Bw+joo*o7f@p*RF-i$3C1uA6S}CX5Of*?Z>(( z1kC^d{`VXIxLkXPFC8VsZ^p0Nw|<`xn%y$w>ScjajKsmW!0Bs(a{x1(_rG#&fC3EF z7MGg5$G*xf75PUBe<(;+kwcmRVG(mMHz=R}S&x3m?SUJ`S4C3JQDyyr4)=uCL(zT- c^Zf~^f`q{YzW}WhKZgbu0jw`9%A}A00MOiGumAu6 literal 0 HcmV?d00001 diff --git a/entry/src/main/resources/base/media/ic_audio_play2.webp b/entry/src/main/resources/base/media/ic_audio_play2.webp new file mode 100644 index 0000000000000000000000000000000000000000..d4b0a6197ae367473fb2370430d274a4dc0d9dde GIT binary patch literal 1434 zcmV;L1!ekDNk&GJ1pok7MM6+kP&il$0000G0001Y004IY06|PpNUQ?@00E%0Y}=f` zdOt}NQ%MRd1;u_A?Jez`MT`iRB3Pvr|A%0ue?bVO&~7%t%5wJ6Ak02S8%YRXzL|4e z;+OaBBVqzT@`RQxmW{z=zII$M3_aIb&nE+;T+C_-z&lxL45u#~Uqt9TFQ&srDT!0T zTx<@3xMOhGEX)En>3rMvgp{7$&ZqInJQ=;^LR$WI^dy5rsYz4ukb{A*8VF;J>AU&P*@RTb%2f6E1e zeA{PovD{doInFVeDt3TJU{@rnedGdB{;?*D+WIMw{n=8bP`W#T?yjpypqNL2@X=K6 zrgo14k_(C!Nr2LZqD={)aiHkXfW$DMC>SQRsUUf(Wna+rB3pE5a*Ac2 zCckV5qKyGng9%lWIaTvDRcnVT$EC{ksPaOpLb^PvJeMlhp~_iPwVqQopHMX!P&F{9 zGRi(pe!1w-s`Y!qVW@hhJ&<`T%ZbJ)Z)<$8H0C#_{7b9U^4a zEq>c7ivpBBetiX^W#a(1V9X%uoXs)gb`BzEm5-Qxtgz?+YCrM%S%dqwc3ACNaA&o9 z#Oc^o?*)o^#OP=$aDSz{!)Mo3Kt{Fo6Puqc6(p^F(Jw;Th$?K6;Fsm}cP`Ln75@-w~nHEv&fI)hlU2bLSgCv>fc3}UM_ty5f1mZ3qM znOstKmh!q-Yl`qNX>*QYP@z>82)WF_t(@~ zihvMPeRoMP`*j`(`MSVE*jWFmcaQ8g3*5OK(%=mm0(Kg@SdJJJKtJf;|MAzWz!r8H z(BEtq3thO-tHQ+Z6=r~ozPAZ-k=@#Gmq(#!Zw?E{S7zv0&IW~e^uCdqeh4+MW zXN;}QC;c?|Urlb4a=Kb{Y|H@@yAGo;O(Vtx3V`)@bQ(rP>1}*-CRvC+#Ba;M3z#kz o+eO~_#s5^JE)V)!Ft7job&ty3#@K?&2QHQz*wKCe_?n;q0JaOSt^fc4 literal 0 HcmV?d00001 diff --git a/entry/src/main/resources/base/media/ic_last_audio_disable.webp b/entry/src/main/resources/base/media/ic_last_audio_disable.webp new file mode 100644 index 0000000000000000000000000000000000000000..690f9a6c8c2d6ac7df35c57e3804331f409bf1f1 GIT binary patch literal 676 zcmV;V0$cr3Nk>0ssJ4MM6+kP&il$0000G0000x0027x06|PpNQ?mh00EG@ZQJoT z&+q-koNU`pR@=6n{0&@d+a9gGoosWCt-JW)=yxC8BSK-@whcQU$a+CUYzl8p&)&?j z7sj%jm;r!=F%7p4aKVvne(k`vTqG z5{Ld5+ce>~7XcE7vM&IMia)jjn&yvNAW=c*0FYRBKiQ)3zq$aB*yq0iNOaMM7C=+; zW)mdJ=O_RY%le0#G+q~G0TSD+=KzT=e9t^+GM{aNCVmm1vAzo;|1bY5>)T8cH^(HI zPdA8kAv@-IL~IOWfg6ML*yrV(y+k5X`DPPf=U8@bC)SjCBC&3Jyu~9b==@*g+Rg46 zc)d#LMz4MR~v$e9l^=XXEDsnB|Je0y5vvS^<{Hqaq{6i8gm20RHZe z>#ARQ89Va!f9&@y|A`_Sfa6k2kLx&Fe%(qh8{LIBi{FG+Y4O2_kOJnllb1-Rz8a}A zPV*kxBr7;r@DdmdsT{{}q#XISRo3qtzJ8)g6a z)~-oSh>gg-EyS=J(08d`D#bql2k1aMV>1(-$Od17vVZ?s$i$456K*7LVVB9lK@G$Z Kd&8NJfB*o}tvwe2 literal 0 HcmV?d00001 diff --git a/entry/src/main/resources/base/media/ic_last_audio_enable.webp b/entry/src/main/resources/base/media/ic_last_audio_enable.webp new file mode 100644 index 0000000000000000000000000000000000000000..c0fd7c7a94c1fabe8521cfd325a3fc20d28ba811 GIT binary patch literal 622 zcmV-!0+IbvNk&Fy0ssJ4MM6+kP&il$0000G0000x0027x06|PpNQ?mh00EG@ZQJoT z&+q-koNU`pR@=6n{0&@d+a9gGoosWCt-JW)=yxC8BSK-@whcQU$a+CUYzl8p&)&?j z7sj%jm;r!=F%7p4aKVvne(k`vTqG z5{Ld5+ce>~7XcE7vM&IMia)jjn&yvNAW=c*0FYRBKiQ)3zq$aB*yq0iNOaMM7C=+; zW)mdJ=O_RY%le0#G+q~G0TSD+=KzT=e9t^+GM{aNCVmm1vAzo;|1bY5>)T8cH^(HI zPdA8kAv@-IL~IOWfg6ML*yrV(y+k5X`DPPf=U8@bC)SjCBC&3Jyu~9b==@*g+Rg46 zc)d#LM-DMW@2YRV5I~m<62K*m2LVg0JbI20RHsA00B7<*Lv}{*bZCzx8P=1 zwNDbQzz7O#>rdX>gN~Qlm=|yFc1+4hZR#^joHanF@=5B$mSh(*@3f;TywDQEm9ueG zg;8)%uH@eMrTL`uWv(M&3*u}>=4-K?{vz)DF-L?`qcjEHPuKbX#@SGC=oad_8UPaj I^AH|r03&=Rn*aa+ literal 0 HcmV?d00001 diff --git a/entry/src/main/resources/base/media/ic_share_audio.webp b/entry/src/main/resources/base/media/ic_share_audio.webp new file mode 100644 index 0000000000000000000000000000000000000000..e7fc064de8946bc6a3407c4c014be73d26014271 GIT binary patch literal 1048 zcmV+z1n2uwNk&Ex1ONb6MM6+kP&il$0000G0000x0027x06|PpNGAdS00EFhZQJoU z-}ukewrwM)wz;xxjlHh1vTfV8ZFj8xCpyW0m%mc(B4Pr>e^;sb=$HhJV+*S)HEC)Y z{aRg2v?*w`#rmtT%yYPw=hDd%BBST#+$stl1=na_eL^zP^TQB76#?OPNb96aYZ-VM zVXdLDyd>1-KMvfls)KYMI9)*)T>3S5R^`^#JP}@15{7sC1o9MZW9<+jj1Nq3LUvnC zaSB+C2rN*x(TLgGZhZ6rk1J?N0BY!0q2JuYuigCIHPt-6byvU6R#0slZI-|)OC0>z zmj3Z|ssbF#XOev3@A%&Hbl0pg-5b^2<$*_4g*gfzu>siDcPyRPPY5y54r%R#DSYeP z1w0=Xmli+tX>JE+e4sh1T~xrep{bwvagE!+fuh0`xvzR4dqN)ZQ_CVZyeT70Vc7tr zjrJ2iFL)Hv+6hzm4$cDmgg~J(V0>aqm}HJ3XMwl?q1sZRVz4kre-E4~Ec6U47;Kny zAF>Dg>XBo{u?3}#>Z!nuTtd&v88{{x^Bp6im8D!`8mNv<-TX@S*8A81# z%nhBqCLTPsyr%C*_tg?!6VyAbv9H${`Ohat0joKzpu}kzZG#ANM1yU#mgb4@vVs{Z zy@JH%TBP&9=}N{`Is=@Sw20O+@G9C`!_a2oF9Er=&>oVBNi#!)j+PMF9CC<74B07(UQXn^<1YDr8`$>dY{hD1@*?y?JemdfMHBeTgjiEo?Vxg0M0@u=ZEZ}uq5R4m~R zHvtcXHUuY}kNcOW|NDx=0OGAcCgDLY3Rh9?8S?+tqmvxN4IFmV|LEEJll?|qiWN-@ zMA=DvUE1ubz9fK&EnHYiKju{UKzI>Yvfy~lVNQ!C!`jMF0By=18!*S9hi+R)1LEgy SQ`LmJbb_=5eTSsYzyJU(pYC1& literal 0 HcmV?d00001 diff --git a/entry/src/main/resources/base/profile/main_pages.json b/entry/src/main/resources/base/profile/main_pages.json index 79fa07c..994f741 100644 --- a/entry/src/main/resources/base/profile/main_pages.json +++ b/entry/src/main/resources/base/profile/main_pages.json @@ -12,11 +12,7 @@ "pages/main/home/tools/AddWatermarkPage", "pages/main/home/tools/RemoveWatermarkPage", "pages/main/home/tools/MD5ResetPage", - "pages/main/home/tools/VideoReversePage", - "pages/main/home/tools/VideoMirrorPage", - "pages/main/home/tools/ClipVideoPage", "pages/main/home/tools/RemoveAudioPage", - "pages/main/home/tools/AddAudioPage", "pages/main/home/tools/VideoToAudioPage", "pages/main/home/tools/ImageMergePage", "pages/main/home/tools/VideoToTextPage",