1/*
2 * Copyright (c) 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 { AsyncCallback} from '@ohos.base';
17import inputMonitor from '@ohos.multimodalInput.inputMonitor';
18import {
19  Log,
20  CommonConstants,
21  settingsDataManager,
22  localEventManager,
23  EventConstants
24} from '@ohos/common';
25import dataShare from '@ohos.data.dataShare';
26import GestureNavigationExecutors from './GestureNavigationExecutors';
27import display from '@ohos.display';
28
29const TAG = 'GestureNavigationManage';
30
31export class GestureNavigationManager {
32  private readonly uri: string | null = null;
33  private helper: dataShare.DataShareHelper;
34  private MAX_RETRY_TIME = 10;
35  private readonly sGestureNavigationExecutors: GestureNavigationExecutors = GestureNavigationExecutors.getInstance();
36  private touchEventCallback: inputMonitor.TouchEventReceiver | null = null;
37
38  private constructor() {
39    this.uri = settingsDataManager.getUri(CommonConstants.NAVIGATION_BAR_STATUS_KEY);
40    this.helper = settingsDataManager.getHelper(globalThis.desktopContext, this.uri);
41  }
42
43  private setValue(value: string) {
44    settingsDataManager.setValue(this.helper, CommonConstants.NAVIGATION_BAR_STATUS_KEY, value);
45  }
46
47  private getValue() {
48    return settingsDataManager.getValue(this.helper, CommonConstants.NAVIGATION_BAR_STATUS_KEY, '1');
49  }
50
51  /**
52   * Monitor data changes.
53   * @param callback
54   */
55  private registerListenForDataChanges(callback: AsyncCallback<void>) {
56    this.helper = settingsDataManager.getHelper(globalThis.desktopContext, this.uri);
57    Log.showInfo(TAG, 'helper:' + this.helper +  'registerListenForDataChanges uri:' + this.uri);
58    try {
59      this.helper.on('dataChange', this.uri, callback);
60    } catch (err) {
61      Log.showError(TAG, `Monitor data changes by dataShare err: ${err.message || err?.code}`);
62    }
63  }
64
65  initWindowSize(display: display.Display) {
66    if (globalThis.sGestureNavigationExecutors) {
67      globalThis.sGestureNavigationExecutors.setScreenWidth(display.width);
68      globalThis.sGestureNavigationExecutors.setScreenHeight(display.height);
69      this.touchEventCallback = globalThis.sGestureNavigationExecutors.touchEventCallback
70        .bind(globalThis.sGestureNavigationExecutors);
71      settingsDataManager.createDataShareHelper(this.MAX_RETRY_TIME);
72    }
73  }
74
75  private getGestureNavigationStatus() {
76    Log.showDebug(TAG, 'getGestureNavigationStatus enter');
77    let gestureNavigationStatus = null;
78    try {
79      gestureNavigationStatus = this.getValue();
80      Log.showDebug(TAG, `getGestureNavigationStatus gestureNavigationStatus:  ${gestureNavigationStatus}`);
81      this.handleEventSwitches(gestureNavigationStatus);
82
83      // 初始化时保持弹窗的距离底部的位置和(打开/关闭)三键时的位置一致
84      AppStorage.setOrCreate('NavigationBarStatusValue', gestureNavigationStatus === '0' ? true : false);
85
86      this.registerListenForDataChanges(this.dataChangesCallback.bind(this));
87    } catch (error) {
88      Log.showError(TAG, `getGestureNavigationStatus error: ${JSON.stringify(error)}`);
89    }
90  }
91
92  private dataChangesCallback(data: any) {
93    Log.showInfo(TAG, 'dataChangesCallback data:' + data);
94    const getRetValue = this.getValue();
95    this.handleEventSwitches(getRetValue);
96    AppStorage.setOrCreate('NavigationBarStatusValue', getRetValue === '0' ? true : false);
97    localEventManager.sendLocalEventSticky(EventConstants.EVENT_NAVIGATOR_BAR_STATUS_CHANGE, getRetValue);
98  }
99
100  private turnOnTouchEventCallback() {
101    Log.showWarn(TAG, 'turnOnTouchEventCallback start');
102    inputMonitor.on('touch', this.touchEventCallback);
103  }
104
105  private turnOffTouchEventCallback() {
106    Log.showWarn(TAG, 'turnOffTouchEventCallback start');
107    inputMonitor.off('touch', this.touchEventCallback);
108  }
109
110  private handleEventSwitches(gestureNavigationStatus: string) {
111    if (gestureNavigationStatus == '0') {
112      this.turnOnTouchEventCallback();
113    } else {
114      this.turnOffTouchEventCallback();
115    }
116  }
117
118  /**
119   * Get the GestureNavigationManage instance.
120   */
121  static getInstance(): GestureNavigationManager {
122    if (globalThis.sGestureNavigationManager == null) {
123      globalThis.sGestureNavigationManager = new GestureNavigationManager();
124    }
125    return globalThis.sGestureNavigationManager;
126  }
127}