• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 Log from '../../../../../../../../common/src/main/ets/default/Log';
17import EventManager from '../../../../../../../../common/src/main/ets/default/event/EventManager';
18import { obtainLocalEvent } from '../../../../../../../../common/src/main/ets/default/event/EventUtil';
19import AbilityManager from '../../../../../../../../common/src/main/ets/default/abilitymanager/abilityManager';
20import createOrGet from '../../../../../../../../common/src/main/ets/default/SingleInstanceHelper';
21import WindowManager, { WindowType } from '../../../../../../../../common/src/main/ets/default/WindowManager';
22import TintStateManager, { TintState, TintContentInfo, getOrCreateTintContentInfo
23} from '../../../../../../../../common/src/main/ets/default/TintStateManager';
24import { FASlotName, Rect } from '../../../../../../../../common/src/main/ets/default/Constants';
25import { PluginType, PluginComponentData
26} from '../../../../../../../../common/src/main/ets/plugindatasource/common/Constants';
27import StyleConfigurationCommon from '../../../../../../../../common/src/main/ets/default/StyleConfiguration';
28import { StatusBarData, StatusBarBackgroundData, StatusBarComponentGroupContentData, StatusBarComponentData,
29  StatusBarConfig } from '../common/Constants';
30import StatusBarService from '../model/StatusBarService';
31import display from '@ohos.display';
32export const STATUS_BAR_LAYOUT_KEY = 'StatusBarLayout';
33
34export const STATUS_BAR_EMPTY_WIDTH_KEY = 'StatusBarEmptyWidth';
35
36const TAG = 'StatusBarVM';
37
38// @ts-ignore
39@Observed
40export class StringArray extends Array<string> {}
41
42export class StatusBarVM {
43  mIsStart = false;
44  mStatusBarLayout: string[][] = [[], [], []];
45  mStatusBarEmptyWidth;
46  mUseCount = 0;
47  mStatusBarEnable = true;
48  mBackgroundDatas: StatusBarBackgroundData[];
49  mStatusBarData: StatusBarData = { ...new StatusBarData() };
50  mComponentAreaMap: Map<string, Rect> = new Map();
51  mComponentGroupContentDatas: StatusBarComponentGroupContentData[] = [
52    new StatusBarComponentGroupContentData(), new StatusBarComponentGroupContentData(), new StatusBarComponentGroupContentData()];
53  mEmptyTintContentInfo: TintContentInfo = getOrCreateTintContentInfo(FASlotName.EMPTY);
54  mNotificationTintContentInfo: TintContentInfo = getOrCreateTintContentInfo(FASlotName.NOTIFICATION);
55  mUseInWindowName: WindowType = WindowType.STATUS_BAR;
56
57  constructor() {
58    Log.showInfo(TAG, 'constructor');
59    this.mStatusBarData = AppStorage.SetAndLink(TAG + '_StatusBarData', this.mStatusBarData).get();
60    StatusBarService.setStatusBarData(this.mStatusBarData);
61
62    this.mStatusBarLayout = AppStorage.SetAndLink(STATUS_BAR_LAYOUT_KEY, this.mStatusBarLayout).get();
63    this.mStatusBarEmptyWidth = AppStorage.SetAndLink(STATUS_BAR_EMPTY_WIDTH_KEY, 0);
64
65    Log.showInfo(TAG, 'constructor mStatusBarLayout: ' + JSON.stringify(this.mStatusBarLayout));
66
67    let defaultBackgroundDatas: StatusBarBackgroundData[] = [];
68    defaultBackgroundDatas.push(new StatusBarBackgroundData());
69    defaultBackgroundDatas.push(new StatusBarBackgroundData());
70    defaultBackgroundDatas.push(new StatusBarBackgroundData());
71    if (this.mStatusBarData.showHorizontal) {
72      defaultBackgroundDatas[0].width = this.mStatusBarData.realWidth;
73    } else {
74      defaultBackgroundDatas[0].width = this.mStatusBarData.realHeight;
75    }
76    this.mBackgroundDatas = AppStorage.SetAndLink(TAG + '_BackgroundDatas', defaultBackgroundDatas).get();
77
78    StatusBarService.registerListener(this);
79  }
80
81  install(): void {
82    Log.showInfo(TAG, `install, useCount: ${this.mUseCount}`);
83    if (!this.mUseCount) {
84      TintStateManager.getInstance().registerListener('status', this);
85    }
86    this.mUseCount++;
87  }
88
89  uninstall(): void {
90    Log.showInfo(TAG, `uninstall, useCount: ${this.mUseCount}`);
91    this.mUseCount--;
92    if (this.mUseCount) {
93      TintStateManager.getInstance().unregisterListener('status');
94    }
95  }
96
97  initViewModel(config: StatusBarConfig, moduleName: string): void {
98    if (this.mIsStart) {
99      return;
100    }
101    Log.showInfo(TAG, `initViewModel, config: ${JSON.stringify(config)}`);
102    this.mIsStart = true;
103
104    this.install();
105    StatusBarService.startService(config, moduleName);
106  }
107
108  setStatusBarLayout(layout: string[][]): void {
109    Log.showInfo(TAG, `setStatusBarLayout, layout: ${JSON.stringify(layout)}`);
110    for (let i = 0;i < layout.length; i++) {
111      if (JSON.stringify(layout[i]) != JSON.stringify(this.mStatusBarLayout[i])) {
112        this.mStatusBarLayout[i] = layout[i];
113      }
114    }
115    Log.showInfo(TAG, `setStatusBarLayout, mStatusBarLayout: ${JSON.stringify(this.mStatusBarLayout)}`);
116  }
117
118  setStatusBarEmptyWidth(width: number): void{
119    Log.showInfo(TAG, `setStatusBarEmptyWidth, width: ${width}`);
120    this.mStatusBarEmptyWidth.set(width);
121  }
122
123  setItemData(id: string, itemData: StatusBarComponentData): void{
124    Log.showInfo(TAG, `setItemData, id: ${id} itemData: ${JSON.stringify(itemData)}`);
125    let storageKey: string = 'StatusBar_' + id;
126    if (itemData) {
127      AppStorage.SetOrCreate(storageKey, itemData);
128    } else {
129      let deleteRs: boolean = AppStorage.Delete(storageKey);
130      Log.showInfo(TAG, `setItemData, AppStorage.Delete rs: ${deleteRs} `);
131    }
132    this.setPluginData(id, itemData);
133  }
134
135  setPluginData(id: string, itemData: StatusBarComponentData): void{
136    Log.showInfo(TAG, `setPluginData, itemData: ${JSON.stringify(itemData)}`);
137    if (itemData && itemData.pluginType == PluginType.PLUGIN_COMPONENT) {
138      let data = undefined;
139      if (itemData.actionData.pluginData && itemData.actionData.pluginData.data) {
140        data = JSON.parse(JSON.stringify(itemData.actionData.pluginData.data));
141        if (Object.keys(data).length > 0) {
142          this.setPluginDataFontColorSize(id, data);
143        }
144      }
145      let pluginData = this.getPluginData(id);
146      pluginData.template = itemData.actionData.pluginData.template;
147      pluginData.data = data;
148      Log.showInfo(TAG, `setPluginData, pluginData: ${JSON.stringify(pluginData)} `);
149    } else {
150      let storageKey = 'StatusBar_PluginIcon_' + id;
151      if (AppStorage.Has(storageKey)) {
152        let deleteRs: boolean = AppStorage.Delete(storageKey);
153        Log.showInfo(TAG, `setPluginData, AppStorage.Delete rs: ${String(deleteRs)} `);
154      }
155    }
156  }
157
158  getPluginData(id: string): PluginComponentData {
159    Log.showInfo(TAG, `getPluginData, id: ${id}`);
160    let storageKey = 'StatusBar_PluginIcon_' + id;
161    if (!AppStorage.Has(storageKey)) {
162      AppStorage.SetOrCreate(storageKey, new PluginComponentData());
163    }
164    return AppStorage.Get(storageKey);
165  }
166
167  setPluginDataFontColorSize(id: string, data): void {
168    if (!data['fontSize']) {
169      data['fontSize'] = StyleConfigurationCommon.getCommonStyle().statusBarFontSize;
170    }
171    if (!data['fontColor']) {
172      if (!this.mComponentAreaMap.get(id)) {
173        this.changeComponentContent(id, { left: 0, top: 0, width: 0, height: 0 });
174      }
175      data['fontColor'] = this.getPluginTintContentInfo(id).contentColor;
176    }
177  }
178
179  onTintStateChange(tintState: TintState): void {
180    Log.showInfo(TAG, `onTintStateChange, tintState: ${JSON.stringify(tintState)}`);
181    if (typeof (tintState.isEnable) == 'boolean') {
182      this.setStatusBarEnable(tintState.isEnable);
183    }
184    if (tintState.backgroundColor) {
185      this.changeBackground(tintState);
186    }
187    if (tintState.contentColor) {
188      this.changeContent(tintState);
189    }
190  }
191
192  setStatusBarEnable(isEnable: boolean): void {
193    Log.showInfo(TAG, `setStatusBarEnable, isEnable ${isEnable}`);
194    if (this.mStatusBarEnable == isEnable) {
195      return;
196    }
197    this.mStatusBarEnable = isEnable;
198    this.mStatusBarEnable ? WindowManager.showWindow(WindowType.STATUS_BAR).then(() => {
199    }).catch((err) => {
200    }) : WindowManager.hideWindow(WindowType.STATUS_BAR).then(() => {
201    }).catch((err) => {
202    });
203  }
204
205  changeBackground(tintState: TintState): void{
206    Log.showInfo(TAG, `changeBackground, backgroundColor: ${tintState.backgroundColor} region: ${JSON.stringify(tintState.region)}`);
207    let data = new StatusBarBackgroundData();
208    data.backgroundColor = tintState.backgroundColor;
209    if (this.mStatusBarData.showHorizontal) {
210      if (!tintState.region) {
211        data.width = this.mStatusBarData.realWidth;
212        this.mBackgroundDatas[0] = data;
213        this.mBackgroundDatas[1] = new StatusBarBackgroundData();
214        this.mBackgroundDatas[2] = new StatusBarBackgroundData();
215      } else {
216        data.width = tintState.region.width;
217        if (tintState.region.left == this.mStatusBarData.left) {
218          this.mBackgroundDatas[0] = data;
219        } else if ((tintState.region.left + tintState.region.width) == (this.mStatusBarData.left + this.mStatusBarData.realWidth)) {
220          this.mBackgroundDatas[2] = data;
221        } else {
222          this.mBackgroundDatas[1] = data;
223        }
224      }
225    } else {
226      if (!tintState.region) {
227        data.width = this.mStatusBarData.realHeight;
228        this.mBackgroundDatas[0] = data;
229        this.mBackgroundDatas[1] = new StatusBarBackgroundData();
230        this.mBackgroundDatas[2] = new StatusBarBackgroundData();
231      } else {
232        data.width = tintState.region.height;
233        if (tintState.region.top == this.mStatusBarData.top) {
234          this.mBackgroundDatas[0] = data;
235        } else if ((tintState.region.top + tintState.region.height) == (this.mStatusBarData.top + this.mStatusBarData.realHeight)) {
236          this.mBackgroundDatas[2] = data;
237        } else {
238          this.mBackgroundDatas[1] = data;
239        }
240      }
241    }
242    Log.showInfo(TAG, `changeBackground, data: ${JSON.stringify(data)}`);
243  }
244
245  changeContent(tintState: TintState): void{
246    Log.showInfo(TAG, `changeContent, contentColor: ${tintState.contentColor} region: ${JSON.stringify(tintState.region)}`);
247    let data = new StatusBarComponentGroupContentData();
248    data.contentColor = tintState.contentColor;
249    if (this.mStatusBarData.showHorizontal) {
250      if (!tintState.region) {
251        data.width = this.mStatusBarData.realWidth;
252        this.mComponentGroupContentDatas[0] = data;
253        this.mComponentGroupContentDatas[1] = new StatusBarComponentGroupContentData();
254        this.mComponentGroupContentDatas[2] = new StatusBarComponentGroupContentData();
255      } else {
256        data.width = tintState.region.width;
257        if (tintState.region.left == this.mStatusBarData.left) {
258          this.mComponentGroupContentDatas[0] = data;
259        } else if ((tintState.region.left + tintState.region.width) == (this.mStatusBarData.left + this.mStatusBarData.realWidth)) {
260          this.mComponentGroupContentDatas[2] = data;
261        } else {
262          this.mComponentGroupContentDatas[1] = data;
263        }
264      }
265    } else {
266      if (!tintState.region) {
267        data.width = this.mStatusBarData.realHeight;
268        this.mComponentGroupContentDatas[0] = data;
269        this.mComponentGroupContentDatas[1] = new StatusBarComponentGroupContentData();
270        this.mComponentGroupContentDatas[2] = new StatusBarComponentGroupContentData();
271      } else {
272        data.width = tintState.region.height;
273        if (tintState.region.top == this.mStatusBarData.top) {
274          this.mComponentGroupContentDatas[0] = data;
275        } else if ((tintState.region.top + tintState.region.height) == (this.mStatusBarData.top + this.mStatusBarData.realHeight)) {
276          this.mComponentGroupContentDatas[2] = data;
277        } else {
278          this.mComponentGroupContentDatas[1] = data;
279        }
280      }
281    }
282    Log.showInfo(TAG, `changeContent, data: ${JSON.stringify(data)}`);
283
284    this.mComponentAreaMap.forEach((value: Rect, key: string) => {
285      this.changeComponentContent(key, value);
286    });
287  }
288
289  changeComponentContent(id: string, area: Rect): void{
290    Log.showInfo(TAG, `changeComponentContent, id ${id} area: ${JSON.stringify(area)}`);
291    if (this.mUseInWindowName != WindowType.STATUS_BAR) {
292      this.setComponentContent(id, '#FFFFFFFF');
293      return;
294    }
295    let startPos = this.mStatusBarData.showHorizontal ? this.mStatusBarData.left : this.mStatusBarData.top;
296    for (let group of this.mComponentGroupContentDatas) {
297      if (group.width == 0) {
298        continue;
299      }
300      let endPos = group.width + startPos;
301      let componentStartPos: number;
302      let componentEndPos: number;
303      if (this.mStatusBarData.showHorizontal) {
304        componentStartPos = area.left;
305        componentEndPos = area.left + area.width;
306      } else {
307        componentStartPos = area.top;
308        componentEndPos = area.top + area.height;
309      }
310      if (!(componentEndPos < startPos || componentStartPos > endPos)) {
311        if (id === 'systemui_controlpanel' || id === 'systemui_notificationpanel') {
312            this.resetWindow(id, area);
313        }
314        this.setComponentContent(id, group.contentColor);
315        break;
316      }
317      startPos = endPos;
318    }
319  }
320
321  async resetWindow(id: string, area: Rect): Promise<void>{
322    Log.showInfo(TAG, `resetWindow, id ${id} contentColor: ${JSON.stringify(area)}`);
323    let panelWidth;
324    let panelHeight;
325    let abilityName;
326    let windowName;
327    if (id === 'systemui_notificationpanel') {
328      abilityName = AbilityManager.ABILITY_NAME_NOTIFICATION_PANEL;
329      let initRect = AbilityManager.getAbilityData(abilityName, 'rect');
330      Log.showInfo(TAG, `id ${id} initRect: ${JSON.stringify(initRect)}`);
331      panelWidth = initRect.width;
332      panelHeight = initRect.height;
333      windowName = WindowType.NOTIFICATION_PANEL;
334    } else if (id === 'systemui_controlpanel') {
335      abilityName = AbilityManager.ABILITY_NAME_CONTROL_PANEL;
336      let initRect = AbilityManager.getAbilityData(abilityName, 'rect');
337      Log.showInfo(TAG, `id ${id} initRect: ${JSON.stringify(initRect)}`);
338      panelWidth = initRect.width;
339      panelHeight = initRect.height;
340      windowName = WindowType.CONTROL_PANEL;
341    } else {
342      return;
343    }
344    let rect = {
345      left: area.left + area.width - panelWidth,
346      top: area.height,
347      width: panelWidth,
348      height: panelHeight,
349    };
350    AbilityManager.setAbilityData(abilityName, 'rect', rect);
351    await WindowManager.moveTo(windowName, rect);
352  }
353
354  setComponentContent(id: string, contentColor: string): void{
355    Log.showInfo(TAG, `setComponentContent, id ${id} contentColor: ${contentColor}`);
356    getOrCreateTintContentInfo(id).contentColor = contentColor;
357  }
358
359  updateComponentArea(id: string, area: Area): void{
360    Log.showInfo(TAG, `updateComponentArea, id ${id} area: ${JSON.stringify(area)}`);
361    let areaInfo = {
362      left: vp2px(area.globalPosition.x as number),
363      top: vp2px(area.globalPosition.y as number),
364      width: vp2px(area.width as number),
365      height: vp2px(area.height as number)
366    };
367    this.mComponentAreaMap.set(id, areaInfo);
368    this.changeComponentContent(id, areaInfo);
369  }
370
371  setUseInWindowName(name: WindowType): void {
372    Log.showInfo(TAG, `setUseInWindowName, name ${name}`);
373    this.mUseInWindowName = name;
374    this.mComponentAreaMap.forEach((value: Rect, key: string) => {
375      this.changeComponentContent(key, value);
376    });
377  }
378
379  getStatusBarData(): StatusBarData {
380    return this.mStatusBarData;
381  }
382
383  updateStatusBarData(data: StatusBarData): void{
384    Log.showDebug(TAG, `updateStatusBarData, data: ${JSON.stringify(data)}`);
385    for (let key in data) {
386      this.mStatusBarData[key] = data[key];
387    }
388  }
389
390  getEmptyTintContentInfo(): TintContentInfo{
391    return this.mEmptyTintContentInfo;
392  }
393
394  getNotificationTintContentInfo(): TintContentInfo{
395    return this.mNotificationTintContentInfo;
396  }
397
398  getPluginTintContentInfo(id: string): TintContentInfo{
399    return getOrCreateTintContentInfo(id);
400  }
401
402  getBackgroundDatas(): StatusBarBackgroundData[]{
403    return this.mBackgroundDatas;
404  }
405}
406
407let sStatusBarVM = createOrGet(StatusBarVM, TAG);
408
409export default sStatusBarVM;