• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2022-2023 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 { MathUtil } from './MathUtil';
17import { Constants } from '../model/common/Constants';
18import { Log } from './Log';
19import { ScreenManager } from '../model/common/ScreenManager';
20import prompt from '@system.prompt';
21import type window from '@ohos.window';
22import type { Action } from '../view/browserOperation/Action';
23import { AlbumInfo } from '../model/browser/album/AlbumInfo';
24import common from '@ohos.app.ability.common';
25
26const TAG: string = 'common_UiUtil';
27
28type Window = window.Window;
29
30export class UiUtil {
31
32  /**
33   * Status bar height
34   */
35  static readonly STATUS_BAR_HEIGHT = 45;
36
37  /**
38   * Navigation bar height
39   */
40  static readonly NAVI_BAR_HEIGHT = 45;
41
42  /**
43   * Hexadecimal Radix
44   */
45  static readonly HEX_BASE = 16;
46
47  /**
48   * Maximum order of color
49   */
50  static readonly MAX_COLOR_ORDER = 255;
51  public static readonly TOAST_DURATION = 3000;
52  /**
53   * 3-bit length hex color
54   */
55  private static readonly HEX_COLOR_LENGTH_THREE = 3;
56  /**
57   * 8-bit length hex color
58   */
59  private static readonly HEX_COLOR_LENGTH_EIGHT = 8;
60  /**
61   * Opacity length of hex color
62   */
63  private static readonly HEX_COLOR_OPACITY_LENGTH = 2;
64  /**
65   * Hexadecimal array
66   */
67  private static readonly HEX_ARRAY = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
68
69  /**
70   * Set status bar color
71   *
72   * @param statusBarColor statusBarColor
73   */
74  static setStatusBarColor(topWindow: Window): void {
75    topWindow.setSystemBarProperties({ navigationBarColor: '#FFF1F3F5', navigationBarContentColor: '#FF000000' },
76      () => {
77        Log.info(TAG, 'setStatusBarColor done');
78      });
79  }
80
81  /**
82   * Gets the hexadecimal color with opacity
83   *
84   * @param color Original hex color
85   * @param opacity Opacity
86   * @returns Hex color with opacity
87   */
88  static getHexOpacityColor(paramColor: string, paramOpacity: number): string {
89    let colorReg = /^\#([0-9a-fA-f]{3}|[0-9a-fA-f]{6}|[0-9a-fA-f]{8})$/;
90    // The input must be # the first 3-bit / 6-bit / 8-bit hex color
91    if (paramColor.match(colorReg) == null) {
92      Log.error(TAG, `getHexOpacityColor failed because of invalid input, color:  ${paramColor}`);
93      return paramColor;
94    }
95    let color = paramColor.replace(/\#/g, '').toUpperCase();
96    let opacity = MathUtil.clamp(0, 1, paramOpacity);
97    // If it is an abbreviated 3-digit color, complete the 3-digit characters to 6-digit characters
98    if (color.length === UiUtil.HEX_COLOR_LENGTH_THREE) {
99      let arr = color.split('');
100      color = '';
101      for (let i = 0; i < arr.length; i++) {
102        color += (arr[i] + arr[i]);
103      }
104    }
105    // If it is an 8-bit color, the original opacity will be removed
106    if (color.length === UiUtil.HEX_COLOR_LENGTH_EIGHT) {
107      color = color.slice(UiUtil.HEX_COLOR_OPACITY_LENGTH, color.length);
108    }
109    let opacityNum = Math.round(UiUtil.MAX_COLOR_ORDER * opacity); // rounding
110    let opacityStr = '';
111    while (opacityNum > 0) {
112      let mod = opacityNum % UiUtil.HEX_BASE;
113      opacityNum = (opacityNum - mod) / UiUtil.HEX_BASE;
114      opacityStr = UiUtil.HEX_ARRAY[mod] + opacityStr;
115    }
116    if (opacityStr.length == 1) {
117      opacityStr = `0${opacityStr}`;
118    }
119    if (opacityStr.length == 0) {
120      opacityStr = '00';
121    }
122    return `#${opacityStr + color}`;
123  }
124
125  /**
126   * Get the content of the resource reference
127   *
128   * @param resource resource reference
129   * @returns resource Corresponding content string
130   */
131  static async getResourceString(resource: Resource): Promise<string> {
132    try {
133      Log.info(TAG, `getResourceString: ${JSON.stringify(resource)}`);
134      if (AppStorage.get('photosAbilityContext') === null || AppStorage.get('photosAbilityContext') === 'undefined') {
135        Log.error(TAG, 'getResourceString error: context is null');
136        return null;
137      }
138      let context: common.UIAbilityContext = AppStorage.get<common.UIAbilityContext>('photosAbilityContext');
139      let mgr: string = await context.resourceManager.getString(resource.id);
140      if (mgr) {
141        return mgr;
142      } else {
143        Log.error(TAG, `getResourceManager instance is none`);
144        return null;
145      }
146    } catch (error) {
147      Log.error(TAG, `getResourceString error: ${error}`);
148      return null;
149    }
150  }
151
152  /**
153   * Get the content of the resource reference
154   *
155   * @param resource resource reference
156   * @returns resource Corresponding content number
157   */
158  static async getResourceNumber(resource: Resource): Promise<number> {
159    try {
160      Log.info(TAG, `getResourceNumber: ${JSON.stringify(resource)}`);
161      if (AppStorage.get('photosAbilityContext') === null || AppStorage.get('photosAbilityContext') === 'undefined') {
162        Log.error(TAG, 'getResourceNumber error: context is null');
163        return null;
164      }
165      let context: common.UIAbilityContext = AppStorage.get<common.UIAbilityContext>('photosAbilityContext');
166      let mgr: number = context.resourceManager.getNumber(resource.id);
167      if (mgr) {
168        return mgr;
169      } else {
170        Log.error(TAG, `getResourceNumber instance is none`);
171        return null;
172      }
173    } catch (error) {
174      Log.error(TAG, `getResourceNumber error: ${error}`);
175      return null;
176    }
177  }
178
179  static async showToast(resource: Resource): Promise<void> {
180    let message = await UiUtil.getResourceString(resource);
181    Log.debug(TAG, `showToast: ${message}`);
182    prompt.showToast({
183      message: message,
184      duration: UiUtil.TOAST_DURATION,
185      bottom: '64vp'
186    });
187  }
188
189  /**
190   * 获取相册封面宫格布局列的个数
191   *
192   * @param isSidebar 是否包含侧边栏
193   */
194  static getAlbumGridCount(isSidebar: boolean): number {
195    Log.info(TAG, `get screen width is : ${ScreenManager.getInstance().getWinWidth()}`);
196    let sideBarWidth = isSidebar ? Constants.TAB_BAR_WIDTH : 0;
197    let contentWidth = ScreenManager.getInstance().getWinWidth() - sideBarWidth;
198    let maxCardWidth = Constants.ALBUM_SET_COVER_SIZE * Constants.GRID_MAX_SIZE_RATIO;
199    let gridColumnsCount = Math.max(Constants.DEFAULT_ALBUM_GRID_COLUMN_MIN_COUNT,
200      Math.ceil((contentWidth - Constants.ALBUM_SET_MARGIN * Constants.NUMBER_2 + Constants.ALBUM_SET_GUTTER) /
201      (maxCardWidth + Constants.ALBUM_SET_GUTTER)));
202    Log.info(TAG, `[getAlbumGridCount] contentWidth: ${contentWidth}, gridColumnsCount: ${gridColumnsCount}`);
203    return gridColumnsCount;
204  }
205
206  static resetGeometryTransitionParams(): void {
207    AppStorage.SetOrCreate<number>('geometryScale', 1);
208    AppStorage.SetOrCreate<number>('geometryOffsetX', 0);
209    AppStorage.SetOrCreate<number>('geometryOffsetY', 0);
210    AppStorage.SetOrCreate<number>('geometryOpacity', 1);
211  }
212
213  static updateGeometryTapInfo(geometryTapIndex: number, geometryTransitionString: string): void {
214    AppStorage.SetOrCreate<number>('placeholderIndex', geometryTapIndex);
215    AppStorage.SetOrCreate<string>('geometryTransitionBrowserId',
216      geometryTransitionString);
217    Log.debug(TAG, 'this.geometryTransitionId = ' + geometryTransitionString +
218      ', placeholderIndex = ' + geometryTapIndex);
219  }
220
221  static getRouterParams(params: Object): Object {
222    let fakeRouterParam: Object = AppStorage.Get('fakeRouterParam');
223    AppStorage.Delete('fakeRouterParam');
224    if (fakeRouterParam) {
225      Log.debug(TAG, 'fakeRouterParam = ' + JSON.stringify(fakeRouterParam));
226    }
227    if (params) {
228      Log.debug(TAG, 'params = ' + JSON.stringify(params));
229    }
230    return params ? params : fakeRouterParam;
231  }
232
233  static isActionArrayEqual(firstList: Array<Action>, secondList: Array<Action>): boolean {
234    if (firstList === secondList) {
235      return true;
236    }
237    if (firstList.length !== secondList.length) {
238      return false;
239    }
240    for (let index = 0; index < firstList.length; index++) {
241      if (!firstList[index].equals(secondList[index])) {
242        return false;
243      }
244    }
245    return true;
246  }
247
248  static getDisplayNameResourceByAlbumInfo(albumInfo: AlbumInfo): Resource {
249    let res: Resource = null;
250    if (albumInfo.isPhotoAlbum) {
251      return $r('app.string.album_photos');
252    } else if (albumInfo.isFavorAlbum) {
253      return $r('app.string.album_favor');
254    } else if (albumInfo.isVideoAlbum) {
255      return $r('app.string.album_video');
256    } else if (albumInfo.isTrashAlbum) {
257      return $r('app.string.album_recycle');
258    } else if (albumInfo.isScreenShotAlbum) {
259      return $r('app.string.album_screen_shot');
260    } else {
261      return res;
262    }
263  }
264}