1/* 2 * Copyright (c) 2021-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 */ 15 16import {isNfcAvailable} from '../../../../../../../../common/src/main/ets/default/Constants'; 17import Log from '../../../../../../../../common/src/main/ets/default/Log' 18import { StatusBarData, StatusBarBackgroundData, StatusBarConfig } from '../common/Constants' 19import { FASlotName } from '../../../../../../../../common/src/main/ets/default/Constants' 20import { TintContentInfo } from '../../../../../../../../common/src/main/ets/default/TintStateManager' 21import StyleConfigurationCommon, { CommonStyle 22} from '../../../../../../../../common/src/main/ets/default/StyleConfiguration' 23import StyleConfiguration, { StatusBarNotificationIconStyle, VerticalStatusBarItemLoadComponentStyle 24} from '../common/StyleConfiguration' 25import ViewModel from '../viewmodel/StatusBarVM' 26import { StringArray } from '../viewmodel/StatusBarVM' 27import IconItemComponent from './IconItemComponent' 28import BatteryIcon from '../../../../../../../batterycomponent/src/main/ets/default/pages/batteryIcon' 29import ClockIcon from '../../../../../../../clockcomponent/src/main/ets/default/pages/clockIcon' 30import AirplaneIcon from '../../../../../../../airplanecomponent/src/main/ets/default/pages/StatusBarIconItemAirplaneComponent' 31import WifiIcon from '../../../../../../../wificomponent/src/main/ets/default/pages/wifiIcon' 32import BluetoothIcon from '../../../../../../../bluetoothcomponent/src/main/ets/com/ohos/pages/StatusBarIconItemBluetoothComponent' 33import SignalIcon from '../../../../../../../signalcomponent/src/main/ets/default/pages/signalIcon' 34import CapsuleIcon from '../../../../../../../capsulecomponent/src/main/ets/default/pages/CapsuleIcon' 35import LocationIcon from '../../../../../../../locationcomponent/src/main/ets/com/ohos/pages/StatusBarIconItemLocationComponent' 36import RingModeIcon from '../../../../../../../ringmodecomponent/src/main/ets/com/ohos/pages/StatusBarIconItemRingModeComponent' 37import NfcIcon from '../../../../../../../nfccomponent/src/main/ets/com/ohos/pages/StatusBarIconItemNFComponent' 38import { NotificationItemData } from '@ohos/common'; 39 40const TAG = 'StatusBarComponent' 41const TAG_StatusBarGroup = 'StatusBarGroup' 42const TAG_VerticalStatusBarItemLoadComponent = 'VerticalStatusBarItemLoadComponent' 43const TAG_StatusBarItemLoadComponent = 'StatusBarItemLoadComponent' 44const TAG_StatusBarEmptyIcon = 'StatusBarEmptyIcon' 45const TAG_StatusBarNotificationIcon = 'StatusBarNotificationIcon' 46const TAG_StatusBarBackground = 'StatusBarBackground' 47 48interface Item { 49 index: number; 50 data: NotificationItemData[]; 51} 52 53@Component 54export default struct StatusBarComponent { 55 private mStatusBarComponentConfig: StatusBarConfig | undefined = undefined 56 @State mStatusBarData: StatusBarData = ViewModel.getStatusBarData() 57 private moduleName: string = '' 58 59 aboutToAppear() { 60 AppStorage.SetOrCreate('size', $r("app.float.status_bar_margin_left_right")); 61 Log.showInfo(TAG, `aboutToAppear Start, mStatusBarComponentConfig: ${JSON.stringify(this.mStatusBarComponentConfig)}`); 62 this.initViewModel(this.moduleName); 63 } 64 65 aboutToDisappear() { 66 Log.showInfo(TAG, `aboutToDisappear`); 67 } 68 69 initViewModel(moduleName: string) { 70 Log.showInfo(TAG, `initViewModel`); 71 ViewModel.initViewModel(this.mStatusBarComponentConfig, moduleName); 72 } 73 74 build() { 75 Stack() { 76 StatusBarBackground() 77 if (this.mStatusBarData.showHorizontal) { 78 Row() { 79 StatusBarGroup({ 80 index: 0, 81 mLayoutWeight: 1, 82 mAlignItems: HorizontalAlign.Start 83 }) 84 StatusBarGroup({ 85 index: 1, 86 mLayoutWeight: 0, 87 mAlignItems: HorizontalAlign.Center 88 }) 89 StatusBarGroup({ 90 index: 2, 91 mLayoutWeight: 1, 92 mAlignItems: HorizontalAlign.End 93 }) 94 } 95 .padding({ left: $r('app.float.status_bar_padding_start'), right: $r('app.float.status_bar_padding_end') }) 96 .width('100%') 97 .height('100%') 98 } else { 99 Column() { 100 StatusBarGroup({ 101 index: 0, 102 mLayoutWeight: 1, 103 mAlignItems: VerticalAlign.Center 104 }) 105 StatusBarGroup({ 106 index: 1, 107 mLayoutWeight: 0, 108 mAlignItems: VerticalAlign.Center 109 }) 110 StatusBarGroup({ 111 index: 2, 112 mLayoutWeight: 1, 113 mAlignItems: VerticalAlign.Center 114 }) 115 } 116 .width('100%') 117 .height('100%') 118 } 119 } 120 .width('100%') 121 .height('100%') 122 } 123} 124 125@Component 126struct StatusBarBackground { 127 @State mStatusBarData: StatusBarData = ViewModel.getStatusBarData() 128 @State mBackgroundDatas: StatusBarBackgroundData[] = ViewModel.getBackgroundDatas() 129 130 aboutToAppear() { 131 Log.showInfo(TAG_StatusBarBackground, `aboutToAppear`); 132 } 133 134 aboutToDisappear() { 135 Log.showInfo(TAG_StatusBarBackground, `aboutToDisAppear`); 136 } 137 138 build() { 139 if (this.mStatusBarData.showHorizontal) { 140 Row() { 141 ForEach(this.mBackgroundDatas, (data: StatusBarBackgroundData) => { 142 if (data.width > 0) { 143 Column() { 144 } 145 .width(data.width + 'px') 146 .height('100%') 147 .backgroundColor(data.backgroundColor) 148 } 149 }) 150 } 151 .width('100%') 152 .height('100%') 153 } else { 154 Column() { 155 ForEach(this.mBackgroundDatas, (data: StatusBarBackgroundData) => { 156 if (data.width > 0) { 157 Column() { 158 } 159 .width('100%') 160 .height(data.width + 'px') 161 .backgroundColor(data.backgroundColor) 162 } 163 }) 164 } 165 .width('100%') 166 .height('100%') 167 } 168 } 169} 170 171@Component 172struct StatusBarGroup { 173 @StorageLink('StatusBarLayout') mStatusBarLayout: string[][] = [[], [], []] 174 private mLayoutWeight: number = 1 175 private mAlignItems: number = HorizontalAlign.Center; 176 private index: number = -1; 177 @State mStatusBarData: StatusBarData = ViewModel.getStatusBarData() 178 179 aboutToAppear() { 180 Log.showInfo(TAG_StatusBarGroup, `aboutToAppear, mLayoutWeight: ${this.mLayoutWeight} mAlignItems: ${this.mAlignItems} `); 181 } 182 183 aboutToDisappear() { 184 Log.showInfo(TAG_StatusBarGroup, `aboutToDisAppear`); 185 } 186 187 build() { 188 if (this.mStatusBarData.showHorizontal) { 189 Column() { 190 Row() { 191 ForEach(this.mStatusBarLayout[this.index], (componentName: string) => { 192 StatusBarItemLoadComponent({ 193 mComponentName: componentName 194 }) 195 }, (componentName: string) => componentName) 196 }.height('100%') 197 } 198 .alignItems(this.mAlignItems) 199 .layoutWeight(this.mLayoutWeight) 200 .height('100%') 201 } else { 202 Row() { 203 Column() { 204 ForEach(this.mStatusBarLayout[this.index], (componentName: string) => { 205 VerticalStatusBarItemLoadComponent({ 206 mComponentName: componentName 207 }) 208 }, (componentName: string) => componentName) 209 }.width('100%') 210 .alignItems(HorizontalAlign.Start) 211 } 212 .alignItems(this.mAlignItems) 213 .width('100%') 214 .layoutWeight(this.mLayoutWeight) 215 } 216 } 217} 218 219@Component 220struct VerticalStatusBarItemLoadComponent { 221 private mComponentName: string = '' 222 @State mComponentHeight: number = 0 223 @State style: VerticalStatusBarItemLoadComponentStyle = StyleConfiguration.getVerticalStatusBarItemLoadComponentStyle() 224 225 aboutToAppear() { 226 Log.showInfo(TAG_VerticalStatusBarItemLoadComponent, `aboutToAppear, mComponentName: ${this.mComponentName}`); 227 } 228 229 aboutToDisappear() { 230 Log.showInfo(TAG_VerticalStatusBarItemLoadComponent, `aboutToDisAppear, mComponentName: ${this.mComponentName}`); 231 } 232 233 build() { 234 Row() { 235 StatusBarItemLoadComponent({ 236 mComponentName: this.mComponentName 237 }) 238 } 239 .height(this.mComponentHeight + 'px') 240 .onAreaChange((e, e2) => { 241 Log.showInfo(TAG_VerticalStatusBarItemLoadComponent, `onAreaChange, mComponentName: ${this.mComponentName} e: ${JSON.stringify(e)} e2: ${JSON.stringify(e2)}`); 242 this.mComponentHeight = e2.width > 0 ? this.style.statusBarVerticalComponentHeight : 0 243 Log.showInfo(TAG_VerticalStatusBarItemLoadComponent, `onAreaChange, mComponentName: ${this.mComponentName} mComponentHeight: ${this.mComponentHeight}`); 244 }) 245 } 246} 247 248@Component 249struct StatusBarItemLoadComponent { 250 private mComponentName: string = '' 251 aboutToAppear() { 252 Log.showInfo(TAG_StatusBarItemLoadComponent, `aboutToAppear, mComponentName: ${this.mComponentName} `) 253 } 254 255 aboutToDisappear() { 256 Log.showInfo(TAG_StatusBarGroup, `aboutToDisAppear, mComponentName: ${this.mComponentName} `) 257 } 258 259 build() { 260 Row() { 261 if (this.mComponentName == FASlotName.EMPTY) { 262 StatusBarEmptyIcon() 263 } else if (this.mComponentName == FASlotName.WIFI) { 264 WifiIcon() 265 } else if (this.mComponentName == FASlotName.BLUETOOTH) { 266 BluetoothIcon() 267 } else if (this.mComponentName == FASlotName.SIGNAL) { 268 SignalIcon() 269 } else if (this.mComponentName == FASlotName.CLOCK) { 270 ClockIcon() 271 } else if (this.mComponentName == FASlotName.BATTERY) { 272 BatteryIcon() 273 } else if (this.mComponentName == FASlotName.AIR_PLANE) { 274 AirplaneIcon() 275 } else if (this.mComponentName == FASlotName.CAPSULE) { 276 CapsuleIcon() 277 } else if (this.mComponentName == FASlotName.NOTIFICATION) { 278 StatusBarNotificationIcon() 279 } else if (this.mComponentName == FASlotName.LOCATION) { 280 LocationIcon() 281 } else if (this.mComponentName == FASlotName.RING_MODE) { 282 RingModeIcon() 283 } else if (this.mComponentName == FASlotName.NFC) { 284 if (isNfcAvailable()) { 285 NfcIcon() 286 } 287 } else { 288 IconItemComponent({ 289 keyId: this.mComponentName 290 }) 291 } 292 }.height('100%') 293 .onAreaChange((e: Area, e2: Area) => { 294 Log.showInfo(TAG_StatusBarItemLoadComponent, `onAreaChange, componentName: ${this.mComponentName}}, new area: ${JSON.stringify(e2)} `) 295 ViewModel.updateComponentArea(this.mComponentName, e2) 296 }) 297 } 298} 299 300@Component 301struct StatusBarEmptyIcon { 302 @StorageLink('StatusBarEmptyWidth') mStatusBarEmptyWidth: number = 0 303 @State mTintContentInfo: TintContentInfo = ViewModel.getEmptyTintContentInfo() 304 305 aboutToAppear() { 306 Log.showInfo(TAG_StatusBarEmptyIcon, `aboutToAppear, mStatusBarEmptyWidth: ${this.mStatusBarEmptyWidth} `) 307 } 308 309 aboutToDisappear() { 310 Log.showInfo(TAG_StatusBarEmptyIcon, `aboutToDisAppear`); 311 } 312 313 build() { 314 Row().width(this.mStatusBarEmptyWidth).height('100%') 315 } 316} 317 318@Component 319struct StatusBarNotificationIcon { 320 @StorageLink('notificationList') notificationList: NotificationItemData[][] = [] 321 @StorageLink('StatusCoefficient') StatusCoefficient: number = 1.0 322 @State mTintContentInfo: TintContentInfo = ViewModel.getNotificationTintContentInfo() 323 @State styleCommon: CommonStyle = StyleConfigurationCommon.getCommonStyle() 324 @State style: StatusBarNotificationIconStyle = StyleConfiguration.getStatusBarNotificationIconStyle() 325 326 aboutToAppear() { 327 Log.showInfo(TAG_StatusBarNotificationIcon, `aboutToAppear`); 328 } 329 330 aboutToDisappear() { 331 Log.showInfo(TAG_StatusBarNotificationIcon, `aboutToDisAppear`); 332 } 333 334 build() { 335 Row() { 336 if (this.notificationList.length > 0) { 337 Row().height(1).width(this.styleCommon.statusBarMarginLeftRight) 338 } 339 if (this.notificationList.length > 3) { 340 ForEach(this.notificationList.slice(0, 3), (item: NotificationItemData[]) => { 341 Image(item[0].smallIcon) 342 .objectFit(ImageFit.ScaleDown) 343 .height(this.style.iconHeight) 344 .width(this.style.iconWidth) 345 .margin({ right: this.style.iconSpace }) 346 .fillColor(this.mTintContentInfo.contentColor) 347 }) 348 Row() { 349 Text('...') 350 .fontSize(this.styleCommon.statusBarFontSize) 351 .fontColor(this.mTintContentInfo.contentColor) 352 } 353 } else { 354 ForEach(this.notificationList.map((item, index1) => { 355 let res: Item = { index: index1, data: item } 356 return res 357 }), (res: Item) => { 358 if (res.index > 0) { 359 Row().height(1).width(this.style.iconSpace) 360 } 361 Image(res.data[0].smallIcon) 362 .objectFit(ImageFit.ScaleDown) 363 .height(this.style.iconHeight) 364 .width(this.style.iconWidth) 365 .fillColor(this.mTintContentInfo.contentColor) 366 }) 367 } 368 if (this.notificationList.length > 0) { 369 Row().height(1).width(this.styleCommon.statusBarMarginLeftRight) 370 } 371 } 372 .height('100%') 373 } 374} 375