Merge branch 'main' of http://192.168.1.42/developOne/harmonyPool into main
* 'main' of http://192.168.1.42/developOne/harmonyPool: ref |> 处理直播上墙、回复消息、封禁、解封、预显控制、弹幕开关、结束直播、显示垫片控制 ref |> 直播IM消息显示,处理竖屏直播 ref |> 直播IM动态接收消息和显示。目前是横屏直播已处理 ref |> 处理播控中心不生效问题 ref |> 音频播放接入系统播控中心
Showing
25 changed files
with
804 additions
and
150 deletions
| @@ -19,11 +19,11 @@ export interface LiveRoomItemBean { | @@ -19,11 +19,11 @@ export interface LiveRoomItemBean { | ||
| 19 | //guest :嘉宾,host:主持人 | 19 | //guest :嘉宾,host:主持人 |
| 20 | role: string | 20 | role: string |
| 21 | //ZH_TEXT_AND_IMAGE_MSG :图文,ZH_TEXT_MSG:文本,ZH_VIDEO_MSG:视频,ZH_AUDIO_MSG:音频 | 21 | //ZH_TEXT_AND_IMAGE_MSG :图文,ZH_TEXT_MSG:文本,ZH_VIDEO_MSG:视频,ZH_AUDIO_MSG:音频 |
| 22 | - dataType: string | 22 | + dataType: LiveMessageOptType |
| 23 | //管理直播间的消息类型 ZH_BARRAGE_SWITCH_MSG:弹幕开关 ZH_TOP_MSG:置顶,ZH_UN_TOP_MSG:取消置顶 ZH_STOP_LIVE: 直播结束,ZH_CHANGE_PAD直播垫片等 | 23 | //管理直播间的消息类型 ZH_BARRAGE_SWITCH_MSG:弹幕开关 ZH_TOP_MSG:置顶,ZH_UN_TOP_MSG:取消置顶 ZH_STOP_LIVE: 直播结束,ZH_CHANGE_PAD直播垫片等 |
| 24 | - optionType: string | 24 | + optionType: LiveMessageOptType |
| 25 | ///房间类型,标识这个消息属于大家聊还是直播间,ZH_VIDEO:直播间 ZH_CHAT:大家聊 | 25 | ///房间类型,标识这个消息属于大家聊还是直播间,ZH_VIDEO:直播间 ZH_CHAT:大家聊 |
| 26 | - messageRoom: string | 26 | + messageRoom: LiveMessageRoomType |
| 27 | //视频封面图 | 27 | //视频封面图 |
| 28 | transcodeImageUrl: string | 28 | transcodeImageUrl: string |
| 29 | //视频地址 | 29 | //视频地址 |
| @@ -39,4 +39,72 @@ export interface LiveRoomItemBean { | @@ -39,4 +39,72 @@ export interface LiveRoomItemBean { | ||
| 39 | //观看人次 | 39 | //观看人次 |
| 40 | pv: string | 40 | pv: string |
| 41 | 41 | ||
| 42 | + ///------- from IM | ||
| 43 | + // 自义定表情 | ||
| 44 | + customizeExpression: number | ||
| 45 | + // 已登录的用户id | ||
| 46 | + senderUserId?: string | ||
| 47 | + // 未登录的设备id | ||
| 48 | + deviceId?: string | ||
| 49 | + // data字段,评论预显开关 | ||
| 50 | + data?: string | ||
| 51 | + // receiver | ||
| 52 | + receiverText?: string | ||
| 53 | + receiverTime?: string | ||
| 54 | + receiverUserId?: string | ||
| 55 | + receiverUserName?: string | ||
| 56 | + receiverAvatarUrl?: string | ||
| 57 | + | ||
| 58 | + // 自定义字段 | ||
| 59 | + customFormIM?: boolean // 默认来自网络接口 | ||
| 60 | +} | ||
| 61 | + | ||
| 62 | +export enum LiveMessageOptType { | ||
| 63 | + ZH_BARRAGE_SWITCH_MSG = "ZH_BARRAGE_SWITCH_MSG", | ||
| 64 | + ZH_UPDATE_MSG = "ZH_UPDATE_MSG", | ||
| 65 | + ZH_DELETE_MSG = "ZH_DELETE_MSG", | ||
| 66 | + ZH_TOP_MSG = "ZH_TOP_MSG", | ||
| 67 | + ZH_UN_TOP_MSG = "ZH_UN_TOP_MSG", | ||
| 68 | + ZH_STOP_LIVE = "ZH_STOP_LIVE", | ||
| 69 | + ZH_CHANGE_PAD = "ZH_CHANGE_PAD", | ||
| 70 | + ZH_PRE_DISPLAY_CHANGE = "ZH_PRE_DISPLAY_CHANGE", | ||
| 71 | + ZH_TEXT_MSG = "ZH_TEXT_MSG", | ||
| 72 | + ZH_IMAGE_MSG = "ZH_IMAGE_MSG", | ||
| 73 | + ZH_TEXT_AND_IMAGE_MSG = "ZH_TEXT_AND_IMAGE_MSG", | ||
| 74 | + ZH_WALL_MSG = "ZH_WALL_MSG", | ||
| 75 | + ZH_AUDIO_MSG = "ZH_AUDIO_MSG", | ||
| 76 | + ZH_VIDEO_MSG = "ZH_VIDEO_MSG", | ||
| 77 | + ZH_REPLY_MSG = "ZH_REPLY_MSG", | ||
| 78 | + ZH_ROOM_NUMBER_MSG = "ZH_ROOM_NUMBER_MSG", | ||
| 79 | + ZH_BARRAGE_BAN_MESSAGE = "ZH_BARRAGE_BAN_MESSAGE", | ||
| 80 | + ZH_BARRAGE_UNBAN_MESSAGE = "ZH_BARRAGE_UNBAN_MESSAGE", | ||
| 81 | + ZH_VOTE_MESSAGE = "ZH_VOTE_MESSAGE", | ||
| 82 | + ZH_START_LIVE = "ZH_START_LIVE", | ||
| 83 | +} | ||
| 84 | + | ||
| 85 | +export enum LiveMessageRoomType { | ||
| 86 | + living = "ZH_VIDEO", // 直播间 | ||
| 87 | + chat = "ZH_CHAT", // 大家聊 | ||
| 88 | +} | ||
| 89 | + | ||
| 90 | +export enum LiveMessageRole { | ||
| 91 | + host = "host", | ||
| 92 | + guest = "guest", | ||
| 93 | + tourist = "tourist", | ||
| 94 | +} | ||
| 95 | + | ||
| 96 | +export function LiveMessageIsHistoryMessage(optionType: LiveMessageOptType): boolean { | ||
| 97 | + let isHistoryMessage = false | ||
| 98 | + switch (optionType) { | ||
| 99 | + case LiveMessageOptType.ZH_TEXT_MSG: | ||
| 100 | + case LiveMessageOptType.ZH_IMAGE_MSG: | ||
| 101 | + case LiveMessageOptType.ZH_TEXT_AND_IMAGE_MSG: | ||
| 102 | + case LiveMessageOptType.ZH_AUDIO_MSG: | ||
| 103 | + case LiveMessageOptType.ZH_VIDEO_MSG: { | ||
| 104 | + isHistoryMessage = true | ||
| 105 | + } break; | ||
| 106 | + default: | ||
| 107 | + break; | ||
| 108 | + } | ||
| 109 | + return isHistoryMessage | ||
| 42 | } | 110 | } |
| 1 | import { DateTimeUtils, Logger } from 'wdKit/Index'; | 1 | import { DateTimeUtils, Logger } from 'wdKit/Index'; |
| 2 | -import { WDPlayerController } from 'wdPlayer/Index'; | 2 | +import { PlayerConstants, WDPlayerController } from 'wdPlayer/Index'; |
| 3 | 3 | ||
| 4 | let TAG: string = 'AudioRowComponent' | 4 | let TAG: string = 'AudioRowComponent' |
| 5 | 5 | ||
| @@ -12,6 +12,16 @@ export struct AudioRowComponent { | @@ -12,6 +12,16 @@ export struct AudioRowComponent { | ||
| 12 | @State isPlaying: boolean = false | 12 | @State isPlaying: boolean = false |
| 13 | 13 | ||
| 14 | aboutToAppear(): void { | 14 | aboutToAppear(): void { |
| 15 | + this.playerController.onCanplay = () => { | ||
| 16 | + this.playerController.play() | ||
| 17 | + } | ||
| 18 | + this.playerController.onStatusChange = (status: number) => { | ||
| 19 | + if (status == PlayerConstants.STATUS_START) { | ||
| 20 | + this.isPlaying = true | ||
| 21 | + } else { | ||
| 22 | + this.isPlaying = false | ||
| 23 | + } | ||
| 24 | + } | ||
| 15 | this.playerController.firstPlay(this.audioUrl) | 25 | this.playerController.firstPlay(this.audioUrl) |
| 16 | // this.playerController.onTimeUpdate = (nowSeconds, totalSeconds) => { | 26 | // this.playerController.onTimeUpdate = (nowSeconds, totalSeconds) => { |
| 17 | // console.log('现在时间', nowSeconds) | 27 | // console.log('现在时间', nowSeconds) |
| @@ -30,7 +40,7 @@ export struct AudioRowComponent { | @@ -30,7 +40,7 @@ export struct AudioRowComponent { | ||
| 30 | left: 8, | 40 | left: 8, |
| 31 | right: 6 | 41 | right: 6 |
| 32 | }) | 42 | }) |
| 33 | - .visibility(this.isPlaying ? Visibility.Visible : Visibility.Hidden) | 43 | + .visibility(this.isPlaying ? Visibility.Hidden : Visibility.Visible) |
| 34 | Text(`${DateTimeUtils.getFormattedDuration(this.duration)}`) | 44 | Text(`${DateTimeUtils.getFormattedDuration(this.duration)}`) |
| 35 | .fontColor('#666666') | 45 | .fontColor('#666666') |
| 36 | .fontWeight(400) | 46 | .fontWeight(400) |
| @@ -73,7 +73,7 @@ export struct LiveOperRowListView { | @@ -73,7 +73,7 @@ export struct LiveOperRowListView { | ||
| 73 | private isLlive = false | 73 | private isLlive = false |
| 74 | /// comment | 74 | /// comment |
| 75 | @State showCommentInput: boolean = false | 75 | @State showCommentInput: boolean = false |
| 76 | - private banComment: boolean = true // 是否已禁言 | 76 | + @Consume banComment: boolean // 上层可以直播IM控制 |
| 77 | private commentInputDialogController?: CustomDialogController | 77 | private commentInputDialogController?: CustomDialogController |
| 78 | @State publishCommentModel: publishCommentModel = new publishCommentModel() | 78 | @State publishCommentModel: publishCommentModel = new publishCommentModel() |
| 79 | 79 |
| @@ -372,7 +372,7 @@ export struct OperRowListView { | @@ -372,7 +372,7 @@ export struct OperRowListView { | ||
| 372 | .gesture( | 372 | .gesture( |
| 373 | TapGesture() | 373 | TapGesture() |
| 374 | .onAction((event: GestureEvent) => { | 374 | .onAction((event: GestureEvent) => { |
| 375 | - this.AudioSuspension.setPlayerUrl(this.audioUrl, this.audioTitle) | 375 | + this.AudioSuspension.setPlayerUrl(this.audioUrl, this.audioTitle, this.contentDetailData.newsId + "", this.contentDetailData.newsSourceName) |
| 376 | TrackingButton.click('suspendedWindow',this.pageId,this.pageName) | 376 | TrackingButton.click('suspendedWindow',this.pageId,this.pageName) |
| 377 | })) | 377 | })) |
| 378 | } | 378 | } |
| 1 | import window from '@ohos.window'; | 1 | import window from '@ohos.window'; |
| 2 | import { Logger } from 'wdKit'; | 2 | import { Logger } from 'wdKit'; |
| 3 | -import { WDPlayerController } from 'wdPlayer'; | 3 | +import { BackgroundAudioController, WDPlayerController } from 'wdPlayer'; |
| 4 | import { BusinessError } from '@ohos.base'; | 4 | import { BusinessError } from '@ohos.base'; |
| 5 | import { EmitterEventId, EmitterUtils } from 'wdKit/Index' | 5 | import { EmitterEventId, EmitterUtils } from 'wdKit/Index' |
| 6 | 6 | ||
| @@ -39,9 +39,18 @@ export class AudioSuspensionModel { | @@ -39,9 +39,18 @@ export class AudioSuspensionModel { | ||
| 39 | /** | 39 | /** |
| 40 | * 配置音频地址 | 40 | * 配置音频地址 |
| 41 | */ | 41 | */ |
| 42 | - public setPlayerUrl(url: string, srcTitle: string) { | 42 | + public async setPlayerUrl(url: string, srcTitle: string, srcContentId?: string, srcSource?: string) { |
| 43 | /*console.log(TAG,'this.url', this.url) | 43 | /*console.log(TAG,'this.url', this.url) |
| 44 | console.log(TAG,'url', url)*/ | 44 | console.log(TAG,'url', url)*/ |
| 45 | + this.playerController.get().keepOnBackground = true | ||
| 46 | + BackgroundAudioController.sharedController().avplayerController = this.playerController.get() | ||
| 47 | + await BackgroundAudioController.sharedController().createSession() | ||
| 48 | + BackgroundAudioController.sharedController().startContinuousTask() | ||
| 49 | + let id = $r('app.media.newspaper_default').id | ||
| 50 | + BackgroundAudioController.sharedController().setSessionMetaData(srcContentId ?? "", srcTitle, 'file://', srcSource ?? "") | ||
| 51 | + BackgroundAudioController.sharedController().stopUseFeatures() | ||
| 52 | + BackgroundAudioController.sharedController().listenPlayEvents() | ||
| 53 | + | ||
| 45 | if (this.url === url) { | 54 | if (this.url === url) { |
| 46 | this.isMinimize = AppStorage.link<boolean>('isMinimize') | 55 | this.isMinimize = AppStorage.link<boolean>('isMinimize') |
| 47 | console.log(TAG, 'this.isMinimize', this.isMinimize?.get()) | 56 | console.log(TAG, 'this.isMinimize', this.isMinimize?.get()) |
| @@ -10,6 +10,8 @@ import { LiveRoomItemBean } from 'wdBean/Index'; | @@ -10,6 +10,8 @@ import { LiveRoomItemBean } from 'wdBean/Index'; | ||
| 10 | import { LiveRoomBaseInfo } from './LiveRoomBaseInfo' | 10 | import { LiveRoomBaseInfo } from './LiveRoomBaseInfo' |
| 11 | 11 | ||
| 12 | import { JSON } from '@kit.ArkTS'; | 12 | import { JSON } from '@kit.ArkTS'; |
| 13 | +import { LiveMessageIsHistoryMessage, LiveMessageOptType } from 'wdBean/src/main/ets/bean/live/LiveRoomBean'; | ||
| 14 | + | ||
| 13 | const TAG = "LiveRoomManager" | 15 | const TAG = "LiveRoomManager" |
| 14 | 16 | ||
| 15 | export class LiveRoom extends ChatroomStatusListener { | 17 | export class LiveRoom extends ChatroomStatusListener { |
| @@ -32,7 +34,7 @@ export class LiveRoom extends ChatroomStatusListener { | @@ -32,7 +34,7 @@ export class LiveRoom extends ChatroomStatusListener { | ||
| 32 | 34 | ||
| 33 | enterRoom() { | 35 | enterRoom() { |
| 34 | let roomId = this.connectRoomBaseInfo?.roomID | 36 | let roomId = this.connectRoomBaseInfo?.roomID |
| 35 | - let msgCount = 10; | 37 | + let msgCount = 0; |
| 36 | 38 | ||
| 37 | Logger.debug(TAG, `will enterRoom roomId: ${roomId}`); | 39 | Logger.debug(TAG, `will enterRoom roomId: ${roomId}`); |
| 38 | IMEngine.getInstance().joinExistingChatroom(roomId, msgCount).then(result => { | 40 | IMEngine.getInstance().joinExistingChatroom(roomId, msgCount).then(result => { |
| @@ -107,7 +109,8 @@ export class LiveRoom extends ChatroomStatusListener { | @@ -107,7 +109,8 @@ export class LiveRoom extends ChatroomStatusListener { | ||
| 107 | 109 | ||
| 108 | let optionType = liveRoomItemBean.optionType != undefined ? liveRoomItemBean.optionType : liveRoomItemBean.dataType | 110 | let optionType = liveRoomItemBean.optionType != undefined ? liveRoomItemBean.optionType : liveRoomItemBean.dataType |
| 109 | 111 | ||
| 110 | - if (this.isHistoryMessage(optionType)) { | 112 | + if (LiveMessageIsHistoryMessage(optionType)) { |
| 113 | + liveRoomItemBean.customFormIM = true | ||
| 111 | if (this.onHistoryMessage) { | 114 | if (this.onHistoryMessage) { |
| 112 | this.onHistoryMessage(liveRoomItemBean) | 115 | this.onHistoryMessage(liveRoomItemBean) |
| 113 | } | 116 | } |
| @@ -120,20 +123,4 @@ export class LiveRoom extends ChatroomStatusListener { | @@ -120,20 +123,4 @@ export class LiveRoom extends ChatroomStatusListener { | ||
| 120 | 123 | ||
| 121 | 124 | ||
| 122 | } | 125 | } |
| 123 | - | ||
| 124 | - isHistoryMessage(optionType: string): boolean { | ||
| 125 | - let isHistoryMessage = false | ||
| 126 | - switch (optionType) { | ||
| 127 | - case "ZH_TEXT_MSG": | ||
| 128 | - case "ZH_IMAGE_MSG": | ||
| 129 | - case "ZH_TEXT_AND_IMAGE_MSG": | ||
| 130 | - case "ZH_AUDIO_MSG": | ||
| 131 | - case "ZH_VIDEO_MSG": { | ||
| 132 | - isHistoryMessage = true | ||
| 133 | - } break; | ||
| 134 | - default: | ||
| 135 | - break; | ||
| 136 | - } | ||
| 137 | - return isHistoryMessage | ||
| 138 | - } | ||
| 139 | } | 126 | } |
| @@ -116,6 +116,7 @@ export class LiveRoomManager { | @@ -116,6 +116,7 @@ export class LiveRoomManager { | ||
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | private connectWithIMToken(token: string) { | 118 | private connectWithIMToken(token: string) { |
| 119 | + Logger.debug(TAG, "连接开始,IM Token:" + token) | ||
| 119 | const timeout = 5 | 120 | const timeout = 5 |
| 120 | IMEngine.getInstance().connect(token, timeout).then(result => { | 121 | IMEngine.getInstance().connect(token, timeout).then(result => { |
| 121 | if (EngineError.Success === result.code) { | 122 | if (EngineError.Success === result.code) { |
| @@ -12,6 +12,8 @@ import { publishCommentModel } from 'wdComponent/src/main/ets/components/comment | @@ -12,6 +12,8 @@ import { publishCommentModel } from 'wdComponent/src/main/ets/components/comment | ||
| 12 | import { TrackConstants, TrackingContent, TrackParamConvert } from 'wdTracking/Index'; | 12 | import { TrackConstants, TrackingContent, TrackParamConvert } from 'wdTracking/Index'; |
| 13 | import { onlyWifiLoadVideo } from 'wdComponent/src/main/ets/utils/lazyloadImg'; | 13 | import { onlyWifiLoadVideo } from 'wdComponent/src/main/ets/utils/lazyloadImg'; |
| 14 | import { LiveDetailChatRoomController } from '../im/LiveDetailChatRoomController'; | 14 | import { LiveDetailChatRoomController } from '../im/LiveDetailChatRoomController'; |
| 15 | +import { LiveMessageOptType, LiveMessageRoomType } from 'wdBean/src/main/ets/bean/live/LiveRoomBean'; | ||
| 16 | +import { LiveDetailPageLogic } from '../viewModel/LiveDetailPageLogic'; | ||
| 15 | 17 | ||
| 16 | let TAG: string = 'DetailPlayLivePage'; | 18 | let TAG: string = 'DetailPlayLivePage'; |
| 17 | 19 | ||
| @@ -40,9 +42,13 @@ export struct DetailPlayLivePage { | @@ -40,9 +42,13 @@ export struct DetailPlayLivePage { | ||
| 40 | // 尽量不要动属性。用来作为输入了评论之后,值传递 | 42 | // 尽量不要动属性。用来作为输入了评论之后,值传递 |
| 41 | @State lastInputedLiveComment: LiveRoomItemBean = {} as LiveRoomItemBean // 上次输入的直播间消息 | 43 | @State lastInputedLiveComment: LiveRoomItemBean = {} as LiveRoomItemBean // 上次输入的直播间消息 |
| 42 | @State lastInputedChatComment: LiveRoomItemBean = {} as LiveRoomItemBean // 上次输入的大家聊消息 | 44 | @State lastInputedChatComment: LiveRoomItemBean = {} as LiveRoomItemBean // 上次输入的大家聊消息 |
| 45 | + @State lastLiveControl: LiveRoomItemBean = {} as LiveRoomItemBean // IM 控制消息 | ||
| 43 | // 顶部状态栏高度 | 46 | // 顶部状态栏高度 |
| 44 | @Consume topSafeHeight: number | 47 | @Consume topSafeHeight: number |
| 45 | chatRoomController: LiveDetailChatRoomController = new LiveDetailChatRoomController() | 48 | chatRoomController: LiveDetailChatRoomController = new LiveDetailChatRoomController() |
| 49 | + @Provide banComment: boolean = true | ||
| 50 | + @State isEnd: boolean = false | ||
| 51 | + @Consume liveDetailPageLogic: LiveDetailPageLogic | ||
| 46 | 52 | ||
| 47 | @State toastText: ResourceStr = "这是一个非Wi-Fi环境。请注意流量消耗" | 53 | @State toastText: ResourceStr = "这是一个非Wi-Fi环境。请注意流量消耗" |
| 48 | dialogToast: CustomDialogController = new CustomDialogController({ | 54 | dialogToast: CustomDialogController = new CustomDialogController({ |
| @@ -83,30 +89,79 @@ export struct DetailPlayLivePage { | @@ -83,30 +89,79 @@ export struct DetailPlayLivePage { | ||
| 83 | if(!await onlyWifiLoadVideo()){ | 89 | if(!await onlyWifiLoadVideo()){ |
| 84 | this.showToastTip(this.toastText) | 90 | this.showToastTip(this.toastText) |
| 85 | } | 91 | } |
| 92 | + this.configChatRoom() | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + async aboutToDisappear() { | ||
| 96 | + Logger.info(TAG, `wyj-aboutToDisappear`) | ||
| 97 | + await this.playerController?.stop() | ||
| 98 | + await this.playerController?.release() | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + configChatRoom() { | ||
| 86 | this.chatRoomController.onHistoryMessage = (liveRoomItemBean: LiveRoomItemBean) => { | 102 | this.chatRoomController.onHistoryMessage = (liveRoomItemBean: LiveRoomItemBean) => { |
| 87 | - if (liveRoomItemBean.messageRoom == "ZH_VIDEO") { | 103 | + const preDisplay = this.contentDetailData.liveInfo.preCommentFlag == 1 |
| 104 | + if (this.liveViewModel.filterMySelfCommentNoPreDisplay(liveRoomItemBean, preDisplay)) { | ||
| 105 | + return | ||
| 106 | + } | ||
| 107 | + if (liveRoomItemBean.messageRoom == LiveMessageRoomType.living) { | ||
| 88 | this.lastInputedLiveComment = liveRoomItemBean | 108 | this.lastInputedLiveComment = liveRoomItemBean |
| 89 | - } else if (liveRoomItemBean.messageRoom == "ZH_CHAT") { | 109 | + } else if (liveRoomItemBean.messageRoom == LiveMessageRoomType.chat) { |
| 90 | this.lastInputedChatComment = liveRoomItemBean | 110 | this.lastInputedChatComment = liveRoomItemBean |
| 91 | } | 111 | } |
| 92 | } | 112 | } |
| 93 | this.chatRoomController.onLiveMessage = (liveRoomItemBean: LiveRoomItemBean) => { | 113 | this.chatRoomController.onLiveMessage = (liveRoomItemBean: LiveRoomItemBean) => { |
| 94 | - if (liveRoomItemBean.optionType == "ZH_ROOM_NUMBER_MSG") { | ||
| 95 | - this.liveRoomDataBean.pv = Number(liveRoomItemBean.pv) | 114 | + switch (liveRoomItemBean.optionType) { |
| 115 | + case LiveMessageOptType.ZH_ROOM_NUMBER_MSG: { | ||
| 116 | + this.liveRoomDataBean.pv = Number(liveRoomItemBean.pv) | ||
| 117 | + } break | ||
| 118 | + case LiveMessageOptType.ZH_BARRAGE_SWITCH_MSG: { | ||
| 119 | + const openComment = liveRoomItemBean.data == "1" | ||
| 120 | + this.contentDetailData.liveInfo.openComment = openComment ? 1 : 0 | ||
| 121 | + } break | ||
| 122 | + case LiveMessageOptType.ZH_PRE_DISPLAY_CHANGE: { | ||
| 123 | + const preCommentFlag = liveRoomItemBean.data == "1" | ||
| 124 | + this.contentDetailData.liveInfo.preCommentFlag = preCommentFlag ? 1 : 0 | ||
| 125 | + } break | ||
| 126 | + case LiveMessageOptType.ZH_BARRAGE_BAN_MESSAGE: | ||
| 127 | + case LiveMessageOptType.ZH_BARRAGE_UNBAN_MESSAGE: { | ||
| 128 | + const banComment = liveRoomItemBean.data == "1" | ||
| 129 | + this.banComment = banComment | ||
| 130 | + } break | ||
| 131 | + case LiveMessageOptType.ZH_STOP_LIVE: | ||
| 132 | + case LiveMessageOptType.ZH_START_LIVE: | ||
| 133 | + case LiveMessageOptType.ZH_CHANGE_PAD: { // 直播垫片控制 | ||
| 134 | + this.lastLiveControl = liveRoomItemBean | ||
| 135 | + } break | ||
| 136 | + case LiveMessageOptType.ZH_REPLY_MSG: { | ||
| 137 | + this.lastInputedChatComment = liveRoomItemBean | ||
| 138 | + } break | ||
| 139 | + case LiveMessageOptType.ZH_UPDATE_MSG: { | ||
| 140 | + this.lastInputedLiveComment = liveRoomItemBean | ||
| 141 | + } break | ||
| 142 | + case LiveMessageOptType.ZH_DELETE_MSG: { | ||
| 143 | + this.lastInputedLiveComment = liveRoomItemBean | ||
| 144 | + } break | ||
| 145 | + case LiveMessageOptType.ZH_TOP_MSG: { | ||
| 146 | + this.lastInputedLiveComment = liveRoomItemBean | ||
| 147 | + } break | ||
| 148 | + case LiveMessageOptType.ZH_UN_TOP_MSG: { | ||
| 149 | + this.lastInputedLiveComment = liveRoomItemBean | ||
| 150 | + } break | ||
| 151 | + case LiveMessageOptType.ZH_WALL_MSG: { | ||
| 152 | + this.lastInputedLiveComment = liveRoomItemBean | ||
| 153 | + } break | ||
| 154 | + default: { | ||
| 155 | + Logger.warn(TAG, "暂未处理类型:" + liveRoomItemBean.optionType) | ||
| 156 | + } break | ||
| 96 | } | 157 | } |
| 97 | } | 158 | } |
| 98 | this.chatRoomController.configDetail(this.contentDetailData) | 159 | this.chatRoomController.configDetail(this.contentDetailData) |
| 99 | } | 160 | } |
| 100 | 161 | ||
| 101 | - async aboutToDisappear() { | ||
| 102 | - Logger.info(TAG, `wyj-aboutToDisappear`) | ||
| 103 | - await this.playerController?.stop() | ||
| 104 | - await this.playerController?.release() | ||
| 105 | - } | ||
| 106 | - | ||
| 107 | build() { | 162 | build() { |
| 108 | Column() { | 163 | Column() { |
| 109 | - TopPlayComponent({ playerController: this.playerController }) | 164 | + TopPlayComponent({ playerController: this.playerController, isEnd: this.isEnd, lastLiveControl: this.lastLiveControl }) |
| 110 | .height(this.displayDirection == DisplayDirection.VERTICAL ? 211 : '100%') | 165 | .height(this.displayDirection == DisplayDirection.VERTICAL ? 211 : '100%') |
| 111 | .margin({ | 166 | .margin({ |
| 112 | top: this.displayDirection == DisplayDirection.VERTICAL ? px2vp(this.topSafeHeight) : 0 | 167 | top: this.displayDirection == DisplayDirection.VERTICAL ? px2vp(this.topSafeHeight) : 0 |
| 1 | -import { ContentDetailDTO, LiveRoomDataBean } from 'wdBean/Index'; | 1 | +import { ContentDetailDTO, LiveRoomDataBean, LiveRoomItemBean } from 'wdBean/Index'; |
| 2 | import { LiveViewModel } from '../viewModel/LiveViewModel'; | 2 | import { LiveViewModel } from '../viewModel/LiveViewModel'; |
| 3 | -import { CustomToast, WindowModel } from 'wdKit/Index'; | 3 | +import { CustomToast, Logger, WindowModel } from 'wdKit/Index'; |
| 4 | import { PlayerComponent } from '../widgets/vertical/PlayerComponent'; | 4 | import { PlayerComponent } from '../widgets/vertical/PlayerComponent'; |
| 5 | import { PlayerInfoComponent } from '../widgets/vertical/PlayerInfoComponent'; | 5 | import { PlayerInfoComponent } from '../widgets/vertical/PlayerInfoComponent'; |
| 6 | import { WDAliPlayerController } from 'wdPlayer/Index'; | 6 | import { WDAliPlayerController } from 'wdPlayer/Index'; |
| @@ -12,6 +12,8 @@ import { LiveDetailPageLogic } from '../viewModel/LiveDetailPageLogic'; | @@ -12,6 +12,8 @@ import { LiveDetailPageLogic } from '../viewModel/LiveDetailPageLogic'; | ||
| 12 | import { onlyWifiLoadVideo } from 'wdComponent/src/main/ets/utils/lazyloadImg'; | 12 | import { onlyWifiLoadVideo } from 'wdComponent/src/main/ets/utils/lazyloadImg'; |
| 13 | import { StringUtils } from 'wdKit'; | 13 | import { StringUtils } from 'wdKit'; |
| 14 | import { LiveDetailChatRoomController } from '../im/LiveDetailChatRoomController'; | 14 | import { LiveDetailChatRoomController } from '../im/LiveDetailChatRoomController'; |
| 15 | +import { LiveMessageOptType } from 'wdBean/src/main/ets/bean/live/LiveRoomBean'; | ||
| 16 | +import { JSON } from '@kit.ArkTS'; | ||
| 15 | 17 | ||
| 16 | const storage = LocalStorage.getShared(); | 18 | const storage = LocalStorage.getShared(); |
| 17 | const TAG = 'DetailPlayVLivePage' | 19 | const TAG = 'DetailPlayVLivePage' |
| @@ -40,11 +42,13 @@ export struct DetailPlayVLivePage { | @@ -40,11 +42,13 @@ export struct DetailPlayVLivePage { | ||
| 40 | @Consume contentId: string | 42 | @Consume contentId: string |
| 41 | @State swiperIndex: number = 1 | 43 | @State swiperIndex: number = 1 |
| 42 | @Consume liveDetailPageLogic: LiveDetailPageLogic | 44 | @Consume liveDetailPageLogic: LiveDetailPageLogic |
| 45 | + @Provide lastInputedComment: LiveRoomItemBean = {} as LiveRoomItemBean // 上次输入的消息 | ||
| 43 | //播放错误 | 46 | //播放错误 |
| 44 | @State isPlayerError: boolean = false | 47 | @State isPlayerError: boolean = false |
| 45 | @State isCanplay: boolean = false | 48 | @State isCanplay: boolean = false |
| 46 | @State toastText: ResourceStr = "这是一个非Wi-Fi环境。请注意流量消耗" | 49 | @State toastText: ResourceStr = "这是一个非Wi-Fi环境。请注意流量消耗" |
| 47 | chatRoomController: LiveDetailChatRoomController = new LiveDetailChatRoomController() | 50 | chatRoomController: LiveDetailChatRoomController = new LiveDetailChatRoomController() |
| 51 | + @Provide banComment: boolean = true | ||
| 48 | 52 | ||
| 49 | dialogToast: CustomDialogController = new CustomDialogController({ | 53 | dialogToast: CustomDialogController = new CustomDialogController({ |
| 50 | builder: CustomToast({ | 54 | builder: CustomToast({ |
| @@ -71,7 +75,7 @@ export struct DetailPlayVLivePage { | @@ -71,7 +75,7 @@ export struct DetailPlayVLivePage { | ||
| 71 | if(!await onlyWifiLoadVideo()){ | 75 | if(!await onlyWifiLoadVideo()){ |
| 72 | this.showToastTip(this.toastText) | 76 | this.showToastTip(this.toastText) |
| 73 | } | 77 | } |
| 74 | - this.chatRoomController.configDetail(this.contentDetailData) | 78 | + this.configChatRoom() |
| 75 | } | 79 | } |
| 76 | 80 | ||
| 77 | aboutToDisappear(): void { | 81 | aboutToDisappear(): void { |
| @@ -92,6 +96,49 @@ export struct DetailPlayVLivePage { | @@ -92,6 +96,49 @@ export struct DetailPlayVLivePage { | ||
| 92 | // WindowModel.shared.setWindowSystemBarProperties({ statusBarContentColor: '#000000', }) | 96 | // WindowModel.shared.setWindowSystemBarProperties({ statusBarContentColor: '#000000', }) |
| 93 | } | 97 | } |
| 94 | 98 | ||
| 99 | + configChatRoom() { | ||
| 100 | + this.chatRoomController.onHistoryMessage = (liveRoomItemBean: LiveRoomItemBean) => { | ||
| 101 | + const preDisplay = this.contentDetailData.liveInfo.preCommentFlag == 1 | ||
| 102 | + if (this.liveViewModel.filterMySelfCommentNoPreDisplay(liveRoomItemBean, preDisplay)) { | ||
| 103 | + return | ||
| 104 | + } | ||
| 105 | + this.lastInputedComment = liveRoomItemBean | ||
| 106 | + } | ||
| 107 | + this.chatRoomController.onLiveMessage = (liveRoomItemBean: LiveRoomItemBean) => { | ||
| 108 | + switch (liveRoomItemBean.optionType) { | ||
| 109 | + case LiveMessageOptType.ZH_ROOM_NUMBER_MSG: { | ||
| 110 | + this.liveRoomDataBean.pv = Number(liveRoomItemBean.pv) | ||
| 111 | + } break | ||
| 112 | + case LiveMessageOptType.ZH_BARRAGE_SWITCH_MSG: { | ||
| 113 | + const openComment = liveRoomItemBean.data == "1" | ||
| 114 | + this.contentDetailData.liveInfo.openComment = openComment ? 1 : 0 | ||
| 115 | + } break | ||
| 116 | + case LiveMessageOptType.ZH_PRE_DISPLAY_CHANGE: { | ||
| 117 | + const preCommentFlag = liveRoomItemBean.data == "1" | ||
| 118 | + this.contentDetailData.liveInfo.preCommentFlag = preCommentFlag ? 1 : 0 | ||
| 119 | + } break | ||
| 120 | + case LiveMessageOptType.ZH_BARRAGE_BAN_MESSAGE: | ||
| 121 | + case LiveMessageOptType.ZH_BARRAGE_UNBAN_MESSAGE: { | ||
| 122 | + const banComment = liveRoomItemBean.data == "1" | ||
| 123 | + this.banComment = banComment | ||
| 124 | + } break | ||
| 125 | + case LiveMessageOptType.ZH_STOP_LIVE: { | ||
| 126 | + this.liveState = "end" | ||
| 127 | + this.contentDetailData.liveInfo.liveState = "end" | ||
| 128 | + } break | ||
| 129 | + case LiveMessageOptType.ZH_CHANGE_PAD: { | ||
| 130 | + const padObj = JSON.parse(liveRoomItemBean.data ?? "") as Record<string, string | number | boolean> | ||
| 131 | + const showPad = padObj["showPad"] == "1" | ||
| 132 | + this.liveDetailPageLogic.showPad = showPad | ||
| 133 | + } break | ||
| 134 | + default: { | ||
| 135 | + Logger.warn(TAG, "暂未处理类型:" + liveRoomItemBean.optionType) | ||
| 136 | + } break | ||
| 137 | + } | ||
| 138 | + } | ||
| 139 | + this.chatRoomController.configDetail(this.contentDetailData) | ||
| 140 | + } | ||
| 141 | + | ||
| 95 | build() { | 142 | build() { |
| 96 | 143 | ||
| 97 | Stack({ alignContent: Alignment.Top }) { | 144 | Stack({ alignContent: Alignment.Top }) { |
| @@ -117,7 +164,7 @@ export struct DetailPlayVLivePage { | @@ -117,7 +164,7 @@ export struct DetailPlayVLivePage { | ||
| 117 | // 有垫片 | 164 | // 有垫片 |
| 118 | if (this.liveDetailPageLogic.padImageUri.length > 0) { | 165 | if (this.liveDetailPageLogic.padImageUri.length > 0) { |
| 119 | // 配置了垫片资源 | 166 | // 配置了垫片资源 |
| 120 | - Image(this.liveDetailPageLogic.padImageUri).objectFit(ImageFit.Fill).width('100%').height('100%') | 167 | + Image(this.liveDetailPageLogic.padImageUri).objectFit(ImageFit.Contain).width('100%').height('100%') |
| 121 | 168 | ||
| 122 | } else { | 169 | } else { |
| 123 | // 没有配置垫片资源 | 170 | // 没有配置垫片资源 |
| 1 | -import { HttpUrlUtils, HttpUtils, ResponseDTO } from 'wdNetwork'; | 1 | +import { HttpBizUtil, HttpUrlUtils, HttpUtils, ResponseDTO } from 'wdNetwork'; |
| 2 | import { HttpRequest } from 'wdNetwork/src/main/ets/http/HttpRequest'; | 2 | import { HttpRequest } from 'wdNetwork/src/main/ets/http/HttpRequest'; |
| 3 | import { Logger, ToastUtils, EmitterEventId, EmitterUtils, SPHelper } from 'wdKit'; | 3 | import { Logger, ToastUtils, EmitterEventId, EmitterUtils, SPHelper } from 'wdKit'; |
| 4 | import { ContentDetailDTO, LiveDetailsBean, LiveRoomBean, LiveRoomDataBean, | 4 | import { ContentDetailDTO, LiveDetailsBean, LiveRoomBean, LiveRoomDataBean, |
| @@ -6,6 +6,7 @@ import { ContentDetailDTO, LiveDetailsBean, LiveRoomBean, LiveRoomDataBean, | @@ -6,6 +6,7 @@ import { ContentDetailDTO, LiveDetailsBean, LiveRoomBean, LiveRoomDataBean, | ||
| 6 | ReserveItemBean, ValueType } from 'wdBean/Index'; | 6 | ReserveItemBean, ValueType } from 'wdBean/Index'; |
| 7 | import { ContentDetailRequest } from 'wdDetailPlayApi/Index'; | 7 | import { ContentDetailRequest } from 'wdDetailPlayApi/Index'; |
| 8 | import { SpConstants } from 'wdConstant/Index'; | 8 | import { SpConstants } from 'wdConstant/Index'; |
| 9 | +import { LiveMessageOptType } from 'wdBean/src/main/ets/bean/live/LiveRoomBean'; | ||
| 9 | 10 | ||
| 10 | const TAG = 'LiveModel' | 11 | const TAG = 'LiveModel' |
| 11 | 12 | ||
| @@ -113,7 +114,7 @@ export class LiveModel { | @@ -113,7 +114,7 @@ export class LiveModel { | ||
| 113 | params['liveId'] = liveId | 114 | params['liveId'] = liveId |
| 114 | params['pageSize'] = pageSize + '' | 115 | params['pageSize'] = pageSize + '' |
| 115 | return new Promise<LiveRoomBean>((success, fail) => { | 116 | return new Promise<LiveRoomBean>((success, fail) => { |
| 116 | - HttpRequest.post<ResponseDTO<LiveRoomBean>>( | 117 | + HttpBizUtil.post<ResponseDTO<LiveRoomBean>>( |
| 117 | HttpUrlUtils.getLiveChatListUrl(), | 118 | HttpUrlUtils.getLiveChatListUrl(), |
| 118 | params, | 119 | params, |
| 119 | ).then((data: ResponseDTO<LiveRoomBean>) => { | 120 | ).then((data: ResponseDTO<LiveRoomBean>) => { |
| @@ -321,7 +322,7 @@ export class LiveModel { | @@ -321,7 +322,7 @@ export class LiveModel { | ||
| 321 | let commentItem: LiveRoomItemBean = {} as LiveRoomItemBean | 322 | let commentItem: LiveRoomItemBean = {} as LiveRoomItemBean |
| 322 | commentItem.text = comment | 323 | commentItem.text = comment |
| 323 | commentItem.isWall = 0 | 324 | commentItem.isWall = 0 |
| 324 | - commentItem.dataType = "ZH_TEXT_MSG" | 325 | + commentItem.dataType = LiveMessageOptType.ZH_TEXT_MSG |
| 325 | 326 | ||
| 326 | let params: Record<string, string | number> = {}; | 327 | let params: Record<string, string | number> = {}; |
| 327 | params["liveId"] = liveId | 328 | params["liveId"] = liveId |
| @@ -7,10 +7,12 @@ import { | @@ -7,10 +7,12 @@ import { | ||
| 7 | LiveRoomItemBean, | 7 | LiveRoomItemBean, |
| 8 | ValueType | 8 | ValueType |
| 9 | } from 'wdBean/Index' | 9 | } from 'wdBean/Index' |
| 10 | +import { LiveMessageIsHistoryMessage } from 'wdBean/src/main/ets/bean/live/LiveRoomBean' | ||
| 11 | +import { SpConstants } from 'wdConstant' | ||
| 10 | import { ContentDetailRequest } from 'wdDetailPlayApi/Index' | 12 | import { ContentDetailRequest } from 'wdDetailPlayApi/Index' |
| 11 | -import { Logger } from 'wdKit/Index' | 13 | +import { Logger, SPHelper } from 'wdKit/Index' |
| 12 | import { ToastUtils } from 'wdKit/src/main/ets/utils/ToastUtils' | 14 | import { ToastUtils } from 'wdKit/src/main/ets/utils/ToastUtils' |
| 13 | -import { ResponseDTO } from 'wdNetwork/Index' | 15 | +import { HttpUtils, ResponseDTO } from 'wdNetwork/Index' |
| 14 | import { LiveModel } from './LiveModel' | 16 | import { LiveModel } from './LiveModel' |
| 15 | 17 | ||
| 16 | const TAG = "LiveViewModel" | 18 | const TAG = "LiveViewModel" |
| @@ -196,4 +198,37 @@ export class LiveViewModel { | @@ -196,4 +198,37 @@ export class LiveViewModel { | ||
| 196 | retItem.fullColumnImgUrlDto = item.fullColumnImgUrlDto | 198 | retItem.fullColumnImgUrlDto = item.fullColumnImgUrlDto |
| 197 | return retItem | 199 | return retItem |
| 198 | } | 200 | } |
| 201 | + | ||
| 202 | + filterMySelfCommentNoPreDisplay(comment: LiveRoomItemBean, openPreDisplay:boolean) { | ||
| 203 | + let mySelf = false | ||
| 204 | + const userId = HttpUtils.getUserId() | ||
| 205 | + const deviceId = HttpUtils.getDeviceId() | ||
| 206 | + if (comment.senderUserId && comment.senderUserId == userId) { | ||
| 207 | + mySelf = true | ||
| 208 | + } else if (comment.deviceId && comment.deviceId == deviceId) { | ||
| 209 | + mySelf = true | ||
| 210 | + } | ||
| 211 | + let optionType = comment.optionType != undefined ? comment.optionType : comment.dataType | ||
| 212 | + | ||
| 213 | + if (mySelf | ||
| 214 | + && openPreDisplay | ||
| 215 | + && comment.customFormIM === true | ||
| 216 | + && LiveMessageIsHistoryMessage(optionType) | ||
| 217 | + ) { | ||
| 218 | + return true | ||
| 219 | + } | ||
| 220 | + return false | ||
| 221 | + } | ||
| 222 | + | ||
| 223 | + isMySelfComment(comment: LiveRoomItemBean) { | ||
| 224 | + let mySelf = false | ||
| 225 | + const userId = HttpUtils.getUserId() | ||
| 226 | + const deviceId = HttpUtils.getDeviceId() | ||
| 227 | + if (comment.senderUserId && comment.senderUserId == userId) { | ||
| 228 | + mySelf = true | ||
| 229 | + } else if (comment.deviceId && comment.deviceId == deviceId) { | ||
| 230 | + mySelf = true | ||
| 231 | + } | ||
| 232 | + return mySelf | ||
| 233 | + } | ||
| 199 | } | 234 | } |
| @@ -53,7 +53,9 @@ export struct TabChatComponent { | @@ -53,7 +53,9 @@ export struct TabChatComponent { | ||
| 53 | 53 | ||
| 54 | this.liveChatList.push(info) | 54 | this.liveChatList.push(info) |
| 55 | this.pageModel.viewType = ViewType.LOADED; | 55 | this.pageModel.viewType = ViewType.LOADED; |
| 56 | - // this.scroller.scrollEdge(Edge.Bottom) | 56 | + if (this.pageModel.viewType == ViewType.LOADED) { |
| 57 | + this.scroller.scrollEdge(Edge.Bottom) | ||
| 58 | + } | ||
| 57 | console.log(TAG, '发布评论:', JSON.stringify(this.publishCommentModel.lastCommentModel)) | 59 | console.log(TAG, '发布评论:', JSON.stringify(this.publishCommentModel.lastCommentModel)) |
| 58 | } | 60 | } |
| 59 | } | 61 | } |
| @@ -63,6 +65,9 @@ export struct TabChatComponent { | @@ -63,6 +65,9 @@ export struct TabChatComponent { | ||
| 63 | lastInputedCommentChanged(info: string) { | 65 | lastInputedCommentChanged(info: string) { |
| 64 | Logger.debug(TAG, "2显示评论》》》: " + JSON.stringify(this.lastInputedComment)) | 66 | Logger.debug(TAG, "2显示评论》》》: " + JSON.stringify(this.lastInputedComment)) |
| 65 | this.liveChatList.push(this.liveViewModel.deepCopyLiveRoomItem(this.lastInputedComment)) | 67 | this.liveChatList.push(this.liveViewModel.deepCopyLiveRoomItem(this.lastInputedComment)) |
| 68 | + if (this.pageModel.viewType == ViewType.LOADED) { | ||
| 69 | + this.scroller.scrollEdge(Edge.Bottom) | ||
| 70 | + } | ||
| 66 | this.pageModel.viewType = ViewType.LOADED; | 71 | this.pageModel.viewType = ViewType.LOADED; |
| 67 | } | 72 | } |
| 68 | 73 |
| @@ -3,6 +3,7 @@ import { Logger, StringUtils } from 'wdKit/Index' | @@ -3,6 +3,7 @@ import { Logger, StringUtils } from 'wdKit/Index' | ||
| 3 | // import { Action, LiveRoomItemBean, Params, PhotoListBean } from 'wdBean/Index' | 3 | // import { Action, LiveRoomItemBean, Params, PhotoListBean } from 'wdBean/Index' |
| 4 | import { WDRouterRule } from 'wdRouter' | 4 | import { WDRouterRule } from 'wdRouter' |
| 5 | import { ExtraDTO } from 'wdBean/src/main/ets/bean/component/extra/ExtraDTO' | 5 | import { ExtraDTO } from 'wdBean/src/main/ets/bean/component/extra/ExtraDTO' |
| 6 | +import { LiveMessageOptType, LiveMessageRole } from 'wdBean/src/main/ets/bean/live/LiveRoomBean' | ||
| 6 | 7 | ||
| 7 | const TAG = "TabChatItemComponent" | 8 | const TAG = "TabChatItemComponent" |
| 8 | 9 | ||
| @@ -22,61 +23,19 @@ export struct TabChatItemComponent { | @@ -22,61 +23,19 @@ export struct TabChatItemComponent { | ||
| 22 | .width(24) | 23 | .width(24) |
| 23 | .height(24) | 24 | .height(24) |
| 24 | Column() { | 25 | Column() { |
| 25 | - if (this.item.dataType == 'ZH_IMAGE_MSG') { | ||
| 26 | - Row() { | ||
| 27 | - Text() { | ||
| 28 | - Span(this.item.senderUserName + ': ') | ||
| 29 | - .fontColor('#666666') | ||
| 30 | - } | ||
| 31 | - .margin({ left: 8 }) | ||
| 32 | - .lineHeight(20) | ||
| 33 | - .layoutWeight(1) | ||
| 34 | - .fontSize('14fp') | ||
| 35 | - .fontWeight(400) | ||
| 36 | - } | ||
| 37 | - .alignItems(VerticalAlign.Top) | ||
| 38 | - | ||
| 39 | - if (this.item.pictureUrls && this.item.pictureUrls.length > 0) { | ||
| 40 | - Image(this.item.pictureUrls[0]) | ||
| 41 | - .width(`100%`) | ||
| 42 | - .objectFit(ImageFit.Contain) | ||
| 43 | - .borderRadius(4) | ||
| 44 | - .margin({ | ||
| 45 | - top: 10 | ||
| 46 | - }) | ||
| 47 | - .onClick(() => { | ||
| 48 | - this.gotoMultipleListImagePage(this.item.pictureUrls[0]) | ||
| 49 | - }) | ||
| 50 | - } | ||
| 51 | - } else { | ||
| 52 | - Row() { | ||
| 53 | - Text() { | ||
| 54 | - Span(this.item.senderUserName + ': ') | ||
| 55 | - .fontColor('#666666') | ||
| 56 | - Span(this.item.text) | ||
| 57 | - .fontColor('#222222') | ||
| 58 | - } | ||
| 59 | - .margin({ left: 8 }) | ||
| 60 | - .lineHeight(20) | ||
| 61 | - .layoutWeight(1) | ||
| 62 | - .fontSize('14fp') | ||
| 63 | - .fontWeight(400) | ||
| 64 | - } | ||
| 65 | - .alignItems(VerticalAlign.Top) | 26 | + this.messageContentText() |
| 66 | 27 | ||
| 67 | - if (this.item.dataType == 'ZH_TEXT_AND_IMAGE_MSG' && this.item.pictureUrls && | ||
| 68 | - this.item.pictureUrls.length > 0) { | ||
| 69 | - Image(this.item.pictureUrls[0]) | ||
| 70 | - .width(`100%`) | ||
| 71 | - .objectFit(ImageFit.Contain) | ||
| 72 | - .borderRadius(4) | ||
| 73 | - .margin({ | ||
| 74 | - top: 10 | ||
| 75 | - }) | ||
| 76 | - .onClick(() => { | ||
| 77 | - this.gotoMultipleListImagePage(this.item.pictureUrls[0]) | ||
| 78 | - }) | ||
| 79 | - } | 28 | + if (this.item.pictureUrls && this.item.pictureUrls.length > 0) { |
| 29 | + Image(this.item.pictureUrls[0]) | ||
| 30 | + .width(this.item.customizeExpression === 1 ? 72 : `100%`) | ||
| 31 | + .objectFit(ImageFit.Contain) | ||
| 32 | + .borderRadius(4) | ||
| 33 | + .margin({ | ||
| 34 | + top: 10, bottom: 4 | ||
| 35 | + }) | ||
| 36 | + .onClick(() => { | ||
| 37 | + this.gotoMultipleListImagePage(this.item.pictureUrls[0]) | ||
| 38 | + }) | ||
| 80 | } | 39 | } |
| 81 | 40 | ||
| 82 | } | 41 | } |
| @@ -96,6 +55,47 @@ export struct TabChatItemComponent { | @@ -96,6 +55,47 @@ export struct TabChatItemComponent { | ||
| 96 | 55 | ||
| 97 | } | 56 | } |
| 98 | 57 | ||
| 58 | + @Builder messageContentText() { | ||
| 59 | + Row() { | ||
| 60 | + Text() { | ||
| 61 | + | ||
| 62 | + if (this.item.receiverUserName && this.item.receiverUserName.length > 0) { | ||
| 63 | + /// 回复的消息处理 | ||
| 64 | + | ||
| 65 | + Span((this.item.senderUserName ?? "游客") + " ").fontColor('#2696FF') | ||
| 66 | + if (this.item.role == LiveMessageRole.host) { | ||
| 67 | + Span(' 主持人 ') | ||
| 68 | + .fontSize(11) | ||
| 69 | + .lineHeight(20) | ||
| 70 | + .textBackgroundStyle({ color: "#70FFC63F", radius: 2 }) | ||
| 71 | + Span(' ') | ||
| 72 | + } | ||
| 73 | + if (this.item.role == LiveMessageRole.guest) { | ||
| 74 | + Span(' 嘉宾 ') | ||
| 75 | + .fontSize(11) | ||
| 76 | + .lineHeight(20) | ||
| 77 | + .textBackgroundStyle({ color: "#70FFC63F", radius: 2 }) | ||
| 78 | + Span(' ') | ||
| 79 | + } | ||
| 80 | + Span("回复了 ").fontColor('#222222') | ||
| 81 | + Span((this.item.receiverUserName ?? "游客") + ': ').fontColor('#666666') | ||
| 82 | + Span(this.item.text).fontColor('#222222') | ||
| 83 | + | ||
| 84 | + } else { | ||
| 85 | + // 普通消息 | ||
| 86 | + Span((this.item.senderUserName ?? "游客") + ': ').fontColor('#666666') | ||
| 87 | + Span(this.item.text).fontColor('#222222') | ||
| 88 | + } | ||
| 89 | + } | ||
| 90 | + .margin({ left: 8 }) | ||
| 91 | + .lineHeight(20) | ||
| 92 | + .layoutWeight(1) | ||
| 93 | + .fontSize('14fp') | ||
| 94 | + .fontWeight(400) | ||
| 95 | + } | ||
| 96 | + .alignItems(VerticalAlign.Top) | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | /** | 99 | /** |
| 100 | * 大图列表页 | 100 | * 大图列表页 |
| 101 | * @param content | 101 | * @param content |
| @@ -10,6 +10,7 @@ import { LiveViewModel } from '../../viewModel/LiveViewModel' | @@ -10,6 +10,7 @@ import { LiveViewModel } from '../../viewModel/LiveViewModel' | ||
| 10 | import { Logger } from 'wdKit' | 10 | import { Logger } from 'wdKit' |
| 11 | import LoadMoreLayout from 'wdComponent/src/main/ets/components/page/LoadMoreLayout' | 11 | import LoadMoreLayout from 'wdComponent/src/main/ets/components/page/LoadMoreLayout' |
| 12 | import { PeopleShipNoMoreData } from 'wdComponent/src/main/ets/components/reusable/PeopleShipNoMoreData' | 12 | import { PeopleShipNoMoreData } from 'wdComponent/src/main/ets/components/reusable/PeopleShipNoMoreData' |
| 13 | +import { LiveMessageOptType } from 'wdBean/src/main/ets/bean/live/LiveRoomBean' | ||
| 13 | 14 | ||
| 14 | const TAG: string = 'TabLiveComponent'; | 15 | const TAG: string = 'TabLiveComponent'; |
| 15 | 16 | ||
| @@ -34,7 +35,29 @@ export struct TabLiveComponent { | @@ -34,7 +35,29 @@ export struct TabLiveComponent { | ||
| 34 | 35 | ||
| 35 | lastInputedCommentChanged(info: string) { | 36 | lastInputedCommentChanged(info: string) { |
| 36 | Logger.debug(TAG, "1显示评论》》》: " + JSON.stringify(this.lastInputedComment)) | 37 | Logger.debug(TAG, "1显示评论》》》: " + JSON.stringify(this.lastInputedComment)) |
| 37 | - this.liveList.push(this.liveViewModel.deepCopyLiveRoomItem(this.lastInputedComment)) | 38 | + switch (this.lastInputedComment.optionType) { |
| 39 | + case LiveMessageOptType.ZH_UPDATE_MSG: { | ||
| 40 | + | ||
| 41 | + } break | ||
| 42 | + case LiveMessageOptType.ZH_DELETE_MSG: { | ||
| 43 | + | ||
| 44 | + } break | ||
| 45 | + case LiveMessageOptType.ZH_TOP_MSG: { | ||
| 46 | + | ||
| 47 | + } break | ||
| 48 | + case LiveMessageOptType.ZH_UN_TOP_MSG: { | ||
| 49 | + | ||
| 50 | + } break | ||
| 51 | + case LiveMessageOptType.ZH_WALL_MSG: { | ||
| 52 | + | ||
| 53 | + } break | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + if (this.liveList.totalCount() === 0) { | ||
| 57 | + this.liveList.push(this.liveViewModel.deepCopyLiveRoomItem(this.lastInputedComment)) | ||
| 58 | + } else { | ||
| 59 | + this.liveList.addFirstItem(this.liveViewModel.deepCopyLiveRoomItem(this.lastInputedComment)) | ||
| 60 | + } | ||
| 38 | this.pageModel.viewType = ViewType.LOADED; | 61 | this.pageModel.viewType = ViewType.LOADED; |
| 39 | } | 62 | } |
| 40 | 63 | ||
| @@ -190,7 +213,7 @@ export struct TabLiveComponent { | @@ -190,7 +213,7 @@ export struct TabLiveComponent { | ||
| 190 | liveRoomItemBeanTemp.senderUserName = '人民日报主持人' | 213 | liveRoomItemBeanTemp.senderUserName = '人民日报主持人' |
| 191 | liveRoomItemBeanTemp.pictureUrls = [] | 214 | liveRoomItemBeanTemp.pictureUrls = [] |
| 192 | liveRoomItemBeanTemp.pictureUrls.push(this.contentDetailData?.fullColumnImgUrls[0]?.url) | 215 | liveRoomItemBeanTemp.pictureUrls.push(this.contentDetailData?.fullColumnImgUrls[0]?.url) |
| 193 | - liveRoomItemBeanTemp.dataType = 'ZH_TEXT_AND_IMAGE_MSG' | 216 | + liveRoomItemBeanTemp.dataType = LiveMessageOptType.ZH_TEXT_AND_IMAGE_MSG |
| 194 | let temp = this.contentDetailData?.fullColumnImgUrls[0] | 217 | let temp = this.contentDetailData?.fullColumnImgUrls[0] |
| 195 | if (temp) { | 218 | if (temp) { |
| 196 | liveRoomItemBeanTemp.pictureResolutions = [] | 219 | liveRoomItemBeanTemp.pictureResolutions = [] |
| 1 | import { Action, LiveRoomItemBean, Params, PhotoListBean } from 'wdBean/Index' | 1 | import { Action, LiveRoomItemBean, Params, PhotoListBean } from 'wdBean/Index' |
| 2 | import { ExtraDTO } from 'wdBean/src/main/ets/bean/component/extra/ExtraDTO' | 2 | import { ExtraDTO } from 'wdBean/src/main/ets/bean/component/extra/ExtraDTO' |
| 3 | +import { LiveMessageOptType, LiveMessageRole } from 'wdBean/src/main/ets/bean/live/LiveRoomBean' | ||
| 3 | import { AudioRowComponent } from 'wdComponent/Index' | 4 | import { AudioRowComponent } from 'wdComponent/Index' |
| 4 | import { DateTimeUtils, StringUtils } from 'wdKit/Index' | 5 | import { DateTimeUtils, StringUtils } from 'wdKit/Index' |
| 5 | import { WDRouterRule } from 'wdRouter/Index' | 6 | import { WDRouterRule } from 'wdRouter/Index' |
| @@ -83,7 +84,7 @@ export struct TabLiveItemComponent { | @@ -83,7 +84,7 @@ export struct TabLiveItemComponent { | ||
| 83 | .textAlign(TextAlign.Start) | 84 | .textAlign(TextAlign.Start) |
| 84 | //ZH_TEXT_AND_IMAGE_MSG :图文,ZH_TEXT_MSG:文本,ZH_VIDEO_MSG:视频,ZH_AUDIO_MSG:音频 | 85 | //ZH_TEXT_AND_IMAGE_MSG :图文,ZH_TEXT_MSG:文本,ZH_VIDEO_MSG:视频,ZH_AUDIO_MSG:音频 |
| 85 | //图文 | 86 | //图文 |
| 86 | - if (this.item.dataType === 'ZH_TEXT_AND_IMAGE_MSG') { | 87 | + if (this.item.dataType === LiveMessageOptType.ZH_TEXT_AND_IMAGE_MSG) { |
| 87 | List({ space: this.item.pictureUrls.length == 1 ? 0 : 5 }) { | 88 | List({ space: this.item.pictureUrls.length == 1 ? 0 : 5 }) { |
| 88 | ForEach(this.item.pictureUrls, (itemSub: string, index: number) => { | 89 | ForEach(this.item.pictureUrls, (itemSub: string, index: number) => { |
| 89 | ListItem() { | 90 | ListItem() { |
| @@ -112,14 +113,14 @@ export struct TabLiveItemComponent { | @@ -112,14 +113,14 @@ export struct TabLiveItemComponent { | ||
| 112 | }) | 113 | }) |
| 113 | } | 114 | } |
| 114 | //音频 | 115 | //音频 |
| 115 | - else if (this.item.dataType === 'ZH_AUDIO_MSG') { | 116 | + else if (this.item.dataType === LiveMessageOptType.ZH_AUDIO_MSG) { |
| 116 | AudioRowComponent({ | 117 | AudioRowComponent({ |
| 117 | audioUrl: this.item.audioUrl, | 118 | audioUrl: this.item.audioUrl, |
| 118 | duration: this.item.duration | 119 | duration: this.item.duration |
| 119 | }) | 120 | }) |
| 120 | } | 121 | } |
| 121 | //视频 | 122 | //视频 |
| 122 | - else if (this.item.dataType === 'ZH_VIDEO_MSG') { | 123 | + else if (this.item.dataType === LiveMessageOptType.ZH_VIDEO_MSG) { |
| 123 | RelativeContainer() { | 124 | RelativeContainer() { |
| 124 | Image(this.item.transcodeImageUrl) | 125 | Image(this.item.transcodeImageUrl) |
| 125 | .width('100%') | 126 | .width('100%') |
| @@ -154,6 +155,11 @@ export struct TabLiveItemComponent { | @@ -154,6 +155,11 @@ export struct TabLiveItemComponent { | ||
| 154 | this.gotoVideoPlayPage() | 155 | this.gotoVideoPlayPage() |
| 155 | }) | 156 | }) |
| 156 | } | 157 | } |
| 158 | + | ||
| 159 | + // 上墙或回复消息 | ||
| 160 | + else if (this.item.receiverUserName && this.item.receiverUserName.length > 0) { | ||
| 161 | + this.wallOrReplySubMessage() | ||
| 162 | + } | ||
| 157 | } | 163 | } |
| 158 | .margin({ | 164 | .margin({ |
| 159 | left: 8, | 165 | left: 8, |
| @@ -233,4 +239,64 @@ export struct TabLiveItemComponent { | @@ -233,4 +239,64 @@ export struct TabLiveItemComponent { | ||
| 233 | } | 239 | } |
| 234 | return 1 | 240 | return 1 |
| 235 | } | 241 | } |
| 242 | + | ||
| 243 | + // 上墙子消息 | ||
| 244 | + @Builder wallOrReplySubMessage() { | ||
| 245 | + Row() { | ||
| 246 | + Image(StringUtils.isEmpty(this.item.receiverAvatarUrl) ? $r('app.media.default_head') : this.item.receiverAvatarUrl) | ||
| 247 | + .borderRadius(90) | ||
| 248 | + .width(24) | ||
| 249 | + .height(24) | ||
| 250 | + Column() { | ||
| 251 | + Row() { | ||
| 252 | + Text() { | ||
| 253 | + Span((this.item.receiverUserName ?? "游客") + ': ').fontColor('#666666') | ||
| 254 | + }.lineHeight(20).fontSize('14fp').fontWeight(400) | ||
| 255 | + | ||
| 256 | + if (this.item.isWall == 1) { | ||
| 257 | + Blank().layoutWeight(1) | ||
| 258 | + | ||
| 259 | + Text() { | ||
| 260 | + Span(' 上墙 ') | ||
| 261 | + .foregroundColor("#CB0000") | ||
| 262 | + .fontSize(11) | ||
| 263 | + .lineHeight(20) | ||
| 264 | + .textBackgroundStyle({ color: "#70FFC63F", radius: 2 }) | ||
| 265 | + }.lineHeight(20).fontSize('14fp').fontWeight(400) | ||
| 266 | + } | ||
| 267 | + } | ||
| 268 | + .alignItems(VerticalAlign.Top) | ||
| 269 | + | ||
| 270 | + Text() { | ||
| 271 | + Span(this.item.receiverText ?? "").fontColor('#222222') | ||
| 272 | + } | ||
| 273 | + .margin({top: 8}) | ||
| 274 | + .lineHeight(20) | ||
| 275 | + .fontSize('14fp') | ||
| 276 | + .fontWeight(400) | ||
| 277 | + | ||
| 278 | + if (this.item.pictureUrls && this.item.pictureUrls.length > 0) { | ||
| 279 | + Image(this.item.pictureUrls[0]) | ||
| 280 | + .width(this.item.customizeExpression === 1 ? 72 : `100%`) | ||
| 281 | + .objectFit(ImageFit.Contain) | ||
| 282 | + .borderRadius(4) | ||
| 283 | + .margin({ | ||
| 284 | + top: 10, bottom: 4 | ||
| 285 | + }) | ||
| 286 | + .onClick(() => { | ||
| 287 | + this.gotoMultipleListImagePage(0) | ||
| 288 | + }) | ||
| 289 | + } | ||
| 290 | + | ||
| 291 | + } | ||
| 292 | + .margin({ | ||
| 293 | + left: 8, | ||
| 294 | + right: 8 | ||
| 295 | + }) | ||
| 296 | + .layoutWeight(1) | ||
| 297 | + .alignItems(HorizontalAlign.Start) | ||
| 298 | + } | ||
| 299 | + .alignItems(VerticalAlign.Top) | ||
| 300 | + .padding({ top: 15 }) | ||
| 301 | + } | ||
| 236 | } | 302 | } |
| 1 | -import { ContentDetailDTO } from 'wdBean/Index'; | 1 | +import { ContentDetailDTO, LiveRoomItemBean } from 'wdBean/Index'; |
| 2 | import { Logger, StringUtils } from 'wdKit/Index'; | 2 | import { Logger, StringUtils } from 'wdKit/Index'; |
| 3 | import { PlayerConstants, WDAliPlayerController, WDPlayerRenderLiveView } from 'wdPlayer/Index'; | 3 | import { PlayerConstants, WDAliPlayerController, WDPlayerRenderLiveView } from 'wdPlayer/Index'; |
| 4 | import { PlayUIComponent } from './PlayUIComponent'; | 4 | import { PlayUIComponent } from './PlayUIComponent'; |
| @@ -6,6 +6,7 @@ import { PictureLoading } from '../../vertical/PictureLoading'; | @@ -6,6 +6,7 @@ import { PictureLoading } from '../../vertical/PictureLoading'; | ||
| 6 | import { TrackConstants } from 'wdTracking/Index'; | 6 | import { TrackConstants } from 'wdTracking/Index'; |
| 7 | import { LiveDetailPageLogic } from '../../../viewModel/LiveDetailPageLogic'; | 7 | import { LiveDetailPageLogic } from '../../../viewModel/LiveDetailPageLogic'; |
| 8 | import { LiveEmptyComponent, WDLiveViewDefaultType } from 'wdComponent/Index'; | 8 | import { LiveEmptyComponent, WDLiveViewDefaultType } from 'wdComponent/Index'; |
| 9 | +import { LiveMessageOptType } from 'wdBean/src/main/ets/bean/live/LiveRoomBean'; | ||
| 9 | 10 | ||
| 10 | const TAG: string = 'TopPlayComponent' | 11 | const TAG: string = 'TopPlayComponent' |
| 11 | 12 | ||
| @@ -23,7 +24,7 @@ export struct TopPlayComponent { | @@ -23,7 +24,7 @@ export struct TopPlayComponent { | ||
| 23 | //未开始 | 24 | //未开始 |
| 24 | @State isWait: boolean = false | 25 | @State isWait: boolean = false |
| 25 | //已结束直播 | 26 | //已结束直播 |
| 26 | - @State isEnd: boolean = false | 27 | + @Link isEnd: boolean |
| 27 | //播放错误 | 28 | //播放错误 |
| 28 | @State isPlayerError: boolean = false | 29 | @State isPlayerError: boolean = false |
| 29 | // loading 控制字段 | 30 | // loading 控制字段 |
| @@ -38,6 +39,7 @@ export struct TopPlayComponent { | @@ -38,6 +39,7 @@ export struct TopPlayComponent { | ||
| 38 | @Consume @Watch('pageShowChange') pageShow: number | 39 | @Consume @Watch('pageShowChange') pageShow: number |
| 39 | @Consume @Watch('pageHideChange') pageHide: number | 40 | @Consume @Watch('pageHideChange') pageHide: number |
| 40 | init: boolean = false | 41 | init: boolean = false |
| 42 | + @Prop @Watch("liveIMControlMessageChange") lastLiveControl: LiveRoomItemBean = {} as LiveRoomItemBean // IM 控制消息 | ||
| 41 | 43 | ||
| 42 | pageShowChange() { | 44 | pageShowChange() { |
| 43 | this.playerController?.play() | 45 | this.playerController?.play() |
| @@ -166,6 +168,27 @@ export struct TopPlayComponent { | @@ -166,6 +168,27 @@ export struct TopPlayComponent { | ||
| 166 | // `---0------>` + this.isWait + ' ->' + this.isHideLoading + ' ->' + this.isEnd + ' -->' + this.isVideoSource) | 168 | // `---0------>` + this.isWait + ' ->' + this.isHideLoading + ' ->' + this.isEnd + ' -->' + this.isVideoSource) |
| 167 | } | 169 | } |
| 168 | 170 | ||
| 171 | + liveIMControlMessageChange() { | ||
| 172 | + switch (this.lastLiveControl.optionType) { | ||
| 173 | + case LiveMessageOptType.ZH_STOP_LIVE: { | ||
| 174 | + this.liveDetailPageLogic.showPad = false | ||
| 175 | + this.contentDetailData.liveInfo.liveState = "end" | ||
| 176 | + this.isEnd = true | ||
| 177 | + } | ||
| 178 | + break | ||
| 179 | + case LiveMessageOptType.ZH_START_LIVE: { | ||
| 180 | + // TODO: | ||
| 181 | + } | ||
| 182 | + break | ||
| 183 | + case LiveMessageOptType.ZH_CHANGE_PAD: { // 直播垫片控制 | ||
| 184 | + const padObj = JSON.parse(this.lastLiveControl.data ?? "") as Record<string, string | number | boolean> | ||
| 185 | + const showPad = padObj["showPad"] == "1" | ||
| 186 | + this.liveDetailPageLogic.showPad = showPad | ||
| 187 | + } | ||
| 188 | + break | ||
| 189 | + } | ||
| 190 | + } | ||
| 191 | + | ||
| 169 | tryToPlay() { | 192 | tryToPlay() { |
| 170 | 193 | ||
| 171 | if (!this.xComponentIsLoaded) { | 194 | if (!this.xComponentIsLoaded) { |
| 1 | import { LiveRoomItemBean } from 'wdBean/Index' | 1 | import { LiveRoomItemBean } from 'wdBean/Index' |
| 2 | +import { LiveMessageRole } from 'wdBean/src/main/ets/bean/live/LiveRoomBean' | ||
| 3 | +import { LengthMetrics } from '@kit.ArkUI' | ||
| 2 | 4 | ||
| 3 | @Component | 5 | @Component |
| 4 | export struct ChatItemComponent { | 6 | export struct ChatItemComponent { |
| @@ -10,17 +12,23 @@ export struct ChatItemComponent { | @@ -10,17 +12,23 @@ export struct ChatItemComponent { | ||
| 10 | build() { | 12 | build() { |
| 11 | Row() { | 13 | Row() { |
| 12 | Text() { | 14 | Text() { |
| 13 | - // if (this.item.senderUserName) { | ||
| 14 | - // Span(' 主持人 ') | ||
| 15 | - // .fontSize(11) | ||
| 16 | - // .lineHeight(20) | ||
| 17 | - // .textBackgroundStyle({ color: '#808562', radius: 2 }) | ||
| 18 | - // Span(' ') | ||
| 19 | - // } | 15 | + if (this.item.role == LiveMessageRole.host) { |
| 16 | + Span(' 主持人 ') | ||
| 17 | + .fontSize(11) | ||
| 18 | + .lineHeight(20) | ||
| 19 | + .textBackgroundStyle({ color: "#70FFC63F", radius: 2 }) | ||
| 20 | + Span(' ') | ||
| 21 | + } | ||
| 22 | + if (this.item.role == LiveMessageRole.guest) { | ||
| 23 | + Span(' 嘉宾 ') | ||
| 24 | + .fontSize(11) | ||
| 25 | + .lineHeight(20) | ||
| 26 | + .textBackgroundStyle({ color: "#70FFC63F", radius: 2 }) | ||
| 27 | + Span(' ') | ||
| 28 | + } | ||
| 20 | Span(this.item.senderUserName + ': ') | 29 | Span(this.item.senderUserName + ': ') |
| 21 | .fontColor('#FFFFC63F') | 30 | .fontColor('#FFFFC63F') |
| 22 | .padding({ right: 118 }) | 31 | .padding({ right: 118 }) |
| 23 | - // | ||
| 24 | 32 | ||
| 25 | Span(this.item.text) | 33 | Span(this.item.text) |
| 26 | } | 34 | } |
| 1 | import { Action, ContentDetailDTO, LiveDetailsBean, LiveRoomDataBean, LiveRoomItemBean } from 'wdBean/Index' | 1 | import { Action, ContentDetailDTO, LiveDetailsBean, LiveRoomDataBean, LiveRoomItemBean } from 'wdBean/Index' |
| 2 | -import { LiveCommentComponent } from 'wdComponent/Index' | ||
| 3 | -import { publishCommentModel } from 'wdComponent/src/main/ets/components/comment/model/PublishCommentModel' | ||
| 4 | import { LiveOperRowListView } from 'wdComponent' | 2 | import { LiveOperRowListView } from 'wdComponent' |
| 5 | import PageModel from 'wdComponent/src/main/ets/viewmodel/PageModel' | 3 | import PageModel from 'wdComponent/src/main/ets/viewmodel/PageModel' |
| 6 | import { DisplayDirection, SpConstants, ViewType } from 'wdConstant/Index' | 4 | import { DisplayDirection, SpConstants, ViewType } from 'wdConstant/Index' |
| @@ -25,8 +23,8 @@ export struct PlayerCommentComponent { | @@ -25,8 +23,8 @@ export struct PlayerCommentComponent { | ||
| 25 | @Consume displayDirection: DisplayDirection | 23 | @Consume displayDirection: DisplayDirection |
| 26 | @State private pageModel: PageModel = new PageModel() | 24 | @State private pageModel: PageModel = new PageModel() |
| 27 | @State liveChatList: Array<LiveRoomItemBean> = [] | 25 | @State liveChatList: Array<LiveRoomItemBean> = [] |
| 26 | + @Consume @Watch("lastInputedCommentChagned") lastInputedComment: LiveRoomItemBean | ||
| 28 | @Consume @Watch('liveDetailsBeanChange') contentDetailData: ContentDetailDTO | 27 | @Consume @Watch('liveDetailsBeanChange') contentDetailData: ContentDetailDTO |
| 29 | - @Consume publishCommentModel: publishCommentModel | ||
| 30 | scroller: Scroller = new Scroller() | 28 | scroller: Scroller = new Scroller() |
| 31 | 29 | ||
| 32 | async aboutToAppear(): Promise<void> { | 30 | async aboutToAppear(): Promise<void> { |
| @@ -81,6 +79,16 @@ export struct PlayerCommentComponent { | @@ -81,6 +79,16 @@ export struct PlayerCommentComponent { | ||
| 81 | }) | 79 | }) |
| 82 | } | 80 | } |
| 83 | 81 | ||
| 82 | + lastInputedCommentChagned() { | ||
| 83 | + Logger.debug(TAG, "2显示评论》》》: " + JSON.stringify(this.lastInputedComment)) | ||
| 84 | + | ||
| 85 | + this.liveChatList.push(this.lastInputedComment) | ||
| 86 | + if (this.pageModel.viewType == ViewType.LOADED) { | ||
| 87 | + this.scroller.scrollEdge(Edge.Bottom) | ||
| 88 | + } | ||
| 89 | + this.pageModel.viewType = ViewType.LOADED; | ||
| 90 | + } | ||
| 91 | + | ||
| 84 | build() { | 92 | build() { |
| 85 | Column() { | 93 | Column() { |
| 86 | Stack({ alignContent: Alignment.BottomStart }) { | 94 | Stack({ alignContent: Alignment.BottomStart }) { |
| @@ -16,4 +16,6 @@ export { WDAliPlayerController } from "./src/main/ets/controller/WDAliPlayerCont | @@ -16,4 +16,6 @@ export { WDAliPlayerController } from "./src/main/ets/controller/WDAliPlayerCont | ||
| 16 | 16 | ||
| 17 | export { WDListPlayerData, WDAliListPlayerController } from "./src/main/ets/controller/WDAliListPlayerController" | 17 | export { WDListPlayerData, WDAliListPlayerController } from "./src/main/ets/controller/WDAliListPlayerController" |
| 18 | 18 | ||
| 19 | -export { AliPlayerRenderView } from "./src/main/ets/pages/AliPlayerRenderView" | ||
| 19 | +export { AliPlayerRenderView } from "./src/main/ets/pages/AliPlayerRenderView" | ||
| 20 | + | ||
| 21 | +export { BackgroundAudioController } from "./src/main/ets/controller/BackgroundAudioController" |
| 1 | +import { Context, WantAgent, wantAgent } from '@kit.AbilityKit' | ||
| 2 | +import { avSession as AVSessionManager } from '@kit.AVSessionKit' | ||
| 3 | +import { backgroundTaskManager } from '@kit.BackgroundTasksKit' | ||
| 4 | +import { BusinessError } from '@kit.BasicServicesKit' | ||
| 5 | +import { Logger } from 'wdKit/Index' | ||
| 6 | +import { PlayerConstants } from '../constants/PlayerConstants' | ||
| 7 | +import { WDPlayerController } from './WDPlayerController' | ||
| 8 | +import { image } from '@kit.ImageKit' | ||
| 9 | + | ||
| 10 | +const TAG = "BackgroundAudioController" | ||
| 11 | + | ||
| 12 | +export class BackgroundAudioController { | ||
| 13 | + | ||
| 14 | + private static bgAudioController: BackgroundAudioController | ||
| 15 | + private constructor() { | ||
| 16 | + } | ||
| 17 | + public static sharedController() { | ||
| 18 | + if (!BackgroundAudioController.bgAudioController) { | ||
| 19 | + BackgroundAudioController.bgAudioController = new BackgroundAudioController() | ||
| 20 | + } | ||
| 21 | + return BackgroundAudioController.bgAudioController | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + public gotContextFunc?: () => Context | ||
| 25 | + public avplayerController?: WDPlayerController | ||
| 26 | + private lastSession?: AVSessionManager.AVSession | ||
| 27 | + private applyedLongTaskPlay: boolean = false | ||
| 28 | + private lastProgress: number = 0.0 | ||
| 29 | + private hasSetupProgress: boolean = false | ||
| 30 | + | ||
| 31 | + // 开始创建并激活媒体会话 | ||
| 32 | + // 创建session | ||
| 33 | + async createSession() { | ||
| 34 | + if (!this.gotContextFunc) { return } | ||
| 35 | + | ||
| 36 | + if (this.lastSession == null) { | ||
| 37 | + this.destorySession() | ||
| 38 | + let type: AVSessionManager.AVSessionType = 'audio'; | ||
| 39 | + let session = await AVSessionManager.createAVSession(this.gotContextFunc(),'SESSION_NAME', type); | ||
| 40 | + this.lastSession = session | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + // 激活接口要在元数据、控制命令注册完成之后再执行 | ||
| 44 | + await this.lastSession?.activate(); | ||
| 45 | + Logger.debug(TAG, `session create done : sessionId : ${this.lastSession?.sessionId}`); | ||
| 46 | + | ||
| 47 | + this.lastProgress = 0 | ||
| 48 | + this.hasSetupProgress = false | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + destorySession() { | ||
| 52 | + if (this.lastSession) { | ||
| 53 | + this.lastSession.deactivate(); | ||
| 54 | + this.lastSession.destroy(); | ||
| 55 | + } | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + //设置播放元数据 | ||
| 59 | + setSessionMetaData(assetId: string, title: string, mediaImage: image.PixelMap | string, artist: string) { | ||
| 60 | + Logger.debug(TAG, `SetAVMetadata assetId: ${assetId}}, title: ${title}, mediaImage: ${mediaImage}, artist: ${artist}`); | ||
| 61 | + let metadata: AVSessionManager.AVMetadata = { | ||
| 62 | + assetId: assetId.length > 0 ? assetId : "fake-asset-id", | ||
| 63 | + title: title.length > 0 ? title : " ", | ||
| 64 | + mediaImage: mediaImage, | ||
| 65 | + artist: artist.length > 0 ? artist : "人日日报", | ||
| 66 | + }; | ||
| 67 | + this.lastSession?.setAVMetadata(metadata).then(() => { | ||
| 68 | + Logger.debug(TAG, `SetAVMetadata successfully`); | ||
| 69 | + }).catch((err: BusinessError) => { | ||
| 70 | + Logger.error(TAG, `Failed to set AVMetadata. Code: ${err.code}, message: ${err.message}`); | ||
| 71 | + }); | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + //设置播放状态 | ||
| 75 | + setSessionPlayStatus(playStatus: number) { | ||
| 76 | + let playbackStatus = AVSessionManager.PlaybackState.PLAYBACK_STATE_PLAY | ||
| 77 | + switch (playStatus){ | ||
| 78 | + case PlayerConstants.STATUS_PAUSE: { | ||
| 79 | + playbackStatus = AVSessionManager.PlaybackState.PLAYBACK_STATE_PAUSE | ||
| 80 | + } break | ||
| 81 | + case PlayerConstants.STATUS_START: { | ||
| 82 | + playbackStatus = AVSessionManager.PlaybackState.PLAYBACK_STATE_PLAY | ||
| 83 | + } break | ||
| 84 | + case PlayerConstants.STATUS_STOP: { | ||
| 85 | + playbackStatus = AVSessionManager.PlaybackState.PLAYBACK_STATE_STOP | ||
| 86 | + } break | ||
| 87 | + case PlayerConstants.STATUS_ERROR: { | ||
| 88 | + playbackStatus = AVSessionManager.PlaybackState.PLAYBACK_STATE_ERROR | ||
| 89 | + } break | ||
| 90 | + case PlayerConstants.STATUS_COMPLETION: { | ||
| 91 | + playbackStatus = AVSessionManager.PlaybackState.PLAYBACK_STATE_COMPLETED | ||
| 92 | + } break | ||
| 93 | + default: { | ||
| 94 | + playbackStatus = AVSessionManager.PlaybackState.PLAYBACK_STATE_IDLE | ||
| 95 | + } break | ||
| 96 | + } | ||
| 97 | + let playbackState: AVSessionManager.AVPlaybackState = { | ||
| 98 | + state:playbackStatus, | ||
| 99 | + // isFavorite:false | ||
| 100 | + }; | ||
| 101 | + this.lastSession?.setAVPlaybackState(playbackState, (err: BusinessError) => { | ||
| 102 | + if (err) { | ||
| 103 | + Logger.error(TAG, `Failed to set AVPlaybackState. Code: ${err.code}, message: ${err.message}`); | ||
| 104 | + } else { | ||
| 105 | + Logger.debug(TAG, `SetAVPlaybackState 设置播放状态成功 ` + playStatus); | ||
| 106 | + } | ||
| 107 | + }); | ||
| 108 | + } | ||
| 109 | + | ||
| 110 | + //设置进度,单位秒 | ||
| 111 | + setSessionPlayProgress(progressDuration: number, totalDuration: number) { | ||
| 112 | + // Logger.debug(TAG, `set progress: ` + progressDuration + " duration: " + totalDuration); | ||
| 113 | + if (totalDuration <= 0) { | ||
| 114 | + return | ||
| 115 | + } | ||
| 116 | + let newProgress = progressDuration / totalDuration | ||
| 117 | + if (Math.abs(newProgress - this.lastProgress) < 0.01) { | ||
| 118 | + return | ||
| 119 | + } | ||
| 120 | + this.lastProgress = newProgress | ||
| 121 | + | ||
| 122 | + if (this.hasSetupProgress) { | ||
| 123 | + return | ||
| 124 | + } | ||
| 125 | + this.hasSetupProgress = true | ||
| 126 | + | ||
| 127 | + Logger.debug(TAG, `set progress: ` + progressDuration + " duration: " + totalDuration); | ||
| 128 | + | ||
| 129 | + // 设置状态: 播放状态,进度位置,播放倍速,缓存的时间 | ||
| 130 | + let playbackState: AVSessionManager.AVPlaybackState = { | ||
| 131 | + state: AVSessionManager.PlaybackState.PLAYBACK_STATE_PLAY, // 播放状态 | ||
| 132 | + position: { | ||
| 133 | + elapsedTime: progressDuration * 1000, // 已经播放的位置,以ms为单位 | ||
| 134 | + updateTime: new Date().getTime(), // 应用更新当前位置时的时间戳,以ms为单位 | ||
| 135 | + }, | ||
| 136 | + duration: totalDuration * 1000, | ||
| 137 | + speed: 1.0, // 可选,默认是1.0,播放的倍速,按照应用内支持的speed进行设置,系统不做校验 | ||
| 138 | + bufferedTime: totalDuration * 1000, // 可选,资源缓存的时间,以ms为单位 | ||
| 139 | + }; | ||
| 140 | + this.lastSession?.setAVPlaybackState(playbackState, (err) => { | ||
| 141 | + if (err) { | ||
| 142 | + Logger.error(TAG, `Failed to set AVPlaybackState. Code: ${err.code}, message: ${err.message}`); | ||
| 143 | + } else { | ||
| 144 | + Logger.debug(TAG, `SetAVPlaybackState successfully`); | ||
| 145 | + } | ||
| 146 | + }); | ||
| 147 | + } | ||
| 148 | + | ||
| 149 | + // 置灰或禁用不支持的按钮 | ||
| 150 | + stopUseFeatures() { | ||
| 151 | + // 取消指定session下的相关监听 | ||
| 152 | + // this.lastSession?.off('playFromAssetId'); | ||
| 153 | + // this.lastSession?.off('setSpeed'); | ||
| 154 | + // this.lastSession?.off('setLoopMode'); | ||
| 155 | + // this.lastSession?.off('toggleFavorite'); | ||
| 156 | + // this.lastSession?.off('skipToQueueItem'); | ||
| 157 | + // this.lastSession?.off('handleKeyEvent'); | ||
| 158 | + // this.lastSession?.off('commonCommand'); | ||
| 159 | + // this.lastSession?.off('rewind'); | ||
| 160 | + // this.lastSession?.off('fastForward'); | ||
| 161 | + } | ||
| 162 | + | ||
| 163 | + listenPlayEvents() { | ||
| 164 | + this.lastSession?.on('play', () => { | ||
| 165 | + Logger.debug(TAG, `on play `); | ||
| 166 | + this.avplayerController?.play() | ||
| 167 | + this.hasSetupProgress = false | ||
| 168 | + }); | ||
| 169 | + this.lastSession?.on('pause', () => { | ||
| 170 | + Logger.debug(TAG, `on pause `); | ||
| 171 | + this.avplayerController?.pause() | ||
| 172 | + }); | ||
| 173 | + this.lastSession?.on('stop', () => { | ||
| 174 | + Logger.debug(TAG, `on stop `); | ||
| 175 | + this.avplayerController?.stop() | ||
| 176 | + }); | ||
| 177 | + // this.lastSession?.on('playNext', () => { | ||
| 178 | + // Logger.debug(TAG, `on playNext `); | ||
| 179 | + // }); | ||
| 180 | + // this.lastSession?.on('playPrevious', () => { | ||
| 181 | + // Logger.debug(TAG, `on playPrevious `); | ||
| 182 | + // }); | ||
| 183 | + this.lastSession?.on('seek', (position: number) => { | ||
| 184 | + Logger.debug(TAG, `on seek , the time is ${JSON.stringify(position)}`); | ||
| 185 | + | ||
| 186 | + // 由于应用内seek可能会触发较长的缓冲等待,可以先把状态设置为 Buffering | ||
| 187 | + let playbackState: AVSessionManager.AVPlaybackState = { | ||
| 188 | + state: AVSessionManager.PlaybackState.PLAYBACK_STATE_BUFFERING, // 缓冲状态 | ||
| 189 | + }; | ||
| 190 | + this.lastSession?.setAVPlaybackState(playbackState, (err) => { | ||
| 191 | + if (err) { | ||
| 192 | + Logger.debug(TAG, `Failed to set AVPlaybackState. Code: ${err.code}, message: ${err.message}`); | ||
| 193 | + } else { | ||
| 194 | + Logger.debug(TAG, `SetAVPlaybackState seek buffering`); | ||
| 195 | + } | ||
| 196 | + }); | ||
| 197 | + | ||
| 198 | + // 应用响应seek命令,使用应用内播放器完成seek实现 | ||
| 199 | + this.avplayerController?.setSeekTime(position * 0.001, SliderChangeMode.End) | ||
| 200 | + this.hasSetupProgress = false | ||
| 201 | + }); | ||
| 202 | + } | ||
| 203 | + | ||
| 204 | + // 开启后台长时任务 | ||
| 205 | + startContinuousTask() { | ||
| 206 | + if (this.applyedLongTaskPlay) { | ||
| 207 | + return | ||
| 208 | + } | ||
| 209 | + let params: Record<string, string> = { | ||
| 210 | + "title": "开始后台任务", | ||
| 211 | + "content": "内容?", | ||
| 212 | + // "pushLink": pushLink, | ||
| 213 | + // "taskid": message.taskId, | ||
| 214 | + // "messageId": message.messageId, | ||
| 215 | + // "gtTransmitMsgLocalNotify": "1", | ||
| 216 | + } | ||
| 217 | + | ||
| 218 | + let wantAgentInfo: wantAgent.WantAgentInfo = { | ||
| 219 | + // 点击通知后,将要执行的动作列表 | ||
| 220 | + // 添加需要被拉起应用的bundleName和abilityName | ||
| 221 | + wants: [ | ||
| 222 | + { | ||
| 223 | + deviceId: '', | ||
| 224 | + bundleName: "com.peopledailychina.hosactivity", | ||
| 225 | + abilityName: "EntryAbility", | ||
| 226 | + // action: 'com.test.pushaction', | ||
| 227 | + // entities: [], | ||
| 228 | + // parameters:params, | ||
| 229 | + } | ||
| 230 | + ], | ||
| 231 | + // 指定点击通知栏消息后的动作是拉起ability | ||
| 232 | + actionType: wantAgent.OperationType.START_ABILITY, | ||
| 233 | + // 使用者自定义的一个私有值 | ||
| 234 | + requestCode: 0, | ||
| 235 | + // 点击通知后,动作执行属性 | ||
| 236 | + wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG], | ||
| 237 | + }; | ||
| 238 | + | ||
| 239 | + // 通过wantAgent模块下getWantAgent方法获取WantAgent对象 | ||
| 240 | + wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj: WantAgent) => { | ||
| 241 | + if (!this.gotContextFunc) { return } | ||
| 242 | + backgroundTaskManager.startBackgroundRunning(this.gotContextFunc(), | ||
| 243 | + backgroundTaskManager.BackgroundMode.AUDIO_PLAYBACK, | ||
| 244 | + wantAgentObj).then(() => { | ||
| 245 | + Logger.debug(TAG, `Succeeded in operationing startBackgroundRunning.`); | ||
| 246 | + this.applyedLongTaskPlay = true | ||
| 247 | + }).catch((err: BusinessError) => { | ||
| 248 | + Logger.error(TAG, `Failed to operation startBackgroundRunning. Code is ${err.code}, message is ${err.message}`); | ||
| 249 | + }); | ||
| 250 | + }); | ||
| 251 | + } | ||
| 252 | + | ||
| 253 | + stopContinuousTask() { | ||
| 254 | + if (!this.gotContextFunc) { return } | ||
| 255 | + backgroundTaskManager.stopBackgroundRunning(this.gotContextFunc()).then(() => { | ||
| 256 | + Logger.debug(TAG, `Succeeded in operationing stopBackgroundRunning.`); | ||
| 257 | + }).catch((err: BusinessError) => { | ||
| 258 | + Logger.error(TAG, `Failed to operation stopBackgroundRunning. Code is ${err.code}, message is ${err.message}`); | ||
| 259 | + }); | ||
| 260 | + this.applyedLongTaskPlay = false | ||
| 261 | + } | ||
| 262 | + | ||
| 263 | +} |
| 1 | import media from '@ohos.multimedia.media'; | 1 | import media from '@ohos.multimedia.media'; |
| 2 | import prompt from '@ohos.promptAction'; | 2 | import prompt from '@ohos.promptAction'; |
| 3 | -import { Logger } from '../utils/Logger'; | ||
| 4 | import { PlayerConstants, AVPlayerStatus, Events } from '../constants/PlayerConstants'; | 3 | import { PlayerConstants, AVPlayerStatus, Events } from '../constants/PlayerConstants'; |
| 5 | import { BusinessError } from '@ohos.base'; | 4 | import { BusinessError } from '@ohos.base'; |
| 6 | import { TrackingPlay } from 'wdTracking/Index'; | 5 | import { TrackingPlay } from 'wdTracking/Index'; |
| 7 | import { ParamType } from 'wdTracking/Index'; | 6 | import { ParamType } from 'wdTracking/Index'; |
| 8 | -import { DateTimeUtils } from 'wdKit/Index'; | 7 | +import { DateTimeUtils, Logger } from 'wdKit/Index'; |
| 8 | +import { BackgroundAudioController } from './BackgroundAudioController'; | ||
| 9 | 9 | ||
| 10 | interface obj { | 10 | interface obj { |
| 11 | loop: boolean | 11 | loop: boolean |
| 12 | } | 12 | } |
| 13 | 13 | ||
| 14 | +const TAG = "WDPlayerController" | ||
| 15 | + | ||
| 14 | @Observed | 16 | @Observed |
| 15 | export class WDPlayerController { | 17 | export class WDPlayerController { |
| 16 | private initPromise: Promise<void>; | 18 | private initPromise: Promise<void>; |
| @@ -41,7 +43,7 @@ export class WDPlayerController { | @@ -41,7 +43,7 @@ export class WDPlayerController { | ||
| 41 | public xComponentController?: XComponentController | 43 | public xComponentController?: XComponentController |
| 42 | public videoWidth: number = 0 | 44 | public videoWidth: number = 0 |
| 43 | public videoHeight: number = 0 | 45 | public videoHeight: number = 0 |
| 44 | - | 46 | + public keepOnBackground = false |
| 45 | 47 | ||
| 46 | 48 | ||
| 47 | 49 | ||
| @@ -58,20 +60,20 @@ export class WDPlayerController { | @@ -58,20 +60,20 @@ export class WDPlayerController { | ||
| 58 | */ | 60 | */ |
| 59 | private createAVPlayer(): Promise<void> { | 61 | private createAVPlayer(): Promise<void> { |
| 60 | return new Promise((resolve, reject) => { | 62 | return new Promise((resolve, reject) => { |
| 61 | - Logger.error("开始创建") | 63 | + Logger.debug(TAG, "开始创建") |
| 62 | media.createAVPlayer().then((avPlayer) => { | 64 | media.createAVPlayer().then((avPlayer) => { |
| 63 | if (avPlayer) { | 65 | if (avPlayer) { |
| 64 | - Logger.error("创建完成1") | 66 | + Logger.debug(TAG, "创建完成1") |
| 65 | this.avPlayer = avPlayer; | 67 | this.avPlayer = avPlayer; |
| 66 | this.bindState(); | 68 | this.bindState(); |
| 67 | resolve(); | 69 | resolve(); |
| 68 | } else { | 70 | } else { |
| 69 | - Logger.error("创建完成0") | ||
| 70 | - Logger.error('[PlayVideoModel] createAvPlayer fail!'); | 71 | + Logger.error(TAG, "创建完成0") |
| 72 | + Logger.error(TAG, '[PlayVideoModel] createAvPlayer fail!'); | ||
| 71 | reject(); | 73 | reject(); |
| 72 | } | 74 | } |
| 73 | }).catch((error: BusinessError) => { | 75 | }).catch((error: BusinessError) => { |
| 74 | - console.error(`AVPlayer catchCallback, error message:${error.message}`); | 76 | + Logger.error(TAG, `AVPlayer catchCallback, error message:${error.message}`); |
| 75 | }); | 77 | }); |
| 76 | ; | 78 | ; |
| 77 | }); | 79 | }); |
| @@ -143,10 +145,10 @@ export class WDPlayerController { | @@ -143,10 +145,10 @@ export class WDPlayerController { | ||
| 143 | this.avPlayer.release(); | 145 | this.avPlayer.release(); |
| 144 | this.status = PlayerConstants.STATUS_STOP; | 146 | this.status = PlayerConstants.STATUS_STOP; |
| 145 | this.watchStatus(); | 147 | this.watchStatus(); |
| 146 | - Logger.info('[PlayVideoModel] state released called') | 148 | + Logger.info(TAG, '[PlayVideoModel] state released called') |
| 147 | break; | 149 | break; |
| 148 | default: | 150 | default: |
| 149 | - Logger.info('[PlayVideoModel] unKnown state: ' + state); | 151 | + Logger.info(TAG, '[PlayVideoModel] unKnown state: ' + state); |
| 150 | break; | 152 | break; |
| 151 | } | 153 | } |
| 152 | }); | 154 | }); |
| @@ -155,7 +157,7 @@ export class WDPlayerController { | @@ -155,7 +157,7 @@ export class WDPlayerController { | ||
| 155 | }); | 157 | }); |
| 156 | this.avPlayer?.on(Events.ERROR, (error) => { | 158 | this.avPlayer?.on(Events.ERROR, (error) => { |
| 157 | this.playError(error.message); | 159 | this.playError(error.message); |
| 158 | - console.log('播放错误',JSON.stringify(error)) | 160 | + Logger.error(TAG, '播放错误' + JSON.stringify(error)) |
| 159 | TrackingPlay.videoPlayError(error.message, this.pageName, this.pageName, this.pageParam) | 161 | TrackingPlay.videoPlayError(error.message, this.pageName, this.pageName, this.pageParam) |
| 160 | }) | 162 | }) |
| 161 | this.avPlayer?.on('seekDone', (time: number) => { | 163 | this.avPlayer?.on('seekDone', (time: number) => { |
| @@ -186,7 +188,7 @@ export class WDPlayerController { | @@ -186,7 +188,7 @@ export class WDPlayerController { | ||
| 186 | this.url = url; | 188 | this.url = url; |
| 187 | //加载时长prepareTime | 189 | //加载时长prepareTime |
| 188 | this.creatStartTime = DateTimeUtils.getTimeStamp() | 190 | this.creatStartTime = DateTimeUtils.getTimeStamp() |
| 189 | - console.log('开始创建',JSON.stringify(this.creatStartTime)) | 191 | + Logger.debug(TAG, '开始创建' + JSON.stringify(this.creatStartTime)) |
| 190 | this.prepareTime = 0 | 192 | this.prepareTime = 0 |
| 191 | if(pageName){ | 193 | if(pageName){ |
| 192 | this.pageName = pageName | 194 | this.pageName = pageName |
| @@ -195,7 +197,7 @@ export class WDPlayerController { | @@ -195,7 +197,7 @@ export class WDPlayerController { | ||
| 195 | this.pageParam = pageParam | 197 | this.pageParam = pageParam |
| 196 | } | 198 | } |
| 197 | if (this.avPlayer == null) { | 199 | if (this.avPlayer == null) { |
| 198 | - console.log("等待") | 200 | + Logger.debug(TAG, "等待") |
| 199 | this.initPromise = this.createAVPlayer(); | 201 | this.initPromise = this.createAVPlayer(); |
| 200 | await this.initPromise; | 202 | await this.initPromise; |
| 201 | } else { | 203 | } else { |
| @@ -209,13 +211,13 @@ export class WDPlayerController { | @@ -209,13 +211,13 @@ export class WDPlayerController { | ||
| 209 | if (this.avPlayer == null) { | 211 | if (this.avPlayer == null) { |
| 210 | return | 212 | return |
| 211 | } | 213 | } |
| 212 | - console.log("开始播放", this.url) | 214 | + Logger.debug(TAG, "开始播放", this.url) |
| 213 | this.avPlayer.url = this.url; | 215 | this.avPlayer.url = this.url; |
| 214 | //加载时长prepareTime | 216 | //加载时长prepareTime |
| 215 | this.creatEndTime = DateTimeUtils.getTimeStamp() | 217 | this.creatEndTime = DateTimeUtils.getTimeStamp() |
| 216 | this.prepareTime = 0 | 218 | this.prepareTime = 0 |
| 217 | this.prepareTime = Math.floor((this.creatEndTime - this.creatStartTime)/1000) | 219 | this.prepareTime = Math.floor((this.creatEndTime - this.creatStartTime)/1000) |
| 218 | - console.log('开始播放2',JSON.stringify(this.prepareTime)) | 220 | + Logger.debug(TAG, '开始播放2',JSON.stringify(this.prepareTime)) |
| 219 | } | 221 | } |
| 220 | 222 | ||
| 221 | async release() { | 223 | async release() { |
| @@ -237,6 +239,7 @@ export class WDPlayerController { | @@ -237,6 +239,7 @@ export class WDPlayerController { | ||
| 237 | // if (this.avPlayer == null) { | 239 | // if (this.avPlayer == null) { |
| 238 | // return | 240 | // return |
| 239 | // } | 241 | // } |
| 242 | + Logger.debug(TAG, "start pause") | ||
| 240 | this.avPlayer?.pause(); | 243 | this.avPlayer?.pause(); |
| 241 | } | 244 | } |
| 242 | 245 | ||
| @@ -253,7 +256,7 @@ export class WDPlayerController { | @@ -253,7 +256,7 @@ export class WDPlayerController { | ||
| 253 | async startRenderFrame(cb: Function) { | 256 | async startRenderFrame(cb: Function) { |
| 254 | this.avPlayer?.on('startRenderFrame', () => { | 257 | this.avPlayer?.on('startRenderFrame', () => { |
| 255 | cb && cb(); | 258 | cb && cb(); |
| 256 | - console.info('startRenderFrame success') | 259 | + Logger.debug(TAG, 'startRenderFrame success') |
| 257 | }) | 260 | }) |
| 258 | } | 261 | } |
| 259 | 262 | ||
| @@ -299,6 +302,7 @@ export class WDPlayerController { | @@ -299,6 +302,7 @@ export class WDPlayerController { | ||
| 299 | // return | 302 | // return |
| 300 | // } | 303 | // } |
| 301 | if (this.status === PlayerConstants.STATUS_START) { | 304 | if (this.status === PlayerConstants.STATUS_START) { |
| 305 | + Logger.debug(TAG, "start pause 1111") | ||
| 302 | this.avPlayer?.pause(); | 306 | this.avPlayer?.pause(); |
| 303 | } else { | 307 | } else { |
| 304 | this.avPlayer?.play(); | 308 | this.avPlayer?.play(); |
| @@ -349,6 +353,11 @@ export class WDPlayerController { | @@ -349,6 +353,11 @@ export class WDPlayerController { | ||
| 349 | this.currentPlayTime=Math.floor(time / 1000); | 353 | this.currentPlayTime=Math.floor(time / 1000); |
| 350 | let nowSeconds = Math.floor(time / 1000); | 354 | let nowSeconds = Math.floor(time / 1000); |
| 351 | let totalSeconds = Math.floor(this.duration / 1000); | 355 | let totalSeconds = Math.floor(this.duration / 1000); |
| 356 | + | ||
| 357 | + if (this.keepOnBackground) { | ||
| 358 | + BackgroundAudioController.sharedController().setSessionPlayProgress(time, this.duration) | ||
| 359 | + } | ||
| 360 | + | ||
| 352 | if (this.onTimeUpdate) { | 361 | if (this.onTimeUpdate) { |
| 353 | this.onTimeUpdate(time, this.duration); | 362 | this.onTimeUpdate(time, this.duration); |
| 354 | } | 363 | } |
| @@ -397,7 +406,7 @@ export class WDPlayerController { | @@ -397,7 +406,7 @@ export class WDPlayerController { | ||
| 397 | if (this.onVolumeUpdate) { | 406 | if (this.onVolumeUpdate) { |
| 398 | this.onVolumeUpdate(this.volume); | 407 | this.onVolumeUpdate(this.volume); |
| 399 | } | 408 | } |
| 400 | - console.log("volume : " + this.volume) | 409 | + Logger.debug(TAG, "volume : " + this.volume) |
| 401 | } | 410 | } |
| 402 | 411 | ||
| 403 | onBrightActionUpdate(event: GestureEvent) { | 412 | onBrightActionUpdate(event: GestureEvent) { |
| @@ -421,22 +430,27 @@ export class WDPlayerController { | @@ -421,22 +430,27 @@ export class WDPlayerController { | ||
| 421 | } | 430 | } |
| 422 | 431 | ||
| 423 | watchStatus() { | 432 | watchStatus() { |
| 424 | - console.log('watchStatus', this.status) | 433 | + |
| 434 | + if (this.keepOnBackground) { | ||
| 435 | + BackgroundAudioController.sharedController().setSessionPlayStatus(this.status) | ||
| 436 | + } | ||
| 437 | + | ||
| 438 | + Logger.debug(TAG, 'watchStatus ' + this.status) | ||
| 425 | if(this.status == PlayerConstants.STATUS_START){ | 439 | if(this.status == PlayerConstants.STATUS_START){ |
| 426 | - console.log('播放视频') | ||
| 427 | - console.log('播放视频prepareTime',JSON.stringify(this.prepareTime)) | ||
| 428 | - console.log('播放视频pageName',JSON.stringify(this.pageName)) | ||
| 429 | - console.log('播放视频pageParam',JSON.stringify(this.pageParam)) | 440 | + Logger.debug(TAG, '播放视频') |
| 441 | + Logger.debug(TAG, '播放视频prepareTime' + JSON.stringify(this.prepareTime)) | ||
| 442 | + Logger.debug(TAG, '播放视频pageName' + JSON.stringify(this.pageName)) | ||
| 443 | + Logger.debug(TAG, '播放视频pageParam' + JSON.stringify(this.pageParam)) | ||
| 430 | // 播放埋点 | 444 | // 播放埋点 |
| 431 | TrackingPlay.videoPositivePlay(Number(this.prepareTime),this.pageName, this.pageName, this.pageParam) | 445 | TrackingPlay.videoPositivePlay(Number(this.prepareTime),this.pageName, this.pageName, this.pageParam) |
| 432 | } | 446 | } |
| 433 | if(this.status == PlayerConstants.STATUS_COMPLETION){ | 447 | if(this.status == PlayerConstants.STATUS_COMPLETION){ |
| 434 | let initDuration = Math.floor(Number(this.duration)/1000) | 448 | let initDuration = Math.floor(Number(this.duration)/1000) |
| 435 | - console.log('播放结束') | ||
| 436 | - console.log('播放结束currentPlayTime',JSON.stringify(this.currentPlayTime)) | ||
| 437 | - console.log('播放结束initDuration',JSON.stringify(initDuration)) | ||
| 438 | - console.log('播放结束pageName',JSON.stringify(this.pageName)) | ||
| 439 | - console.log('播放结束pageParam',JSON.stringify(this.pageParam)) | 449 | + Logger.debug(TAG, '播放结束') |
| 450 | + Logger.debug(TAG, '播放结束currentPlayTime' + JSON.stringify(this.currentPlayTime)) | ||
| 451 | + Logger.debug(TAG, '播放结束initDuration' + JSON.stringify(initDuration)) | ||
| 452 | + Logger.debug(TAG, '播放结束pageName' + JSON.stringify(this.pageName)) | ||
| 453 | + Logger.debug(TAG, '播放结束pageParam' + JSON.stringify(this.pageParam)) | ||
| 440 | // 播放结束埋点 | 454 | // 播放结束埋点 |
| 441 | TrackingPlay.videoPlayEnd(this.currentPlayTime, initDuration, this.currentPlayTime, this.pageName, this.pageName, this.pageParam) | 455 | TrackingPlay.videoPlayEnd(this.currentPlayTime, initDuration, this.currentPlayTime, this.pageName, this.pageName, this.pageParam) |
| 442 | } | 456 | } |
| @@ -88,7 +88,8 @@ struct Index { | @@ -88,7 +88,8 @@ struct Index { | ||
| 88 | 88 | ||
| 89 | onPageHide() { | 89 | onPageHide() { |
| 90 | // this.status = PlayerConstants.STATUS_PAUSE; | 90 | // this.status = PlayerConstants.STATUS_PAUSE; |
| 91 | - this.AudioSuspension.playerController.get()?.pause(); | 91 | + console.info('onPageHide'); |
| 92 | + // this.AudioSuspension.playerController.get()?.pause(); | ||
| 92 | } | 93 | } |
| 93 | 94 | ||
| 94 | build() { | 95 | build() { |
| @@ -22,6 +22,7 @@ import { webview } from '@kit.ArkWeb' | @@ -22,6 +22,7 @@ import { webview } from '@kit.ArkWeb' | ||
| 22 | import { NewspaperWidgetCommon } from '../dailynewspaperwidget/common/NewspaperWidgetCommon' | 22 | import { NewspaperWidgetCommon } from '../dailynewspaperwidget/common/NewspaperWidgetCommon' |
| 23 | import { LiveRoomManager } from 'wdDetailPlayLive/Index' | 23 | import { LiveRoomManager } from 'wdDetailPlayLive/Index' |
| 24 | import { initGlobalPlayerSettings } from 'wdPlayer/src/main/ets/utils/GlobalSetting' | 24 | import { initGlobalPlayerSettings } from 'wdPlayer/src/main/ets/utils/GlobalSetting' |
| 25 | +import { BackgroundAudioController } from 'wdPlayer/Index' | ||
| 25 | 26 | ||
| 26 | const TAG = "[StartupManager]" | 27 | const TAG = "[StartupManager]" |
| 27 | 28 | ||
| @@ -115,6 +116,8 @@ export class StartupManager { | @@ -115,6 +116,8 @@ export class StartupManager { | ||
| 115 | this.initAuthLogin() | 116 | this.initAuthLogin() |
| 116 | 117 | ||
| 117 | this.initLiveChatRoom() | 118 | this.initLiveChatRoom() |
| 119 | + | ||
| 120 | + this.initBackgroundAudioTask() | ||
| 118 | Logger.debug(TAG, "App 必要初始化完成") | 121 | Logger.debug(TAG, "App 必要初始化完成") |
| 119 | } | 122 | } |
| 120 | 123 | ||
| @@ -210,6 +213,12 @@ export class StartupManager { | @@ -210,6 +213,12 @@ export class StartupManager { | ||
| 210 | } | 213 | } |
| 211 | } | 214 | } |
| 212 | 215 | ||
| 216 | + private initBackgroundAudioTask() { | ||
| 217 | + BackgroundAudioController.sharedController().gotContextFunc = () => { | ||
| 218 | + return StartupManager.sharedInstance().context! | ||
| 219 | + } | ||
| 220 | + } | ||
| 221 | + | ||
| 213 | private initThirdPlatformSDK() { | 222 | private initThirdPlatformSDK() { |
| 214 | 223 | ||
| 215 | } | 224 | } |
| @@ -24,6 +24,9 @@ | @@ -24,6 +24,9 @@ | ||
| 24 | "startWindowIcon": "$media:app_icon", | 24 | "startWindowIcon": "$media:app_icon", |
| 25 | "startWindowBackground": "$color:start_window_background", | 25 | "startWindowBackground": "$color:start_window_background", |
| 26 | "exported": true, | 26 | "exported": true, |
| 27 | + "backgroundModes": [ | ||
| 28 | + "audioPlayback" | ||
| 29 | + ], | ||
| 27 | "skills": [ | 30 | "skills": [ |
| 28 | { | 31 | { |
| 29 | "entities": [ | 32 | "entities": [ |
| @@ -33,6 +36,8 @@ | @@ -33,6 +36,8 @@ | ||
| 33 | "action.system.home", | 36 | "action.system.home", |
| 34 | "com.test.pushaction" | 37 | "com.test.pushaction" |
| 35 | ], | 38 | ], |
| 39 | + }, | ||
| 40 | + { | ||
| 36 | "uris": [ | 41 | "uris": [ |
| 37 | { | 42 | { |
| 38 | "scheme": 'rmrbapp', | 43 | "scheme": 'rmrbapp', |
| @@ -40,7 +45,7 @@ | @@ -40,7 +45,7 @@ | ||
| 40 | 'port': '8080', | 45 | 'port': '8080', |
| 41 | "path": 'openwith' | 46 | "path": 'openwith' |
| 42 | } | 47 | } |
| 43 | - ] | 48 | + ], |
| 44 | } | 49 | } |
| 45 | ] | 50 | ] |
| 46 | } | 51 | } |
| @@ -103,6 +108,16 @@ | @@ -103,6 +108,16 @@ | ||
| 103 | } | 108 | } |
| 104 | }, | 109 | }, |
| 105 | { | 110 | { |
| 111 | + "name": "ohos.permission.KEEP_BACKGROUND_RUNNING", | ||
| 112 | + "reason": "$string:permission_background_audio", | ||
| 113 | + "usedScene": { | ||
| 114 | + "abilities": [ | ||
| 115 | + "FormAbility" | ||
| 116 | + ], | ||
| 117 | + "when": "always" | ||
| 118 | + } | ||
| 119 | + }, | ||
| 120 | + { | ||
| 106 | "name": "ohos.permission.INTERNET" | 121 | "name": "ohos.permission.INTERNET" |
| 107 | }, | 122 | }, |
| 108 | ], | 123 | ], |
| @@ -29,6 +29,10 @@ | @@ -29,6 +29,10 @@ | ||
| 29 | "value": "开启之后即可用于收录声音进行拍摄视频、语音搜索、语音评论功能," | 29 | "value": "开启之后即可用于收录声音进行拍摄视频、语音搜索、语音评论功能," |
| 30 | }, | 30 | }, |
| 31 | { | 31 | { |
| 32 | + "name": "permission_background_audio", | ||
| 33 | + "value": "开启之后即可用于后台音频播放" | ||
| 34 | + }, | ||
| 35 | + { | ||
| 32 | "name": "dialog_text_title", | 36 | "name": "dialog_text_title", |
| 33 | "value": "个人隐私保护指引" | 37 | "value": "个人隐私保护指引" |
| 34 | }, | 38 | }, |
-
Please register or login to post a comment