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