Toggle navigation
Toggle navigation
This project
Loading...
Sign in
developOne
/
harmonyPool
Go to a project
Toggle navigation
Projects
Groups
Snippets
Help
Toggle navigation pinning
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
陈剑华
2024-06-11 16:31:30 +0800
Browse Files
Options
Browse Files
Download
Plain Diff
Commit
b16be31ea806b307fdeee585750e67f49cae7bea
b16be31e
2 parents
a37ced65
6a4957f5
Merge remote-tracking branch 'origin/main'
Show whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
140 additions
and
75 deletions
sight_harmony/features/wdComponent/src/main/ets/components/cardCommon/LiveFollowComponent.ets
sight_harmony/features/wdComponent/src/main/ets/components/comment/view/CommentListDialog.ets
sight_harmony/features/wdComponent/src/main/ets/components/mine/home/HomePageBottomCommentComponent.ets
sight_harmony/features/wdComponent/src/main/ets/components/mine/home/OtherHomePageBottomCommentComponent.ets
sight_harmony/features/wdComponent/src/main/ets/components/page/TopNavigationComponentNew.ets
sight_harmony/features/wdComponent/src/main/ets/components/view/LiveOperRowListView.ets
sight_harmony/features/wdComponent/src/main/ets/pages/MineHomePage.ets
sight_harmony/features/wdDetailPlayLive/src/main/ets/pages/DetailPlayLiveCommon.ets
sight_harmony/features/wdDetailPlayLive/src/main/ets/pages/DetailPlayVLivePage.ets
sight_harmony/features/wdDetailPlayLive/src/main/ets/widgets/details/video/PlayUIComponent.ets
sight_harmony/features/wdDetailPlayLive/src/main/ets/widgets/vertical/PlayerInfoComponent.ets
sight_harmony/features/wdDetailPlayShortVideo/src/main/ets/pages/DetailPlayShortVideoPage.ets
sight_harmony/features/wdDetailPlayShortVideo/src/main/ets/view/CommentDialogView.ets
sight_harmony/features/wdPlayer/src/main/ets/pages/WDPlayerRenderView.ets
sight_harmony/features/wdTracking/src/main/ets/tracking/Tracking.ets
sight_harmony/products/phone/src/main/ets/dailynewspaperformability/DailyNewspaperFormAbility.ets
sight_harmony/products/phone/src/main/ets/dailynewspaperformability/NewspaperDataFetcher.ets
sight_harmony/features/wdComponent/src/main/ets/components/cardCommon/LiveFollowComponent.ets
View file @
b16be31
/**
* 直播详情 关注相关信息
* 直播详情 关注相关信息
直播详情页用户信息行
*/
import {
ContentDetailRequest,
...
...
@@ -40,6 +40,7 @@ export struct LiveFollowComponent {
bottomLeft: 90
})
Row() {
//号主头像
Image(this.rmhInfo.rmhHeadUrl)
.width(24)
.height(24)
...
...
@@ -54,6 +55,7 @@ export struct LiveFollowComponent {
WDRouterRule.jumpWithPage(WDRouterPage.peopleShipHomePage, params)
}
})
//号主名称
Text(this.rmhInfo.rmhName)
.fontColor(Color.White)
.maxLines(1)
...
...
@@ -65,6 +67,7 @@ export struct LiveFollowComponent {
right: 6
})
Blank()
//关注状态
Text(this.followStatus === '0' ? '关注' : '已关注')
.fontColor(Color.White)
.fontWeight(500)
...
...
sight_harmony/features/wdComponent/src/main/ets/components/comment/view/CommentListDialog.ets
View file @
b16be31
import { ContentDetailDTO, PageInfoDTO } from 'wdBean/Index'
import { PublicDialogManager } from 'wdKit/Index'
import {
Logger,
PublicDialogManager } from 'wdKit/Index'
import { TrackConstants } from 'wdTracking/Index'
import { OperRowListView } from '../../view/OperRowListView'
import { publishCommentModel } from '../model/PublishCommentModel'
import { CommentComponent } from './CommentComponent'
const TAG = "CommentListDialogView"
/// 评论列表弹框
@Component
export struct CommentListDialogView {
@Link @Watch('showCommentListChange') showCommentList: boolean
@State windowWidth: number = AppStorage.get<number>('windowWidth') || 0
@State windowHeight: number = AppStorage.get<number>('windowHeight') || 0
@Link showCommentList: boolean
@Link contentDetailData: ContentDetailDTO // 详情页传
@Link pageInfo: PageInfoDTO // 专题页传
@Link publishCommentModel: publishCommentModel
private maxHeight: number = 0 // px
onClose?: () => void
onHeightDidChange?: Callback<number>
// @Consume pageId: TrackConstants.PageName
// @Consume pageName: TrackConstants.PageName
aboutToAppear(): void {
this.maxHeight = this.windowHeight - this.windowWidth * 9 / 16
}
private dialogController: CustomDialogController = new CustomDialogController({
builder: CommentListDialog({
contentDetailData: this.contentDetailData,
publishCommentModel:this.publishCommentModel,
pageInfo: this.pageInfo,
onClose: this.onClose
}),
autoCancel: true,
cancel: () => {
PublicDialogManager.shareInstance().closeDialog(this.dialogController)
build() {
Row() {
}
.height("100%").width("100%")
.bindSheet($$this.showCommentList,
this.commentListDialog(),
{
height: this.maxHeight + 'px',
preferType: SheetType.BOTTOM,
showClose: false,
dragBar: false,
onDisappear: () => {
this.showCommentList = false
if (this.onClose) { this.onClose() }
},
customStyle: true,
alignment: DialogAlignment.Bottom,
})
showCommentListChange(val: boolean) {
if (this.showCommentList) {
PublicDialogManager.shareInstance().openDialog(this.dialogController, this.closeAction.bind(this))
} else {
PublicDialogManager.shareInstance().closeDialog(this.dialogController)
shouldDismiss:((sheetDismiss: SheetDismiss)=> {
console.log("bind sheet shouldDismiss")
sheetDismiss.dismiss()
}),
onHeightDidChange: (number: number) => {
Logger.debug(TAG, "onHeightDidChange : " + number)
let height = number
if (height > this.maxHeight) {
height = this.maxHeight
}
if (this.onHeightDidChange) {
this.onHeightDidChange(height)
}
closeAction() {
if (this.onClose) {
this.onClose()
} else {
this.showCommentList = false
}
})
}
build() {
@Builder commentListDialog() {
Column() {
CommentListDialog({
contentDetailData: this.contentDetailData,
publishCommentModel:this.publishCommentModel,
pageInfo: this.pageInfo,
onClose: this.onClose
})
}.height("100%").width("100%")
}
}
@C
ustomDialog
@C
omponent
struct CommentListDialog {
/// 内部使用
@Link publishCommentModel: publishCommentModel
@State private operationButtonList: string[] = []
controller?: CustomDialogController
@State windowWidth: number = AppStorage.get<number>('windowWidth') || 0
@State windowHeight: number = AppStorage.get<number>('windowHeight') || 0
/// 外部初始化
@Link contentDetailData: ContentDetailDTO // 详情页传
...
...
@@ -97,6 +110,7 @@ struct CommentListDialog {
build() {
Column() {
Row().height(10)
this.titleHeaderView()
CommentComponent({
...
...
@@ -117,11 +131,11 @@ struct CommentListDialog {
styleType: 1,
inDialog: true,
dialogBeforeJumpOtherPageAction: () => {
PublicDialogManager.shareInstance().closeLastDialog()
//
PublicDialogManager.shareInstance().closeLastDialog()
}
})
}
.height(
this.windowHeight - this.windowWidth * 9 / 16 + 'px'
)
.height(
"100%").width("100%"
)
.backgroundColor(Color.White)
}
...
...
sight_harmony/features/wdComponent/src/main/ets/components/mine/home/HomePageBottomCommentComponent.ets
View file @
b16be31
...
...
@@ -58,7 +58,6 @@ export struct HomePageBottomCommentComponent {
this.curPageNum = 1;
this.hasMore = true
this.isGetRequest = false
this.data_comment.clear()
if (!this.isLoading){
this.getNewPageData()
...
...
@@ -71,6 +70,7 @@ export struct HomePageBottomCommentComponent {
this.isLoading = true
//加载分页数据
this.getNewPageData()
if(resolve) resolve('刷新成功')
}
}
})
...
...
@@ -98,7 +98,7 @@ export struct HomePageBottomCommentComponent {
.onVisibleAreaChange([0.0, 1.0], (isVisible: boolean, currentRatio: number) => {
if (isVisible) {
let contentDTO = getParams(item)
TrackingContent.common(TrackConstants.EventType.Show, TrackConstants.PageName.Main_Personal,TrackConstants.PageName.Main_Personal, TrackParamConvert.program(contentDTO))
//
TrackingContent.common(TrackConstants.EventType.Show, TrackConstants.PageName.Main_Personal,TrackConstants.PageName.Main_Personal, TrackParamConvert.program(contentDTO))
}
})
}, (item: CommentListItem, index: number) => index.toString())
...
...
@@ -127,6 +127,7 @@ export struct HomePageBottomCommentComponent {
let object = new FollowListDetailRequestItem(-1, 20, this.curPageNum)
MinePageDatasModel.getMineCommentListData(time, object, getContext(this)).then((value) => {
if (this.curPageNum === 1) this.data_comment.clear()
if (!this.data_comment || value.list.length == 0) {
this.hasMore = false
this.isLoading = false
...
...
@@ -185,7 +186,7 @@ export struct HomePageBottomCommentComponent {
this.count = this.data_comment.totalCount()
this.commentNum = value.totalCount
if (value.
pageNum
=== 1) {
if (value.
hasNext
=== 1) {
this.curPageNum++
} else {
this.hasMore = false
...
...
@@ -218,7 +219,7 @@ export struct HomePageBottomCommentComponent {
this.count = this.data_comment.totalCount()
this.commentNum = value.totalCount
if (value.
pageNum
=== 1) {
if (value.
hasNext
=== 1) {
this.curPageNum++
} else {
this.hasMore = false
...
...
sight_harmony/features/wdComponent/src/main/ets/components/mine/home/OtherHomePageBottomCommentComponent.ets
View file @
b16be31
...
...
@@ -99,7 +99,7 @@ export struct OtherHomePageBottomCommentComponent {
if (isVisible) {
let contentDTO = getParams(item)
//埋点crash 后面看看
TrackingContent.common(TrackConstants.EventType.Show, TrackConstants.PageName.Customer_Personal,TrackConstants.PageName.Customer_Personal, TrackParamConvert.program(contentDTO))
//
TrackingContent.common(TrackConstants.EventType.Show, TrackConstants.PageName.Customer_Personal,TrackConstants.PageName.Customer_Personal, TrackParamConvert.program(contentDTO))
}
})
}, (item: CommentListItem, index: number) => index.toString())
...
...
sight_harmony/features/wdComponent/src/main/ets/components/page/TopNavigationComponentNew.ets
View file @
b16be31
...
...
@@ -61,6 +61,8 @@ export struct TopNavigationComponentNew {
@State indicatorLeftMargin: number = 0
@State indicatorWidth: number = 0
@State isClickMorningEveningPaper: boolean = false
build() {
Column() {
// 频道分类list
...
...
@@ -171,6 +173,12 @@ export struct TopNavigationComponentNew {
.height(30)
.width(124)
.onClick(() => {
//防止多次点击
if(!this.isClickMorningEveningPaper) {
this.isClickMorningEveningPaper = true;
let c = setInterval(() => {
this.isClickMorningEveningPaper = false
}, 1000);
// 早晚报埋点
const params: ParamType = {
...
...
@@ -180,6 +188,7 @@ export struct TopNavigationComponentNew {
Tracking.event("morning_evening_news_click", params)
this.clickMorningEveningPaper()
}
})
}.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
...
...
sight_harmony/features/wdComponent/src/main/ets/components/view/LiveOperRowListView.ets
View file @
b16be31
...
...
@@ -189,7 +189,7 @@ export struct LiveOperRowListView {
Stack({ alignContent: Alignment.Start }) {
RelativeContainer() {
Image(
$r('app.media.comment_img_input_hui
'))
Image(
this.styleType == 1 ? $r('app.media.comment_img_input_hui'):$r('app.media.comment_img_input_black
'))
.objectFit(ImageFit.Fill)
.resizable({
slice: {
...
...
@@ -208,7 +208,7 @@ export struct LiveOperRowListView {
.id("Image")
Text("说两句...")
.fontSize(12)
.fontColor(
'#999999
')
.fontColor(
this.styleType == 1 ? '#999999':'#CCFFFFFF
')
.margin({ left: 10 })
.alignRules({
top: { anchor: "__container__", align: VerticalAlign.Top },
...
...
sight_harmony/features/wdComponent/src/main/ets/pages/MineHomePage.ets
View file @
b16be31
...
...
@@ -73,6 +73,7 @@ struct MineHomePage {
}
build() {
Column(){
if(this.isConnectNetwork){
Stack({ alignContent: Alignment.Top }){
Stack({ alignContent: Alignment.Top }){
...
...
@@ -299,7 +300,7 @@ struct MineHomePage {
}
.margin({top:px2vp(this.topSafeHeight)})
}.width('100%')
.padding({bottom:px2vp(this.bottomSafeHeight)})
//
.padding({bottom:px2vp(this.bottomSafeHeight)})
.layoutWeight(1)
}else{
Column(){
...
...
@@ -316,6 +317,8 @@ struct MineHomePage {
}
}
}.padding({bottom:px2vp(this.bottomSafeHeight)})
}
@Builder MineHomeTitleTransparent() {
RelativeContainer() {
...
...
sight_harmony/features/wdDetailPlayLive/src/main/ets/pages/DetailPlayLiveCommon.ets
View file @
b16be31
...
...
@@ -13,6 +13,7 @@ import { LiveDetailPageLogic } from '../viewModel/LiveDetailPageLogic';
const TAG = 'DetailPlayLiveCommon'
/**
* 直播详情页
* @Description: 沉浸式和非沉浸式直播页面
* @Author:
* @Email:
...
...
sight_harmony/features/wdDetailPlayLive/src/main/ets/pages/DetailPlayVLivePage.ets
View file @
b16be31
...
...
@@ -10,6 +10,7 @@ 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';
const storage = LocalStorage.getShared();
const TAG = 'DetailPlayVLivePage'
...
...
@@ -97,7 +98,7 @@ export struct DetailPlayVLivePage {
.blur(100)
.renderFit(RenderFit.RESIZE_COVER)
// 直播结束且无回看
if (this.liveState === 'end' &&
!this.playUrl
) {
if (this.liveState === 'end' &&
StringUtils.isEmpty(this.playUrl)
) {
PlayerEndView()
} else {
// 直播暂停,仍然可以评论
...
...
sight_harmony/features/wdDetailPlayLive/src/main/ets/widgets/details/video/PlayUIComponent.ets
View file @
b16be31
...
...
@@ -6,7 +6,7 @@ import { DateFormatUtil, PlayerConstants, WDAliPlayerController } from 'wdPlayer
import { ContentDetailDTO, LiveRoomDataBean } from 'wdBean/Index';
import { DisplayDirection } from 'wdConstant/Index';
import { LiveFollowComponent, LottieView } from 'wdComponent/Index';
//直播间播放器上层覆盖物
@Component
export struct PlayUIComponent {
playerController?: WDAliPlayerController;
...
...
@@ -84,11 +84,12 @@ export struct PlayUIComponent {
.height('100%')
.alignItems(HorizontalAlign.Start)
}
//最顶部UI
@Builder
getTopUIComponent() {
Column() {
Row() {
//返回键
Image($r('app.media.icon_arrow_left_white'))
.width(24)
.aspectRatio(1)
...
...
@@ -105,6 +106,7 @@ export struct PlayUIComponent {
})
if (this.contentDetailData.liveInfo?.liveState != 'wait') {
//标题
Text(this.contentDetailData.newsTitle)
.maxLines(1)
.textOverflow({ overflow: TextOverflow.MARQUEE })
...
...
@@ -116,6 +118,7 @@ export struct PlayUIComponent {
} else {
Blank()
}
//分享按钮
Image($r('app.media.icon_share'))
.width(24)
.aspectRatio(1)
...
...
@@ -126,16 +129,18 @@ export struct PlayUIComponent {
.margin({
bottom: 10
})
//第二行左边号主信息
Row() {
if (this.contentDetailData?.rmhInfo) {
LiveFollowComponent({
rmhInfo: this.contentDetailData.rmhInfo
})
.margin({
top:-7,
right: 10
})
}
//第二行右边直播状态参与人数
this.getLiveStatusView()
}
}
...
...
sight_harmony/features/wdDetailPlayLive/src/main/ets/widgets/vertical/PlayerInfoComponent.ets
View file @
b16be31
import { WDAliPlayerController } from 'wdPlayer/Index'
import { PlayerUIComponent } from './PlayerUIComponent'
//竖屏直播详情页左右滑动浮层
@Component
export struct PlayerInfoComponent {
swiperController?: SwiperController
...
...
sight_harmony/features/wdDetailPlayShortVideo/src/main/ets/pages/DetailPlayShortVideoPage.ets
View file @
b16be31
...
...
@@ -8,7 +8,7 @@ import {
postInteractBrowsOperateParams
} from 'wdDetailPlayApi/src/main/ets/request/ContentDetailRequest';
import { HttpUtils } from 'wdNetwork/Index';
import { DateTimeUtils, WindowModel } from 'wdKit/Index';
import { DateTimeUtils,
Logger,
WindowModel } from 'wdKit/Index';
import { PlayerBottomView } from '../view/PlayerBottomView';
import { PlayerRightView } from '../view/PlayerRightView';
import { DisplayDirection } from 'wdConstant/Index';
...
...
@@ -229,7 +229,7 @@ export struct DetailPlayShortVideoPage {
showCommentListChanged() {
if (this.showCommentList) {
this.playerWidth = px2vp(this.windowWidth)
this.playerHeight = px2vp(this.windowWidth) / (16 / 9.0)
//
this.playerHeight = px2vp(this.windowWidth) / (16 / 9.0)
} else {
this.calculatePlayerRect()
}
...
...
@@ -245,6 +245,11 @@ export struct DetailPlayShortVideoPage {
showCommentList: $showCommentList,
publishCommentModel: $publishCommentModel,
interactData: $interactData,
onHeightDidChange: (height: number) => {
this.playerWidth = px2vp(this.windowWidth)
this.playerHeight = px2vp(this.windowHeight - height)
Logger.debug(TAG, "height: " + px2vp(height) + " ===> 视频高度: " + this.playerHeight + " window height: " + px2vp(this.windowHeight))
}
})
this.playerViewBuilder()
...
...
@@ -338,7 +343,7 @@ export struct DetailPlayShortVideoPage {
// 横屏-全屏观看
// 点击查看详情 不展示
if (this.videoLandScape === 1 && !this.isOpenDetail && this.displayDirection === DisplayDirection.VERTICAL) {
if (this.videoLandScape === 1 && !this.isOpenDetail && this.displayDirection === DisplayDirection.VERTICAL
&& !this.showCommentList
) {
this.playerFullscreenBuilder()
}
...
...
sight_harmony/features/wdDetailPlayShortVideo/src/main/ets/view/CommentDialogView.ets
View file @
b16be31
...
...
@@ -12,6 +12,7 @@ export struct CommentDialogView {
@Link interactData: InteractDataDTO
@State fakePageInfo: PageInfoDTO = {} as PageInfoDTO
@State dialogOffsetY: number = 0 // (this.windowHeight - this.windowWidth * 9 / 16)
onHeightDidChange?: Callback<number>
@State @Watch("innerShowCommentChange") innerShowComment: boolean = false
...
...
@@ -38,7 +39,8 @@ export struct CommentDialogView {
if (Number.parseInt(this.publishCommentModel.totalCommentNumer) > Number.parseInt(this.interactData.commentNum + "")) {
this.interactData.commentNum = Number.parseInt(this.publishCommentModel.totalCommentNumer)
}
}
},
onHeightDidChange: this.onHeightDidChange
})
}
}
\ No newline at end of file
...
...
sight_harmony/features/wdPlayer/src/main/ets/pages/WDPlayerRenderView.ets
View file @
b16be31
...
...
@@ -141,7 +141,27 @@ export struct WDPlayerRenderView {
this.xComponentController.setXComponentSurfaceRect({
surfaceWidth: info.size.height * ratio,
surfaceHeight: info.size.height
surfaceHeight: info.size.height,
offsetY: 0
});
return
}
} else {
// 横屏
let ratio = this.videoWidth / this.videoHeight
const height = info.size.width / ratio
// 横屏,缩放高度小 视频区域高度
if (height < info.size.height) {
Logger.debug(TAG, "ratio = " + ratio + " ==> new height = " + height)
Logger.debug(TAG, "宽度固定,求高度: " + height)
this.xComponentController.setXComponentSurfaceRect({
surfaceWidth: info.size.width,
surfaceHeight: height,
offsetY: (info.size.height - height) / 2
});
return
}
...
...
@@ -149,7 +169,8 @@ export struct WDPlayerRenderView {
this.xComponentController.setXComponentSurfaceRect({
surfaceWidth: info.size.width,
surfaceHeight: info.size.height
surfaceHeight: info.size.height,
offsetY: 0
});
}
...
...
sight_harmony/features/wdTracking/src/main/ets/tracking/Tracking.ets
View file @
b16be31
...
...
@@ -18,23 +18,23 @@ export class Tracking {
}
//TODO: 添加运行单独线程?
taskpool.execute(doTrack, eventId, params).then(() => {
Logger.error('yyyy','event track success')
}).catch(()=>{
Logger.error('yyyy','event track failed')
})
// let publicParams = new PublicParams()
// publicParams.getPublicParams().then((pubParams) => {
//
// if (params) {
// for (const obj of Object.entries(params)) {
// // Logger.info(TAG, ` ${obj[0]} => ` + `${obj[1]}`);
// pubParams[obj[0]] = obj[1]
// }
// }
// sensors.track(eventId, pubParams)
// taskpool.execute(doTrack, eventId, params).then(() => {
// Logger.error('yyyy','event track success')
// }).catch(()=>{
// Logger.error('yyyy','event track failed')
// })
let publicParams = new PublicParams()
publicParams.getPublicParams().then((pubParams) => {
if (params) {
for (const obj of Object.entries(params)) {
// Logger.info(TAG, ` ${obj[0]} => ` + `${obj[1]}`);
pubParams[obj[0]] = obj[1]
}
}
sensors.track(eventId, pubParams)
})
}
}
...
...
sight_harmony/products/phone/src/main/ets/dailynewspaperformability/DailyNewspaperFormAbility.ets
View file @
b16be31
...
...
@@ -80,7 +80,7 @@ export default class DailyNewspaperFormAbility extends FormExtensionAbility {
Logger.debug(TAG, ` xFailed to updateForm. Code: ${err.code}, message: ${err.message}`);
});
let fileDir = this.context.getApplicationContext().
files
Dir + "/widget-daily-newspaper"
let fileDir = this.context.getApplicationContext().
temp
Dir + "/widget-daily-newspaper"
await FileUtils.makeDirIfNotExsit(fileDir)
NewspaperDataFetcher.dealWithPictures(data, formId, fileDir, (data) => {
...
...
sight_harmony/products/phone/src/main/ets/dailynewspaperformability/NewspaperDataFetcher.ets
View file @
b16be31
...
...
@@ -92,7 +92,7 @@ export class NewspaperDataFetcher {
CrptoUtils.md5(data.paperInfo.leftImageUrl).then((md5String) => {
const fileName = formId + "file" +
md5String
;
const fileName = formId + "file" +
Date.now()
;
const filePath = tempDir + "/" + fileName
NewspaperDataFetcher.downloadUrlToPath(data.paperInfo.leftImageUrl!, filePath).then(() => {
let file = fs.openSync(filePath)
...
...
@@ -119,7 +119,7 @@ export class NewspaperDataFetcher {
}
CrptoUtils.md5(content.coverUrl).then((md5String) => {
const fileName = formId + "file" +
md5String
;
const fileName = formId + "file" +
Date.now() + index
;
const filePath = tempDir + "/" + fileName
NewspaperDataFetcher.downloadUrlToPath(content.coverUrl!, filePath).then(() => {
Logger.debug(TAG, "open file for display ");
...
...
Please
register
or
login
to post a comment