• 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.isEnable) {
185      if (tintState.backgroundColor) {
186        this.changeBackground(tintState);
187      }
188      if (tintState.contentColor) {
189        this.changeContent(tintState);
190      }
191    }
192  }
193
194  setStatusBarEnable(isEnable: boolean): void {
195    Log.showInfo(TAG, `setStatusBarEnable, isEnable ${isEnable}`);
196    if (this.mStatusBarEnable == isEnable) {
197      return;
198    }
199    this.mStatusBarEnable = isEnable;
200    this.mStatusBarEnable ? WindowManager.showWindow(WindowType.STATUS_BAR).then(() => {
201    }).catch((err) => {
202    }) : WindowManager.hideWindow(WindowType.STATUS_BAR).then(() => {
203    }).catch((err) => {
204    });
205  }
206
207  changeBackground(tintState: TintState): void{
208    Log.showInfo(TAG, `changeBackground, backgroundColor: ${tintState.backgroundColor} region: ${JSON.stringify(tintState.region)}`);
209    let data = new StatusBarBackgroundData();
210    data.backgroundColor = tintState.backgroundColor;
211    if (this.mStatusBarData.showHorizontal) {
212      if (!tintState.region) {
213        data.width = this.mStatusBarData.realWidth;
214        this.mBackgroundDatas[0] = data;
215        this.mBackgroundDatas[1] = new StatusBarBackgroundData();
216        this.mBackgroundDatas[2] = new StatusBarBackgroundData();
217      } else {
218        data.width = tintState.region.width;
219        if (tintState.region.left == this.mStatusBarData.left) {
220          this.mBackgroundDatas[0] = data;
221        } else if ((tintState.region.left + tintState.region.width) == (this.mStatusBarData.left + this.mStatusBarData.realWidth)) {
222          this.mBackgroundDatas[2] = data;
223        } else {
224          this.mBackgroundDatas[1] = data;
225        }
226      }
227    } else {
228      if (!tintState.region) {
229        data.width = this.mStatusBarData.realHeight;
230        this.mBackgroundDatas[0] = data;
231        this.mBackgroundDatas[1] = new StatusBarBackgroundData();
232        this.mBackgroundDatas[2] = new StatusBarBackgroundData();
233      } else {
234        data.width = tintState.region.height;
235        if (tintState.region.top == this.mStatusBarData.top) {
236          this.mBackgroundDatas[0] = data;
237        } else if ((tintState.region.top + tintState.region.height) == (this.mStatusBarData.top + this.mStatusBarData.realHeight)) {
238          this.mBackgroundDatas[2] = data;
239        } else {
240          this.mBackgroundDatas[1] = data;
241        }
242      }
243    }
244    Log.showInfo(TAG, `changeBackground, data: ${JSON.stringify(data)}`);
245  }
246
247  changeContent(tintState: TintState): void{
248    Log.showInfo(TAG, `changeContent, contentColor: ${tintState.contentColor} region: ${JSON.stringify(tintState.region)}`);
249    let data = new StatusBarComponentGroupContentData();
250    data.contentColor = tintState.contentColor;
251    if (this.mStatusBarData.showHorizontal) {
252      if (!tintState.region) {
253        data.width = this.mStatusBarData.realWidth;
254        this.mComponentGroupContentDatas[0] = data;
255        this.mComponentGroupContentDatas[1] = new StatusBarComponentGroupContentData();
256        this.mComponentGroupContentDatas[2] = new StatusBarComponentGroupContentData();
257      } else {
258        data.width = tintState.region.width;
259        if (tintState.region.left == this.mStatusBarData.left) {
260          this.mComponentGroupContentDatas[0] = data;
261        } else if ((tintState.region.left + tintState.region.width) == (this.mStatusBarData.left + this.mStatusBarData.realWidth)) {
262          this.mComponentGroupContentDatas[2] = data;
263        } else {
264          this.mComponentGroupContentDatas[1] = data;
265        }
266      }
267    } else {
268      if (!tintState.region) {
269        data.width = this.mStatusBarData.realHeight;
270        this.mComponentGroupContentDatas[0] = data;
271        this.mComponentGroupContentDatas[1] = new StatusBarComponentGroupContentData();
272        this.mComponentGroupContentDatas[2] = new StatusBarComponentGroupContentData();
273      } else {
274        data.width = tintState.region.height;
275        if (tintState.region.top == this.mStatusBarData.top) {
276          this.mComponentGroupContentDatas[0] = data;
277        } else if ((tintState.region.top + tintState.region.height) == (this.mStatusBarData.top + this.mStatusBarData.realHeight)) {
278          this.mComponentGroupContentDatas[2] = data;
279        } else {
280          this.mComponentGroupContentDatas[1] = data;
281        }
282      }
283    }
284    Log.showInfo(TAG, `changeContent, data: ${JSON.stringify(data)}`);
285
286    this.mComponentAreaMap.forEach((value: Rect, key: string) => {
287      this.changeComponentContent(key, value);
288    });
289  }
290
291  changeComponentContent(id: string, area: Rect): void{
292    Log.showInfo(TAG, `changeComponentContent, id ${id} area: ${JSON.stringify(area)}`);
293    if (this.mUseInWindowName != WindowType.STATUS_BAR) {
294      this.setComponentContent(id, '#FFFFFFFF');
295      return;
296    }
297    let startPos = this.mStatusBarData.showHorizontal ? this.mStatusBarData.left : this.mStatusBarData.top;
298    for (let group of this.mComponentGroupContentDatas) {
299      if (group.width == 0) {
300        continue;
301      }
302      let endPos = group.width + startPos;
303      let componentStartPos: number;
304      let componentEndPos: number;
305      if (this.mStatusBarData.showHorizontal) {
306        componentStartPos = area.left;
307        componentEndPos = area.left + area.width;
308      } else {
309        componentStartPos = area.top;
310        componentEndPos = area.top + area.height;
311      }
312      if (!(componentEndPos < startPos || componentStartPos > endPos)) {
313        if (id === 'systemui_controlpanel' || id === 'systemui_notificationpanel') {
314            this.resetWindow(id, area);
315        }
316        this.setComponentContent(id, group.contentColor);
317        break;
318      }
319      startPos = endPos;
320    }
321  }
322
323  async resetWindow(id: string, area: Rect): Promise<void>{
324    Log.showInfo(TAG, `resetWindow, id ${id} contentColor: ${JSON.stringify(area)}`);
325    let panelWidth;
326    let panelHeight;
327    let abilityName;
328    let windowName;
329    if (id === 'systemui_notificationpanel') {
330      abilityName = AbilityManager.ABILITY_NAME_NOTIFICATION_PANEL;
331      let initRect = AbilityManager.getAbilityData(abilityName, 'rect');
332      Log.showInfo(TAG, `id ${id} initRect: ${JSON.stringify(initRect)}`);
333      panelWidth = initRect.width;
334      panelHeight = initRect.height;
335      windowName = WindowType.NOTIFICATION_PANEL;
336    } else if (id === 'systemui_controlpanel') {
337      abilityName = AbilityManager.ABILITY_NAME_CONTROL_PANEL;
338      let initRect = AbilityManager.getAbilityData(abilityName, 'rect');
339      Log.showInfo(TAG, `id ${id} initRect: ${JSON.stringify(initRect)}`);
340      panelWidth = initRect.width;
341      panelHeight = initRect.height;
342      windowName = WindowType.CONTROL_PANEL;
343    } else {
344      return;
345    }
346    let rect = {
347      left: area.left + area.width - panelWidth,
348      top: area.height,
349      width: panelWidth,
350      height: panelHeight,
351    };
352    AbilityManager.setAbilityData(abilityName, 'rect', rect);
353    await WindowManager.moveTo(windowName, rect);
354  }
355
356  setComponentContent(id: string, contentColor: string): void{
357    Log.showInfo(TAG, `setComponentContent, id ${id} contentColor: ${contentColor}`);
358    getOrCreateTintContentInfo(id).contentColor = contentColor;
359  }
360
361  updateComponentArea(id: string, area: Area): void{
362    Log.showInfo(TAG, `updateComponentArea, id ${id} area: ${JSON.stringify(area)}`);
363    let areaInfo = {
364      left: vp2px(area.globalPosition.x as number),
365      top: vp2px(area.globalPosition.y as number),
366      width: vp2px(area.width as number),
367      height: vp2px(area.height as number)
368    };
369    this.mComponentAreaMap.set(id, areaInfo);
370    this.changeComponentContent(id, areaInfo);
371  }
372
373  setUseInWindowName(name: WindowType): void {
374    Log.showInfo(TAG, `setUseInWindowName, name ${name}`);
375    this.mUseInWindowName = name;
376    this.mComponentAreaMap.forEach((value: Rect, key: string) => {
377      this.changeComponentContent(key, value);
378    });
379  }
380
381  getStatusBarData(): StatusBarData {
382    return this.mStatusBarData;
383  }
384
385  updateStatusBarData(data: StatusBarData): void{
386    Log.showDebug(TAG, `updateStatusBarData, data: ${JSON.stringify(data)}`);
387    for (let key in data) {
388      this.mStatusBarData[key] = data[key];
389    }
390  }
391
392  getEmptyTintContentInfo(): TintContentInfo{
393    return this.mEmptyTintContentInfo;
394  }
395
396  getNotificationTintContentInfo(): TintContentInfo{
397    return this.mNotificationTintContentInfo;
398  }
399
400  getPluginTintContentInfo(id: string): TintContentInfo{
401    return getOrCreateTintContentInfo(id);
402  }
403
404  getBackgroundDatas(): StatusBarBackgroundData[]{
405    return this.mBackgroundDatas;
406  }
407}
408
409let sStatusBarVM = createOrGet(StatusBarVM, TAG);
410
411export default sStatusBarVM;