DetailPlayVLivePage.ets 9.94 KB
import { ContentDetailDTO, LiveRoomDataBean, LiveRoomItemBean } from 'wdBean/Index';
import { LiveViewModel } from '../viewModel/LiveViewModel';
import { CustomToast, Logger, WindowModel } from 'wdKit/Index';
import { PlayerComponent } from '../widgets/vertical/PlayerComponent';
import { PlayerInfoComponent } from '../widgets/vertical/PlayerInfoComponent';
import { WDAliPlayerController } from 'wdPlayer/Index';
import { DisplayDirection } from 'wdConstant/Index';
import { LiveEmptyComponent, WDLiveViewDefaultType } from 'wdComponent/Index';
import { PlayerEndView } from '../widgets/vertical/PlayerEndView';
import { TrackConstants, TrackingButton } from 'wdTracking/Index';
import { LiveDetailPageLogic } from '../viewModel/LiveDetailPageLogic';
import { onlyWifiLoadVideo } from 'wdComponent/src/main/ets/utils/lazyloadImg';
import { StringUtils } from 'wdKit';
import { LiveDetailChatRoomController } from '../im/LiveDetailChatRoomController';
import { LiveMessageOptType } from 'wdBean/src/main/ets/bean/live/LiveRoomBean';
import { JSON } from '@kit.ArkTS';

const storage = LocalStorage.getShared();
const TAG = 'DetailPlayVLivePage'

/**
 *  沉浸式房间直播组件
 */
@Entry(storage)
@Component
export struct DetailPlayVLivePage {
  private liveViewModel: LiveViewModel = new LiveViewModel()
  private playerController: WDAliPlayerController = new WDAliPlayerController();
  private swiperController: SwiperController = new SwiperController()
  @Consume contentDetailData: ContentDetailDTO
  @Consume bottomSafeHeight: number
  @Consume topSafeHeight: number
  @Provide liveRoomDataBean: LiveRoomDataBean = {} as LiveRoomDataBean
  @Provide isShowControl: boolean = false
  @Provide displayDirection: DisplayDirection = DisplayDirection.VERTICAL //横竖屏,默认竖屏
  @Consume liveState: string
  @Consume liveStyle: number
  @Consume playUrl: string
  // @Consume imgUrl: string
  @Consume @Watch('openFullScreen') pageShow: number
  @Consume @Watch('closeFullScreen') pageHide: number
  @Consume contentId: string
  @State swiperIndex: number = 1
  ///是否展示清屏按钮
  @State showClearButton: boolean = false
  @Consume liveDetailPageLogic: LiveDetailPageLogic
  @Provide lastInputedComment: LiveRoomItemBean = {} as LiveRoomItemBean // 上次输入的消息
  //播放错误
  @State isPlayerError: boolean = false
  @State isCanplay: boolean = false
  @State toastText: ResourceStr = "这是一个非Wi-Fi环境。请注意流量消耗"
  chatRoomController: LiveDetailChatRoomController = new LiveDetailChatRoomController()
  @Provide banComment: boolean = true

  dialogToast: CustomDialogController = new CustomDialogController({
    builder: CustomToast({
      bgColor: 0xB3000000,
      opacityValue: 1,
      fontSizeValue: "25lpx",
      lineHeightValue: "36lpx",
      msg: this.toastText,
    }),
    autoCancel: false,
    alignment: DialogAlignment.Center,
    customStyle: true,
    maskColor: "#00000000"
  })

  showToastTip(msg: ResourceStr) {
    this.toastText = msg
    this.dialogToast.open()
  }

  async aboutToAppear(): Promise<void> {
    this.openFullScreen()
    this.getLiveRoomData()
    if(!await onlyWifiLoadVideo()){
      this.showToastTip(this.toastText)
    }
    this.configChatRoom()
  }

  aboutToDisappear(): void {
    this.closeFullScreen()
  }

  openFullScreen() {
    console.log(TAG, 'openFullScreen')
   // WindowModel.shared.setWindowLayoutFullScreen(true)
   // WindowModel.shared.setSpecificSystemBarEnabled()
   // WindowModel.shared.setWindowSystemBarProperties({ statusBarContentColor: '#ffffff', })
  }

  closeFullScreen() {
    console.log(TAG, 'closeFullScreen')
  //  WindowModel.shared.setWindowLayoutFullScreen(false)
  //  WindowModel.shared.setSpecificSystemBarEnabled(true)
 //   WindowModel.shared.setWindowSystemBarProperties({ statusBarContentColor: '#000000', })
  }

