Showing
132 changed files
with
3102 additions
and
26 deletions
| 1 | +import { AuthorListDTO } from './AuthorListDTO'; | ||
| 2 | +import { FullColumnImgUrlDTO } from './FullColumnImgUrlDTO'; | ||
| 3 | +import { ReLInfoDTO } from './ReLInfoDTO'; | ||
| 4 | +import { ShareInfoDTO } from './ShareInfoDTO'; | ||
| 5 | +import { VideoInfoDTO } from './VideoInfoDTO'; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * 接口定义: | ||
| 9 | + * http://192.168.1.3:3300/project/3802/interface/api/200915 | ||
| 10 | + */ | ||
| 11 | +export interface ContentDetailDTO { | ||
| 12 | + newsId: string; | ||
| 13 | + newsTitle: string; | ||
| 14 | + newsShortTitle: string; | ||
| 15 | + newsDownTitle: string; | ||
| 16 | + newsBodyTitle: string; | ||
| 17 | + publishTime: string; | ||
| 18 | + appstyle: number; | ||
| 19 | + newsType: number; | ||
| 20 | + newsSummary: string; | ||
| 21 | + newsSource: string; | ||
| 22 | + newsSourceName: string; | ||
| 23 | + newsContent: string; | ||
| 24 | + newsContentBak: string; | ||
| 25 | + newsLinkUrl: string; | ||
| 26 | + bestNoticer: number; | ||
| 27 | + newLinkObject?: any; | ||
| 28 | + newIntroduction: string; | ||
| 29 | + authorList: AuthorListDTO[]; | ||
| 30 | + editorName: string; | ||
| 31 | + openAudio: number; | ||
| 32 | + audioList: any[]; | ||
| 33 | + hasPopUp?: any; | ||
| 34 | + popUps?: any[]; | ||
| 35 | + firstFrameImageUri: string; | ||
| 36 | + reLInfo?: ReLInfoDTO; | ||
| 37 | + fullColumnImgUrls: FullColumnImgUrlDTO[]; | ||
| 38 | + shareInfo: ShareInfoDTO; | ||
| 39 | + photoList: any[]; | ||
| 40 | + videoInfo: VideoInfoDTO[]; | ||
| 41 | + liveInfo?: any; | ||
| 42 | + voteInfo?: any; | ||
| 43 | + rmhInfo?: any; | ||
| 44 | + userInfo?: any; | ||
| 45 | + openLikes: number; | ||
| 46 | + openComment: number; | ||
| 47 | + likesStyle: number; | ||
| 48 | + preCommentFlag: number; | ||
| 49 | + commentDisplay: number; | ||
| 50 | + keyArticle: number; | ||
| 51 | + rmhPlatform: number; | ||
| 52 | + readFlag?: number; | ||
| 53 | + topicInfo?: any; | ||
| 54 | + traceId: string; | ||
| 55 | + itemId: string; | ||
| 56 | + sceneId: string; | ||
| 57 | + subSceneId: string; | ||
| 58 | + activityInfos: any[]; | ||
| 59 | + recommendShow: number; | ||
| 60 | + visitorComment: number; | ||
| 61 | + itemTypeCode: string; | ||
| 62 | + menuShow: number; | ||
| 63 | + newsTags: string; | ||
| 64 | + specialColumnId?: any; | ||
| 65 | + specialColumnName: string; | ||
| 66 | + timeline?: any; | ||
| 67 | + traceInfo: string; | ||
| 68 | + viewCount: number; | ||
| 69 | +} |
| @@ -5,13 +5,13 @@ | @@ -5,13 +5,13 @@ | ||
| 5 | "name": "default", | 5 | "name": "default", |
| 6 | "type": "HarmonyOS", | 6 | "type": "HarmonyOS", |
| 7 | "material": { | 7 | "material": { |
| 8 | - "certpath": "C:\\Users\\PC\\.ohos\\config\\auto_debug_sight_harmony_com.wondertek.sight_70086000327424393.cer", | ||
| 9 | - "storePassword": "0000001B4100D63EDF7155D2954BDDEC8F40FA74E710B0D1FF3C0782DE2745F90F1B83D1C1C110398F4559", | 8 | + "certpath": "C:\\Users\\PC\\.ohos\\config\\auto_debug_sight_harmony_com.wondertek.sight_70086000309521319.cer", |
| 9 | + "storePassword": "0000001B264B065AE68D1C7F3C0863A33C083D91E12CC54AA36D44179AA8DBA37EA3C50E7F3692F5EB6F3E", | ||
| 10 | "keyAlias": "debugKey", | 10 | "keyAlias": "debugKey", |
| 11 | - "keyPassword": "0000001B157D6824BE8F21F112459AD1B61654DE9396A50B0CE60898F02F4C95CBF127122F293DD6C80C62", | ||
| 12 | - "profile": "C:\\Users\\PC\\.ohos\\config\\auto_debug_sight_harmony_com.wondertek.sight_70086000327424393.p7b", | 11 | + "keyPassword": "0000001BFB62A8007F44B0EAAF9CF878A92620ED75A21E53B3740EA60DEBF6543F6E16AA7200542280D746", |
| 12 | + "profile": "C:\\Users\\PC\\.ohos\\config\\auto_debug_sight_harmony_com.wondertek.sight_70086000309521319.p7b", | ||
| 13 | "signAlg": "SHA256withECDSA", | 13 | "signAlg": "SHA256withECDSA", |
| 14 | - "storeFile": "C:\\Users\\PC\\.ohos\\config\\auto_debug_sight_harmony_com.wondertek.sight_70086000327424393.p12" | 14 | + "storeFile": "C:\\Users\\PC\\.ohos\\config\\auto_debug_sight_harmony_com.wondertek.sight_70086000309521319.p12" |
| 15 | } | 15 | } |
| 16 | } | 16 | } |
| 17 | ], | 17 | ], |
| @@ -133,7 +133,7 @@ | @@ -133,7 +133,7 @@ | ||
| 133 | ] | 133 | ] |
| 134 | } | 134 | } |
| 135 | ] | 135 | ] |
| 136 | - } | 136 | + }, |
| 137 | // { | 137 | // { |
| 138 | // "name": "wdLayout", | 138 | // "name": "wdLayout", |
| 139 | // "srcPath": "./wdLayout", | 139 | // "srcPath": "./wdLayout", |
| @@ -145,6 +145,66 @@ | @@ -145,6 +145,66 @@ | ||
| 145 | // ] | 145 | // ] |
| 146 | // } | 146 | // } |
| 147 | // ] | 147 | // ] |
| 148 | - // } | 148 | + // }, |
| 149 | + { | ||
| 150 | + "name": "wdPlayer", | ||
| 151 | + "srcPath": "./wdPlayer", | ||
| 152 | + "targets": [ | ||
| 153 | + { | ||
| 154 | + "name": "default", | ||
| 155 | + "applyToProducts": [ | ||
| 156 | + "default" | ||
| 157 | + ] | ||
| 158 | + } | ||
| 159 | + ] | ||
| 160 | + }, | ||
| 161 | + { | ||
| 162 | + "name": "wdDetailPlayApi", | ||
| 163 | + "srcPath": "./wdDetailPlayApi", | ||
| 164 | + "targets": [ | ||
| 165 | + { | ||
| 166 | + "name": "default", | ||
| 167 | + "applyToProducts": [ | ||
| 168 | + "default" | ||
| 169 | + ] | ||
| 170 | + } | ||
| 171 | + ] | ||
| 172 | + }, | ||
| 173 | + { | ||
| 174 | + "name": "wdDetailPlayShortVideo", | ||
| 175 | + "srcPath": "./wdDetailPlayShortVideo", | ||
| 176 | + "targets": [ | ||
| 177 | + { | ||
| 178 | + "name": "default", | ||
| 179 | + "applyToProducts": [ | ||
| 180 | + "default" | ||
| 181 | + ] | ||
| 182 | + } | ||
| 183 | + ] | ||
| 184 | + }, | ||
| 185 | + { | ||
| 186 | + "name": "wdDetailPlayVod", | ||
| 187 | + "srcPath": "./wdDetailPlayVod", | ||
| 188 | + "targets": [ | ||
| 189 | + { | ||
| 190 | + "name": "default", | ||
| 191 | + "applyToProducts": [ | ||
| 192 | + "default" | ||
| 193 | + ] | ||
| 194 | + } | ||
| 195 | + ] | ||
| 196 | + }, | ||
| 197 | + { | ||
| 198 | + "name": "wdDetailPlayLive", | ||
| 199 | + "srcPath": "./wdDetailPlayLive", | ||
| 200 | + "targets": [ | ||
| 201 | + { | ||
| 202 | + "name": "default", | ||
| 203 | + "applyToProducts": [ | ||
| 204 | + "default" | ||
| 205 | + ] | ||
| 206 | + } | ||
| 207 | + ] | ||
| 208 | + } | ||
| 149 | ] | 209 | ] |
| 150 | } | 210 | } |
| @@ -4,6 +4,7 @@ import UIAbility from '@ohos.app.ability.UIAbility'; | @@ -4,6 +4,7 @@ import UIAbility from '@ohos.app.ability.UIAbility'; | ||
| 4 | import Want from '@ohos.app.ability.Want'; | 4 | import Want from '@ohos.app.ability.Want'; |
| 5 | import window from '@ohos.window'; | 5 | import window from '@ohos.window'; |
| 6 | import { registerRouter } from 'wdRouter'; | 6 | import { registerRouter } from 'wdRouter'; |
| 7 | +import { WindowModel } from 'wdKit'; | ||
| 7 | 8 | ||
| 8 | export default class EntryAbility extends UIAbility { | 9 | export default class EntryAbility extends UIAbility { |
| 9 | onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { | 10 | onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { |
| @@ -18,7 +19,16 @@ export default class EntryAbility extends UIAbility { | @@ -18,7 +19,16 @@ export default class EntryAbility extends UIAbility { | ||
| 18 | onWindowStageCreate(windowStage: window.WindowStage): void { | 19 | onWindowStageCreate(windowStage: window.WindowStage): void { |
| 19 | // Main window is created, set main page for this ability | 20 | // Main window is created, set main page for this ability |
| 20 | hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); | 21 | hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); |
| 21 | - | 22 | + WindowModel.shared.setWindowStage(windowStage); |
| 23 | + // let a = new WindowModel(); | ||
| 24 | + // 设置窗口的显示方向属性 | ||
| 25 | + WindowModel.shared.setPreferredOrientation(window.Orientation.PORTRAIT) | ||
| 26 | + .then(() => { | ||
| 27 | + hilog.info(0x0000, 'testTag', 'setPreferredOrientation Succeeded'); | ||
| 28 | + }) | ||
| 29 | + .catch((err: Error) => { | ||
| 30 | + hilog.error(0x0000, 'testTag', `setPreferredOrientation catch, error error.name : ${err.name}, error.message:${err.message}`); | ||
| 31 | + }) | ||
| 22 | windowStage.loadContent('pages/Index', (err, data) => { | 32 | windowStage.loadContent('pages/Index', (err, data) => { |
| 23 | if (err.code) { | 33 | if (err.code) { |
| 24 | hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); | 34 | hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); |
| 1 | +{ | ||
| 2 | + "code":"0", | ||
| 3 | + "data":[ | ||
| 4 | + { | ||
| 5 | + "activityInfos":[ | ||
| 6 | + | ||
| 7 | + ], | ||
| 8 | + "appstyle":13, | ||
| 9 | + "audioList":[ | ||
| 10 | + | ||
| 11 | + ], | ||
| 12 | + "authorList":[ | ||
| 13 | + { | ||
| 14 | + "authorName":"" | ||
| 15 | + } | ||
| 16 | + ], | ||
| 17 | + "bestNoticer":1, | ||
| 18 | + "commentDisplay":1, | ||
| 19 | + "editorName":"韩文鋆", | ||
| 20 | + "firstFrameImageUri":"https://cdnjdout.aikan.pdnews.cn/zhbj-20240127/vod/content/output/f45ef51bb33f4ffd9458f8b386aa3227_opt.png", | ||
| 21 | + "fullColumnImgUrls":[ | ||
| 22 | + { | ||
| 23 | + "format":null, | ||
| 24 | + "height":837, | ||
| 25 | + "landscape":1, | ||
| 26 | + "size":1222753, | ||
| 27 | + "url":"https://cdnjdphoto.aikan.pdnews.cn/sjbj-20240127/image/display/efd5771a861f45dd8170da1c3c8c4d04.png", | ||
| 28 | + "weight":1256 | ||
| 29 | + } | ||
| 30 | + ], | ||
| 31 | + "hasPopUp":null, | ||
| 32 | + "itemId":"", | ||
| 33 | + "itemTypeCode":"", | ||
| 34 | + "keyArticle":0, | ||
| 35 | + "likesStyle":1, | ||
| 36 | + "liveInfo":null, | ||
| 37 | + "menuShow":1, | ||
| 38 | + "newIntroduction":"", | ||
| 39 | + "newLinkObject":null, | ||
| 40 | + "newsBodyTitle":"", | ||
| 41 | + "newsContent":"", | ||
| 42 | + "newsContentBak":"", | ||
| 43 | + "newsDownTitle":"", | ||
| 44 | + "newsId":30013266075, | ||
| 45 | + "newsLinkUrl":"", | ||
| 46 | + "newsShortTitle":"", | ||
| 47 | + "newsSource":"41", | ||
| 48 | + "newsSourceName":"中国铁路微信公号", | ||
| 49 | + "newsSummary":"", | ||
| 50 | + "newsTags":"", | ||
| 51 | + "newsTitle":"旅途平安!这首歌送给即将启程回家的你", | ||
| 52 | + "newsType":1, | ||
| 53 | + "openAudio":1, | ||
| 54 | + "openComment":1, | ||
| 55 | + "openLikes":1, | ||
| 56 | + "photoList":[ | ||
| 57 | + | ||
| 58 | + ], | ||
| 59 | + "popUps":[ | ||
| 60 | + | ||
| 61 | + ], | ||
| 62 | + "preCommentFlag":1, | ||
| 63 | + "publishTime":"2024-01-27 14:18:52", | ||
| 64 | + "reLInfo":{ | ||
| 65 | + "channelId":2002, | ||
| 66 | + "relId":"500000301942", | ||
| 67 | + "relObjectId":2002, | ||
| 68 | + "relType":"1" | ||
| 69 | + }, | ||
| 70 | + "readFlag":0, | ||
| 71 | + "recommendShow":1, | ||
| 72 | + "rmhInfo":null, | ||
| 73 | + "rmhPlatform":0, | ||
| 74 | + "sceneId":"", | ||
| 75 | + "shareInfo":{ | ||
| 76 | + "shareCoverUrl":"https://cdnjdphoto.aikan.pdnews.cn/zhbj-20240127/image/content/6706775f96a346a8a1e7393c325e043d.png?x-oss-process=image/resize,w_200", | ||
| 77 | + "shareOpen":1, | ||
| 78 | + "sharePosterCoverUrl":"https://cdnjdphoto.aikan.pdnews.cn/sjbj-20240127/image/display/efd5771a861f45dd8170da1c3c8c4d04.png", | ||
| 79 | + "sharePosterOpen":1, | ||
| 80 | + "shareSummary":"人民日报,有品质的新闻", | ||
| 81 | + "shareTitle":"旅途平安!这首歌送给即将启程回家的你", | ||
| 82 | + "shareUrl":"https://people.pdnews.cn/vod/rel/500000301942/30013266075" | ||
| 83 | + }, | ||
| 84 | + "specialColumnId":null, | ||
| 85 | + "specialColumnName":"", | ||
| 86 | + "subSceneId":"", | ||
| 87 | + "timeline":null, | ||
| 88 | + "topicInfo":null, | ||
| 89 | + "traceId":"", | ||
| 90 | + "traceInfo":"", | ||
| 91 | + "userInfo":null, | ||
| 92 | + "videoInfo":[ | ||
| 93 | + { | ||
| 94 | + "clarity":5, | ||
| 95 | + "resolutionHeight":1080, | ||
| 96 | + "resolutionWidth":1920, | ||
| 97 | + "videoDuration":143, | ||
| 98 | + "videoLandScape":1, | ||
| 99 | + "videoType":1, | ||
| 100 | + "videoUrl":"https://cdnjdout.aikan.pdnews.cn/zhbj-20240127/vod/content/output/f45ef51bb33f4ffd9458f8b386aa3227_opt.mp4" | ||
| 101 | + } | ||
| 102 | + ], | ||
| 103 | + "viewCount":0, | ||
| 104 | + "voteInfo":null | ||
| 105 | + } | ||
| 106 | + ], | ||
| 107 | + "message":"Success", | ||
| 108 | + "meta":null, | ||
| 109 | + "requestId":"", | ||
| 110 | + "success":true, | ||
| 111 | + "timestamp":1706514747211 | ||
| 112 | +} |
| @@ -30,6 +30,8 @@ export { Action } from './src/main/ets/bean/programme/Action' | @@ -30,6 +30,8 @@ export { Action } from './src/main/ets/bean/programme/Action' | ||
| 30 | 30 | ||
| 31 | export { Params } from './src/main/ets/bean/programme/Params' | 31 | export { Params } from './src/main/ets/bean/programme/Params' |
| 32 | 32 | ||
| 33 | +export { Pic } from './src/main/ets/bean/programme/Pic' | ||
| 34 | + | ||
| 33 | export { LabelBean } from './src/main/ets/bean/component/extra/LabelBean'; | 35 | export { LabelBean } from './src/main/ets/bean/component/extra/LabelBean'; |
| 34 | 36 | ||
| 35 | export { LabelDTO } from './src/main/ets/bean/component/extra/LabelDTO'; | 37 | export { LabelDTO } from './src/main/ets/bean/component/extra/LabelDTO'; |
| @@ -48,6 +50,6 @@ export { NewspaperPositionItemBean } from './src/main/ets/bean/newspaper/Newspap | @@ -48,6 +50,6 @@ export { NewspaperPositionItemBean } from './src/main/ets/bean/newspaper/Newspap | ||
| 48 | 50 | ||
| 49 | export { NewspaperShareBean } from './src/main/ets/bean/newspaper/NewspaperShareBean'; | 51 | export { NewspaperShareBean } from './src/main/ets/bean/newspaper/NewspaperShareBean'; |
| 50 | 52 | ||
| 51 | -export { NewspaperTimeInfoBean} from './src/main/ets/bean/newspaper/NewspaperTimeInfoBean'; | 53 | +export { NewspaperTimeInfoBean } from './src/main/ets/bean/newspaper/NewspaperTimeInfoBean'; |
| 52 | 54 | ||
| 53 | export { NewspaperTimeItemBean } from './src/main/ets/bean/newspaper/NewspaperTimeItemBean'; | 55 | export { NewspaperTimeItemBean } from './src/main/ets/bean/newspaper/NewspaperTimeItemBean'; |
| @@ -6,5 +6,15 @@ export interface Params { | @@ -6,5 +6,15 @@ export interface Params { | ||
| 6 | path?: string; | 6 | path?: string; |
| 7 | url?: string; | 7 | url?: string; |
| 8 | extra?: ExtraDTO; // 跳转时额外需要带的参数:map<String,String> 即仅有一层的json | 8 | extra?: ExtraDTO; // 跳转时额外需要带的参数:map<String,String> 即仅有一层的json |
| 9 | + | ||
| 10 | + // 详情页类型 | ||
| 11 | + // 1.点播详情页 | ||
| 12 | + // 2.直播详情页 | ||
| 13 | + // 3.图文详情页 | ||
| 14 | + // 4.全民播详情页 | ||
| 15 | + // 5.欢喜详情页 | ||
| 16 | + // 6.挂件详情页 | ||
| 17 | + // 7.沉浸式竖屏详情页 | ||
| 18 | + // 8.专辑竖屏详情页 | ||
| 9 | detailPageType?:number; // 详情页类型 | 19 | detailPageType?:number; // 详情页类型 |
| 10 | } | 20 | } |
| 1 | import { CompDTO, ContentDTO, DelayTimeEnum } from 'wdBean'; | 1 | import { CompDTO, ContentDTO, DelayTimeEnum } from 'wdBean'; |
| 2 | -import { BreakpointConstants, CommonConstants } from 'wdConstant'; | 2 | +import { BreakpointConstants } from 'wdConstant'; |
| 3 | import { BreakPointType, Logger } from 'wdKit'; | 3 | import { BreakPointType, Logger } from 'wdKit'; |
| 4 | -import { CompUtils } from '../utils/CompUtils'; | ||
| 5 | import { CarouselLayout01CardView } from './CardView'; | 4 | import { CarouselLayout01CardView } from './CardView'; |
| 6 | import { EmptyComponent } from './EmptyComponent'; | 5 | import { EmptyComponent } from './EmptyComponent'; |
| 7 | 6 |
| @@ -71,10 +71,19 @@ export struct CarouselLayout01CardView { | @@ -71,10 +71,19 @@ export struct CarouselLayout01CardView { | ||
| 71 | .hoverEffect(HoverEffect.Scale) | 71 | .hoverEffect(HoverEffect.Scale) |
| 72 | .onClick((event: ClickEvent) => { | 72 | .onClick((event: ClickEvent) => { |
| 73 | Logger.info(TAG, `BannerComponent onClick event index: ${this.index}`); | 73 | Logger.info(TAG, `BannerComponent onClick event index: ${this.index}`); |
| 74 | + // let taskAction: Action = { | ||
| 75 | + // type: 'JUMP_H5_BY_WEB_VIEW', | ||
| 76 | + // params: { | ||
| 77 | + // url: ConfigConstants.DETAIL_URL | ||
| 78 | + // } as Params, | ||
| 79 | + // }; | ||
| 80 | + // WDRouterRule.jumpWithAction(taskAction) | ||
| 81 | + | ||
| 74 | let taskAction: Action = { | 82 | let taskAction: Action = { |
| 75 | - type: 'JUMP_H5_BY_WEB_VIEW', | 83 | + type: 'JUMP_DETAIL_PAGE', |
| 76 | params: { | 84 | params: { |
| 77 | - url: ConfigConstants.DETAIL_URL | 85 | + detailPageType: 7, // 沉浸式竖屏详情页 |
| 86 | + contentID: '863556812' | ||
| 78 | } as Params, | 87 | } as Params, |
| 79 | }; | 88 | }; |
| 80 | WDRouterRule.jumpWithAction(taskAction) | 89 | WDRouterRule.jumpWithAction(taskAction) |
sight_harmony/wdDetailPlayApi/.gitignore
0 → 100644
sight_harmony/wdDetailPlayApi/Index.ets
0 → 100644
| 1 | +export { ContentDetailRequest, ContentDetailRequestParams } from './src/main/ets/request/ContentDetailRequest' | ||
| 2 | + | ||
| 3 | +// export { PlaySetting } from './src/main/ets/utils/PlaySetting' | ||
| 4 | +export { PlaySpeedDialog, } from './src/main/ets/view/PlayDialog' | ||
| 5 | + | ||
| 6 | +export { PlayError } from './src/main/ets/view/PlayError' | ||
| 7 | + | ||
| 8 | +export { devicePLSensorManager } from './src/main/ets/utils/devicePortLandSensor' | ||
| 9 | + | ||
| 10 | + |
| 1 | +{ | ||
| 2 | + "apiType": "stageMode", | ||
| 3 | + "buildOption": { | ||
| 4 | + "arkOptions": { | ||
| 5 | + // "apPath": "./modules.ap" /* Profile used for profile-guided optimization (PGO), a compiler optimization technique to improve app runtime performance. */ | ||
| 6 | + } | ||
| 7 | + }, | ||
| 8 | + "buildOptionSet": [ | ||
| 9 | + { | ||
| 10 | + "name": "release", | ||
| 11 | + "arkOptions": { | ||
| 12 | + "obfuscation": { | ||
| 13 | + "ruleOptions": { | ||
| 14 | + "enable": true, | ||
| 15 | + "files": [ | ||
| 16 | + "./obfuscation-rules.txt" | ||
| 17 | + ] | ||
| 18 | + } | ||
| 19 | + } | ||
| 20 | + } | ||
| 21 | + }, | ||
| 22 | + ], | ||
| 23 | + "targets": [ | ||
| 24 | + { | ||
| 25 | + "name": "default" | ||
| 26 | + } | ||
| 27 | + ] | ||
| 28 | +} |
sight_harmony/wdDetailPlayApi/hvigorfile.ts
0 → 100644
| 1 | +# Define project specific obfuscation rules here. | ||
| 2 | +# You can include the obfuscation configuration files in the current module's build-profile.json5. | ||
| 3 | +# | ||
| 4 | +# For more details, see | ||
| 5 | +# https://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md | ||
| 6 | + | ||
| 7 | +# Obfuscation options: | ||
| 8 | +# -disable-obfuscation: disable all obfuscations | ||
| 9 | +# -enable-property-obfuscation: obfuscate the property names | ||
| 10 | +# -enable-toplevel-obfuscation: obfuscate the names in the global scope | ||
| 11 | +# -compact: remove unnecessary blank spaces and all line feeds | ||
| 12 | +# -remove-log: remove all console.* statements | ||
| 13 | +# -print-namecache: print the name cache that contains the mapping from the old names to new names | ||
| 14 | +# -apply-namecache: reuse the given cache file | ||
| 15 | + | ||
| 16 | +# Keep options: | ||
| 17 | +# -keep-property-name: specifies property names that you want to keep | ||
| 18 | +# -keep-global-name: specifies names that you want to keep in the global scope |
| 1 | +{ | ||
| 2 | + "name": "wddetailplayapi", | ||
| 3 | + "version": "1.0.0", | ||
| 4 | + "description": "Please describe the basic information.", | ||
| 5 | + "main": "Index.ets", | ||
| 6 | + "author": "", | ||
| 7 | + "license": "Apache-2.0", | ||
| 8 | + "dependencies": { | ||
| 9 | + "wdBean": "file:../wdBean", | ||
| 10 | + "wdKit": "file:../wdKit", | ||
| 11 | + "wdNetwork": "file:../wdNetwork", | ||
| 12 | + "wdRouter": "file:../wdRouter" | ||
| 13 | + } | ||
| 14 | +} |
| 1 | +import { AuthorListDTO } from './AuthorListDTO'; | ||
| 2 | +import { FullColumnImgUrlDTO } from './FullColumnImgUrlDTO'; | ||
| 3 | +import { ReLInfoDTO } from './ReLInfoDTO'; | ||
| 4 | +import { ShareInfoDTO } from './ShareInfoDTO'; | ||
| 5 | +import { VideoInfoDTO } from './VideoInfoDTO'; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * 接口定义: | ||
| 9 | + * http://192.168.1.3:3300/project/3802/interface/api/200915 | ||
| 10 | + */ | ||
| 11 | +export interface ContentDetailDTO { | ||
| 12 | + newsId: string; | ||
| 13 | + newsTitle: string; | ||
| 14 | + newsShortTitle: string; | ||
| 15 | + newsDownTitle: string; | ||
| 16 | + newsBodyTitle: string; | ||
| 17 | + publishTime: string; | ||
| 18 | + appstyle: number; | ||
| 19 | + newsType: number; | ||
| 20 | + newsSummary: string; | ||
| 21 | + newsSource: string; | ||
| 22 | + newsSourceName: string; | ||
| 23 | + newsContent: string; | ||
| 24 | + newsContentBak: string; | ||
| 25 | + newsLinkUrl: string; | ||
| 26 | + bestNoticer: number; | ||
| 27 | + newLinkObject?: any; | ||
| 28 | + newIntroduction: string; | ||
| 29 | + authorList: AuthorListDTO[]; | ||
| 30 | + editorName: string; | ||
| 31 | + openAudio: number; | ||
| 32 | + audioList: any[]; | ||
| 33 | + hasPopUp?: any; | ||
| 34 | + popUps?: any[]; | ||
| 35 | + firstFrameImageUri: string; | ||
| 36 | + reLInfo?: ReLInfoDTO; | ||
| 37 | + fullColumnImgUrls: FullColumnImgUrlDTO[]; | ||
| 38 | + shareInfo: ShareInfoDTO; | ||
| 39 | + photoList: any[]; | ||
| 40 | + videoInfo: VideoInfoDTO[]; | ||
| 41 | + liveInfo?: any; | ||
| 42 | + voteInfo?: any; | ||
| 43 | + rmhInfo?: any; | ||
| 44 | + userInfo?: any; | ||
| 45 | + openLikes: number; | ||
| 46 | + openComment: number; | ||
| 47 | + likesStyle: number; | ||
| 48 | + preCommentFlag: number; | ||
| 49 | + commentDisplay: number; | ||
| 50 | + keyArticle: number; | ||
| 51 | + rmhPlatform: number; | ||
| 52 | + readFlag?: number; | ||
| 53 | + topicInfo?: any; | ||
| 54 | + traceId: string; | ||
| 55 | + itemId: string; | ||
| 56 | + sceneId: string; | ||
| 57 | + subSceneId: string; | ||
| 58 | + activityInfos: any[]; | ||
| 59 | + recommendShow: number; | ||
| 60 | + visitorComment: number; | ||
| 61 | + itemTypeCode: string; | ||
| 62 | + menuShow: number; | ||
| 63 | + newsTags: string; | ||
| 64 | + specialColumnId?: any; | ||
| 65 | + specialColumnName: string; | ||
| 66 | + timeline?: any; | ||
| 67 | + traceInfo: string; | ||
| 68 | + viewCount: number; | ||
| 69 | +} |
| 1 | +import { Logger, ResourcesUtils } from 'wdKit'; | ||
| 2 | +import { WDHttp } from 'wdNetwork' | ||
| 3 | +import { ContentDetailDTO } from '../bean/ContentDetailDTO' | ||
| 4 | + | ||
| 5 | +const TAG = 'ContentDetailRequest'; | ||
| 6 | + | ||
| 7 | +const mock_switch = true; | ||
| 8 | + | ||
| 9 | +export interface ContentDetailRequestParams { | ||
| 10 | + contentId: string | ||
| 11 | + relId: string | ||
| 12 | + relType: string | ||
| 13 | +} | ||
| 14 | + | ||
| 15 | +export class ContentDetailRequest { | ||
| 16 | + static getContentDetailDataMock(context: Context): Promise<WDHttp.ResponseDTO<ContentDetailDTO[]>> { | ||
| 17 | + Logger.info(TAG, `getContentDetailDataMock start`); | ||
| 18 | + return ResourcesUtils.getResourcesJson<WDHttp.ResponseDTO<ContentDetailDTO[]>>(context, 'content_detail.json') | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + /** | ||
| 22 | + * 现网-新闻内容详情域名 | ||
| 23 | + */ | ||
| 24 | + static readonly HOST2: string = "https://pdapis.pdnews.cn"; | ||
| 25 | + /** | ||
| 26 | + * 新闻内容详情【get】接口 | ||
| 27 | + */ | ||
| 28 | + static readonly CONTENT_DETAIL_PATH: string = "/api/rmrb-bff-display-zh/content/zh/c/content/detail"; | ||
| 29 | + | ||
| 30 | + static getContentDetailUrl(contentId: string, relId: string, relType: string) { | ||
| 31 | + let url = ContentDetailRequest.HOST2 + ContentDetailRequest.CONTENT_DETAIL_PATH | ||
| 32 | + url = url + "?&contentId=" + contentId | ||
| 33 | + + "&relId=" + relId | ||
| 34 | + + "&relType=" + relType; | ||
| 35 | + return url; | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + static getContentDetail(params: ContentDetailRequestParams): Promise<WDHttp.ResponseDTO<ContentDetailDTO[]>> { | ||
| 39 | + if (mock_switch) { | ||
| 40 | + return ContentDetailRequest.getContentDetailDataMock(getContext()); | ||
| 41 | + } | ||
| 42 | + let headers: Record<string, string> = {}; | ||
| 43 | + let url = ContentDetailRequest.getContentDetailUrl(params.contentId, params.relId, params.relType) | ||
| 44 | + // let headers: HashMap<string, string> = HttpUrlUtils.getCommonHeaders(); | ||
| 45 | + return WDHttp.Request.get<WDHttp.ResponseDTO<ContentDetailDTO[]>>(url, headers) | ||
| 46 | + } | ||
| 47 | +} |
| 1 | +import sensor from '@ohos.sensor'; | ||
| 2 | +import window from '@ohos.window'; | ||
| 3 | +import { WindowModel } from 'wdKit' | ||
| 4 | + | ||
| 5 | +export class devicePLSensorManager{ | ||
| 6 | + public static devicePLSensorOn(targetOrientation:number) { | ||
| 7 | + try { | ||
| 8 | + sensor.off(sensor.SensorId.ACCELEROMETER); | ||
| 9 | + } catch (e) {} | ||
| 10 | + let requestOrientation = -1; // sensor旋转的角度 | ||
| 11 | + let num = -1; | ||
| 12 | + try{ | ||
| 13 | + // 订阅加速度传感器数据 | ||
| 14 | + sensor.on(sensor.SensorId.ACCELEROMETER, (response: sensor.AccelerometerResponse) => { | ||
| 15 | + if(num < 5){ | ||
| 16 | + num ++; | ||
| 17 | + return; | ||
| 18 | + } else { | ||
| 19 | + num = -1; | ||
| 20 | + } | ||
| 21 | + let orientation = -1; | ||
| 22 | + let X = -response.x; | ||
| 23 | + let Y = -response.y; | ||
| 24 | + let Z = -response.z; | ||
| 25 | + let magnitude = X * X + Y * Y; | ||
| 26 | + if (magnitude * 4 >= Z * Z) { | ||
| 27 | + let OneEightyOverPi = 57.29577957855; | ||
| 28 | + let angle = Math.atan2(-Y, X) * OneEightyOverPi; | ||
| 29 | + orientation = 90 - Math.round(angle); | ||
| 30 | + while (orientation >= 360) { | ||
| 31 | + orientation -= 360; | ||
| 32 | + } | ||
| 33 | + while (orientation < 0) { | ||
| 34 | + orientation += 360; | ||
| 35 | + } | ||
| 36 | + } | ||
| 37 | + if (orientation == -1) return; // 水平方向不处理 | ||
| 38 | + if (orientation > 315 || orientation < 45){ | ||
| 39 | + requestOrientation = window.Orientation.PORTRAIT; | ||
| 40 | + } | ||
| 41 | + else if (orientation > 45 && orientation < 135){ | ||
| 42 | + requestOrientation = window.Orientation.LANDSCAPE; | ||
| 43 | + } | ||
| 44 | + else if (orientation > 225 && orientation < 315){ | ||
| 45 | + requestOrientation = window.Orientation.LANDSCAPE_INVERTED; | ||
| 46 | + } | ||
| 47 | + if(targetOrientation == window.Orientation.PORTRAIT && requestOrientation == window.Orientation.PORTRAIT){ | ||
| 48 | + WindowModel.shared.setPreferredOrientation(window.Orientation.AUTO_ROTATION_RESTRICTED); | ||
| 49 | + sensor.off(sensor.SensorId.ACCELEROMETER); | ||
| 50 | + } | ||
| 51 | + if(targetOrientation == window.Orientation.LANDSCAPE && (requestOrientation == window.Orientation.LANDSCAPE || requestOrientation == window.Orientation.LANDSCAPE_INVERTED)){ | ||
| 52 | + WindowModel.shared.setPreferredOrientation(window.Orientation.AUTO_ROTATION_RESTRICTED); | ||
| 53 | + sensor.off(sensor.SensorId.ACCELEROMETER); | ||
| 54 | + } | ||
| 55 | + }, { interval: 2000000000 }) | ||
| 56 | + } catch (e) { | ||
| 57 | + console.error(`屏幕状态报错:${e}`); | ||
| 58 | + try { | ||
| 59 | + sensor.off(sensor.SensorId.ACCELEROMETER); | ||
| 60 | + } catch (e) { | ||
| 61 | + | ||
| 62 | + } | ||
| 63 | + } | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + public static devicePLSensorOff(){ | ||
| 67 | + try { | ||
| 68 | + sensor.off(sensor.SensorId.ACCELEROMETER); | ||
| 69 | + } catch (e) {} | ||
| 70 | + } | ||
| 71 | +} |
| 1 | +import { SpeedBean, PlayerConstants } from 'wdPlayer'; | ||
| 2 | + | ||
| 3 | +// 倍速Dialog | ||
| 4 | +@Preview | ||
| 5 | +@CustomDialog | ||
| 6 | +export struct PlaySpeedDialog { | ||
| 7 | + @Link playSpeed: number; | ||
| 8 | + @Link @Watch('closeDialog') isFullScreen: boolean | ||
| 9 | + controller: CustomDialogController; | ||
| 10 | + | ||
| 11 | + closeDialog(propName: string) { | ||
| 12 | + if (this.isFullScreen == false) { | ||
| 13 | + this.controller.close(); | ||
| 14 | + } | ||
| 15 | + } | ||
| 16 | + | ||
| 17 | + build() { | ||
| 18 | + Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { | ||
| 19 | + List({ space: '10%', initialIndex: 0 }) { | ||
| 20 | + ForEach(PlayerConstants.SPEED_ARRAY, (item: SpeedBean) => { | ||
| 21 | + ListItem() { | ||
| 22 | + Text(item.text) | ||
| 23 | + .width('100%') | ||
| 24 | + .textAlign(TextAlign.Center) | ||
| 25 | + .fontColor(this.playSpeed == item.value ? Color.Blue : Color.White) | ||
| 26 | + .fontSize(16) | ||
| 27 | + .fontWeight(FontWeight.Medium) | ||
| 28 | + .onClick(() => { | ||
| 29 | + this.playSpeed = item.value; | ||
| 30 | + }) | ||
| 31 | + } | ||
| 32 | + }) | ||
| 33 | + } | ||
| 34 | + .padding(12) | ||
| 35 | + .alignListItem(ListItemAlign.Center) | ||
| 36 | + } | ||
| 37 | + .width('20%') | ||
| 38 | + .height('100%') | ||
| 39 | + .backgroundColor('rgba(0,0,0,0.8)') | ||
| 40 | + } | ||
| 41 | +} | ||
| 42 | + | ||
| 43 | +// 码率.. |
| 1 | +import router from '@ohos.router'; | ||
| 2 | +import window from '@ohos.window'; | ||
| 3 | +import { WindowModel } from 'wdKit'; | ||
| 4 | +import { devicePLSensorManager } from '../utils/devicePortLandSensor'; | ||
| 5 | + | ||
| 6 | +@Component | ||
| 7 | +export struct PlayError { | ||
| 8 | + @Consume message: string; | ||
| 9 | + @Consume isFullScreen: boolean; | ||
| 10 | + | ||
| 11 | + build() { | ||
| 12 | + Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { | ||
| 13 | + Image($r('app.media.ic_back')) | ||
| 14 | + .width($r("app.float.back_image_width")) | ||
| 15 | + .height($r("app.float.back_image_width")) | ||
| 16 | + .position({ x: $r("app.float.back_image_width"), y: $r("app.float.back_image_width") }) | ||
| 17 | + .aspectRatio(1) | ||
| 18 | + .onClick(() => { | ||
| 19 | + if (this.isFullScreen) { | ||
| 20 | + this.isFullScreen = false; | ||
| 21 | + WindowModel.shared.setPreferredOrientation(window.Orientation.PORTRAIT); | ||
| 22 | + devicePLSensorManager.devicePLSensorOn(window.Orientation.PORTRAIT); | ||
| 23 | + } else { | ||
| 24 | + router.back(); | ||
| 25 | + } | ||
| 26 | + }) | ||
| 27 | + | ||
| 28 | + Text(this.message) | ||
| 29 | + .width('100%') | ||
| 30 | + .textAlign(TextAlign.Center) | ||
| 31 | + .fontColor(Color.White) | ||
| 32 | + .fontSize($r("app.float.font_size_14")) | ||
| 33 | + .visibility(this.message ? Visibility.Visible : Visibility.None) | ||
| 34 | + } | ||
| 35 | + .width('100%') | ||
| 36 | + .height('100%') | ||
| 37 | + } | ||
| 38 | +} |
| 1 | +{ | ||
| 2 | + "module": { | ||
| 3 | + "name": "wdDetailPlayApi", | ||
| 4 | + "type": "shared", | ||
| 5 | + "description": "$string:shared_desc", | ||
| 6 | + "deviceTypes": [ | ||
| 7 | + "phone", | ||
| 8 | + "tablet", | ||
| 9 | + "2in1" | ||
| 10 | + ], | ||
| 11 | + "deliveryWithInstall": true, | ||
| 12 | + "requestPermissions": [ | ||
| 13 | + { | ||
| 14 | + "name":"ohos.permission.ACCELEROMETER" | ||
| 15 | + } | ||
| 16 | + ] | ||
| 17 | + } | ||
| 18 | +} |
2.15 KB
6.63 KB
11.1 KB
| 1 | +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; | ||
| 2 | + | ||
| 3 | +export default function localUnitTest() { | ||
| 4 | + describe('localUnitTest',() => { | ||
| 5 | + // Defines a test suite. Two parameters are supported: test suite name and test suite function. | ||
| 6 | + beforeAll(() => { | ||
| 7 | + // Presets an action, which is performed only once before all test cases of the test suite start. | ||
| 8 | + // This API supports only one parameter: preset action function. | ||
| 9 | + }); | ||
| 10 | + beforeEach(() => { | ||
| 11 | + // Presets an action, which is performed before each unit test case starts. | ||
| 12 | + // The number of execution times is the same as the number of test cases defined by **it**. | ||
| 13 | + // This API supports only one parameter: preset action function. | ||
| 14 | + }); | ||
| 15 | + afterEach(() => { | ||
| 16 | + // Presets a clear action, which is performed after each unit test case ends. | ||
| 17 | + // The number of execution times is the same as the number of test cases defined by **it**. | ||
| 18 | + // This API supports only one parameter: clear action function. | ||
| 19 | + }); | ||
| 20 | + afterAll(() => { | ||
| 21 | + // Presets a clear action, which is performed after all test cases of the test suite end. | ||
| 22 | + // This API supports only one parameter: clear action function. | ||
| 23 | + }); | ||
| 24 | + it('assertContain', 0, () => { | ||
| 25 | + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. | ||
| 26 | + let a = 'abc'; | ||
| 27 | + let b = 'b'; | ||
| 28 | + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. | ||
| 29 | + expect(a).assertContain(b); | ||
| 30 | + expect(a).assertEqual(a); | ||
| 31 | + }); | ||
| 32 | + }); | ||
| 33 | +} |
sight_harmony/wdDetailPlayLive/.gitignore
0 → 100644
sight_harmony/wdDetailPlayLive/Index.ets
0 → 100644
| 1 | +export { DetailPlayLivePage } from './src/main/ets/pages/DetailPlayLivePage' |
| 1 | +{ | ||
| 2 | + "apiType": "stageMode", | ||
| 3 | + "buildOption": { | ||
| 4 | + "arkOptions": { | ||
| 5 | + // "apPath": "./modules.ap" /* Profile used for profile-guided optimization (PGO), a compiler optimization technique to improve app runtime performance. */ | ||
| 6 | + } | ||
| 7 | + }, | ||
| 8 | + "buildOptionSet": [ | ||
| 9 | + { | ||
| 10 | + "name": "release", | ||
| 11 | + "arkOptions": { | ||
| 12 | + "obfuscation": { | ||
| 13 | + "ruleOptions": { | ||
| 14 | + "enable": true, | ||
| 15 | + "files": [ | ||
| 16 | + "./obfuscation-rules.txt" | ||
| 17 | + ] | ||
| 18 | + } | ||
| 19 | + } | ||
| 20 | + } | ||
| 21 | + }, | ||
| 22 | + ], | ||
| 23 | + "targets": [ | ||
| 24 | + { | ||
| 25 | + "name": "default" | ||
| 26 | + } | ||
| 27 | + ] | ||
| 28 | +} |
sight_harmony/wdDetailPlayLive/hvigorfile.ts
0 → 100644
| 1 | +# Define project specific obfuscation rules here. | ||
| 2 | +# You can include the obfuscation configuration files in the current module's build-profile.json5. | ||
| 3 | +# | ||
| 4 | +# For more details, see | ||
| 5 | +# https://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md | ||
| 6 | + | ||
| 7 | +# Obfuscation options: | ||
| 8 | +# -disable-obfuscation: disable all obfuscations | ||
| 9 | +# -enable-property-obfuscation: obfuscate the property names | ||
| 10 | +# -enable-toplevel-obfuscation: obfuscate the names in the global scope | ||
| 11 | +# -compact: remove unnecessary blank spaces and all line feeds | ||
| 12 | +# -remove-log: remove all console.* statements | ||
| 13 | +# -print-namecache: print the name cache that contains the mapping from the old names to new names | ||
| 14 | +# -apply-namecache: reuse the given cache file | ||
| 15 | + | ||
| 16 | +# Keep options: | ||
| 17 | +# -keep-property-name: specifies property names that you want to keep | ||
| 18 | +# -keep-global-name: specifies names that you want to keep in the global scope |
| 1 | +@Entry | ||
| 2 | +@Component | ||
| 3 | +export struct DetailPlayLivePage { | ||
| 4 | + @State message: string = 'Detail Play Live Page'; | ||
| 5 | + | ||
| 6 | + build() { | ||
| 7 | + Row() { | ||
| 8 | + Column() { | ||
| 9 | + Text(this.message) | ||
| 10 | + .fontSize(50) | ||
| 11 | + .fontWeight(FontWeight.Bold) | ||
| 12 | + } | ||
| 13 | + .width('100%') | ||
| 14 | + } | ||
| 15 | + .height('100%') | ||
| 16 | + } | ||
| 17 | +} |
6.63 KB
11.1 KB
| 1 | +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; | ||
| 2 | + | ||
| 3 | +export default function localUnitTest() { | ||
| 4 | + describe('localUnitTest',() => { | ||
| 5 | + // Defines a test suite. Two parameters are supported: test suite name and test suite function. | ||
| 6 | + beforeAll(() => { | ||
| 7 | + // Presets an action, which is performed only once before all test cases of the test suite start. | ||
| 8 | + // This API supports only one parameter: preset action function. | ||
| 9 | + }); | ||
| 10 | + beforeEach(() => { | ||
| 11 | + // Presets an action, which is performed before each unit test case starts. | ||
| 12 | + // The number of execution times is the same as the number of test cases defined by **it**. | ||
| 13 | + // This API supports only one parameter: preset action function. | ||
| 14 | + }); | ||
| 15 | + afterEach(() => { | ||
| 16 | + // Presets a clear action, which is performed after each unit test case ends. | ||
| 17 | + // The number of execution times is the same as the number of test cases defined by **it**. | ||
| 18 | + // This API supports only one parameter: clear action function. | ||
| 19 | + }); | ||
| 20 | + afterAll(() => { | ||
| 21 | + // Presets a clear action, which is performed after all test cases of the test suite end. | ||
| 22 | + // This API supports only one parameter: clear action function. | ||
| 23 | + }); | ||
| 24 | + it('assertContain', 0, () => { | ||
| 25 | + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. | ||
| 26 | + let a = 'abc'; | ||
| 27 | + let b = 'b'; | ||
| 28 | + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. | ||
| 29 | + expect(a).assertContain(b); | ||
| 30 | + expect(a).assertEqual(a); | ||
| 31 | + }); | ||
| 32 | + }); | ||
| 33 | +} |
| 1 | +export { DetailPlayShortVideoPage } from './src/main/ets/pages/DetailPlayShortVideoPage' |
| 1 | +{ | ||
| 2 | + "apiType": "stageMode", | ||
| 3 | + "buildOption": { | ||
| 4 | + "arkOptions": { | ||
| 5 | + // "apPath": "./modules.ap" /* Profile used for profile-guided optimization (PGO), a compiler optimization technique to improve app runtime performance. */ | ||
| 6 | + } | ||
| 7 | + }, | ||
| 8 | + "buildOptionSet": [ | ||
| 9 | + { | ||
| 10 | + "name": "release", | ||
| 11 | + "arkOptions": { | ||
| 12 | + "obfuscation": { | ||
| 13 | + "ruleOptions": { | ||
| 14 | + "enable": true, | ||
| 15 | + "files": [ | ||
| 16 | + "./obfuscation-rules.txt" | ||
| 17 | + ] | ||
| 18 | + } | ||
| 19 | + } | ||
| 20 | + } | ||
| 21 | + }, | ||
| 22 | + ], | ||
| 23 | + "targets": [ | ||
| 24 | + { | ||
| 25 | + "name": "default" | ||
| 26 | + } | ||
| 27 | + ] | ||
| 28 | +} |
| 1 | +# Define project specific obfuscation rules here. | ||
| 2 | +# You can include the obfuscation configuration files in the current module's build-profile.json5. | ||
| 3 | +# | ||
| 4 | +# For more details, see | ||
| 5 | +# https://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md | ||
| 6 | + | ||
| 7 | +# Obfuscation options: | ||
| 8 | +# -disable-obfuscation: disable all obfuscations | ||
| 9 | +# -enable-property-obfuscation: obfuscate the property names | ||
| 10 | +# -enable-toplevel-obfuscation: obfuscate the names in the global scope | ||
| 11 | +# -compact: remove unnecessary blank spaces and all line feeds | ||
| 12 | +# -remove-log: remove all console.* statements | ||
| 13 | +# -print-namecache: print the name cache that contains the mapping from the old names to new names | ||
| 14 | +# -apply-namecache: reuse the given cache file | ||
| 15 | + | ||
| 16 | +# Keep options: | ||
| 17 | +# -keep-property-name: specifies property names that you want to keep | ||
| 18 | +# -keep-global-name: specifies names that you want to keep in the global scope |
| 1 | +{ | ||
| 2 | + "name": "wddetailplayshortvideo", | ||
| 3 | + "version": "1.0.0", | ||
| 4 | + "description": "Please describe the basic information.", | ||
| 5 | + "main": "Index.ets", | ||
| 6 | + "author": "", | ||
| 7 | + "license": "Apache-2.0", | ||
| 8 | + "dependencies": { | ||
| 9 | + "wdBean": "file:../wdBean", | ||
| 10 | + "wdPlayer": "file:../wdPlayer", | ||
| 11 | + "wdKit": "file:../wdKit", | ||
| 12 | + "wdNetwork": "file:../wdNetwork", | ||
| 13 | + "wdDetailPlayApi": "file:../wdDetailPlayApi", | ||
| 14 | + "wdRouter": "file:../wdRouter" | ||
| 15 | + } | ||
| 16 | +} |
| 1 | +import router from '@ohos.router'; | ||
| 2 | +import mediaquery from '@ohos.mediaquery'; | ||
| 3 | +import window from '@ohos.window'; | ||
| 4 | +import { Action } from 'wdBean'; | ||
| 5 | +import { WindowModel, SPHelper, Logger } from 'wdKit'; | ||
| 6 | +import { WDPlayerController, WDPlayerRenderView, PlayerConstants } from 'wdPlayer'; | ||
| 7 | +import { devicePLSensorManager } from 'wdDetailPlayApi'; | ||
| 8 | +import { PlayControlViewContainer } from '../view/PlayControlViewContainer'; | ||
| 9 | +import { PlayerDetailContainer } from '../view/PlayerDetailContainer'; | ||
| 10 | +import { PlayViewModel } from '../viewmodel/PlayViewModel'; | ||
| 11 | +import { DetailContainer } from '../view/DetailContainer'; | ||
| 12 | + | ||
| 13 | +const TAG = 'DetailPlayShortVideoPage'; | ||
| 14 | + | ||
| 15 | +/** | ||
| 16 | + * 详情&短视频播放页面 | ||
| 17 | + */ | ||
| 18 | +@Entry | ||
| 19 | +@Component | ||
| 20 | +export struct DetailPlayShortVideoPage { | ||
| 21 | + private contentId?: string = undefined | ||
| 22 | + private playerController: WDPlayerController = new WDPlayerController(); | ||
| 23 | + @Watch("urlChanged") @State url?: string = undefined | ||
| 24 | + @Watch('changeContinue') @Provide nextContId?: string = ''; | ||
| 25 | + @Watch('getPlayHistory') @Provide curContId?: string = undefined; | ||
| 26 | + @Watch("playVMChanged") @Provide playVM: PlayViewModel = new PlayViewModel(); | ||
| 27 | + @Provide isFullScreen: boolean = false; | ||
| 28 | + @Provide canStart?: boolean = false; | ||
| 29 | + @Provide status: number = PlayerConstants.STATUS_START; | ||
| 30 | + @Provide userId: string = ''; | ||
| 31 | + @Provide title?: string = undefined | ||
| 32 | + @Provide message?: string = undefined | ||
| 33 | + | ||
| 34 | + playVMChanged(name: string) { | ||
| 35 | + this.url = this.playVM.url | ||
| 36 | + this.title = this.playVM.title | ||
| 37 | + this.curContId = this.playVM.contentId | ||
| 38 | + this.nextContId = this.playVM.nextContId | ||
| 39 | + this.canStart = this.playVM.canStart; | ||
| 40 | + this.message = this.playVM.message | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + aboutToAppear() { | ||
| 44 | + let action: Action = router.getParams() as Action | ||
| 45 | + if (action) { | ||
| 46 | + this.contentId = action.params?.contentID | ||
| 47 | + } | ||
| 48 | + // 设置播放地址 | ||
| 49 | + // this.url = 'https://media.w3.org/2010/05/sintel/trailer.mp4' | ||
| 50 | + let listener = mediaquery.matchMediaSync('(orientation: landscape)'); | ||
| 51 | + listener.on("change", (mediaQueryResult) => { | ||
| 52 | + if (mediaQueryResult.matches) { | ||
| 53 | + console.log("横屏 yes") | ||
| 54 | + this.isFullScreen = true | ||
| 55 | + } else { | ||
| 56 | + this.isFullScreen = false | ||
| 57 | + console.log("横屏 no") | ||
| 58 | + } | ||
| 59 | + WindowModel.shared.setMainWindowFullScreen(this.isFullScreen) | ||
| 60 | + }) | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + onPageShow() { | ||
| 64 | + WindowModel.shared.setPreferredOrientation(window.Orientation.AUTO_ROTATION_RESTRICTED); | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + onPageHide() { | ||
| 68 | + WindowModel.shared.setPreferredOrientation(window.Orientation.PORTRAIT); | ||
| 69 | + devicePLSensorManager.devicePLSensorOff(); | ||
| 70 | + this.status = PlayerConstants.STATUS_PAUSE; | ||
| 71 | + this.playerController?.pause(); | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + @Builder | ||
| 75 | + playerViewContainer() { | ||
| 76 | + // 播放窗口 | ||
| 77 | + WDPlayerRenderView({ | ||
| 78 | + playerController: this.playerController, | ||
| 79 | + onLoad: async () => { | ||
| 80 | + this.playVM.playWithContentId(this.contentId ?? "846899373") | ||
| 81 | + } | ||
| 82 | + }) | ||
| 83 | + .height('100%') | ||
| 84 | + .width('100%') | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + @Builder | ||
| 88 | + playControlViewContainer() { | ||
| 89 | + // 播放窗口控制bar | ||
| 90 | + PlayControlViewContainer({ | ||
| 91 | + playerController: this.playerController | ||
| 92 | + }) | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + @Builder | ||
| 96 | + detailContainer() { | ||
| 97 | + // DetailTabBarPageComponent({ pageId: this.pageId }).backgroundColor(Color.Black) | ||
| 98 | + DetailContainer() | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + build() { | ||
| 102 | + Row() { | ||
| 103 | + PlayerDetailContainer({ playerView: () => { | ||
| 104 | + this.playerViewContainer() | ||
| 105 | + }, playControlView: () => { | ||
| 106 | + this.playControlViewContainer() | ||
| 107 | + }, detailView: () => { | ||
| 108 | + this.detailContainer() | ||
| 109 | + } }) | ||
| 110 | + .height('100%') | ||
| 111 | + .width('100%') | ||
| 112 | + } | ||
| 113 | + .height('100%') | ||
| 114 | + .width('100%') | ||
| 115 | + .backgroundColor(Color.Black) | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | + // 续播判断 | ||
| 119 | + changeContinue() { | ||
| 120 | + if (this.nextContId) { | ||
| 121 | + this.playerController.continue = () => { | ||
| 122 | + this.playerController?.stop(); | ||
| 123 | + this.playVM.playWithContentId(this.nextContId ?? ''); | ||
| 124 | + } | ||
| 125 | + return; | ||
| 126 | + } | ||
| 127 | + this.playerController.continue = undefined; | ||
| 128 | + } | ||
| 129 | + | ||
| 130 | + urlChanged(name: string) { | ||
| 131 | + if (this.url) { | ||
| 132 | + console.log("url:" + this.url); | ||
| 133 | + this.status = PlayerConstants.STATUS_START; | ||
| 134 | + this.playerController.firstPlay(this.url); | ||
| 135 | + } | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + getPlayHistory() { | ||
| 139 | + SPHelper.default.get('playHistory', '').then((str) => { | ||
| 140 | + let result = str.toString(); | ||
| 141 | + let time = 0; | ||
| 142 | + if (result != null && result != "") { | ||
| 143 | + let playHistory: Record<string, Record<string, number>> = JSON.parse(result); | ||
| 144 | + let userData: Record<string, number> = {}; | ||
| 145 | + if (this.userId) { | ||
| 146 | + userData = playHistory[this.userId] ?? {}; | ||
| 147 | + } | ||
| 148 | + if (this.curContId) { | ||
| 149 | + time = userData?.[this.curContId] ?? 0; | ||
| 150 | + } | ||
| 151 | + } | ||
| 152 | + this.playerController?.setStartTime(time); | ||
| 153 | + }).catch((err: Error) => { | ||
| 154 | + // Error: Inner error. Error code 15500000 | ||
| 155 | + Logger.error(TAG, 'catch err:' + JSON.stringify(err)); | ||
| 156 | + this.playerController?.setStartTime(0); | ||
| 157 | + }); | ||
| 158 | + } | ||
| 159 | +} |
| 1 | +import window from '@ohos.window'; | ||
| 2 | +import { WindowModel, SPHelper } from 'wdKit'; | ||
| 3 | +import { DateFormatUtil, WDPlayerController, PlayerConstants } from 'wdPlayer'; | ||
| 4 | +import { devicePLSensorManager, PlayError } from 'wdDetailPlayApi'; | ||
| 5 | +import { PlayerProgressBar } from './PlayerProgressBar'; | ||
| 6 | +import { PlayerTitle } from './PlayerTitle'; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * 播放窗口上层的控制view | ||
| 10 | + */ | ||
| 11 | +@Component | ||
| 12 | +export struct PlayControlViewContainer { | ||
| 13 | + playerController?: WDPlayerController; | ||
| 14 | + @Consume status: number; | ||
| 15 | + @Provide currentTime: string = "00:00"; | ||
| 16 | + @Provide totalTime: string = "00:00"; | ||
| 17 | + @Provide progressVal: number = 0; | ||
| 18 | + @Provide isShowVolume: boolean = false; | ||
| 19 | + @Provide volumeProgress: number = 1; | ||
| 20 | + @Consume isFullScreen: boolean; | ||
| 21 | + @State isLocked: boolean = false; | ||
| 22 | + @Provide setAuto: number | undefined = undefined; | ||
| 23 | + @Consume canStart: boolean; | ||
| 24 | + @Consume userId: string; | ||
| 25 | + @Consume curContId: string; | ||
| 26 | + @Consume message: string; | ||
| 27 | + // 用于触发拖动手势事件,滑动的最小距离为5vp时拖动手势识别成功。 | ||
| 28 | + private panOptionBright: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.Vertical }); | ||
| 29 | + private panOptionVolume: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.Vertical }); | ||
| 30 | + | ||
| 31 | + aboutToAppear() { | ||
| 32 | + if (this.playerController == null) { | ||
| 33 | + return | ||
| 34 | + } | ||
| 35 | + this.playerController.onTimeUpdate = (position, duration) => { | ||
| 36 | + this.currentTime = DateFormatUtil.secondToTime(position); | ||
| 37 | + this.totalTime = DateFormatUtil.secondToTime(duration); | ||
| 38 | + this.progressVal = Math.floor(position * 100 / duration); | ||
| 39 | + this.setPlayHistory(position); | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + this.playerController.onVolumeUpdate = (volume) => { | ||
| 43 | + this.volumeProgress = volume; | ||
| 44 | + } | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + aboutToDisappear() { | ||
| 48 | + this.playerController?.release(); | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + build() { | ||
| 52 | + Stack({ alignContent: Alignment.Start }) { | ||
| 53 | + Stack() { | ||
| 54 | + Column() { | ||
| 55 | + PlayerTitle({ playerController: this.playerController }) | ||
| 56 | + .width('100%') | ||
| 57 | + .height(44) | ||
| 58 | + .visibility(this.isFullScreen ? Visibility.Visible : Visibility.None) | ||
| 59 | + | ||
| 60 | + Row() { | ||
| 61 | + Column() | ||
| 62 | + .width('50%') | ||
| 63 | + .height('100%') | ||
| 64 | + .gesture( | ||
| 65 | + PanGesture(this.panOptionBright) | ||
| 66 | + .onActionStart((event?: GestureEvent) => { | ||
| 67 | + this.playerController?.onBrightActionStart(event!); | ||
| 68 | + }) | ||
| 69 | + .onActionUpdate((event?: GestureEvent) => { | ||
| 70 | + this.playerController?.onBrightActionUpdate(event!); | ||
| 71 | + }) | ||
| 72 | + .onActionEnd(() => { | ||
| 73 | + this.playerController?.onActionEnd(); | ||
| 74 | + }) | ||
| 75 | + ) | ||
| 76 | + Column() | ||
| 77 | + .width('50%') | ||
| 78 | + .height('100%') | ||
| 79 | + .gesture( | ||
| 80 | + PanGesture(this.panOptionVolume) | ||
| 81 | + .onActionStart((event?: GestureEvent) => { | ||
| 82 | + this.isShowVolume = true | ||
| 83 | + this.playerController?.onVolumeActionStart(event!); | ||
| 84 | + }) | ||
| 85 | + .onActionUpdate((event?: GestureEvent) => { | ||
| 86 | + this.playerController?.onVolumeActionUpdate(event!); | ||
| 87 | + }) | ||
| 88 | + .onActionEnd(() => { | ||
| 89 | + setTimeout(() => { | ||
| 90 | + this.isShowVolume = false | ||
| 91 | + }, 500) | ||
| 92 | + this.playerController?.onActionEnd(); | ||
| 93 | + }) | ||
| 94 | + ) | ||
| 95 | + } | ||
| 96 | + .width('100%') | ||
| 97 | + .layoutWeight(1) | ||
| 98 | + | ||
| 99 | + PlayerProgressBar({ playerController: this.playerController }) | ||
| 100 | + .width('100%') | ||
| 101 | + .height(this.isFullScreen ? 66 : 44) | ||
| 102 | + } | ||
| 103 | + .height('100%') | ||
| 104 | + .width('100%') | ||
| 105 | + .zIndex(1) | ||
| 106 | + .gesture(TapGesture({ count: 2 }) | ||
| 107 | + .onAction((event: GestureEvent) => { | ||
| 108 | + let curStatus = (this.status === PlayerConstants.STATUS_START); | ||
| 109 | + this.status = curStatus ? PlayerConstants.STATUS_PAUSE : PlayerConstants.STATUS_START; | ||
| 110 | + this.playerController?.switchPlayOrPause(); | ||
| 111 | + })) | ||
| 112 | + | ||
| 113 | + Row() { | ||
| 114 | + Image($r('app.media.ic_volume')) | ||
| 115 | + .width(20) | ||
| 116 | + .height(20) | ||
| 117 | + Progress({ value: this.volumeProgress * 100, total: 100, type: ProgressType.Linear }) | ||
| 118 | + .width(100) | ||
| 119 | + .height(5) | ||
| 120 | + .zIndex(2) | ||
| 121 | + } | ||
| 122 | + .width(140) | ||
| 123 | + .height(40) | ||
| 124 | + .borderRadius(4) | ||
| 125 | + .backgroundColor("#FFFFFF") | ||
| 126 | + .opacity(0.5) | ||
| 127 | + .justifyContent(FlexAlign.Center) | ||
| 128 | + .visibility(this.isShowVolume ? Visibility.Visible : Visibility.None) | ||
| 129 | + | ||
| 130 | + }.visibility(!this.canStart || this.isLocked ? Visibility.None : Visibility.Visible) | ||
| 131 | + | ||
| 132 | + Image(this.isLocked ? $r('app.media.ic_lock') : $r('app.media.ic_unlock')) | ||
| 133 | + .width(20) | ||
| 134 | + .height(20) | ||
| 135 | + .margin({ left: 20 }) | ||
| 136 | + .borderRadius(4) | ||
| 137 | + .zIndex(2) | ||
| 138 | + .visibility(this.canStart && this.isFullScreen ? Visibility.Visible : Visibility.None) | ||
| 139 | + .gesture(TapGesture() | ||
| 140 | + .onAction((event: GestureEvent) => { | ||
| 141 | + this.isLocked = !this.isLocked; | ||
| 142 | + if (this.isLocked) { | ||
| 143 | + WindowModel.shared.setPreferredOrientation(window.Orientation.LOCKED); | ||
| 144 | + devicePLSensorManager.devicePLSensorOff(); | ||
| 145 | + } else { | ||
| 146 | + WindowModel.shared.setPreferredOrientation(window.Orientation.AUTO_ROTATION_RESTRICTED); | ||
| 147 | + } | ||
| 148 | + })) | ||
| 149 | + | ||
| 150 | + PlayError() | ||
| 151 | + .width('100%') | ||
| 152 | + .height('100%') | ||
| 153 | + .zIndex(3)// zIndex值越大,显示层级越高,即zIndex值大的组件会覆盖在zIndex值小的组件上方。 | ||
| 154 | + .visibility(this.canStart == undefined && this.message != undefined ? Visibility.Visible : Visibility.None) | ||
| 155 | + } | ||
| 156 | + } | ||
| 157 | + | ||
| 158 | + setPlayHistory(position: number) { | ||
| 159 | + if (this.userId && this.curContId) { | ||
| 160 | + SPHelper.default.get('playHistory', '').then((str) => { | ||
| 161 | + let result = str.toString(); | ||
| 162 | + let playHistory: Record<string, Record<string, number>> = {}; | ||
| 163 | + if (result != null && result != "") { | ||
| 164 | + playHistory = JSON.parse(result); | ||
| 165 | + } | ||
| 166 | + let userData = playHistory[this.userId] ?? {}; | ||
| 167 | + userData[this.curContId] = position; | ||
| 168 | + playHistory[this.userId] = userData; | ||
| 169 | + SPHelper.default.save('playHistory', JSON.stringify(playHistory)); | ||
| 170 | + }) | ||
| 171 | + } | ||
| 172 | + } | ||
| 173 | +} |
| 1 | +/** | ||
| 2 | + * 详情view&播放器view的容器布局组件 | ||
| 3 | + */ | ||
| 4 | +@Component | ||
| 5 | +export struct PlayerDetailContainer { | ||
| 6 | + @BuilderParam playerView: () => void | ||
| 7 | + @BuilderParam playControlView: () => void | ||
| 8 | + @BuilderParam detailView: () => void | ||
| 9 | + @Consume isFullScreen: boolean | ||
| 10 | + | ||
| 11 | + build() { | ||
| 12 | + RelativeContainer() { | ||
| 13 | + Stack() { | ||
| 14 | + Row() { | ||
| 15 | + this.playerView() | ||
| 16 | + } | ||
| 17 | + .height('100%') | ||
| 18 | + .width('100%') | ||
| 19 | + .zIndex(0) | ||
| 20 | + | ||
| 21 | + Row() { | ||
| 22 | + this.playControlView() | ||
| 23 | + } | ||
| 24 | + .height('100%') | ||
| 25 | + .width('100%') | ||
| 26 | + .zIndex(1) | ||
| 27 | + } | ||
| 28 | + .width('100%') | ||
| 29 | + .aspectRatio(this.isFullScreen ? 0 : 16 / 9.0) | ||
| 30 | + .alignRules({ | ||
| 31 | + center: { anchor: '__container__', align: VerticalAlign.Center }, | ||
| 32 | + middle: { anchor: '__container__', align: HorizontalAlign.Center } | ||
| 33 | + }) | ||
| 34 | + .id('txt_title') | ||
| 35 | + | ||
| 36 | + if (!this.isFullScreen) { | ||
| 37 | + Row() { | ||
| 38 | + this.detailView() | ||
| 39 | + } | ||
| 40 | + .width('100%') | ||
| 41 | + .alignRules({ | ||
| 42 | + bottom: { anchor: '__container__', align: VerticalAlign.Bottom } | ||
| 43 | + }) | ||
| 44 | + .id('row_bottomView') | ||
| 45 | + } | ||
| 46 | + } | ||
| 47 | + .width('100%') | ||
| 48 | + .height('100%') | ||
| 49 | + } | ||
| 50 | +} |
| 1 | +import window from '@ohos.window'; | ||
| 2 | +import { WindowModel } from 'wdKit'; | ||
| 3 | +import { WDPlayerController, PlayerConstants } from 'wdPlayer'; | ||
| 4 | +import { devicePLSensorManager } from 'wdDetailPlayApi'; | ||
| 5 | +import { PlaySpeedDialog } from 'wdDetailPlayApi'; | ||
| 6 | +import { PlayViewModel } from '../viewmodel/PlayViewModel'; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * 全屏播放器进度条 | ||
| 10 | + */ | ||
| 11 | +@Component | ||
| 12 | +export struct PlayerProgressBar { | ||
| 13 | + private playerController?: WDPlayerController; | ||
| 14 | + @State curContId?: string = undefined; | ||
| 15 | + @State @Watch('switchSpeed') playSpeed: number = 1; | ||
| 16 | + @Consume currentTime: string; | ||
| 17 | + @Consume totalTime: string; | ||
| 18 | + @Consume progressVal: number; | ||
| 19 | + @Consume status: number; | ||
| 20 | + @Consume isFullScreen: boolean; | ||
| 21 | + @Consume nextContId: string; | ||
| 22 | + @Consume @Watch("playVMChanged") playVM: PlayViewModel; | ||
| 23 | + speedDialogController: CustomDialogController = new CustomDialogController({ | ||
| 24 | + builder: PlaySpeedDialog({ | ||
| 25 | + playSpeed: $playSpeed, | ||
| 26 | + isFullScreen: $isFullScreen | ||
| 27 | + }), | ||
| 28 | + alignment: DialogAlignment.CenterEnd, | ||
| 29 | + customStyle: true | ||
| 30 | + }) | ||
| 31 | + | ||
| 32 | + switchSpeed() { | ||
| 33 | + this.playerController?.setSpeed(this.playSpeed); | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + switchPause() { | ||
| 37 | + this.status = PlayerConstants.STATUS_PAUSE; | ||
| 38 | + this.playerController?.pause(); | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + switchSubId(contId?: string) { | ||
| 42 | + if (contId) { | ||
| 43 | + this.playerController?.stop(); | ||
| 44 | + this.playVM.playWithContentId(contId); | ||
| 45 | + } | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + playVMChanged(name: string) { | ||
| 49 | + this.curContId = this.playVM.contentId | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + build() { | ||
| 53 | + Column() { | ||
| 54 | + Row() { | ||
| 55 | + Column() { | ||
| 56 | + Image(this.status === PlayerConstants.STATUS_START ? | ||
| 57 | + $r('app.media.ic_pause') : $r('app.media.ic_play')) | ||
| 58 | + .width($r('app.float.control_image_width')) | ||
| 59 | + .aspectRatio(1) | ||
| 60 | + .onClick(() => { | ||
| 61 | + let curStatus = (this.status === PlayerConstants.STATUS_START); | ||
| 62 | + this.status = curStatus ? PlayerConstants.STATUS_PAUSE : PlayerConstants.STATUS_START; | ||
| 63 | + this.playerController?.switchPlayOrPause(); | ||
| 64 | + }) | ||
| 65 | + } | ||
| 66 | + .justifyContent(FlexAlign.Center) | ||
| 67 | + .alignItems(HorizontalAlign.Center) | ||
| 68 | + .width(44) | ||
| 69 | + .height('100%') | ||
| 70 | + | ||
| 71 | + Text(this.currentTime) | ||
| 72 | + .fontSize($r("app.float.font_size_14")) | ||
| 73 | + .fontColor(Color.White) | ||
| 74 | + Slider({ | ||
| 75 | + value: this.progressVal, | ||
| 76 | + step: 1, | ||
| 77 | + style: SliderStyle.OutSet | ||
| 78 | + }) | ||
| 79 | + .blockColor(Color.White) | ||
| 80 | + .trackColor($r('app.color.track_color')) | ||
| 81 | + .selectedColor($r('app.color.index_tab_selected_font_color')) | ||
| 82 | + .trackThickness(1) | ||
| 83 | + .layoutWeight(1) | ||
| 84 | + .onChange((value: number, mode: SliderChangeMode) => { | ||
| 85 | + this.playerController?.setSeekTime(value, mode); | ||
| 86 | + }) | ||
| 87 | + Text(this.totalTime) | ||
| 88 | + .fontSize($r("app.float.font_size_14")) | ||
| 89 | + .fontColor(Color.White) | ||
| 90 | + | ||
| 91 | + Column() { | ||
| 92 | + Image($r('app.media.ic_fullscreen')) | ||
| 93 | + .width($r('app.float.control_image_width')) | ||
| 94 | + .aspectRatio(1) | ||
| 95 | + .onClick(() => { | ||
| 96 | + this.isFullScreen = !this.isFullScreen; | ||
| 97 | + WindowModel.shared.setPreferredOrientation(window.Orientation.LANDSCAPE); | ||
| 98 | + devicePLSensorManager.devicePLSensorOn(window.Orientation.LANDSCAPE); | ||
| 99 | + }) | ||
| 100 | + } | ||
| 101 | + .justifyContent(FlexAlign.Center) | ||
| 102 | + .alignItems(HorizontalAlign.Center) | ||
| 103 | + .width(44) | ||
| 104 | + .height('100%') | ||
| 105 | + } | ||
| 106 | + .width('100%') | ||
| 107 | + .visibility(this.isFullScreen ? Visibility.None : Visibility.Visible) | ||
| 108 | + | ||
| 109 | + Column() { | ||
| 110 | + Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) { | ||
| 111 | + Text(this.currentTime) | ||
| 112 | + .fontSize($r("app.float.font_size_14")) | ||
| 113 | + .fontColor(Color.White) | ||
| 114 | + | ||
| 115 | + Slider({ | ||
| 116 | + value: this.progressVal, | ||
| 117 | + step: 1 | ||
| 118 | + }) | ||
| 119 | + .blockColor(Color.White) | ||
| 120 | + .trackColor($r('app.color.track_color')) | ||
| 121 | + .selectedColor($r('app.color.index_tab_selected_font_color')) | ||
| 122 | + .trackThickness(1) | ||
| 123 | + .layoutWeight(1) | ||
| 124 | + .onChange((value: number, mode: SliderChangeMode) => { | ||
| 125 | + this.playerController?.setSeekTime(value, mode); | ||
| 126 | + }) | ||
| 127 | + | ||
| 128 | + Text(this.totalTime) | ||
| 129 | + .fontSize($r("app.float.font_size_14")) | ||
| 130 | + .fontColor(Color.White) | ||
| 131 | + } | ||
| 132 | + .width('98%') | ||
| 133 | + .height('40%') | ||
| 134 | + .padding({ left: '1%', right: '1%' }) | ||
| 135 | + | ||
| 136 | + Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Start }) { | ||
| 137 | + Row() { | ||
| 138 | + Image(this.status === PlayerConstants.STATUS_START ? | ||
| 139 | + $r('app.media.ic_pause') : $r('app.media.ic_play')) | ||
| 140 | + .width($r('app.float.control_image_width')) | ||
| 141 | + .aspectRatio(1) | ||
| 142 | + .onClick(() => { | ||
| 143 | + let curStatus = (this.status === PlayerConstants.STATUS_START); | ||
| 144 | + this.status = curStatus ? PlayerConstants.STATUS_PAUSE : PlayerConstants.STATUS_START; | ||
| 145 | + this.playerController?.switchPlayOrPause(); | ||
| 146 | + }) | ||
| 147 | + .margin({ right: '4%' }) | ||
| 148 | + | ||
| 149 | + Image($r('app.media.ic_next')) | ||
| 150 | + .width($r('app.float.control_image_width')) | ||
| 151 | + .aspectRatio(1) | ||
| 152 | + .margin({ right: '4%' }) | ||
| 153 | + .visibility(this.nextContId ? Visibility.Visible : Visibility.None) | ||
| 154 | + .onClick(() => { | ||
| 155 | + this.playerController?.stop(); | ||
| 156 | + this.playVM.playWithContentId(this.nextContId); | ||
| 157 | + }) | ||
| 158 | + | ||
| 159 | + } | ||
| 160 | + .justifyContent(FlexAlign.Start) | ||
| 161 | + .width('50%') | ||
| 162 | + .height('100%') | ||
| 163 | + .padding({ left: '2%' }) | ||
| 164 | + | ||
| 165 | + Row() { | ||
| 166 | + Text(this.playSpeed == 1 ? '倍速' : PlayerConstants.SPEED_ARRAY[this.playSpeed].text) | ||
| 167 | + .fontSize($r("app.float.font_size_14")) | ||
| 168 | + .fontColor(Color.White) | ||
| 169 | + .margin({ right: '4%' }) | ||
| 170 | + .onClick(() => { | ||
| 171 | + this.speedDialogController.open(); | ||
| 172 | + }) | ||
| 173 | + | ||
| 174 | + Column() { | ||
| 175 | + Image($r('app.media.ic_fullscreen')) | ||
| 176 | + .width($r('app.float.control_image_width')) | ||
| 177 | + .aspectRatio(1) | ||
| 178 | + .onClick(() => { | ||
| 179 | + this.isFullScreen = !this.isFullScreen; | ||
| 180 | + WindowModel.shared.setPreferredOrientation(window.Orientation.PORTRAIT); | ||
| 181 | + devicePLSensorManager.devicePLSensorOn(window.Orientation.PORTRAIT); | ||
| 182 | + }) | ||
| 183 | + } | ||
| 184 | + .justifyContent(FlexAlign.Center) | ||
| 185 | + .alignItems(HorizontalAlign.Center) | ||
| 186 | + .width(44) | ||
| 187 | + .height('100%') | ||
| 188 | + .margin({ right: '2%' }) | ||
| 189 | + } | ||
| 190 | + .justifyContent(FlexAlign.End) | ||
| 191 | + .width('50%') | ||
| 192 | + .height('100%') | ||
| 193 | + .margin({ right: '2%' }) | ||
| 194 | + } | ||
| 195 | + .width('100%') | ||
| 196 | + .height('60%') | ||
| 197 | + } | ||
| 198 | + .width('100%') | ||
| 199 | + .height('100%') | ||
| 200 | + .visibility(this.isFullScreen ? Visibility.Visible : Visibility.None) | ||
| 201 | + | ||
| 202 | + } | ||
| 203 | + .width('100%') | ||
| 204 | + .height('100%') | ||
| 205 | + .justifyContent(FlexAlign.Center) | ||
| 206 | + } | ||
| 207 | +} |
| 1 | +import router from '@ohos.router'; | ||
| 2 | +import window from '@ohos.window'; | ||
| 3 | +import deviceInfo from '@ohos.deviceInfo' | ||
| 4 | +import { WindowModel } from 'wdKit'; | ||
| 5 | +import { WDPlayerController } from 'wdPlayer'; | ||
| 6 | +import { devicePLSensorManager } from 'wdDetailPlayApi'; | ||
| 7 | + | ||
| 8 | +@Component | ||
| 9 | +export struct PlayerTitle { | ||
| 10 | + private playerController?: WDPlayerController; | ||
| 11 | + @Consume title?: string | ||
| 12 | + @Consume isFullScreen: boolean; | ||
| 13 | + @State @Watch('watchSpeed') playSpeed: number = 1; | ||
| 14 | + | ||
| 15 | + aboutToAppear() { | ||
| 16 | + } | ||
| 17 | + | ||
| 18 | + watchSpeed() { | ||
| 19 | + this.playerController?.setSpeed(this.playSpeed); | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + build() { | ||
| 23 | + Row() { | ||
| 24 | + Image($r('app.media.ic_back')) | ||
| 25 | + .width(44) | ||
| 26 | + .padding(13) | ||
| 27 | + .aspectRatio(1) | ||
| 28 | + .onClick(() => { | ||
| 29 | + if (this.isFullScreen) { | ||
| 30 | + if (deviceInfo.deviceType != "phone") { | ||
| 31 | + WindowModel.shared.getWindowSize().then((size) => { | ||
| 32 | + if (size.width > size.height) { | ||
| 33 | + router.back(); | ||
| 34 | + } else { | ||
| 35 | + this.isFullScreen = !this.isFullScreen; | ||
| 36 | + WindowModel.shared.setPreferredOrientation(window.Orientation.PORTRAIT); | ||
| 37 | + devicePLSensorManager.devicePLSensorOn(window.Orientation.PORTRAIT); | ||
| 38 | + } | ||
| 39 | + }) | ||
| 40 | + } else { | ||
| 41 | + this.isFullScreen = !this.isFullScreen; | ||
| 42 | + WindowModel.shared.setPreferredOrientation(window.Orientation.PORTRAIT); | ||
| 43 | + devicePLSensorManager.devicePLSensorOn(window.Orientation.PORTRAIT); | ||
| 44 | + } | ||
| 45 | + } else { | ||
| 46 | + router.back(); | ||
| 47 | + } | ||
| 48 | + }) | ||
| 49 | + Text(this.title) | ||
| 50 | + .fontColor(Color.White) | ||
| 51 | + .fontSize('14fp') | ||
| 52 | + .maxLines(2) | ||
| 53 | + .layoutWeight(1) | ||
| 54 | + }.alignItems(VerticalAlign.Center) | ||
| 55 | + } | ||
| 56 | +} |
| 1 | +import router from '@ohos.router'; | ||
| 2 | +import window from '@ohos.window'; | ||
| 3 | +import deviceInfo from '@ohos.deviceInfo' | ||
| 4 | +import { WindowModel } from 'wdKit'; | ||
| 5 | +import { WDPlayerController } from 'wdPlayer'; | ||
| 6 | +import { devicePLSensorManager } from 'wdDetailPlayApi'; | ||
| 7 | + | ||
| 8 | +@Component | ||
| 9 | +export struct PlayerTitleComment { | ||
| 10 | + private playerController?: WDPlayerController; | ||
| 11 | + @Consume title?: string | ||
| 12 | + @State @Watch('watchSpeed') playSpeed: number = 1; | ||
| 13 | + @Consume isFullScreen: boolean; | ||
| 14 | + @State comment: string = ''; | ||
| 15 | + | ||
| 16 | + aboutToAppear() { | ||
| 17 | + } | ||
| 18 | + | ||
| 19 | + watchSpeed() { | ||
| 20 | + this.playerController?.setSpeed(this.playSpeed); | ||
| 21 | + } | ||
| 22 | + | ||
| 23 | + build() { | ||
| 24 | + Column() { | ||
| 25 | + Text(this.title) | ||
| 26 | + .fontColor(Color.White) | ||
| 27 | + .fontSize(14) | ||
| 28 | + .maxLines(1) | ||
| 29 | + | ||
| 30 | + Text('查看详情 > ') | ||
| 31 | + .fontColor(Color.White) | ||
| 32 | + .fontSize('14fp') | ||
| 33 | + .maxLines(2) | ||
| 34 | + | ||
| 35 | + Divider().height(30) | ||
| 36 | + | ||
| 37 | + Row() { | ||
| 38 | + Image($r('app.media.ic_back')) | ||
| 39 | + .width(44) | ||
| 40 | + .aspectRatio(1) | ||
| 41 | + .padding(13) | ||
| 42 | + .margin({ left: 13 }) | ||
| 43 | + .onClick(() => { | ||
| 44 | + if (this.isFullScreen) { | ||
| 45 | + if (deviceInfo.deviceType != "phone") { | ||
| 46 | + WindowModel.shared.getWindowSize().then((size) => { | ||
| 47 | + if (size.width > size.height) { | ||
| 48 | + router.back(); | ||
| 49 | + } else { | ||
| 50 | + this.isFullScreen = !this.isFullScreen; | ||
| 51 | + WindowModel.shared.setPreferredOrientation(window.Orientation.PORTRAIT); | ||
| 52 | + devicePLSensorManager.devicePLSensorOn(window.Orientation.PORTRAIT); | ||
| 53 | + } | ||
| 54 | + }) | ||
| 55 | + } else { | ||
| 56 | + this.isFullScreen = !this.isFullScreen; | ||
| 57 | + WindowModel.shared.setPreferredOrientation(window.Orientation.PORTRAIT); | ||
| 58 | + devicePLSensorManager.devicePLSensorOn(window.Orientation.PORTRAIT); | ||
| 59 | + } | ||
| 60 | + } else { | ||
| 61 | + router.back(); | ||
| 62 | + } | ||
| 63 | + }) | ||
| 64 | + | ||
| 65 | + TextInput({ placeholder: '说两句...', text: this.comment }) | ||
| 66 | + .placeholderColor(Color.White) | ||
| 67 | + .placeholderFont({ size: 14 }) | ||
| 68 | + .fontColor(Color.White) | ||
| 69 | + .fontSize(14) | ||
| 70 | + .maxLines(1) | ||
| 71 | + .layoutWeight(1) | ||
| 72 | + }.alignItems(VerticalAlign.Center) | ||
| 73 | + } | ||
| 74 | + .width('100%') | ||
| 75 | + .alignItems(HorizontalAlign.Start) | ||
| 76 | + } | ||
| 77 | +} |
| 1 | +import { BusinessError } from '@ohos.base' | ||
| 2 | +import { Logger } from 'wdKit' | ||
| 3 | +import { WDHttp } from 'wdNetwork' | ||
| 4 | +import { ContentDetailRequest } from 'wdDetailPlayApi' | ||
| 5 | +import { ContentDetailDTO } from 'wdDetailPlayApi/src/main/ets/bean/ContentDetailDTO' | ||
| 6 | + | ||
| 7 | +const TAG = 'PlayViewModel'; | ||
| 8 | + | ||
| 9 | +@Observed | ||
| 10 | +export class PlayViewModel { | ||
| 11 | + contentId: string | ||
| 12 | + relId: string | ||
| 13 | + relType: string | ||
| 14 | + title?: string | ||
| 15 | + url?: string | ||
| 16 | + nextContId?: string | ||
| 17 | + canStart?: boolean | ||
| 18 | + message?: string | ||
| 19 | + | ||
| 20 | + constructor() { | ||
| 21 | + // todo: | ||
| 22 | + this.contentId = '30013266075' | ||
| 23 | + this.relId = '500000301942' | ||
| 24 | + this.relType = '1' | ||
| 25 | + | ||
| 26 | + // this.getGlobalInfo(); | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + playWithContentId(contentId: string) { | ||
| 30 | + this.contentId = contentId; | ||
| 31 | + this.getContentDetailData() // 包括播放地址PlayUrl | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + getContentDetailData() { | ||
| 35 | + ContentDetailRequest.getContentDetail({ | ||
| 36 | + contentId: this.contentId, | ||
| 37 | + relId: this.relId, | ||
| 38 | + relType: this.relType | ||
| 39 | + }).then((resDTO: WDHttp.ResponseDTO<ContentDetailDTO[]>) => { | ||
| 40 | + if (!resDTO) { | ||
| 41 | + Logger.error(TAG, 'getContentDetailData then resDTO is empty'); | ||
| 42 | + return | ||
| 43 | + } | ||
| 44 | + // Logger.info(TAG, "getNavData then,navResDTO.timeStamp:" + navResDTO.timeStamp); | ||
| 45 | + if (!resDTO.data || resDTO.data.length == 0) { | ||
| 46 | + Logger.error(TAG, `getContentDetailData then body is empty`); | ||
| 47 | + return | ||
| 48 | + } | ||
| 49 | + this.title = resDTO.data[0].newsTitle | ||
| 50 | + this.url = resDTO.data[0].videoInfo[0].videoUrl | ||
| 51 | + this.canStart = true; | ||
| 52 | + this.message = ''; | ||
| 53 | + }).catch((err: BusinessError) => { | ||
| 54 | + Logger.error(TAG, `getContentDetailData catch, error.code : ${err.code}, error.message:${err.message}`); | ||
| 55 | + // todo: | ||
| 56 | + // this.title = '旅途平安!这首歌送给即将启程回家的你' | ||
| 57 | + // this.url = 'https://cdnjdout.aikan.pdnews.cn/zhbj-20240127/vod/content/output/f45ef51bb33f4ffd9458f8b386aa3227_opt.mp4' | ||
| 58 | + this.canStart = false; | ||
| 59 | + this.message = '获取播放地址错误'; | ||
| 60 | + }) | ||
| 61 | + .finally(() => { | ||
| 62 | + Logger.debug(TAG, `getContentDetailData finally`); | ||
| 63 | + }) | ||
| 64 | + } | ||
| 65 | +} |
| 1 | +{ | ||
| 2 | + "color": [ | ||
| 3 | + { | ||
| 4 | + "name": "index_tab_selected_font_color", | ||
| 5 | + "value": "#007DFF" | ||
| 6 | + }, | ||
| 7 | + { | ||
| 8 | + "name": "divider_color", | ||
| 9 | + "value": "#D3D3D3" | ||
| 10 | + }, | ||
| 11 | + { | ||
| 12 | + "name": "track_color", | ||
| 13 | + "value": "#888888" | ||
| 14 | + }, | ||
| 15 | + { | ||
| 16 | + "name": "speed_text_color", | ||
| 17 | + "value": "#DDDDDD" | ||
| 18 | + }, | ||
| 19 | + { | ||
| 20 | + "name": "detail_tab_bar_select", | ||
| 21 | + "value": "#333333" | ||
| 22 | + }, | ||
| 23 | + { | ||
| 24 | + "name": "detail_tab_bar_unselect", | ||
| 25 | + "value": "#666666" | ||
| 26 | + } | ||
| 27 | + ] | ||
| 28 | +} |
| 1 | +{ | ||
| 2 | + "float": [ | ||
| 3 | + { | ||
| 4 | + "name": "control_image_width", | ||
| 5 | + "value": "24vp" | ||
| 6 | + }, | ||
| 7 | + { | ||
| 8 | + "name": "font_size_14", | ||
| 9 | + "value": "14fp" | ||
| 10 | + }, | ||
| 11 | + { | ||
| 12 | + "name": "title_popup_image_size", | ||
| 13 | + "value": "24vp" | ||
| 14 | + }, | ||
| 15 | + { | ||
| 16 | + "name": "back_image_width", | ||
| 17 | + "value": "16vp" | ||
| 18 | + }, | ||
| 19 | + { | ||
| 20 | + "name": "title_popup_text_left", | ||
| 21 | + "value": "8vp" | ||
| 22 | + }, | ||
| 23 | + { | ||
| 24 | + "name": "title_popup_divider_left", | ||
| 25 | + "value": "47vp" | ||
| 26 | + }, | ||
| 27 | + { | ||
| 28 | + "name": "title_popup_font_size", | ||
| 29 | + "value": "16fp" | ||
| 30 | + }, | ||
| 31 | + { | ||
| 32 | + "name": "title_dialog_font_size", | ||
| 33 | + "value": "16fp" | ||
| 34 | + }, | ||
| 35 | + { | ||
| 36 | + "name": "text_border_radius", | ||
| 37 | + "value": "8vp" | ||
| 38 | + }, | ||
| 39 | + { | ||
| 40 | + "name": "main_margin", | ||
| 41 | + "value": "14vp" | ||
| 42 | + }, | ||
| 43 | + { | ||
| 44 | + "name": "text_right_bottom_font", | ||
| 45 | + "value": "12vp" | ||
| 46 | + } | ||
| 47 | + ] | ||
| 48 | +} |
3.25 KB
1.62 KB
677 Bytes
1.63 KB
1.75 KB
6.63 KB
| 1 | +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; | ||
| 2 | + | ||
| 3 | +export default function localUnitTest() { | ||
| 4 | + describe('localUnitTest',() => { | ||
| 5 | + // Defines a test suite. Two parameters are supported: test suite name and test suite function. | ||
| 6 | + beforeAll(() => { | ||
| 7 | + // Presets an action, which is performed only once before all test cases of the test suite start. | ||
| 8 | + // This API supports only one parameter: preset action function. | ||
| 9 | + }); | ||
| 10 | + beforeEach(() => { | ||
| 11 | + // Presets an action, which is performed before each unit test case starts. | ||
| 12 | + // The number of execution times is the same as the number of test cases defined by **it**. | ||
| 13 | + // This API supports only one parameter: preset action function. | ||
| 14 | + }); | ||
| 15 | + afterEach(() => { | ||
| 16 | + // Presets a clear action, which is performed after each unit test case ends. | ||
| 17 | + // The number of execution times is the same as the number of test cases defined by **it**. | ||
| 18 | + // This API supports only one parameter: clear action function. | ||
| 19 | + }); | ||
| 20 | + afterAll(() => { | ||
| 21 | + // Presets a clear action, which is performed after all test cases of the test suite end. | ||
| 22 | + // This API supports only one parameter: clear action function. | ||
| 23 | + }); | ||
| 24 | + it('assertContain', 0, () => { | ||
| 25 | + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. | ||
| 26 | + let a = 'abc'; | ||
| 27 | + let b = 'b'; | ||
| 28 | + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. | ||
| 29 | + expect(a).assertContain(b); | ||
| 30 | + expect(a).assertEqual(a); | ||
| 31 | + }); | ||
| 32 | + }); | ||
| 33 | +} |
sight_harmony/wdDetailPlayVod/.gitignore
0 → 100644
sight_harmony/wdDetailPlayVod/Index.ets
0 → 100644
| 1 | +export { DetailPlayVodPage } from './src/main/ets/pages/DetailPlayVodPage' |
| 1 | +{ | ||
| 2 | + "apiType": "stageMode", | ||
| 3 | + "buildOption": { | ||
| 4 | + "arkOptions": { | ||
| 5 | + // "apPath": "./modules.ap" /* Profile used for profile-guided optimization (PGO), a compiler optimization technique to improve app runtime performance. */ | ||
| 6 | + } | ||
| 7 | + }, | ||
| 8 | + "buildOptionSet": [ | ||
| 9 | + { | ||
| 10 | + "name": "release", | ||
| 11 | + "arkOptions": { | ||
| 12 | + "obfuscation": { | ||
| 13 | + "ruleOptions": { | ||
| 14 | + "enable": true, | ||
| 15 | + "files": [ | ||
| 16 | + "./obfuscation-rules.txt" | ||
| 17 | + ] | ||
| 18 | + } | ||
| 19 | + } | ||
| 20 | + } | ||
| 21 | + }, | ||
| 22 | + ], | ||
| 23 | + "targets": [ | ||
| 24 | + { | ||
| 25 | + "name": "default" | ||
| 26 | + } | ||
| 27 | + ] | ||
| 28 | +} |
sight_harmony/wdDetailPlayVod/hvigorfile.ts
0 → 100644
| 1 | +# Define project specific obfuscation rules here. | ||
| 2 | +# You can include the obfuscation configuration files in the current module's build-profile.json5. | ||
| 3 | +# | ||
| 4 | +# For more details, see | ||
| 5 | +# https://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md | ||
| 6 | + | ||
| 7 | +# Obfuscation options: | ||
| 8 | +# -disable-obfuscation: disable all obfuscations | ||
| 9 | +# -enable-property-obfuscation: obfuscate the property names | ||
| 10 | +# -enable-toplevel-obfuscation: obfuscate the names in the global scope | ||
| 11 | +# -compact: remove unnecessary blank spaces and all line feeds | ||
| 12 | +# -remove-log: remove all console.* statements | ||
| 13 | +# -print-namecache: print the name cache that contains the mapping from the old names to new names | ||
| 14 | +# -apply-namecache: reuse the given cache file | ||
| 15 | + | ||
| 16 | +# Keep options: | ||
| 17 | +# -keep-property-name: specifies property names that you want to keep | ||
| 18 | +# -keep-global-name: specifies names that you want to keep in the global scope |
| 1 | +{ | ||
| 2 | + "name": "wddetailplayvod", | ||
| 3 | + "version": "1.0.0", | ||
| 4 | + "description": "Please describe the basic information.", | ||
| 5 | + "main": "Index.ets", | ||
| 6 | + "author": "", | ||
| 7 | + "license": "Apache-2.0", | ||
| 8 | + "dependencies": { | ||
| 9 | + "wdBean": "file:../wdBean", | ||
| 10 | + "wdPlayer": "file:../wdPlayer", | ||
| 11 | + "wdKit": "file:../wdKit", | ||
| 12 | + "wdDetailPlayApi": "file:../wdDetailPlayApi", | ||
| 13 | + "wdRouter": "file:../wdRouter" | ||
| 14 | + } | ||
| 15 | +} |
| 1 | +@Entry | ||
| 2 | +@Component | ||
| 3 | +export struct DetailPlayVodPage { | ||
| 4 | + @State message: string = 'Detail Play Vod Page'; | ||
| 5 | + | ||
| 6 | + build() { | ||
| 7 | + Row() { | ||
| 8 | + Column() { | ||
| 9 | + Text(this.message) | ||
| 10 | + .fontSize(50) | ||
| 11 | + .fontWeight(FontWeight.Bold) | ||
| 12 | + } | ||
| 13 | + .width('100%') | ||
| 14 | + } | ||
| 15 | + .height('100%') | ||
| 16 | + } | ||
| 17 | +} |
6.63 KB
11.1 KB
| 1 | +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; | ||
| 2 | + | ||
| 3 | +export default function localUnitTest() { | ||
| 4 | + describe('localUnitTest',() => { | ||
| 5 | + // Defines a test suite. Two parameters are supported: test suite name and test suite function. | ||
| 6 | + beforeAll(() => { | ||
| 7 | + // Presets an action, which is performed only once before all test cases of the test suite start. | ||
| 8 | + // This API supports only one parameter: preset action function. | ||
| 9 | + }); | ||
| 10 | + beforeEach(() => { | ||
| 11 | + // Presets an action, which is performed before each unit test case starts. | ||
| 12 | + // The number of execution times is the same as the number of test cases defined by **it**. | ||
| 13 | + // This API supports only one parameter: preset action function. | ||
| 14 | + }); | ||
| 15 | + afterEach(() => { | ||
| 16 | + // Presets a clear action, which is performed after each unit test case ends. | ||
| 17 | + // The number of execution times is the same as the number of test cases defined by **it**. | ||
| 18 | + // This API supports only one parameter: clear action function. | ||
| 19 | + }); | ||
| 20 | + afterAll(() => { | ||
| 21 | + // Presets a clear action, which is performed after all test cases of the test suite end. | ||
| 22 | + // This API supports only one parameter: clear action function. | ||
| 23 | + }); | ||
| 24 | + it('assertContain', 0, () => { | ||
| 25 | + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. | ||
| 26 | + let a = 'abc'; | ||
| 27 | + let b = 'b'; | ||
| 28 | + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. | ||
| 29 | + expect(a).assertContain(b); | ||
| 30 | + expect(a).assertEqual(a); | ||
| 31 | + }); | ||
| 32 | + }); | ||
| 33 | +} |
| @@ -15,3 +15,7 @@ export { LazyDataSource } from './src/main/ets/utils/LazyDataSource' | @@ -15,3 +15,7 @@ export { LazyDataSource } from './src/main/ets/utils/LazyDataSource' | ||
| 15 | export { BreakpointSystem, BreakPointType } from './src/main/ets/utils/BreakPointSystem'; | 15 | export { BreakpointSystem, BreakPointType } from './src/main/ets/utils/BreakPointSystem'; |
| 16 | 16 | ||
| 17 | export { ToastUtils } from './src/main/ets/utils/ToastUtils'; | 17 | export { ToastUtils } from './src/main/ets/utils/ToastUtils'; |
| 18 | + | ||
| 19 | +export { WindowModel } from './src/main/ets/utils/WindowModel' | ||
| 20 | + | ||
| 21 | +export { SPHelper } from './src/main/ets/utils/SPHelper' |
| 1 | +import data_preferences from '@ohos.data.preferences'; | ||
| 2 | + | ||
| 3 | +/* | ||
| 4 | +// SPHelper.default.get("key1", "defValue1").then((value1) => { | ||
| 5 | +// this.message = value1.toString(); | ||
| 6 | +// }) | ||
| 7 | + | ||
| 8 | +// let value2: string = await SPHelper.default.get("key2", "defValue2"); | ||
| 9 | +// this.message = result; | ||
| 10 | +* | ||
| 11 | +* 单例模式 | ||
| 12 | + */ | ||
| 13 | +export class SPHelper { | ||
| 14 | + private static context: Context; | ||
| 15 | + private static spFilename: string = '__SPHelper'; | ||
| 16 | + | ||
| 17 | + static init(context: Context) { | ||
| 18 | + SPHelper.context = context; | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + static setSpFilename(spFilename: string) { | ||
| 22 | + SPHelper.spFilename = spFilename; | ||
| 23 | + } | ||
| 24 | + | ||
| 25 | + // 静态属性 | ||
| 26 | + static default: SPHelper = new SPHelper(); | ||
| 27 | + | ||
| 28 | + // 私有构造函数 | ||
| 29 | + private constructor() { | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + private async getVideoPreferences(): Promise<data_preferences.Preferences> { | ||
| 33 | + let preferences: data_preferences.Preferences = await data_preferences.getPreferences(SPHelper.context, SPHelper.spFilename); | ||
| 34 | + return preferences; | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + private getVideoPreferencesSync(): data_preferences.Preferences { | ||
| 38 | + let options: data_preferences.Options = { name: SPHelper.spFilename }; | ||
| 39 | + let preferences: data_preferences.Preferences = data_preferences.getPreferencesSync(SPHelper.context, options); | ||
| 40 | + return preferences; | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + async save(key: string, value: data_preferences.ValueType) { | ||
| 44 | + const preferences: data_preferences.Preferences = await this.getVideoPreferences(); | ||
| 45 | + await preferences.put(key, value) | ||
| 46 | + await preferences.flush() | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + saveSync(key: string, value: data_preferences.ValueType) { | ||
| 50 | + const preferences: data_preferences.Preferences = this.getVideoPreferencesSync(); | ||
| 51 | + preferences.putSync(key, value) | ||
| 52 | + preferences.flush() // todo:Asynchronously | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + async get(key: string, defValue: data_preferences.ValueType): Promise<data_preferences.ValueType> { | ||
| 56 | + const preferences: data_preferences.Preferences = await this.getVideoPreferences(); | ||
| 57 | + return await preferences.get(key, defValue); | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + getSync(key: string, defValue: data_preferences.ValueType): data_preferences.ValueType { | ||
| 61 | + const preferences: data_preferences.Preferences = this.getVideoPreferencesSync(); | ||
| 62 | + return preferences.getSync(key, defValue); | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + async has(key: string): Promise<boolean> { | ||
| 66 | + const preferences: data_preferences.Preferences = await this.getVideoPreferences(); | ||
| 67 | + return await preferences.has(key); | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + hasSync(key: string): boolean { | ||
| 71 | + const preferences: data_preferences.Preferences = this.getVideoPreferencesSync(); | ||
| 72 | + return preferences.hasSync(key); | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + async delete(key: string) { | ||
| 76 | + const preferences: data_preferences.Preferences = await this.getVideoPreferences(); | ||
| 77 | + preferences.delete(key).then(async () => { | ||
| 78 | + await preferences.flush(); | ||
| 79 | + }).catch((err: Error) => { | ||
| 80 | + // Logger.error(TAG, 'Failed to delete the key. Cause: ' + err); | ||
| 81 | + }); | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + deleteSync(key: string) { | ||
| 85 | + const preferences: data_preferences.Preferences = this.getVideoPreferencesSync(); | ||
| 86 | + preferences.deleteSync(key) | ||
| 87 | + preferences.flush(); // todo:Asynchronously | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + async clearSync() { | ||
| 91 | + this.getVideoPreferences().then(async (preferences: data_preferences.Preferences) => { | ||
| 92 | + preferences.clearSync() | ||
| 93 | + await preferences.flush() | ||
| 94 | + }).catch((err: Error) => { | ||
| 95 | + // Logger.error(TAG, 'get the preferences failed, Cause: ' + err); | ||
| 96 | + }); | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + // clearSync() { | ||
| 100 | + // let preferences: data_preferences.Preferences = this.getVideoPreferencesSync() | ||
| 101 | + // preferences.clearSync() | ||
| 102 | + // preferences.flush() | ||
| 103 | + // } | ||
| 104 | +} |
| 1 | +import window from '@ohos.window'; | ||
| 2 | +import { BusinessError } from '@ohos.base'; | ||
| 3 | +import deviceInfo from '@ohos.deviceInfo' | ||
| 4 | +import display from '@ohos.display'; | ||
| 5 | + | ||
| 6 | +export class Size { | ||
| 7 | + width: number = 0 | ||
| 8 | + height: number = 0 | ||
| 9 | + | ||
| 10 | + constructor(width: number, height: number) { | ||
| 11 | + this.width = width; | ||
| 12 | + this.height = height; | ||
| 13 | + } | ||
| 14 | +} | ||
| 15 | + | ||
| 16 | +export class WindowModel { | ||
| 17 | + private windowStage?: window.WindowStage; | ||
| 18 | + | ||
| 19 | + static shared: WindowModel = new WindowModel() | ||
| 20 | + | ||
| 21 | + static TAG = "WindowModel"; | ||
| 22 | + | ||
| 23 | + setWindowStage(windowStage: window.WindowStage) { | ||
| 24 | + this.windowStage = windowStage; | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + setMainWindowFullScreen(fullScreen: boolean) { | ||
| 28 | + if (deviceInfo.deviceType != "phone") { | ||
| 29 | + return | ||
| 30 | + } | ||
| 31 | + if (this.windowStage === undefined) { | ||
| 32 | + return; | ||
| 33 | + } | ||
| 34 | + this.windowStage.getMainWindow((err, windowClass: window.Window) => { | ||
| 35 | + if (err.code) { | ||
| 36 | + return; | ||
| 37 | + } | ||
| 38 | + windowClass.setWindowLayoutFullScreen(fullScreen, (err) => { | ||
| 39 | + if (err.code) { | ||
| 40 | + return; | ||
| 41 | + } | ||
| 42 | + }); | ||
| 43 | + windowClass.setWindowSystemBarEnable(fullScreen ? [] : ['status', 'navigation'], (err) => { | ||
| 44 | + if (err.code) { | ||
| 45 | + return; | ||
| 46 | + } | ||
| 47 | + }); | ||
| 48 | + }); | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + getWindowSize(): Promise<Size> { | ||
| 52 | + return new Promise((resolve, reject) => { | ||
| 53 | + if (!this.windowStage) { | ||
| 54 | + let dis = display.getDefaultDisplaySync(); | ||
| 55 | + reject(new Size(dis.width, dis.height)) | ||
| 56 | + return; | ||
| 57 | + } | ||
| 58 | + let rect = this.windowStage.getMainWindowSync().getWindowProperties().windowRect; | ||
| 59 | + resolve(new Size(rect.width, rect.height)); | ||
| 60 | + }); | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + setWindowKeepScreenOn(isKeepScreenOn: boolean) { | ||
| 64 | + this.windowStage?.getMainWindow((err, windowClass: window.Window) => { | ||
| 65 | + windowClass.setWindowKeepScreenOn(isKeepScreenOn, (err: BusinessError) => { | ||
| 66 | + const errCode: number = err.code; | ||
| 67 | + if (errCode) { | ||
| 68 | + console.error(WindowModel.TAG +'设置屏幕常亮:' + isKeepScreenOn + ',失败: ' + JSON.stringify(err)); | ||
| 69 | + return; | ||
| 70 | + } | ||
| 71 | + console.info(WindowModel.TAG +'设置屏幕常亮:' + isKeepScreenOn + ",成功"); | ||
| 72 | + }) | ||
| 73 | + }) | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + /** | ||
| 77 | + * 设置窗口的显示方向属性 | ||
| 78 | + * @param orientation | ||
| 79 | + */ | ||
| 80 | + setPreferredOrientation(orientation: window.Orientation): Promise<void> { | ||
| 81 | + return new Promise((resolve, reject) => { | ||
| 82 | + if (!this.windowStage) { | ||
| 83 | + console.error('Failed, the main window is empty'); | ||
| 84 | + reject("Failed, the main window is empty") | ||
| 85 | + return; | ||
| 86 | + } | ||
| 87 | + this.windowStage.getMainWindow((err: BusinessError, windowClass: window.Window) => { | ||
| 88 | + if (err.code) { | ||
| 89 | + console.error('Failed to obtain the main window. Cause: ' + err.message); | ||
| 90 | + reject(err) | ||
| 91 | + return; | ||
| 92 | + } | ||
| 93 | + // 2.设置窗口的显示方向属性,使用Promise异步回调。 | ||
| 94 | + windowClass.setPreferredOrientation(orientation).then(() => { | ||
| 95 | + console.info('Succeeded in setting the window orientation.'); | ||
| 96 | + resolve() | ||
| 97 | + }).catch((err: BusinessError) => { | ||
| 98 | + console.error('Failed to set the window orientation. Cause: ' + err.message); | ||
| 99 | + reject(err) | ||
| 100 | + }); | ||
| 101 | + }); | ||
| 102 | + }) | ||
| 103 | + } | ||
| 104 | +} | ||
| 105 | + |
| 1 | export { ResponseDTO } from './src/main/ets/bean/ResponseDTO' | 1 | export { ResponseDTO } from './src/main/ets/bean/ResponseDTO' |
| 2 | + | ||
| 2 | export { ResponseVO } from './src/main/ets/bean/ResponseVO' | 3 | export { ResponseVO } from './src/main/ets/bean/ResponseVO' |
| 4 | + | ||
| 3 | export { ResultCode } from './src/main/ets/bean/ResultCode' | 5 | export { ResultCode } from './src/main/ets/bean/ResultCode' |
| 4 | 6 | ||
| 5 | export { WDHttp } from './src/main/ets/http/WDHttp' | 7 | export { WDHttp } from './src/main/ets/http/WDHttp' |
| 1 | import http from '@ohos.net.http'; | 1 | import http from '@ohos.net.http'; |
| 2 | import { BusinessError } from '@ohos.base'; | 2 | import { BusinessError } from '@ohos.base'; |
| 3 | import ArrayList from '@ohos.util.ArrayList'; | 3 | import ArrayList from '@ohos.util.ArrayList'; |
| 4 | -import {Logger} from 'wdKit'; | 4 | +import { Logger } from 'wdKit'; |
| 5 | import { HttpUtils } from '../utils/HttpUtils'; | 5 | import { HttpUtils } from '../utils/HttpUtils'; |
| 6 | 6 | ||
| 7 | const TAG = 'WDHttp'; | 7 | const TAG = 'WDHttp'; |
| @@ -67,9 +67,11 @@ export namespace WDHttp { | @@ -67,9 +67,11 @@ export namespace WDHttp { | ||
| 67 | 67 | ||
| 68 | // 响应结果 | 68 | // 响应结果 |
| 69 | body?: T; | 69 | body?: T; |
| 70 | + data?: T; | ||
| 70 | 71 | ||
| 71 | // 请求响应时间戳(unix格式) | 72 | // 请求响应时间戳(unix格式) |
| 72 | timeStamp?: number; | 73 | timeStamp?: number; |
| 74 | + | ||
| 73 | // timestamp?: number; | 75 | // timestamp?: number; |
| 74 | 76 | ||
| 75 | // 返回当前时间戳,格式:yyyyMMddHHmmss,如20230918102124 | 77 | // 返回当前时间戳,格式:yyyyMMddHHmmss,如20230918102124 |
| @@ -261,7 +263,7 @@ export namespace WDHttp { | @@ -261,7 +263,7 @@ export namespace WDHttp { | ||
| 261 | } else if (!options.header['Content-Type']) { | 263 | } else if (!options.header['Content-Type']) { |
| 262 | options.header['Content-Type'] = 'application/json;charset=utf-8'; | 264 | options.header['Content-Type'] = 'application/json;charset=utf-8'; |
| 263 | } | 265 | } |
| 264 | - let commonHeader: Record<string, string | number> = { }; | 266 | + let commonHeader: Record<string, string | number> = {}; |
| 265 | Request.globalHeaderProviders.forEach((func) => { | 267 | Request.globalHeaderProviders.forEach((func) => { |
| 266 | let headers = func(); | 268 | let headers = func(); |
| 267 | for (const obj of Object.entries(headers)) { | 269 | for (const obj of Object.entries(headers)) { |
sight_harmony/wdPlayer/.gitignore
0 → 100644
sight_harmony/wdPlayer/Index.ets
0 → 100644
| 1 | +export { WDPlayerController } from "./src/main/ets/controller/WDPlayerController" | ||
| 2 | + | ||
| 3 | +export { WDPlayerRenderView } from "./src/main/ets/pages/WDPlayerRenderView" | ||
| 4 | + | ||
| 5 | +export { PlayerConstants } from "./src/main/ets/constants/PlayerConstants" | ||
| 6 | + | ||
| 7 | +export { SpeedBean } from "./src/main/ets/bean/SpeedBean" | ||
| 8 | + | ||
| 9 | +export { DateFormatUtil } from "./src/main/ets/utils/DateFormatUtil" |
sight_harmony/wdPlayer/build-profile.json5
0 → 100644
| 1 | +{ | ||
| 2 | + "apiType": "stageMode", | ||
| 3 | + "buildOption": { | ||
| 4 | + "arkOptions": { | ||
| 5 | + // "apPath": "./modules.ap" /* Profile used for profile-guided optimization (PGO), a compiler optimization technique to improve app runtime performance. */ | ||
| 6 | + } | ||
| 7 | + }, | ||
| 8 | + "buildOptionSet": [ | ||
| 9 | + { | ||
| 10 | + "name": "release", | ||
| 11 | + "arkOptions": { | ||
| 12 | + "obfuscation": { | ||
| 13 | + "ruleOptions": { | ||
| 14 | + "enable": true, | ||
| 15 | + "files": [ | ||
| 16 | + "./obfuscation-rules.txt" | ||
| 17 | + ] | ||
| 18 | + } | ||
| 19 | + } | ||
| 20 | + } | ||
| 21 | + }, | ||
| 22 | + ], | ||
| 23 | + "targets": [ | ||
| 24 | + { | ||
| 25 | + "name": "default" | ||
| 26 | + } | ||
| 27 | + ] | ||
| 28 | +} |
sight_harmony/wdPlayer/hvigorfile.ts
0 → 100644
sight_harmony/wdPlayer/obfuscation-rules.txt
0 → 100644
| 1 | +# Define project specific obfuscation rules here. | ||
| 2 | +# You can include the obfuscation configuration files in the current module's build-profile.json5. | ||
| 3 | +# | ||
| 4 | +# For more details, see | ||
| 5 | +# https://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md | ||
| 6 | + | ||
| 7 | +# Obfuscation options: | ||
| 8 | +# -disable-obfuscation: disable all obfuscations | ||
| 9 | +# -enable-property-obfuscation: obfuscate the property names | ||
| 10 | +# -enable-toplevel-obfuscation: obfuscate the names in the global scope | ||
| 11 | +# -compact: remove unnecessary blank spaces and all line feeds | ||
| 12 | +# -remove-log: remove all console.* statements | ||
| 13 | +# -print-namecache: print the name cache that contains the mapping from the old names to new names | ||
| 14 | +# -apply-namecache: reuse the given cache file | ||
| 15 | + | ||
| 16 | +# Keep options: | ||
| 17 | +# -keep-property-name: specifies property names that you want to keep | ||
| 18 | +# -keep-global-name: specifies names that you want to keep in the global scope |
sight_harmony/wdPlayer/oh-package.json5
0 → 100644
| 1 | +import { SpeedBean } from '../bean/SpeedBean'; | ||
| 2 | + | ||
| 3 | +export class PlayerConstants { | ||
| 4 | + static readonly STATUS_IDLE: number = 0; | ||
| 5 | + static readonly STATUS_START: number = 1; | ||
| 6 | + static readonly STATUS_PAUSE: number = 2; | ||
| 7 | + static readonly STATUS_STOP: number = 3; | ||
| 8 | + | ||
| 9 | + static readonly OPERATE_STATE: Array<string> = ['prepared','playing', 'paused', 'completed']; | ||
| 10 | + | ||
| 11 | + static readonly SPEED_ARRAY:SpeedBean[] = [ | ||
| 12 | + { text: '0.75X', value: 0 }, | ||
| 13 | + { text: '1.0X', value: 1 }, | ||
| 14 | + { text: '1.25X', value: 2 }, | ||
| 15 | + { text: '1.75X', value: 3 }, | ||
| 16 | + { text: '2.0X', value: 4 } | ||
| 17 | + ]; | ||
| 18 | +} | ||
| 19 | + | ||
| 20 | +export enum AVPlayerStatus { | ||
| 21 | + IDLE = 'idle', | ||
| 22 | + INITIALIZED = 'initialized', | ||
| 23 | + PREPARED = 'prepared', | ||
| 24 | + PLAYING = 'playing', | ||
| 25 | + PAUSED = 'paused', | ||
| 26 | + COMPLETED = 'completed', | ||
| 27 | + STOPPED = 'stopped', | ||
| 28 | + RELEASED = 'released', | ||
| 29 | + ERROR = 'error' | ||
| 30 | +} | ||
| 31 | + | ||
| 32 | +export enum Events { | ||
| 33 | + STATE_CHANGE = 'stateChange', | ||
| 34 | + VIDEO_SIZE_CHANGE = "videoSizeChange", | ||
| 35 | + TIME_UPDATE = 'timeUpdate', | ||
| 36 | + ERROR = 'error' | ||
| 37 | +} |
| 1 | +import media from '@ohos.multimedia.media'; | ||
| 2 | +import prompt from '@ohos.promptAction'; | ||
| 3 | +import { Logger } from '../utils/Logger'; | ||
| 4 | +import { PlayerConstants, AVPlayerStatus, Events } from '../constants/PlayerConstants'; | ||
| 5 | + | ||
| 6 | +@Observed | ||
| 7 | +export class WDPlayerController { | ||
| 8 | + private initPromise: Promise<void>; | ||
| 9 | + private avPlayer?: media.AVPlayer; | ||
| 10 | + private duration: number = 0; | ||
| 11 | + private status: number = PlayerConstants.STATUS_IDLE; | ||
| 12 | + private loop: boolean = false; | ||
| 13 | + private url: string = ''; | ||
| 14 | + private surfaceId: string = ''; // 若播放音频,无需设置surfaceId | ||
| 15 | + private playSpeed: number = 1; | ||
| 16 | + private seekTime: number = 0; | ||
| 17 | + private positionY: number = 0; | ||
| 18 | + private startTime: number = 0; | ||
| 19 | + public onVideoSizeChange?: (width: number, height: number) => void; | ||
| 20 | + public onTimeUpdate?: (position: number, duration: number) => void; | ||
| 21 | + public onVolumeUpdate?: (volume: number) => void; | ||
| 22 | + public continue?: () => void; | ||
| 23 | + | ||
| 24 | + constructor() { | ||
| 25 | + Logger.error("初始化") | ||
| 26 | + this.initPromise = this.createAVPlayer(); | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + /** | ||
| 30 | + * 创建 videoPlayer对象 | ||
| 31 | + */ | ||
| 32 | + private createAVPlayer(): Promise<void> { | ||
| 33 | + return new Promise((resolve, reject) => { | ||
| 34 | + Logger.error("开始创建") | ||
| 35 | + media.createAVPlayer().then((avPlayer) => { | ||
| 36 | + if (avPlayer) { | ||
| 37 | + Logger.error("创建完成1") | ||
| 38 | + this.avPlayer = avPlayer; | ||
| 39 | + this.bindState(); | ||
| 40 | + resolve(); | ||
| 41 | + } else { | ||
| 42 | + Logger.error("创建完成0") | ||
| 43 | + Logger.error('[PlayVideoModel] createAvPlayer fail!'); | ||
| 44 | + reject(); | ||
| 45 | + } | ||
| 46 | + }); | ||
| 47 | + }); | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + /** | ||
| 51 | + * AVPlayer 绑定事件. | ||
| 52 | + */ | ||
| 53 | + private bindState() { | ||
| 54 | + this.avPlayer?.on(Events.STATE_CHANGE, async (state) => { | ||
| 55 | + if (this.avPlayer == null) { | ||
| 56 | + return | ||
| 57 | + } | ||
| 58 | + switch (state) { | ||
| 59 | + case AVPlayerStatus.IDLE: | ||
| 60 | + this.resetProgress(); | ||
| 61 | + this.avPlayer.url = this.url; | ||
| 62 | + break; | ||
| 63 | + case AVPlayerStatus.INITIALIZED: | ||
| 64 | + this.avPlayer.surfaceId = this.surfaceId; | ||
| 65 | + this.avPlayer?.prepare(); | ||
| 66 | + break; | ||
| 67 | + case AVPlayerStatus.PREPARED: | ||
| 68 | + this.avPlayer.videoScaleType = 0; | ||
| 69 | + if (this.startTime) { | ||
| 70 | + this.setSeekTime(this.startTime, SliderChangeMode.Begin); | ||
| 71 | + } | ||
| 72 | + this.avPlayer.play(); | ||
| 73 | + this.duration = this.avPlayer.duration; | ||
| 74 | + break; | ||
| 75 | + case AVPlayerStatus.PLAYING: | ||
| 76 | + this.setBright(); | ||
| 77 | + this.status = PlayerConstants.STATUS_START; | ||
| 78 | + this.watchStatus(); | ||
| 79 | + break; | ||
| 80 | + case AVPlayerStatus.PAUSED: | ||
| 81 | + this.status = PlayerConstants.STATUS_PAUSE; | ||
| 82 | + this.watchStatus(); | ||
| 83 | + break; | ||
| 84 | + case AVPlayerStatus.COMPLETED: | ||
| 85 | + // this.titleThis.playSpeed = 1; | ||
| 86 | + if (this.continue) { | ||
| 87 | + this.continue(); | ||
| 88 | + } else { | ||
| 89 | + this.duration = 0; | ||
| 90 | + this.url = this.avPlayer.url || ''; | ||
| 91 | + this.avPlayer.reset(); | ||
| 92 | + } | ||
| 93 | + break; | ||
| 94 | + case AVPlayerStatus.RELEASED: | ||
| 95 | + this.avPlayer.release(); | ||
| 96 | + this.status = PlayerConstants.STATUS_STOP; | ||
| 97 | + this.watchStatus(); | ||
| 98 | + Logger.info('[PlayVideoModel] state released called') | ||
| 99 | + break; | ||
| 100 | + default: | ||
| 101 | + Logger.info('[PlayVideoModel] unKnown state: ' + state); | ||
| 102 | + break; | ||
| 103 | + } | ||
| 104 | + }); | ||
| 105 | + this.avPlayer?.on(Events.TIME_UPDATE, (time: number) => { | ||
| 106 | + this.initProgress(time); | ||
| 107 | + }); | ||
| 108 | + this.avPlayer?.on(Events.ERROR, (error) => { | ||
| 109 | + this.playError(error.message); | ||
| 110 | + }) | ||
| 111 | + this.avPlayer?.on(Events.VIDEO_SIZE_CHANGE, (width: number, height: number) => { | ||
| 112 | + if (this.onVideoSizeChange) { | ||
| 113 | + this.onVideoSizeChange(width, height); | ||
| 114 | + } | ||
| 115 | + }) | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | + public setXComponentController(controller: XComponentController) { | ||
| 119 | + this.surfaceId = controller.getXComponentSurfaceId() | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + async firstPlay(url: string) { | ||
| 123 | + this.url = url; | ||
| 124 | + if (this.avPlayer == null) { | ||
| 125 | + Logger.error("等待") | ||
| 126 | + await this.initPromise; | ||
| 127 | + } else { | ||
| 128 | + if (this.avPlayer.state != AVPlayerStatus.IDLE) { | ||
| 129 | + await this.avPlayer.stop() | ||
| 130 | + await this.avPlayer.release() | ||
| 131 | + this.initPromise = this.createAVPlayer(); | ||
| 132 | + await this.initPromise; | ||
| 133 | + } | ||
| 134 | + } | ||
| 135 | + if (this.avPlayer == null) { | ||
| 136 | + return | ||
| 137 | + } | ||
| 138 | + Logger.error("开始播放") | ||
| 139 | + this.avPlayer.url = this.url; | ||
| 140 | + } | ||
| 141 | + | ||
| 142 | + async release() { | ||
| 143 | + if (this.avPlayer == null) { | ||
| 144 | + await this.initPromise; | ||
| 145 | + } | ||
| 146 | + if (this.avPlayer == null) { | ||
| 147 | + return | ||
| 148 | + } | ||
| 149 | + this.avPlayer.release(); | ||
| 150 | + } | ||
| 151 | + | ||
| 152 | + async pause() { | ||
| 153 | + if (this.avPlayer == null) { | ||
| 154 | + await this.initPromise; | ||
| 155 | + } | ||
| 156 | + if (this.avPlayer == null) { | ||
| 157 | + return | ||
| 158 | + } | ||
| 159 | + this.avPlayer.pause(); | ||
| 160 | + } | ||
| 161 | + | ||
| 162 | + async stop() { | ||
| 163 | + if (this.avPlayer == null) { | ||
| 164 | + await this.initPromise; | ||
| 165 | + } | ||
| 166 | + if (this.avPlayer == null) { | ||
| 167 | + return | ||
| 168 | + } | ||
| 169 | + this.avPlayer.stop(); | ||
| 170 | + } | ||
| 171 | + | ||
| 172 | + async setLoop() { | ||
| 173 | + if (this.avPlayer == null) { | ||
| 174 | + await this.initPromise; | ||
| 175 | + } | ||
| 176 | + if (this.avPlayer == null) { | ||
| 177 | + return | ||
| 178 | + } | ||
| 179 | + this.loop = !this.loop; | ||
| 180 | + } | ||
| 181 | + | ||
| 182 | + async setSpeed(playSpeed: number) { | ||
| 183 | + if (this.avPlayer == null) { | ||
| 184 | + await this.initPromise; | ||
| 185 | + } | ||
| 186 | + if (this.avPlayer == null) { | ||
| 187 | + return | ||
| 188 | + } | ||
| 189 | + if (PlayerConstants.OPERATE_STATE.indexOf(this.avPlayer.state) === -1) { | ||
| 190 | + return; | ||
| 191 | + } | ||
| 192 | + this.playSpeed = playSpeed; | ||
| 193 | + this.avPlayer.setSpeed(this.playSpeed); | ||
| 194 | + } | ||
| 195 | + | ||
| 196 | + async switchPlayOrPause() { | ||
| 197 | + if (this.avPlayer == null) { | ||
| 198 | + await this.initPromise; | ||
| 199 | + } | ||
| 200 | + if (this.avPlayer == null) { | ||
| 201 | + return | ||
| 202 | + } | ||
| 203 | + if (this.status === PlayerConstants.STATUS_START) { | ||
| 204 | + this.avPlayer.pause(); | ||
| 205 | + } else { | ||
| 206 | + this.avPlayer.play(); | ||
| 207 | + } | ||
| 208 | + } | ||
| 209 | + | ||
| 210 | + async setSeekTime(value: number, mode: SliderChangeMode) { | ||
| 211 | + if (this.avPlayer == null) { | ||
| 212 | + await this.initPromise; | ||
| 213 | + } | ||
| 214 | + if (this.avPlayer == null) { | ||
| 215 | + return | ||
| 216 | + } | ||
| 217 | + if (mode == SliderChangeMode.Begin) { | ||
| 218 | + this.seekTime = value * 1000; | ||
| 219 | + this.avPlayer.seek(this.seekTime, media.SeekMode.SEEK_PREV_SYNC); | ||
| 220 | + } | ||
| 221 | + if (mode === SliderChangeMode.Moving) { | ||
| 222 | + // this.progressThis.progressVal = value; | ||
| 223 | + // this.progressThis.currentTime = DateFormatUtil.secondToTime(Math.floor(value * this.duration / | ||
| 224 | + // 100 / 1000)); | ||
| 225 | + } | ||
| 226 | + if (mode === SliderChangeMode.End) { | ||
| 227 | + this.seekTime = value * this.duration / 100; | ||
| 228 | + this.avPlayer.seek(this.seekTime, media.SeekMode.SEEK_PREV_SYNC); | ||
| 229 | + } | ||
| 230 | + } | ||
| 231 | + | ||
| 232 | + setBright() { | ||
| 233 | + // globalThis.windowClass.setWindowBrightness(this.playerThis.bright) | ||
| 234 | + } | ||
| 235 | + | ||
| 236 | + getStatus() { | ||
| 237 | + return this.status; | ||
| 238 | + } | ||
| 239 | + | ||
| 240 | + initProgress(time: number) { | ||
| 241 | + let nowSeconds = Math.floor(time / 1000); | ||
| 242 | + let totalSeconds = Math.floor(this.duration / 1000); | ||
| 243 | + if (this.onTimeUpdate) { | ||
| 244 | + this.onTimeUpdate(nowSeconds, totalSeconds); | ||
| 245 | + } | ||
| 246 | + } | ||
| 247 | + | ||
| 248 | + resetProgress() { | ||
| 249 | + this.seekTime = 0; | ||
| 250 | + // this.progressThis.currentTime = '00:00'; | ||
| 251 | + // this.progressThis.progressVal = 0; | ||
| 252 | + } | ||
| 253 | + | ||
| 254 | + onVolumeActionStart(event: GestureEvent) { | ||
| 255 | + this.positionY = event.offsetY; | ||
| 256 | + } | ||
| 257 | + | ||
| 258 | + onBrightActionStart(event: GestureEvent) { | ||
| 259 | + this.positionY = event.offsetY; | ||
| 260 | + } | ||
| 261 | + | ||
| 262 | + volume: number = 1 | ||
| 263 | + | ||
| 264 | + onVolumeActionUpdate(event: GestureEvent) { | ||
| 265 | + if (!this.avPlayer) { | ||
| 266 | + return | ||
| 267 | + } | ||
| 268 | + if (PlayerConstants.OPERATE_STATE.indexOf(this.avPlayer.state) === -1) { | ||
| 269 | + return; | ||
| 270 | + } | ||
| 271 | + let changeVolume = (event.offsetY - this.positionY) / 300; | ||
| 272 | + let currentVolume = this.volume - changeVolume; | ||
| 273 | + if (currentVolume > 1) { | ||
| 274 | + currentVolume = 1; | ||
| 275 | + } | ||
| 276 | + if (currentVolume <= 0) { | ||
| 277 | + currentVolume = 0; | ||
| 278 | + } | ||
| 279 | + this.volume = currentVolume; | ||
| 280 | + this.avPlayer?.setVolume(this.volume); | ||
| 281 | + this.positionY = event.offsetY; | ||
| 282 | + if (this.onVolumeUpdate) { | ||
| 283 | + this.onVolumeUpdate(this.volume); | ||
| 284 | + } | ||
| 285 | + console.log("volume : " + this.volume) | ||
| 286 | + } | ||
| 287 | + | ||
| 288 | + onBrightActionUpdate(event: GestureEvent) { | ||
| 289 | + // if (!this.playerThis.volumeShow) { | ||
| 290 | + // this.playerThis.brightShow = true; | ||
| 291 | + // let changeBright = (this.positionY - event.offsetY) / globalThis.screenHeight; | ||
| 292 | + // let currentBright = this.playerThis.bright + changeBright; | ||
| 293 | + // let brightMinFlag = currentBright <= 0; | ||
| 294 | + // let brightMaxFlag = currentBright > 1; | ||
| 295 | + // this.playerThis.bright = brightMinFlag ? 0 : | ||
| 296 | + // (brightMaxFlag ? 1 : currentBright); | ||
| 297 | + // this.setBright(); | ||
| 298 | + // this.positionY = event.offsetY; | ||
| 299 | + // } | ||
| 300 | + } | ||
| 301 | + | ||
| 302 | + onActionEnd() { | ||
| 303 | + setTimeout(() => { | ||
| 304 | + this.positionY = 0; | ||
| 305 | + }, 200); | ||
| 306 | + } | ||
| 307 | + | ||
| 308 | + watchStatus() { | ||
| 309 | + // if (this.status === PlayConstants.STATUS_START) { | ||
| 310 | + // globalThis.windowClass.setWindowKeepScreenOn(true); | ||
| 311 | + // } else { | ||
| 312 | + // globalThis.windowClass.setWindowKeepScreenOn(false); | ||
| 313 | + // } | ||
| 314 | + } | ||
| 315 | + | ||
| 316 | + playError(msg?: string) { | ||
| 317 | + prompt.showToast({ | ||
| 318 | + duration: 3000, | ||
| 319 | + message: msg ? msg : "请检查地址输入正确且网络正常" | ||
| 320 | + }); | ||
| 321 | + } | ||
| 322 | + | ||
| 323 | + setStartTime(time?: number) { | ||
| 324 | + this.startTime = time ?? 0; | ||
| 325 | + } | ||
| 326 | +} |
| 1 | +import componentUtils from '@ohos.arkui.componentUtils'; | ||
| 2 | +import { WDPlayerController } from '../controller/WDPlayerController' | ||
| 3 | +import { WindowModel } from 'wdKit'; | ||
| 4 | + | ||
| 5 | +class Size { | ||
| 6 | + width: Length = "100%"; | ||
| 7 | + height: Length = "100%"; | ||
| 8 | + | ||
| 9 | + constructor(width: Length, height: Length) { | ||
| 10 | + this.width = width; | ||
| 11 | + this.height = height; | ||
| 12 | + } | ||
| 13 | +} | ||
| 14 | + | ||
| 15 | +let insIndex: number = 0; | ||
| 16 | + | ||
| 17 | +class MGPlayRenderViewIns { | ||
| 18 | + static intCount: number = 0; | ||
| 19 | + | ||
| 20 | + static add() { | ||
| 21 | + MGPlayRenderViewIns.intCount++; | ||
| 22 | + WindowModel.shared.setWindowKeepScreenOn(true); | ||
| 23 | + console.log("add-- +1") | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + static del() { | ||
| 27 | + console.log("add-- -1") | ||
| 28 | + MGPlayRenderViewIns.intCount--; | ||
| 29 | + if (MGPlayRenderViewIns.intCount <= 0) { | ||
| 30 | + WindowModel.shared.setWindowKeepScreenOn(false); | ||
| 31 | + } | ||
| 32 | + } | ||
| 33 | +} | ||
| 34 | + | ||
| 35 | +/** | ||
| 36 | + * 播放窗口组件 | ||
| 37 | + */ | ||
| 38 | +@Entry | ||
| 39 | +@Component | ||
| 40 | +export struct WDPlayerRenderView { | ||
| 41 | + private playerController?: WDPlayerController; | ||
| 42 | + private xComponentController: XComponentController = new XComponentController(); | ||
| 43 | + onLoad?: ((event?: object) => void); | ||
| 44 | + videoWidth: number = 0 | ||
| 45 | + videoHeight: number = 0 | ||
| 46 | + @State selfSize: Size = new Size('100%', '100%'); | ||
| 47 | + private insId: string = "WDPlayRenderView" + insIndex; | ||
| 48 | + | ||
| 49 | + aboutToAppear() { | ||
| 50 | + MGPlayRenderViewIns.add(); | ||
| 51 | + | ||
| 52 | + insIndex++; | ||
| 53 | + | ||
| 54 | + if (!this.playerController) { | ||
| 55 | + return | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + this.playerController.onVideoSizeChange = (width: number, height: number) => { | ||
| 59 | + this.videoWidth = width; | ||
| 60 | + this.videoHeight = height; | ||
| 61 | + this.updateLayout() | ||
| 62 | + } | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + aboutToDisappear() { | ||
| 66 | + MGPlayRenderViewIns.del(); | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + build() { | ||
| 70 | + Row() { | ||
| 71 | + // 设置为“surface“类型时XComponent组件可以和其他组件一起进行布局和渲染。 | ||
| 72 | + XComponent({ | ||
| 73 | + id: 'xComponentId112233', | ||
| 74 | + type: 'surface', | ||
| 75 | + controller: this.xComponentController | ||
| 76 | + }) | ||
| 77 | + .onLoad(async (event) => { | ||
| 78 | + this.xComponentController.setXComponentSurfaceSize({ | ||
| 79 | + surfaceWidth: 1920, | ||
| 80 | + surfaceHeight: 1080 | ||
| 81 | + }); | ||
| 82 | + this.playerController?.setXComponentController(this.xComponentController) | ||
| 83 | + if (this.onLoad) { | ||
| 84 | + this.onLoad(event) | ||
| 85 | + } | ||
| 86 | + }) | ||
| 87 | + .width(this.selfSize.width) | ||
| 88 | + .height(this.selfSize.height) | ||
| 89 | + } | ||
| 90 | + .id(this.insId) | ||
| 91 | + .onAreaChange(() => { | ||
| 92 | + this.updateLayout() | ||
| 93 | + }) | ||
| 94 | + .backgroundColor("#000000") | ||
| 95 | + .justifyContent(FlexAlign.Center) | ||
| 96 | + .height('100%') | ||
| 97 | + .width('100%') | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + updateLayout() { | ||
| 101 | + let info = componentUtils.getRectangleById(this.insId); | ||
| 102 | + if (info.size.width > 0 && info.size.height > 0 && this.videoHeight > 0 && this.videoWidth > 0) { | ||
| 103 | + if (info.size.width / info.size.height > this.videoWidth / this.videoHeight) { | ||
| 104 | + let scale = info.size.height / this.videoHeight; | ||
| 105 | + this.selfSize = new Size((this.videoWidth * scale / info.size.width) * 100 + "%", '100%'); | ||
| 106 | + } else { | ||
| 107 | + let scale = info.size.width / this.videoWidth; | ||
| 108 | + this.selfSize = new Size('100%', (this.videoHeight * scale / info.size.height) * 100 + "%"); | ||
| 109 | + } | ||
| 110 | + } | ||
| 111 | + } | ||
| 112 | +} |
| 1 | +import { PlayerConstants } from '../constants/PlayerConstants' | ||
| 2 | + | ||
| 3 | +export class DateFormatUtil { | ||
| 4 | + | ||
| 5 | + static secondToTime(seconds: number) { | ||
| 6 | + let time = '00:00' | ||
| 7 | + let hourUnit = 60 * 60; | ||
| 8 | + let hour = Math.floor(seconds / hourUnit); | ||
| 9 | + let minute = Math.floor((seconds - hour * hourUnit) / 60); | ||
| 10 | + let second = seconds - hour * hourUnit - minute * 60; | ||
| 11 | + if (hour > 0) { | ||
| 12 | + return `${DateFormatUtil.padding(hour.toString())}${':'}${DateFormatUtil.padding(minute.toString())}${':'}${DateFormatUtil.padding(second.toString())}`; | ||
| 13 | + } | ||
| 14 | + if (minute > 0) { | ||
| 15 | + return `${DateFormatUtil.padding(minute.toString())}${':'}${DateFormatUtil.padding(second.toString())}`; | ||
| 16 | + } else { | ||
| 17 | + return `${'00'}${':'}${DateFormatUtil.padding(second.toString())}`; | ||
| 18 | + } | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + static padding(num: string) { | ||
| 22 | + let length = 2; | ||
| 23 | + for (let len = (num.toString()).length; len < length; len = num.length) { | ||
| 24 | + num = `${'0'}${num}`; | ||
| 25 | + } | ||
| 26 | + return num; | ||
| 27 | + } | ||
| 28 | +} | ||
| 29 | + |
| 1 | +import hilog from '@ohos.hilog'; | ||
| 2 | + | ||
| 3 | +/** | ||
| 4 | + * Log level define | ||
| 5 | + * | ||
| 6 | + * @syscap SystemCapability.HiviewDFX.HiLog | ||
| 7 | + */ | ||
| 8 | +enum LogLevel { | ||
| 9 | + DEBUG = 3, | ||
| 10 | + INFO = 4, | ||
| 11 | + WARN = 5, | ||
| 12 | + ERROR = 6, | ||
| 13 | + FATAL = 7 | ||
| 14 | +} | ||
| 15 | + | ||
| 16 | +/** | ||
| 17 | + * Common log for all features. | ||
| 18 | + * | ||
| 19 | + * @param {string} prefix Identifies the log tag. | ||
| 20 | + */ | ||
| 21 | +export class Logger { | ||
| 22 | + private static domain: number = 0xFF00; | ||
| 23 | + private static prefix: string = 'MiguVideoApp'; | ||
| 24 | + private static format: string = `%{public}s, %{public}s`; | ||
| 25 | + | ||
| 26 | + /** | ||
| 27 | + * constructor. | ||
| 28 | + * | ||
| 29 | + * @param Prefix Identifies the log tag. | ||
| 30 | + * @param domain Domain Indicates the service domain, which is a hexadecimal integer ranging from 0x0 to 0xFFFFF. | ||
| 31 | + */ | ||
| 32 | + constructor(prefix: string = 'MiguVideoApp', domain: number = 0xFF00) { | ||
| 33 | + Logger.prefix = prefix; | ||
| 34 | + Logger.domain = domain; | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + static debug(...args: string[]) { | ||
| 38 | + hilog.debug(Logger.domain, Logger.prefix, Logger.format, args); | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + static info(...args: string[]) { | ||
| 42 | + hilog.info(Logger.domain, Logger.prefix, Logger.format, args); | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + static warn(...args: string[]) { | ||
| 46 | + hilog.warn(Logger.domain, Logger.prefix, Logger.format, args); | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + static error(...args: string[]) { | ||
| 50 | + hilog.error(Logger.domain, Logger.prefix, Logger.format, args); | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + static fatal(...args: string[]) { | ||
| 54 | + hilog.fatal(Logger.domain, Logger.prefix, Logger.format, args); | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + static isLoggable(level: LogLevel) { | ||
| 58 | + hilog.isLoggable(Logger.domain, Logger.prefix, level); | ||
| 59 | + } | ||
| 60 | +} | ||
| 61 | + | ||
| 62 | +export default new Logger('MiguVideoApp', 0xFF00) |
sight_harmony/wdPlayer/src/main/module.json5
0 → 100644
6.63 KB
11.1 KB
| 1 | +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; | ||
| 2 | + | ||
| 3 | +export default function localUnitTest() { | ||
| 4 | + describe('localUnitTest',() => { | ||
| 5 | + // Defines a test suite. Two parameters are supported: test suite name and test suite function. | ||
| 6 | + beforeAll(() => { | ||
| 7 | + // Presets an action, which is performed only once before all test cases of the test suite start. | ||
| 8 | + // This API supports only one parameter: preset action function. | ||
| 9 | + }); | ||
| 10 | + beforeEach(() => { | ||
| 11 | + // Presets an action, which is performed before each unit test case starts. | ||
| 12 | + // The number of execution times is the same as the number of test cases defined by **it**. | ||
| 13 | + // This API supports only one parameter: preset action function. | ||
| 14 | + }); | ||
| 15 | + afterEach(() => { | ||
| 16 | + // Presets a clear action, which is performed after each unit test case ends. | ||
| 17 | + // The number of execution times is the same as the number of test cases defined by **it**. | ||
| 18 | + // This API supports only one parameter: clear action function. | ||
| 19 | + }); | ||
| 20 | + afterAll(() => { | ||
| 21 | + // Presets a clear action, which is performed after all test cases of the test suite end. | ||
| 22 | + // This API supports only one parameter: clear action function. | ||
| 23 | + }); | ||
| 24 | + it('assertContain', 0, () => { | ||
| 25 | + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. | ||
| 26 | + let a = 'abc'; | ||
| 27 | + let b = 'b'; | ||
| 28 | + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. | ||
| 29 | + expect(a).assertContain(b); | ||
| 30 | + expect(a).assertEqual(a); | ||
| 31 | + }); | ||
| 32 | + }); | ||
| 33 | +} |
| 1 | -import { WDRouterPage } from './WDRouterPage' | ||
| 2 | -import { Action } from 'wdBean' | ||
| 3 | import ArrayList from '@ohos.util.ArrayList'; | 1 | import ArrayList from '@ohos.util.ArrayList'; |
| 2 | +import { Action } from 'wdBean' | ||
| 3 | +import { WDRouterPage } from './WDRouterPage' | ||
| 4 | 4 | ||
| 5 | interface HandleObject { | 5 | interface HandleObject { |
| 6 | handle: (action: Action) => (WDRouterPage | undefined) | 6 | handle: (action: Action) => (WDRouterPage | undefined) |
| @@ -8,7 +8,6 @@ interface HandleObject { | @@ -8,7 +8,6 @@ interface HandleObject { | ||
| 8 | } | 8 | } |
| 9 | 9 | ||
| 10 | export class Action2Page { | 10 | export class Action2Page { |
| 11 | - | ||
| 12 | private static handles: Record<string, ArrayList<HandleObject>> = {}; | 11 | private static handles: Record<string, ArrayList<HandleObject>> = {}; |
| 13 | 12 | ||
| 14 | static register(actionType: string, handle: (action: Action) => (WDRouterPage | undefined), priority: number = 0) { | 13 | static register(actionType: string, handle: (action: Action) => (WDRouterPage | undefined), priority: number = 0) { |
| @@ -49,15 +48,15 @@ export function registerRouter() { | @@ -49,15 +48,15 @@ export function registerRouter() { | ||
| 49 | // return WDRouterPage.webLoginPage | 48 | // return WDRouterPage.webLoginPage |
| 50 | // }) | 49 | // }) |
| 51 | 50 | ||
| 52 | - // Action2Page.register("JUMP_DETAIL_PAGE", (action) => { | ||
| 53 | - // if (action.params?.pageID == "296ff8a4b07d457cb15b6f9e5f433cc0") { | ||
| 54 | - // return WDRouterPage.tvLivePage | 51 | + Action2Page.register("JUMP_DETAIL_PAGE", (action: Action) => { |
| 52 | + // if (action.params?.detailPageType == 2 || action.params?.detailPageType == 6) { | ||
| 53 | + // return WDRouterPage.detailPlayLivePage | ||
| 55 | // } | 54 | // } |
| 56 | - // if (action.params?.detailPageType == 7 || action.params?.detailPageType == 8) { | ||
| 57 | - // return WDRouterPage.shortVideoDetail | ||
| 58 | - // } | ||
| 59 | - // return WDRouterPage.playDetail | ||
| 60 | - // }) | 55 | + if (action.params?.detailPageType == 7 || action.params?.detailPageType == 8) { |
| 56 | + return WDRouterPage.detailPlayShortVideoPage | ||
| 57 | + } | ||
| 58 | + return WDRouterPage.detailPlayVodPage | ||
| 59 | + }) | ||
| 61 | 60 | ||
| 62 | Action2Page.register("JUMP_H5_BY_WEB_VIEW", (action) => { | 61 | Action2Page.register("JUMP_H5_BY_WEB_VIEW", (action) => { |
| 63 | return WDRouterPage.defaultWebPage | 62 | return WDRouterPage.defaultWebPage |
| @@ -22,4 +22,10 @@ export class WDRouterPage { | @@ -22,4 +22,10 @@ export class WDRouterPage { | ||
| 22 | static defaultWebPage = new WDRouterPage("entry", "ets/pages/web/DefaultWebPage"); | 22 | static defaultWebPage = new WDRouterPage("entry", "ets/pages/web/DefaultWebPage"); |
| 23 | // 电子报页面 | 23 | // 电子报页面 |
| 24 | static eNewspaper = new WDRouterPage("entry", "ets/pages/ENewspaper") | 24 | static eNewspaper = new WDRouterPage("entry", "ets/pages/ENewspaper") |
| 25 | + // 短视频详情页 | ||
| 26 | + static detailPlayShortVideoPage = new WDRouterPage("wdDetailPlayShortVideo", "ets/pages/DetailPlayShortVideoPage"); | ||
| 27 | + // 点播详情页 | ||
| 28 | + static detailPlayVodPage = new WDRouterPage("wdDetailPlayVod", "ets/pages/DetailPlayVodPage"); | ||
| 29 | + // 直播详情页 | ||
| 30 | + static detailPlayLivePage = new WDRouterPage("wdDetailPlayLive", "ets/pages/DetailPlayLivePage"); | ||
| 25 | } | 31 | } |
-
Please register or login to post a comment