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 CapsuleModel from '../model/CapsuleModel';
17import Log from '../../../../../../../common/src/main/ets/default/Log';
18import AbilityManager from '../../../../../../../common/src/main/ets/default/abilitymanager/abilityManager';
19import ResourceUtil from '../../../../../../../common/src/main/ets/default/ResourceUtil';
20import Trace from '../../../../../../../common/src/main/ets/default/Trace'
21
22let sCapsuleViewModel;
23
24const SEC_VAL = 1000;
25const MIN_VAL = 60 * SEC_VAL;
26const TAG = "CapsuleViewModel";
27
28function fixInteger(num) {
29  return (num >= 10) ? String(num) : '0' + num;
30}
31
32function parseTime(num) {
33  return fixInteger(Math.floor(num / MIN_VAL)) + ":" + fixInteger(Math.floor((num % MIN_VAL) / SEC_VAL));
34}
35
36export const VIEW_MODEL_ID = "CapsuleViewModelVm";
37
38export enum CallState {
39  CALL_ACTIVE, //通话中*
40  CALL_HOLDING, //通话保持
41  CALL_DIALING, //拨号开始
42  CALL_ALERTING, //正在呼出
43  CALL_INCOMING, //来电*
44  CALL_WAITING, //第三方来电*
45  CALL_DISCONNECTED, //挂断完成 *
46  CALL_DISCONNECTING, //正在挂断
47  CALL_IDLE //空闲
48}
49
50export default class CapsuleViewModel {
51  mText: string = "00:00";
52  mStartTime: number = 0;
53  mCallState: CallState = CallState.CALL_DISCONNECTED;
54  mIsBackground: boolean = false;
55  mWantBundleName: string = "";
56  mWantAbilityName: string = "";
57  mTimeMeter: any;
58  mCallback: any;
59
60  async initViewModel() {
61    this.mCallback = {
62      "onStateChange": this.onStateChange.bind(this)
63    };
64    CapsuleModel.registerCallback(this.mCallback);
65  }
66
67  async onStateChange(data) {
68    Log.showInfo(TAG, `onStateChange, data: ${JSON.stringify(data)}`);
69    this.mIsBackground = data.isBackground;
70    this.mWantBundleName = data.wantBundleName;
71    this.mWantAbilityName = data.wantAbilityName;
72    await ResourceUtil.initResourceManager(AbilityManager.ABILITY_NAME_STATUS_BAR);
73    if (data.callState == CallState.CALL_INCOMING || data.callState == CallState.CALL_WAITING) {
74      this.mStartTime = 0;
75      this.mText = await ResourceUtil.getString($r("app.string.incoming_call"));
76    } else if (data.callState == CallState.CALL_ACTIVE) {
77      clearTimeout(this.mTimeMeter);
78      if (this.mCallState != CallState.CALL_ACTIVE) {
79        this.mStartTime = new Date().valueOf();
80      };
81      this.mCallState = data.callState;
82
83      let startTime;
84      let commonTimeDiff = new Date().valueOf() - data.startTime;
85      let localTimeDiff = new Date().valueOf() - this.mStartTime;
86      if (commonTimeDiff < 0) {
87        if (localTimeDiff < 0) {
88          startTime = new Date().valueOf();
89        } else {
90          startTime = this.mStartTime;
91        };
92      } else {
93        startTime = data.startTime;
94      };
95
96      this.startUpdateTime(startTime);
97    } else if (data.callState == CallState.CALL_DISCONNECTED){
98      clearTimeout(this.mTimeMeter);
99      this.mStartTime = 0;
100      this.mIsBackground = false;
101      this.mText = "";
102      Log.showInfo(TAG, `cannot show`);
103    } else {
104      this.mStartTime = 0;
105      this.mText = await ResourceUtil.getString($r("app.string.communicate_by_phone"));
106    };
107    this.mCallState = data.callState;
108  }
109
110  startUpdateTime(startTime) {
111    if (!this.mIsBackground || this.mCallState != CallState.CALL_ACTIVE) {
112      return;
113    }
114    let val = new Date().valueOf() - startTime.valueOf();
115    if (val < 0) {
116      val = 0;
117    }
118    this.mText = parseTime(val);
119    this.mTimeMeter = setTimeout(() => {
120      this.startUpdateTime(startTime);
121    }, 1000 - val % 1000);
122  }
123
124  onClickEvent() {
125    Trace.start(Trace.CORE_METHOD_CLICK_CAPSULE);
126    if (this.mIsBackground) {
127      this.mIsBackground = false;
128    }
129    Log.showDebug(TAG, `onClickEvent `);
130    Log.showDebug(TAG, `startAbility`);
131    AbilityManager.startAbility(AbilityManager.getContext(AbilityManager.ABILITY_NAME_STATUS_BAR), {
132      bundleName: this.mWantBundleName,
133      abilityName: this.mWantAbilityName
134    }, () => {
135      Trace.end(Trace.CORE_METHOD_CLICK_CAPSULE);
136    });
137  }
138
139  static getInstance() {
140    if (sCapsuleViewModel == null) {
141      sCapsuleViewModel = new CapsuleViewModel();
142      AppStorage.SetAndLink(VIEW_MODEL_ID, sCapsuleViewModel);
143    };
144    return sCapsuleViewModel;
145  }
146}