  configChatRoom() {
    this.chatRoomController.onHistoryMessage = (liveRoomItemBean: LiveRoomItemBean) => {
      const preDisplay = this.contentDetailData.liveInfo.preCommentFlag == 1
      if (this.liveViewModel.filterMySelfCommentNoPreDisplay(liveRoomItemBean, preDisplay)) {
        return
      }
      this.lastInputedComment = liveRoomItemBean
    }
    this.chatRoomController.onLiveMessage = (liveRoomItemBean: LiveRoomItemBean) => {
      switch (liveRoomItemBean.optionType) {
        case LiveMessageOptType.ZH_ROOM_NUMBER_MSG: {
          this.liveRoomDataBean.pv = Number(liveRoomItemBean.pv)
        } break
        case LiveMessageOptType.ZH_BARRAGE_SWITCH_MSG: {
          const openComment = liveRoomItemBean.data == "1"
          this.contentDetailData.liveInfo.openComment = openComment ? 1 : 0
        } break
        case LiveMessageOptType.ZH_PRE_DISPLAY_CHANGE: {
          const preCommentFlag = liveRoomItemBean.data == "1"
          this.contentDetailData.liveInfo.preCommentFlag = preCommentFlag ? 1 : 0
        } break
        case LiveMessageOptType.ZH_BARRAGE_BAN_MESSAGE:
        case LiveMessageOptType.ZH_BARRAGE_UNBAN_MESSAGE: {
          const banComment = liveRoomItemBean.data == "1"
          this.banComment = banComment
        } break
        case LiveMessageOptType.ZH_STOP_LIVE: {
          this.liveState = "end"
          this.contentDetailData.liveInfo.liveState = "end"
        } break
        case LiveMessageOptType.ZH_CHANGE_PAD: {
          const padObj = JSON.parse(liveRoomItemBean.data ?? "") as Record<string, string | number | boolean>
          const showPad = padObj["showPad"] == "1"
          this.liveDetailPageLogic.showPad = showPad
        } break
        default: {
          Logger.warn(TAG, "暂未处理类型:" + liveRoomItemBean.optionType)
        } break
      }
    }
    this.chatRoomController.configDetail(this.contentDetailData)
  }

  build() {

    Stack({ alignContent: Alignment.Top }) {
      // 直播背景图,模糊处理
      Image(this.liveDetailPageLogic.getLiveCoverUrl())
        .height('100%')
        .width('100%')
        .blur(100)
        .renderFit(RenderFit.RESIZE_COVER)
      RelativeContainer()
        .backgroundColor(Color.Black)
        .visibility(this.isPlayerError ? Visibility.Visible :
        Visibility.None)

      // 直播结束且无回看
      if (this.liveState === 'end' && StringUtils.isEmpty(this.playUrl)) {
        PlayerEndView()
      } else {
        // 直播暂停,仍然可以评论
        if (this.liveState === 'pause') {
          RelativeContainer()
            .backgroundColor('#000000')
            .opacity(0.5)
          LiveEmptyComponent({
            emptyType: WDLiveViewDefaultType.WDViewDefaultType_NoLiveSuspend
          })
            .height('40%').margin({ top: this.topSafeHeight })
        } else {

          if (this.liveDetailPageLogic.showPad) {
            // 有垫片
            if (this.liveDetailPageLogic.padImageUri.length > 0) {
              // 配置了垫片资源
              Image(this.liveDetailPageLogic.padImageUri).objectFit(ImageFit.Contain).width('100%').height('100%')

            } else {
              // 没有配置垫片资源
              RelativeContainer()
                .backgroundColor('#000000')
                .opacity(0.5)
              LiveEmptyComponent({
                emptyType: WDLiveViewDefaultType.WDViewDefaultType_NoLiveSuspend
              })
                .height('40%').margin({ top: this.topSafeHeight })
            }

          } else {
            // 播放器
            PlayerComponent({
              playerController: this.playerController, isPlayerError: this.isPlayerError, isCanplay: this.isCanplay
            })
          }
        }

        // 直播详情  左右滑动业务数据
        PlayerInfoComponent({
          playerController: this.playerController,
          swiperController: this.swiperController,
          swiperIndex: $swiperIndex,
          showClearButton: $showClearButton
        })

        // 直播资源加载失败
        Column() {
          Text('直播加载中,请稍候重试')
            .fontSize('20fp')
            .fontWeight(500)
            .margin({ top: 16 })
            .fontColor(Color.White)

          Button('点击重试')
            .type(ButtonType.Normal)
            .width(80)
            .height(28)
            .backgroundColor(Color.Transparent)
            .fontColor('#ffcccccc')
            .border({ width: 1 })
            .borderColor('#4dffffff')
            .borderRadius(4)
            .fontSize($r('app.float.font_size_12'))
            .margin({ top: 16 })
            .padding(0)
            .onClick(() => {

              this.isCanplay = false
              this.isPlayerError = false
              this.playerController?.firstPlay(this.playUrl, TrackConstants.PageName.Live_Detail, {
                'contentType': `${this.contentDetailData.newsType}`,
                'contentId': `${this.contentDetailData.newsId}`,
                'contentName': `${this.contentDetailData.newsTitle || ''}`,
              });
            })
        }
        .width('100%')
        .margin({ top: 195 })
        .justifyContent(FlexAlign.Center)
        .visibility(this.isPlayerError ? Visibility.Visible :
        Visibility.None)

        // 清屏按钮
        Image($r('app.media.icon_live_more'))
          .width(40)
          .aspectRatio(1)
          .visibility(this.showClearButton ? Visibility.Visible : Visibility.Hidden)
          .position({ x: '100%', y: '100%' })
          .markAnchor({ x: 56, y: this.bottomSafeHeight })
          .onClick(() => {
            this.swiperController.showNext()
            // 埋点
            TrackingButton.click('clearScreen', TrackConstants.PageName.Live_Detail,
              TrackConstants.PageName.Live_Detail)
          })

      }
    }
    .height('100%')
    .width('100%')

  }

  getLiveRoomData() {
    this.liveViewModel.getLiveRoomData(this.contentId)
      .then(
        (data) => {
          this.liveRoomDataBean = data
          console.log(TAG, 'getLiveRoomData', JSON.stringify((this.liveRoomDataBean)))
        },
        (message: string) => {
          console.error(TAG, 'getLiveDetails catch', message)
        })
  }
}