wangliang_wd

Merge branch 'main' of http://192.168.1.42/developOne/harmonyPool into main

* 'main' of http://192.168.1.42/developOne/harmonyPool:
  ref |> 处理播控中心进度条问题
  ref |> App内链跳转专题处理
  ref |> 修改工程配置,为推送、播控中心、App Linkg统一调整
  fix |> 修复进入大专题卡,少了更多按钮问题
  轮播卡-文章专题_已收藏专题进入详情页、收藏按钮未点亮展示
  ref |> H5专题页面pageinfo数据来源调整为由H5提供
  fix:频道页下配置的回看类直播节目无进度条
  fix:UI还原问题-【uat】进入竖屏直播详情页-“出发吧!穿越219国道-德天跨国瀑布”,直播间评论显示位置和android不一致,偏上
Showing 23 changed files with 352 additions and 169 deletions
... ... @@ -24,7 +24,7 @@ interface dataObject {
// 9、活动投稿 视频跳转
// 10、活动投稿 动态跳转
// 11、活动投稿 图集跳转
dataSource: string
dataSource: WDH5WebDataSource
operateType?: string
webViewHeight?: string
dataJson?: string
... ... @@ -69,3 +69,20 @@ export class Message {
return JSON.parse(jsonStr)
}
}
export enum WDH5WebDataSource {
WDH5WebDataSourceUnknown = 0,
WDH5WebDataSourceImageTextDetail = 1,
WDH5WebDataSourceContentInfo = 2,
WDH5WebDataSourcePictures = 3,
WDH5WebDataSourceTopicPageInfo = 4,
WDH5WebDataSourceCompPositionData = 5,
WDH5WebDataSourceArticleRefDataJump = 6,
WDH5WebDataSourceSharePosterListDatas = 7,
WDH5WebDataSourcePartinActivityPublishArticle = 8,
WDH5WebDataSourcePartinActivityPublishVideo = 9,
WDH5WebDataSourcePartinActivityPublishDynamic = 10,
WDH5WebDataSourcePartinActivityPublishPicture = 11,
}
\ No newline at end of file
... ...
... ... @@ -101,8 +101,23 @@ export class AppInnerLink {
return
}
if (params.type == "topic") {
if (params.type == "topic" && params.subType == "h5") {
let taskAction: Action = {
type: 'JUMP_INNER_NEW_PAGE',
params: {
contentID: params.pageId,
url: params.url,
pageID: 'SPACIAL_TOPIC_PAGE',
backVisibility: true,
extra: {
relType: params.relType,
relId: params.relId,
pageId: params.pageId
} as ExtraDTO,
} as Params,
};
WDRouterRule.jumpWithAction(taskAction)
}
if (params.type == "channel") {
... ...
... ... @@ -5,7 +5,8 @@ import { setDefaultNativeWebSettings } from './WebComponentUtil';
import { Action } from 'wdBean';
import { performJSCallNative } from './JsBridgeBiz';
import { H5CallNativeType } from './H5CallNativeType';
import { Message } from 'wdJsBridge/src/main/ets/bean/Message';
import { Message,WDH5WebDataSource } from 'wdJsBridge/src/main/ets/bean/Message';
import { JSON } from '@kit.ArkTS';
const TAG = 'WdWebComponent';
... ... @@ -14,6 +15,9 @@ export struct WdWebComponent {
webviewControl: BridgeWebViewControl = new BridgeWebViewControl()
onWebPrepared: () => void = () => {
}
receiveH5SendToNativeData: (dataString:string | undefined) => void = () =>{
}
@Prop webUrl: string = ''
@Prop @Watch('onReloadStateChanged') reload: number = 0
@Link isPageEnd: boolean
... ... @@ -61,16 +65,26 @@ export struct WdWebComponent {
* 默认【CallNative】逻辑处理
*/
private defaultPerformJSCallNative: (data: Message, f: Callback) => void = (data: Message, f: Callback) => {
// H5内部跳转逻辑(前端调用原生的js方法处理)
performJSCallNative(data, f)
}
/**
* 获取前端返回的数据
*/
private defaultGetReceiveSubjectData: (data: Message, f: Callback) => void = (data: Message, f: Callback) => {
if(data.handlerName === H5CallNativeType.jsCall_receiveSubjectData) {
f('')
return
}
if (data.handlerName === H5CallNativeType.jsCall_receiveH5Data) {
if (data.data?.dataSource === WDH5WebDataSource.WDH5WebDataSourceTopicPageInfo) {
this.receiveH5SendToNativeData(data.data?.dataJson)
return
}
}
}
onPageBegin: (url?: string) => void = () => {
Logger.debug(TAG, 'onPageBegin');
this.registerHandlers();
... ...
... ... @@ -175,6 +175,7 @@ export { MasterDetailRes } from './src/main/ets/bean/user/MasterDetailRes';
export { ReserveItemBean } from './src/main/ets/bean/live/ReserveItemBean';
export { PageTrackBean } from './src/main/ets/bean/component/PageTrackBean';
export { TopicDetailData,GroupItem } from './src/main/ets/bean/content/TopicDetailData'
export { FeedbackTypeBean } from './src/main/ets/bean/detail/FeedbackTypeBean';
... ...
import { TopicInfo } from '../morningevening/TopicInfo';
import { ArrayList } from '@kit.ArkTS';
export interface GroupItem {
id: number;
blockDesc: string;
groupStrategy: number;
itemNum: number;
showType: number;
sortValue: number;
}
export interface TopicDetailData {
backIconUrl: string;
shareSummary: string;
id: number;
baselineCopywriting: string;
cornersAdv: string;
backgroundImgUrl: string;
description: string;
imgSize: string;
pageTopType: number;
pushupLogoImgUrl: string;
backgroundColor: string;
shareCoverUrl: string;
shareName: string;
mainLogoImgUrl: string;
titleColor: string;
baselineShow: number;
pageType: number;
shareIconUrl: string;
shareUrl: string;
name: string;
hasAdInfo: number;
hasPopUp: number;
statusBarColor: string;
templateType: number;
topicInfo: TopicInfo;
baselineColor: string;
groups: ArrayList<GroupItem>;
}
\ No newline at end of file
... ...
... ... @@ -76,4 +76,5 @@ export class ContentDetailDTO {
// 本地字段
showTime:boolean = false;
isLogin?:string
}
\ No newline at end of file
... ...
... ... @@ -48,7 +48,6 @@ export struct ImageAndTextPageComponent {
@Provide contentDetailData: ContentDetailDTO = {} as ContentDetailDTO
@State recommendList: ContentDTO[] = []
@State newsStatusOfUser: batchLikeAndCollectResult | undefined = undefined // 点赞、收藏状态
@State getNewsStatusOfUser: boolean = false // 接口获取点赞、收藏状态,为true时获取失败
@State interactData: InteractDataDTO = {} as InteractDataDTO
@State isPageEnd: boolean = false
@State publishTime: string = ''
... ... @@ -74,10 +73,6 @@ export struct ImageAndTextPageComponent {
pageShowForUpdateData() {
this.pageShowTime = DateTimeUtils.getTimeStamp()
// 未登录查不到稿件收藏状态,导致newsStatusOfUser为undefined,影响后续点赞效果
if(this.getNewsStatusOfUser) {
this.getInteractDataStatus()
}
}
//内容浏览Tracking
... ... @@ -373,11 +368,9 @@ export struct ImageAndTextPageComponent {
// console.log(TAG,'contentDetailData', JSON.stringify(params.contentList))
let data = await MultiPictureDetailViewModel.getInteractDataStatus(params)
console.log(TAG, '查询用户对作品点赞、收藏状态', JSON.stringify(data))
this.getNewsStatusOfUser = false // 获取成功
this.newsStatusOfUser = data[0];
// console.log(TAG, `newsStatusOfUser:${JSON.stringify(this.newsStatusOfUser)}`)
} catch (exception) {
this.getNewsStatusOfUser = true // 获取失败
console.error(TAG,'exception', JSON.stringify(exception))
}
}
... ... @@ -461,6 +454,10 @@ export struct ImageAndTextPageComponent {
}
}
})
// 登录成功
EmitterUtils.receiveEvent(EmitterEventId.LOGIN_SUCCESS, () => {
this.getInteractDataStatus()
})
}
aboutToDisappear() {
... ...
import { Action, H5ReceiveDetailBean, ContentDetailDTO, InteractDataDTO, TopicInfo } from 'wdBean';
import { Action, H5ReceiveDetailBean, ContentDetailDTO, InteractDataDTO, TopicInfo,TopicDetailData,ShareInfoDTO } from 'wdBean';
import { WdWebComponent } from 'wdWebComponent';
import { CommonConstants } from 'wdConstant'
import { BridgeWebViewControl } from 'wdJsBridge/Index';
... ... @@ -7,7 +7,7 @@ import { OperRowListView } from './view/OperRowListView';
import DetailViewModel from '../viewmodel/DetailViewModel';
import { publishCommentModel } from '../components/comment/model/PublishCommentModel';
import { EmptyComponent } from '../components/view/EmptyComponent';
import { NetworkUtil, WindowModel } from 'wdKit';
import { NetworkUtil, WindowModel,Logger } from 'wdKit';
import { viewBlogItemInsightIntentShare } from '../utils/InsightIntentShare'
import { common } from '@kit.AbilityKit';
import { PageRepository } from '../repository/PageRepository';
... ... @@ -34,7 +34,7 @@ export struct SpacialTopicPageComponent {
@Provide contentDetailData: ContentDetailDTO = {} as ContentDetailDTO
private h5ReceiveAppData: H5ReceiveDetailBean = { dataSource: '2' } as H5ReceiveDetailBean
private webPrepared = false;
private dataPrepared = false;
// private dataPrepared = false;
@State publishCommentModel: publishCommentModel = new publishCommentModel()
@State operationButtonList: string[] = ['comment', 'collect', 'share']
@State bottomSafeHeight: number = AppStorage.get<number>('bottomSafeHeight') || 0
... ... @@ -42,9 +42,12 @@ export struct SpacialTopicPageComponent {
@Provide topSafeHeight: number = AppStorage.get<number>('topSafeHeight') || 0
@State showComment: boolean = false
@State topicInfo: TopicInfo = {} as TopicInfo
@State topicDetail: TopicDetailData = {} as TopicDetailData
@State shareInfo: ShareInfoDTO = {} as ShareInfoDTO
@State showBottomView: boolean = false;
private trySendData2H5() {
if (!this.webPrepared || !this.dataPrepared) {
if (!this.webPrepared) {
return
}
// 数据、web组件,都准备好了,开始塞详情数据
... ... @@ -57,73 +60,52 @@ export struct SpacialTopicPageComponent {
}
private sendContentData2H5(h5ReceiveAppData: H5ReceiveDetailBean) {
Logger.debug('SpacialTopicPageComponent', 'jsCall_receiveAppData',JSON.stringify(h5ReceiveAppData));
this.webviewControl.callHandle(NativeCallH5Type.jsCall_receiveAppData,
JSON.stringify(h5ReceiveAppData), (data: string) => {
Logger.debug('SpacialTopicPageComponent', "from js data = " + data);
})
}
//意图上报
private viewBlogInsightIntentShare(){
let context = getContext(this) as common.UIAbilityContext;
viewBlogItemInsightIntentShare(context,this.contentDetailData)
}
async getWebviewPageData (){
let pageId = this.action.params?.extra?.pageId
let relId: string = ''
let relType: string = ''
let contentId: string = ''
if (this.action && this.action.params) {
if (this.action.params.contentID) {
contentId = this.action.params.contentID;
}
if (this.action && this.action.params && this.action.params.extra) {
if (this.action.params.extra.relId) {
relId = this.action.params.extra.relId;
}
if (this.action.params.extra.relType) {
relType = this.action.params.extra.relType
}
}
}
if(pageId){
// let pageInfoMsg = await PageRepository.fetchMorningEveningPageInfo(pageId)
// let pageCompInfoMsg = await PageRepository.fetchMorningEveningCompInfo(Number(pageId), groupId, refreshTime, topicId, 1, 20)
// let res = {
// dataJson: {
// pageInfoResponseMap: pageInfoMsg,
// compInfoResponseMap: pageCompInfoMsg,
// },
// }
}
private receiveH5SendToNativeData(dataString:string | undefined) {
// this.topicDetail = JSON.parse(dataString);
if (dataString == undefined) {
return
}
Logger.debug('SpacialTopicPageComponent111',dataString);
this.topicDetail = JSON.parse(dataString);
this.topicInfo = this.topicDetail.topicInfo;
private async getDetail() {
this.isNetConnected = NetworkUtil.isNetConnected()
let contentId: string = ''
let relId: string = ''
let relType: string = ''
if (this.action && this.action.params) {
if (this.action.params.contentID) {
contentId = this.action.params.contentID;
}
if (this.action && this.action.params && this.action.params.extra) {
if (this.action.params.extra.relId) {
relId = this.action.params.extra.relId;
}
if (this.action.params.extra.relType) {
relType = this.action.params.extra.relType
}
}
let pageId = this.action.params.extra?.pageId
console.log('pageIdpageId',pageId)
if(pageId){
let pageInfoMsg = await PageRepository.fetchMorningEveningPageInfo(pageId,contentId)
let detailBeans = await DetailViewModel.getDetailPageData(relId, contentId, relType)
if (detailBeans?.length > 0) {
this.contentDetailData = JSON.parse(JSON.stringify(detailBeans[0]));
this.viewBlogInsightIntentShare()
// if (this.contentDetailData[0]?.openComment) {
if(this.topicInfo){
// 转换详情数据
this.contentDetailData.openComment = Number(this.topicInfo.commentFlag)
this.contentDetailData.commentDisplay = Number(this.topicInfo.commentShowFlag)
this.contentDetailData.newsId = Number(this.topicInfo.topicId)
this.contentDetailData.newsType = this.topicInfo.topicType
this.contentDetailData.newsTitle = this.topicInfo.title;
this.contentDetailData.newsType = this.topicInfo.topicType;
this.contentDetailData.visitorComment = this.topicInfo.visitorComment;
//转换分享数据
this.shareInfo.shareCoverUrl = this.topicInfo.shareCoverUrl
this.shareInfo.shareOpen = this.topicInfo.shareOpen
this.shareInfo.sharePosterCoverUrl = this.topicInfo.sharePosterCoverUrl
this.shareInfo.shareSummary = this.topicInfo.shareSummary
this.shareInfo.shareTitle = this.topicInfo.shareTitle
this.shareInfo.shareUrl = this.topicInfo.shareUrl
this.contentDetailData.shareInfo = this.shareInfo
console.log('contentDetailData111', JSON.stringify(this.contentDetailData))
// if(this.topicInfo.shareOpen === 1){
// if (!this.operationButtonList.includes('share')) {
// this.operationButtonList.push('share');
// }
// } else {
// this.operationButtonList = this.operationButtonList.filter(e =>e !== 'share')
// }
// 转换评论数据
this.publishCommentModel.targetId = String(this.contentDetailData?.newsId || '')
this.publishCommentModel.targetRelId = String(this.contentDetailData?.reLInfo?.relId || '')
this.publishCommentModel.targetTitle = this.contentDetailData?.newsTitle
... ... @@ -132,59 +114,40 @@ export struct SpacialTopicPageComponent {
this.publishCommentModel.keyArticle = String(this.contentDetailData?.keyArticle || '')
this.publishCommentModel.targetType = String(this.contentDetailData?.newsType || '')
this.publishCommentModel.visitorComment = String(this.contentDetailData?.visitorComment || '')
this.showBottomView = true
// }
this.subjectData = 'dasdasdadas'
//TODO
// this.trySendData2H5()
}
if(pageInfoMsg && pageInfoMsg.data){
this.contentDetailData.openComment = Number(pageInfoMsg.data.topicInfo?.commentFlag)
this.contentDetailData.commentDisplay = Number(pageInfoMsg.data.topicInfo?.commentShowFlag)
console.log('contentDetailData pageInfoMsg.data', JSON.stringify(pageInfoMsg.data))
this.topicInfo = pageInfoMsg.data.topicInfo
this.contentDetailData.newsId = Number(this.topicInfo.topicId)
this.contentDetailData.newsType = this.topicInfo.topicType
if(this.topicInfo?.shareOpen === 1){
this.contentDetailData.shareInfo.shareOpen = this.topicInfo?.shareOpen
console.log('contentDetailData this.topicInfo', JSON.stringify(this.topicInfo))
if (!this.operationButtonList.includes('share')) {
this.operationButtonList.push('share');
}
} else {
this.operationButtonList = this.operationButtonList.filter(e =>e !== 'share')
}
// this.viewBlogInsightIntentShare();
}
console.log('contentDetailData', JSON.stringify(this.contentDetailData))
}
}
//意图上报
private viewBlogInsightIntentShare(){
let context = getContext(this) as common.UIAbilityContext;
viewBlogItemInsightIntentShare(context,this.contentDetailData)
}
build() {
Column() {
Stack({ alignContent: Alignment.Bottom }) {
Column() {
Text(this.contentDetailData?.newsTitle)
.backgroundColor(Color.White)
.width('100%')
.height(40)
.fontSize(18)
.textAlign(TextAlign.Center)
.fontWeight(500)
.visibility(this.action?.params?.backVisibility && this.isPageEnd ? Visibility.Visible : Visibility.None)
if(this.subjectData.length > 0){
// Text(this.contentDetailData?.newsTitle)
// .backgroundColor(Color.White)
// .width('100%')
// .height(40)
// .fontSize(18)
// .textAlign(TextAlign.Center)
// .fontWeight(500)
// .visibility(this.action?.params?.backVisibility && this.isPageEnd ? Visibility.Visible : Visibility.None)
WdWebComponent({
webviewControl: this.webviewControl,
webUrl: this.webUrl,
reload: this.reload,
onWebPrepared: this.onWebPrepared.bind(this),
isPageEnd: $isPageEnd,
subjectData: this.subjectData
receiveH5SendToNativeData: this.receiveH5SendToNativeData.bind(this)
})
}
}
.width(CommonConstants.FULL_WIDTH)
.height(CommonConstants.FULL_HEIGHT)
.padding({ bottom: this.action?.params?.backVisibility ? 115 : 75 })
... ... @@ -194,7 +157,8 @@ export struct SpacialTopicPageComponent {
emptyType: 1,
emptyButton: true,
retry: () => {
this.getDetail()
// this.getDetail()
this.reload ++
}
}).padding({ bottom: 200 })
} else {
... ... @@ -203,6 +167,7 @@ export struct SpacialTopicPageComponent {
}
}
//底部交互区
if (this.showBottomView){
OperRowListView({
contentDetailData: this.contentDetailData,
publishCommentModel: this.publishCommentModel,
... ... @@ -222,6 +187,7 @@ export struct SpacialTopicPageComponent {
interactData: $interactData,
}).visibility(this.showComment?Visibility.Visible:Visibility.Hidden)
}
}
}.width(CommonConstants.FULL_WIDTH).height(CommonConstants.FULL_HEIGHT)
}
... ... @@ -230,7 +196,8 @@ export struct SpacialTopicPageComponent {
// WindowModel.shared.setWindowLayoutFullScreen(true)
}
this.webUrl = this.action?.params?.url || ''
this.getDetail()
this.isNetConnected = NetworkUtil.isNetConnected()
// this.getDetail()
}
aboutToDisappear() {
... ...
... ... @@ -83,6 +83,12 @@ export struct LiveOperRowListView {
this.onDetailUpdated()
this.contentTrackingDict()
this.checkCanInputComment()
// 登录成功
EmitterUtils.receiveEvent(EmitterEventId.LOGIN_SUCCESS, () => {
this.getInteractDataStatus()
// 激活点赞组件监听
this.contentDetailData['isLogin'] = 'y'
})
}
contentTrackingDict(){
... ... @@ -103,7 +109,7 @@ export struct LiveOperRowListView {
if (user_id) {
this.getInteractDataStatus()
}
await this.queryContentInteractCount()
this.queryContentInteractCount()
console.info(TAG, 'contentDetailData----', JSON.stringify(this.contentDetailData))
console.info(TAG, 'this.operationButtonList', JSON.stringify(this.operationButtonList))
... ...
... ... @@ -96,6 +96,7 @@ export struct OperRowListView {
@State likesStyle: number | string = 1 // 赞样式 1红心(点赞) 2大拇指(祈福) 3蜡烛(默哀) 4置空
@State openLikes: boolean = false // 是否可以点赞 1:可以 0:不可以
@Prop topicInfo?: TopicInfo = {} as TopicInfo
private shareOpen = 0;
async aboutToAppear() {
console.info(TAG, 'this.needLike', this.needLike)
... ... @@ -114,6 +115,12 @@ export struct OperRowListView {
}
}
})
// 登录成功
EmitterUtils.receiveEvent(EmitterEventId.LOGIN_SUCCESS, () => {
this.getInteractDataStatus()
// 激活点赞组件监听
this.likeBean['isLogin'] = 'y'
})
this.contentTrackingDict()
}
... ... @@ -131,11 +138,12 @@ export struct OperRowListView {
if (!this.contentDetailData) {
return
}
this.shareOpen = this.contentDetailData.shareInfo.shareOpen;
const user_id = await SPHelper.default.get(SpConstants.USER_ID, '')
if (user_id) {
this.getInteractDataStatus()
}
await this.queryContentInteractCount()
this.queryContentInteractCount()
// 点赞需要数据
this.likeBean['contentId'] = this.contentDetailData.newsId + ''
if(this.contentDetailData.userInfo?.userName) {
... ... @@ -387,10 +395,11 @@ export struct OperRowListView {
*/
@Builder
builderShare() {
if(this.contentDetailData?.shareInfo?.shareOpen == 1) {
Column() {
Image(this.styleType == 1 ? $r('app.media.iv_live_comment_share') :
$r('app.media.iv_live_comment_share_white'))
Image(this.styleType == 1 ? (this.shareOpen == 1?$r('app.media.iv_live_comment_share'):$r('app.media.more_icon_black')) :
(this.shareOpen == 1?$r('app.media.iv_live_comment_share_white'):$r('app.media.more_icon_white')))
.width(24)
.height(24)
.aspectRatio(1)
... ... @@ -405,7 +414,9 @@ export struct OperRowListView {
.borderRadius(18)
.backgroundColor(this.pageComponentType === 2 ? '#4D000000' : Color.Transparent)
}
}
// if(this.contentDetailData?.shareInfo?.shareOpen == 1) {
//
// }
handleStyle() {
if (this.styleType == 1) {
... ... @@ -434,7 +445,7 @@ export struct OperRowListView {
appCustomTargetRelType: this.topicInfo?.relType,
appCustomShowReport: false,
appCustomShowLike: -1,
shareOpen: 1,
shareOpen: this.shareOpen,
sharePosterOpen: this.topicInfo?.posterFlag,
appCustomShowPoster: this.topicInfo?.posterFlag && this.topicInfo?.posterFlag > 0 ? 1 : -1,
}
... ...
... ... @@ -312,7 +312,7 @@ export class PageRepository {
// 批量查询内容当前用户点赞、收藏状态
static fetchInteractDataStatus(param: object) {
let url = PageRepository.getInteractDataStatusUrl()
return WDHttp.post<ResponseDTO<batchLikeAndCollectResult[]>>(url, param)
return HttpBizUtil.post<ResponseDTO<batchLikeAndCollectResult[]>>(url, param)
};
/**
... ...
... ... @@ -45,11 +45,10 @@ export class AudioSuspensionModel {
this.playerController.get().keepOnBackground = true
BackgroundAudioController.sharedController().avplayerController = this.playerController.get()
await BackgroundAudioController.sharedController().createSession()
BackgroundAudioController.sharedController().startContinuousTask()
let id = $r('app.media.newspaper_default').id
BackgroundAudioController.sharedController().setSessionMetaData(srcContentId ?? "", srcTitle, 'file://', srcSource ?? "")
BackgroundAudioController.sharedController().stopUseFeatures()
// BackgroundAudioController.sharedController().startContinuousTask()
BackgroundAudioController.sharedController().listenPlayEvents()
await BackgroundAudioController.sharedController().setSessionMetaData(srcContentId ?? "", srcTitle, $r("app.media.system_audio_icon_bk_center"), srcSource ?? "")
BackgroundAudioController.sharedController().stopUseFeatures()
if (this.url === url) {
this.isMinimize = AppStorage.link<boolean>('isMinimize')
... ...
... ... @@ -15,26 +15,38 @@ export struct ChatItemComponent {
if (this.item.role == LiveMessageRole.host) {
Span(' 主持人 ')
.fontSize(11)
.lineHeight(20)
// .lineHeight(16)
.textBackgroundStyle({ color: "#70FFC63F", radius: 2 })
.fontColor('#FFFFFFFF')
.fontFamily('PingFang SC-Regular')
.fontWeight(400)
Span(' ')
}
if (this.item.role == LiveMessageRole.guest) {
Span(' 嘉宾 ')
.fontSize(11)
.lineHeight(20)
// .lineHeight(16)
.textBackgroundStyle({ color: "#70FFC63F", radius: 2 })
.fontColor('#FFFFFFFF')
.fontFamily('PingFang SC-Regular')
.fontWeight(400)
Span(' ')
}
Span(this.item.senderUserName + ': ')
.fontSize(14)
.lineHeight(22)
.fontColor('#FFFFC63F')
.padding({ right: 118 })
.fontFamily('PingFang SC-Semibold')
.fontWeight(600)
Span(this.item.text)
}
.fontSize(14)
.fontColor('#FFFFFFFF')
.lineHeight(22)
.fontColor('#FFFFFFFF')
.fontFamily('PingFang SC-Semibold')
.fontWeight(600)
}
.textShadow({ offsetX: 1, offsetY: 1, color: '#4D000000', radius: 1 })
}
... ...
... ... @@ -94,9 +94,9 @@ export struct PlayerCommentComponent {
Stack({ alignContent: Alignment.BottomStart }) {
List({ scroller: this.scroller }) {
// 主持人
if (this.contentDetailData.oldNewsId) {
/*if (this.contentDetailData.oldNewsId) {
ChartItemCompereComponent()
}
}*/
ForEach(this.liveChatList, (item: LiveRoomItemBean) => {
ListItem() {
ChatItemComponent({ item: item })
... ... @@ -106,7 +106,10 @@ export struct PlayerCommentComponent {
.width('80%')
.scrollBar(BarState.Off)
}.height(280)
}
.constraintSize({
maxHeight: 280
})
// 收藏、分享、点赞是否需要根据字段显隐
LiveOperRowListView({
... ...
... ... @@ -16,8 +16,9 @@ export struct PlayerInfoComponent {
Column() {
Swiper(this.swiperController) {
Text('')
PlayerUIComponent({ playerController: this.playerController }).margin({
bottom: this.bottomSafeHeight + 'px',
PlayerUIComponent({ playerController: this.playerController })
.margin({
// bottom: this.bottomSafeHeight + 'px',
top: this.topSafeHeight + 'px'
})
}
... ... @@ -28,11 +29,11 @@ export struct PlayerInfoComponent {
.width('100%')
.height('100%')
.index(this.swiperIndex)
// .onClick(() => {
// if (this.liveState === 'end') {
// this.isShowControl = !this.isShowControl
// }
// })
.onClick(() => {
if (this.liveState === 'end') {
this.isShowControl = !this.isShowControl
}
})
.onChange((index) => {
this.swiperIndex = index
})
... ...
... ... @@ -37,9 +37,9 @@ export struct PlayerUIComponent {
PlayerVideoControlComponent({ playerController: this.playerController })
.visibility(this.isShowControl ? Visibility.Visible : this.isSmall? Visibility.Visible:Visibility.Hidden)
.animation({ duration: 500 })
// .position({ y: '100%' })
// .markAnchor({ y: '100%' })
.margin({ top: this.isSmall?195 +211 - 105:0})
.position({ y: '100%' })
.markAnchor({ y: '100%' })
.margin({ top: this.isSmall ? 195 + 211 - 105 : 0})
}
.height('100%')
.width('100%')
... ...
... ... @@ -2,10 +2,11 @@ import { Context, WantAgent, wantAgent } from '@kit.AbilityKit'
import { avSession as AVSessionManager } from '@kit.AVSessionKit'
import { backgroundTaskManager } from '@kit.BackgroundTasksKit'
import { BusinessError } from '@kit.BasicServicesKit'
import { Logger } from 'wdKit/Index'
import { PlayerConstants } from '../constants/PlayerConstants'
import { DateTimeUtils, EmitterEventId, EmitterUtils, Logger } from 'wdKit/Index'
import { Events, PlayerConstants } from '../constants/PlayerConstants'
import { WDPlayerController } from './WDPlayerController'
import { image } from '@kit.ImageKit'
import { JSON } from '@kit.ArkTS'
const TAG = "BackgroundAudioController"
... ... @@ -13,6 +14,9 @@ export class BackgroundAudioController {
private static bgAudioController: BackgroundAudioController
private constructor() {
EmitterUtils.receiveEvent(EmitterEventId.APP_ENTER_BACKGROUD, () => {
this.startContinuousTask()
})
}
public static sharedController() {
if (!BackgroundAudioController.bgAudioController) {
... ... @@ -24,9 +28,17 @@ export class BackgroundAudioController {
public gotContextFunc?: () => Context
public avplayerController?: WDPlayerController
private lastSession?: AVSessionManager.AVSession
private applyedLongTaskPlay: boolean = false
private lastProgress: number = 0.0
private hasSetupProgress: boolean = false
private playing: boolean = false
private lastItemAssetId?: string
private lastItemTitle?: string
private lastItemMediaImage?: Resource
private lastItemArtist?: string
private lastItemTotalDuration: number = 0
// 开始创建并激活媒体会话
// 创建session
... ... @@ -56,23 +68,53 @@ export class BackgroundAudioController {
}
//设置播放元数据
setSessionMetaData(assetId: string, title: string, mediaImage: image.PixelMap | string, artist: string) {
Logger.debug(TAG, `SetAVMetadata assetId: ${assetId}}, title: ${title}, mediaImage: ${mediaImage}, artist: ${artist}`);
async setSessionMetaData(assetId: string, title: string, mediaImage: Resource, artist: string) {
this.lastItemAssetId = assetId
this.lastItemTitle = title
this.lastItemMediaImage = mediaImage
this.lastItemArtist = artist
}
async setSessionMetaDataWithDuration(assetId: string, title: string, mediaImage: Resource, artist: string, duration: number) {
Logger.debug(TAG, `SetAVMetadata assetId: ${assetId}}, title: ${title}, mediaImage: ${mediaImage}, artist: ${artist}, duration: ${duration}`);
if (!this.gotContextFunc) { return }
let pixelMapImage:image.PixelMap | null = null
try {
const data:Uint8Array = await this.gotContextFunc().resourceManager.getMediaContent(mediaImage)
pixelMapImage = await image.createPixelMap(data.buffer as ArrayBuffer, {
editable: false,
alphaType: image.AlphaType.UNKNOWN,
srcPixelFormat: image.PixelMapFormat.RGB_888,
size: { width:300, height:300 }
})
} catch (e) {
Logger.error(TAG, `SetAVMetadata ` + JSON.stringify(e));
} finally {
// Logger.debug(TAG, `SetAVMetadata ` + JSON.stringify(pixelMapImage));
let metadata: AVSessionManager.AVMetadata = {
assetId: assetId.length > 0 ? assetId : "fake-asset-id",
title: title.length > 0 ? title : " ",
mediaImage: mediaImage,
mediaImage: pixelMapImage ?? ("file://" + mediaImage.id),
artist: artist.length > 0 ? artist : "人日日报",
duration: duration
};
this.lastSession?.setAVMetadata(metadata).then(() => {
try {
await this.lastSession?.setAVMetadata(metadata)
Logger.debug(TAG, `SetAVMetadata successfully`);
}).catch((err: BusinessError) => {
} catch (err) {
Logger.error(TAG, `Failed to set AVMetadata. Code: ${err.code}, message: ${err.message}`);
});
} finally {
pixelMapImage?.release()
}
}
}
//设置播放状态
setSessionPlayStatus(playStatus: number) {
let needUpdateProgress = false
let playbackStatus = AVSessionManager.PlaybackState.PLAYBACK_STATE_PLAY
switch (playStatus){
case PlayerConstants.STATUS_PAUSE: {
... ... @@ -80,6 +122,7 @@ export class BackgroundAudioController {
} break
case PlayerConstants.STATUS_START: {
playbackStatus = AVSessionManager.PlaybackState.PLAYBACK_STATE_PLAY
needUpdateProgress = true
} break
case PlayerConstants.STATUS_STOP: {
playbackStatus = AVSessionManager.PlaybackState.PLAYBACK_STATE_STOP
... ... @@ -103,13 +146,15 @@ export class BackgroundAudioController {
Logger.error(TAG, `Failed to set AVPlaybackState. Code: ${err.code}, message: ${err.message}`);
} else {
Logger.debug(TAG, `SetAVPlaybackState 设置播放状态成功 ` + playStatus);
if (needUpdateProgress) {
this.hasSetupProgress = false
}
}
});
}
//设置进度,单位秒
setSessionPlayProgress(progressDuration: number, totalDuration: number) {
// Logger.debug(TAG, `set progress: ` + progressDuration + " duration: " + totalDuration);
//设置进度,单位ms
async setSessionPlayProgress(progressDuration: number, totalDuration: number) {
if (totalDuration <= 0) {
return
}
... ... @@ -117,25 +162,38 @@ export class BackgroundAudioController {
if (Math.abs(newProgress - this.lastProgress) < 0.01) {
return
}
// Logger.debug(TAG, `set progress: ` + progressDuration + " duration: " + totalDuration);
this.lastProgress = newProgress
if (this.lastItemAssetId) {
this.lastItemTotalDuration = totalDuration
await this.setSessionMetaDataWithDuration(
this.lastItemAssetId ?? "",
this.lastItemTitle ?? "",
this.lastItemMediaImage!,
this.lastItemArtist ?? "",
totalDuration
)
this.lastItemAssetId = undefined
}
if (this.hasSetupProgress) {
return
}
this.hasSetupProgress = true
Logger.debug(TAG, `set progress: ` + progressDuration + " duration: " + totalDuration);
Logger.debug(TAG, `set progress: ` + DateTimeUtils.secondToTime(progressDuration / 1000)
+ " duration: " + DateTimeUtils.secondToTime(totalDuration / 1000));
// 设置状态: 播放状态,进度位置,播放倍速,缓存的时间
let playbackState: AVSessionManager.AVPlaybackState = {
state: AVSessionManager.PlaybackState.PLAYBACK_STATE_PLAY, // 播放状态
position: {
elapsedTime: progressDuration * 1000, // 已经播放的位置,以ms为单位
elapsedTime: progressDuration, // 已经播放的位置,以ms为单位
updateTime: new Date().getTime(), // 应用更新当前位置时的时间戳,以ms为单位
},
duration: totalDuration * 1000,
speed: 1.0, // 可选,默认是1.0,播放的倍速,按照应用内支持的speed进行设置,系统不做校验
bufferedTime: totalDuration * 1000, // 可选,资源缓存的时间,以ms为单位
// duration: totalDuration,
// speed: 1.0, // 可选,默认是1.0,播放的倍速,按照应用内支持的speed进行设置,系统不做校验
// bufferedTime: totalDuration, // 可选,资源缓存的时间,以ms为单位
};
this.lastSession?.setAVPlaybackState(playbackState, (err) => {
if (err) {
... ... @@ -181,8 +239,12 @@ export class BackgroundAudioController {
// Logger.debug(TAG, `on playPrevious `);
// });
this.lastSession?.on('seek', (position: number) => {
Logger.debug(TAG, `on seek , the time is ${JSON.stringify(position)}`);
Logger.debug(TAG, `on seek , the time is ${position}`);
if (this.lastItemTotalDuration == 0) {
return
}
this.hasSetupProgress = true
// 由于应用内seek可能会触发较长的缓冲等待,可以先把状态设置为 Buffering
let playbackState: AVSessionManager.AVPlaybackState = {
state: AVSessionManager.PlaybackState.PLAYBACK_STATE_BUFFERING, // 缓冲状态
... ... @@ -193,11 +255,13 @@ export class BackgroundAudioController {
} else {
Logger.debug(TAG, `SetAVPlaybackState seek buffering`);
}
});
// 应用响应seek命令,使用应用内播放器完成seek实现
this.avplayerController?.setSeekTime(position * 0.001, SliderChangeMode.End)
this.avplayerController?.setSeekMicroSecondsTime(position)
setTimeout(() => {
this.hasSetupProgress = false
}, 1000)
});
});
}
... ... @@ -239,6 +303,7 @@ export class BackgroundAudioController {
// 通过wantAgent模块下getWantAgent方法获取WantAgent对象
wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj: WantAgent) => {
if (!this.gotContextFunc) { return }
this.lastSession?.setLaunchAbility(wantAgentObj)
backgroundTaskManager.startBackgroundRunning(this.gotContextFunc(),
backgroundTaskManager.BackgroundMode.AUDIO_PLAYBACK,
wantAgentObj).then(() => {
... ...
... ... @@ -336,6 +336,13 @@ export class WDPlayerController {
this.avPlayer?.seek(this.seekTime);
}
}
async setSeekMicroSecondsTime(value: number) {
// 防止seek报错
if (this.avPlayer && PlayerConstants.OPERATE_STATE.indexOf(this.avPlayer?.state) === -1) {
return;
}
this.avPlayer?.seek(value);
}
setBright() {
// globalThis.windowClass.setWindowBrightness(this.playerThis.bright)
... ...
... ... @@ -96,12 +96,12 @@ export struct WDPlayerRenderVLiveView {
if (this.onLoad) {
this.onLoad(event)
}
})// .width(this.selfSize.width)
// .height(this.selfSize.height)
.height('100%')
.width('100%')
.renderFit(RenderFit.RESIZE_COVER)
.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
})
.width(this.selfSize.width)
.height(this.selfSize.height)
/*.height('100%')
.width('100%')*/
.renderFit(RenderFit.RESIZE_FILL)
}
.id(this.insId)
.onAreaChange(() => {
... ... @@ -110,7 +110,7 @@ export struct WDPlayerRenderVLiveView {
.backgroundColor("#000000")
.height('100%')
.width('100%')
.renderFit(RenderFit.RESIZE_COVER)
.renderFit(RenderFit.RESIZE_FILL)
}
updateLayout() {
... ...
... ... @@ -13,6 +13,7 @@
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
"querySchemes": ["rmrbapp"],
"abilities": [
{
"name": "EntryAbility",
... ... @@ -30,22 +31,47 @@
"skills": [
{
"entities": [
"entity.system.home"
"entity.system.home",
"entity.system.browsable"
],
"actions": [
"action.system.home",
"com.test.pushaction"
"com.test.pushaction",
"ohos.want.action.viewData"
],
// "uris": [{
// // 之前的 推送配置
// "scheme": 'rmrbapp',
// "host": 'rmrb.app',
// 'port': '8080',
// "path": 'openwith'
// }]
},
{
"uris": [
{
{ // 配置 - (播控中心用)
"scheme": 'rmrbapp',
"host": 'rmrb.app',
'port': '8080',
"path": 'openwith'
},
{ // 普通配置 - 暂时无法跳转 - ??
"scheme": "rmrbapp",
"host": "rmrb.app",
"path": "openwith"
},
{ // 分享用 - 正式环境地址
"scheme": "https",
"host": "www.peopleapp.com",
"pathStartWith": "column"
},
{ // 分享用 - 测试环境地址
"scheme": "https",
"host": "pd-people-uat.pdnews.cn",
"pathStartWith": "column"
}
],
"domainVerify": true
}
]
}
... ...