1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15import { Browser, LoadingStatus, WebObject } from '../model/Browser' 16import Logger from '../model/Logger' 17 18const TAG: string = '[TitleBar]' 19const BUTTON_WIDTH: number = 22 20const BUTTON_RADIUS: number = 4 21const DOWN_COLOR: string = '#e4e4e4' 22const UP_COLOR: string = '#00000000' 23const PAD_USER_AGENT: string = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTMl, like Gecko) Chrome/92.0.4515.105 Safari/537.36' 24const PHONE_USER_AGENT: string = 'Mozilla/5.0 (Linux; Android 9; VRD-AL10; HMSCore 6.3.0.331) AppleWebKit/537.36 (KHTMl, like Gecko) Chrome/92.0.4515.105 HuaweiBrowser/12.0.4.1 Mobile Safari/537.36' 25 26@Component 27export struct TabletTitle { 28 @Link browser: Browser; 29 @State inputValue: string = '' 30 @State arrayIndex: number = 0 31 private addr: string = '' 32 private navigationButton: Array<{ 33 imageSrc: Resource, 34 id: number 35 }> = [ 36 { 37 imageSrc: $r('app.media.ic_public_back'), 38 id: 1 39 }, 40 { 41 imageSrc: $r('app.media.ic_public_advance'), 42 id: 2 43 }, 44 { 45 imageSrc: $r('app.media.ic_public_refresh'), 46 id: 3 47 }, 48 { 49 imageSrc: $r('app.media.ic_public_home'), 50 id: 4 51 }, 52 ] 53 private actionButton: Array<{ 54 imageSrc: Resource, 55 id: number 56 }> = [ 57 { 58 imageSrc: $r('app.media.submit'), 59 id: 5 60 }, 61 { 62 imageSrc: $r('app.media.ic_public_add'), 63 id: 6 64 }, 65 ] 66 67 build() { 68 Row() { 69 ForEach(this.navigationButton, item => { 70 Button({ type: ButtonType.Normal }) { 71 Image(item.imageSrc) 72 } 73 .margin(8) 74 .width(BUTTON_WIDTH) 75 .height(BUTTON_WIDTH) 76 .backgroundColor(this.arrayIndex === item.id ? DOWN_COLOR : UP_COLOR) 77 .borderRadius(BUTTON_RADIUS) 78 .flexShrink(0) 79 .onTouch((event: TouchEvent) => { 80 if (event.type === TouchType.Down) { 81 this.arrayIndex = item.id 82 } 83 84 if (event.type === TouchType.Up) { 85 this.arrayIndex = 0 86 } 87 }) 88 .onClick((event: ClickEvent) => { 89 switch (item.id) { 90 case 1: 91 this.browser.Back() 92 break; 93 case 2: 94 this.browser.Forward() 95 break; 96 case 3: 97 this.browser.Refresh() 98 break; 99 case 4: 100 this.browser.webControllerArray[this.browser.tabArrayIndex].controller.loadUrl({ 101 url: $rawfile('pad.html') 102 }) 103 break; 104 } 105 }) 106 }, item => item.id) 107 108 TextInput({ placeholder: '输入网址...', text: this.browser.inputValue }) 109 .placeholderFont({ size: 18, weight: 500 }) 110 .fontSize(18) 111 .margin(2) 112 .width('51%') 113 .onChange((value: string) => { 114 this.addr = value 115 }) 116 .onSubmit((enterKey: EnterKeyType) => { 117 Logger.info(TAG, `onSubmit`) 118 if (this.addr.length !== 0) { 119 this.browser.webControllerArray[this.browser.tabArrayIndex].controller.loadUrl({ 120 url: `https://${this.addr}` 121 }) 122 this.addr = '' 123 } 124 }) 125 126 ForEach(this.actionButton, item => { 127 Button({ type: ButtonType.Normal }) { 128 Image(item.imageSrc) 129 } 130 .margin(8) 131 .width(BUTTON_WIDTH) 132 .height(BUTTON_WIDTH) 133 .backgroundColor(this.arrayIndex === item.id ? DOWN_COLOR : UP_COLOR) 134 .borderRadius(BUTTON_RADIUS) 135 .flexShrink(0) 136 .onTouch((event: TouchEvent) => { 137 if (event.type === TouchType.Down) { 138 this.arrayIndex = item.id 139 } else if (event.type === TouchType.Up) { 140 this.arrayIndex = 0 141 } 142 }) 143 .onClick((event: ClickEvent) => { 144 if (this.arrayIndex === 5) { 145 this.browser.loadUrl(this.addr) 146 this.addr = '' 147 } else if (this.arrayIndex === 6) { 148 Logger.info(TAG, `add tab`) 149 this.browser.addTab() 150 } 151 }) 152 }, item => item.id) 153 } 154 .width('100%') 155 .padding({ right: 5 }) 156 } 157} 158 159@Component 160export struct BrowserTabs { 161 @Link browser: Browser; 162 @State tabButtonIndex: number = -1; 163 164 build() { 165 Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Start }) { 166 ForEach(this.browser.webArray, item => { 167 Row() { 168 Row() { 169 Text('主页') 170 }.width('100%').flexShrink(1).justifyContent(FlexAlign.Center).height('100%') 171 172 Button({ type: ButtonType.Normal }) { 173 Image($r('app.media.ic_public_cancel_filled')).width(24).height(24) 174 } 175 .backgroundColor(this.tabButtonIndex == item.key ? DOWN_COLOR : '#00000000') 176 .margin({ right: 2 }) 177 .width(33) 178 .height(33) 179 .borderRadius(5) 180 .onTouch((event: TouchEvent) => { 181 if (event.type === TouchType.Down) { 182 this.tabButtonIndex = item.key 183 } else if (event.type == TouchType.Up) { 184 this.tabButtonIndex = -1 185 } 186 }) 187 .onClick((event: ClickEvent) => { 188 if (this.browser.webArray.length > 1) { 189 this.browser.deleteTab(this.tabButtonIndex) 190 } 191 }) 192 }.width(180).height('100%').backgroundColor(this.browser.tabArrayIndex == item.key ? '#ffffff' : '#ececec') 193 .onClick((event: ClickEvent) => { 194 Logger.info(TAG, `key= ${item.key}`) 195 this.browser.setTabArrayIndex(item.key) 196 this.browser.tabsController.changeIndex(item.key) 197 }) 198 199 Divider().vertical(true).color('#c6c6c6') 200 }, item => item.timestamp.toString()) 201 }.height(33).flexShrink(0).backgroundColor('#ececec') 202 } 203} 204 205@Component 206export struct WebTab { 207 @Link browser: Browser; 208 @Link isPhone: boolean; 209 isRegistered: boolean = false 210 testObj = { 211 test: (addr) => { 212 Logger.info(TAG, `addr= ${this.browser.tabArrayIndex}`) 213 this.browser.webControllerArray[this.browser.tabArrayIndex].controller.loadUrl({ url: `https://${addr}` }) 214 }, 215 searchWord: (word: string) => { 216 Logger.info(`search word= ${word}`) 217 let code = encodeURI(word) 218 this.browser.webControllerArray[this.browser.tabArrayIndex].controller.loadUrl({ 219 url: `https://www.bing.com/search?q=${code}` 220 }) 221 } 222 } 223 224 build() { 225 Tabs({ barPosition: BarPosition.Start, controller: this.browser.tabsController }) { 226 ForEach(this.browser.webArray, item => { 227 TabContent() { 228 Web({ 229 src: this.isPhone ? $rawfile('phone.html') : $rawfile('pad.html'), 230 controller: this.browser.webControllerArray[item.key].controller 231 }) 232 .javaScriptAccess(true) 233 .fileAccess(true) 234 .domStorageAccess(true) 235 .userAgent(this.isPhone ? PHONE_USER_AGENT : PAD_USER_AGENT) 236 .onPageBegin((event) => { 237 Logger.info(TAG, `onPageBegin= ${JSON.stringify(event)}`) 238 this.browser.loadingStatus = LoadingStatus.LOADING 239 }) 240 .onPageEnd((event) => { 241 Logger.info(TAG, `onPageEnd= ${JSON.stringify(event)}`) 242 if (item.key < this.browser.webControllerArray.length && this.browser.webControllerArray[item.key].controller) { 243 this.browser.webControllerArray[item.key].controller.runJavaScript({ script: 'adapterDevice()' }) 244 this.browser.loadingStatus = LoadingStatus.END 245 this.registerFunc(this.browser.webControllerArray[item.key]) 246 if (event.url.startsWith('http')) { 247 this.browser.inputValue = event.url 248 } else { 249 this.browser.inputValue = '' 250 } 251 } 252 }) 253 .onProgressChange((event) => { 254 Logger.info(TAG, `onProgressChange`) 255 this.browser.progress = event.newProgress 256 if (this.browser.progress === 100) { 257 this.browser.hideProgress = true 258 } else { 259 this.browser.hideProgress = false 260 } 261 }) 262 } 263 }, item => item.timestamp.toString()) 264 } 265 .barHeight(0) 266 .scrollable(false) 267 } 268 269 registerFunc(webObject: WebObject) { 270 if (!webObject.isRegistered) { 271 Logger.info(TAG, `registerFunc`) 272 webObject.controller.registerJavaScriptProxy({ 273 object: this.testObj, name: 'etsObj', methodList: ['test', 'searchWord'] 274 }) 275 webObject.isRegistered = true 276 webObject.controller.refresh() 277 } 278 } 279}