18779efd5Sopenharmony_ci/**
28779efd5Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
38779efd5Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48779efd5Sopenharmony_ci * you may not use this file except in compliance with the License.
58779efd5Sopenharmony_ci * You may obtain a copy of the License at
68779efd5Sopenharmony_ci *
78779efd5Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88779efd5Sopenharmony_ci *
98779efd5Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108779efd5Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118779efd5Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128779efd5Sopenharmony_ci * See the License for the specific language governing permissions and
138779efd5Sopenharmony_ci * limitations under the License.
148779efd5Sopenharmony_ci */
158779efd5Sopenharmony_ciimport Notification from '@ohos.notificationManager'
168779efd5Sopenharmony_ciimport WantAgent from '@ohos.app.ability.wantAgent';
178779efd5Sopenharmony_ciimport { HiLog, sharedPreferencesUtils } from '../../../../../../common';
188779efd5Sopenharmony_ciimport notificationSubscribe from '@ohos.notificationSubscribe';
198779efd5Sopenharmony_ciimport call from '@ohos.telephony.call';
208779efd5Sopenharmony_ciimport { NotificationSubscriber } from 'notification/notificationSubscriber';
218779efd5Sopenharmony_ci
228779efd5Sopenharmony_ciconst TAG = 'MissedCallNotifier';
238779efd5Sopenharmony_ci
248779efd5Sopenharmony_ciconst BUNDLE_NAME: string = 'com.ohos.contacts';
258779efd5Sopenharmony_ciconst ABILITY_NAME: string = 'com.ohos.contacts.MainAbility';
268779efd5Sopenharmony_ciconst GROUP_NAME: string = 'MissedCall'
278779efd5Sopenharmony_ciconst KEY_MISSED_BADGE_NUM = 'missed_badge_number'
288779efd5Sopenharmony_ciconst KEY_ID = 'unread_call_notification_id'
298779efd5Sopenharmony_ciconst KEY_DISPLAY_NAME = 'unread_call_notification_displayName'
308779efd5Sopenharmony_ciconst KEY_COUNT = 'unread_call_notification_count'
318779efd5Sopenharmony_ciconst KEY_CREATE_TIME = 'unread_call_notification_create_time'
328779efd5Sopenharmony_ciconst KEY_RING_DURATION = 'unread_call_notification_ring_duration'
338779efd5Sopenharmony_ciconst actionBtnMaps =
348779efd5Sopenharmony_ci  {
358779efd5Sopenharmony_ci    'notification.event.dialBack': $r('app.string.dial_back'),
368779efd5Sopenharmony_ci    'notification.event.message': $r('app.string.message'),
378779efd5Sopenharmony_ci  };
388779efd5Sopenharmony_ci
398779efd5Sopenharmony_ciexport class MissedCallNotifyData {
408779efd5Sopenharmony_ci  id?: number;
418779efd5Sopenharmony_ci  displayName?: string;
428779efd5Sopenharmony_ci  readonly phoneNumber: string;
438779efd5Sopenharmony_ci  count?: number;
448779efd5Sopenharmony_ci  createTime?: number;
458779efd5Sopenharmony_ci  ringDuration?: number;
468779efd5Sopenharmony_ci}
478779efd5Sopenharmony_ci
488779efd5Sopenharmony_ciexport class MissedCallNotifier {
498779efd5Sopenharmony_ci  private label: string;
508779efd5Sopenharmony_ci  private context: Context;
518779efd5Sopenharmony_ci  private static sInstance: MissedCallNotifier = undefined;
528779efd5Sopenharmony_ci  private missedBadgeNumber: number = -1;
538779efd5Sopenharmony_ci  private UnReadMissedCallData: MissedCallNotifyData;
548779efd5Sopenharmony_ci
558779efd5Sopenharmony_ci  /**
568779efd5Sopenharmony_ci   * getInstance for MissedCallNotifier
578779efd5Sopenharmony_ci   */
588779efd5Sopenharmony_ci  public static getInstance() {
598779efd5Sopenharmony_ci    if (!MissedCallNotifier.sInstance || MissedCallNotifier.sInstance == undefined) {
608779efd5Sopenharmony_ci      MissedCallNotifier.sInstance = new MissedCallNotifier();
618779efd5Sopenharmony_ci    }
628779efd5Sopenharmony_ci    return MissedCallNotifier.sInstance;
638779efd5Sopenharmony_ci  }
648779efd5Sopenharmony_ci
658779efd5Sopenharmony_ci  /**
668779efd5Sopenharmony_ci   * init
678779efd5Sopenharmony_ci   *
688779efd5Sopenharmony_ci   * @param ctx context needed init
698779efd5Sopenharmony_ci   */
708779efd5Sopenharmony_ci  public init(ctx: Context) {
718779efd5Sopenharmony_ci    this.context = ctx;
728779efd5Sopenharmony_ci    if (!this.label) {
738779efd5Sopenharmony_ci      this.label = this.getContext()?.resourceManager.getStringSync($r('app.string.missed_call'));
748779efd5Sopenharmony_ci    }
758779efd5Sopenharmony_ci    sharedPreferencesUtils.init(this.getContext());
768779efd5Sopenharmony_ci  }
778779efd5Sopenharmony_ci
788779efd5Sopenharmony_ci  /**
798779efd5Sopenharmony_ci   * update Missed Call Notification
808779efd5Sopenharmony_ci   *
818779efd5Sopenharmony_ci   * @param missedData missedCallData - missed call data for notification
828779efd5Sopenharmony_ci   */
838779efd5Sopenharmony_ci  public async updateMissedCallNotifications(missedData: Map<string, MissedCallNotifyData>) {
848779efd5Sopenharmony_ci    let notifyData = await this.getMissedCallNotifyDatas();
858779efd5Sopenharmony_ci    HiLog.i(TAG, `updateMissedCallNotifications notifyData:${notifyData.length} missedData: ${missedData.size}`)
868779efd5Sopenharmony_ci    let badgeNumber: number = 0;
878779efd5Sopenharmony_ci    if (notifyData.length > 0) {
888779efd5Sopenharmony_ci      for (let notify of notifyData) {
898779efd5Sopenharmony_ci        let key: string = notify.displayName;
908779efd5Sopenharmony_ci        if (missedData.has(key)) {
918779efd5Sopenharmony_ci          let missed = missedData.get(key)
928779efd5Sopenharmony_ci          missedData.delete(key)
938779efd5Sopenharmony_ci          if (missed.id != notify.id) {
948779efd5Sopenharmony_ci            notify.createTime = missed.createTime;
958779efd5Sopenharmony_ci            notify.ringDuration = missed.ringDuration;
968779efd5Sopenharmony_ci            notify.count += missed.count;
978779efd5Sopenharmony_ci            this.sendNotification(notify);
988779efd5Sopenharmony_ci          }
998779efd5Sopenharmony_ci        }
1008779efd5Sopenharmony_ci        badgeNumber += notify.count;
1018779efd5Sopenharmony_ci      }
1028779efd5Sopenharmony_ci    }
1038779efd5Sopenharmony_ci    for (let notify of missedData.values()) {
1048779efd5Sopenharmony_ci      await this.sendNotification(notify);
1058779efd5Sopenharmony_ci      badgeNumber += notify.count;
1068779efd5Sopenharmony_ci    }
1078779efd5Sopenharmony_ci    if (badgeNumber > 0) {
1088779efd5Sopenharmony_ci      this.setMissedBadgeNumber(badgeNumber);
1098779efd5Sopenharmony_ci    }
1108779efd5Sopenharmony_ci  }
1118779efd5Sopenharmony_ci
1128779efd5Sopenharmony_ci  /**
1138779efd5Sopenharmony_ci   * cancel Missed Call Notification
1148779efd5Sopenharmony_ci   */
1158779efd5Sopenharmony_ci  public cancelAllNotification() {
1168779efd5Sopenharmony_ci    HiLog.i(TAG, 'cancelNotification,cancel all')
1178779efd5Sopenharmony_ci    this.setMissedBadgeNumber(0);
1188779efd5Sopenharmony_ci    Notification.cancelGroup(GROUP_NAME).catch(error => {
1198779efd5Sopenharmony_ci      HiLog.e(TAG, `cancelNotification,err ${JSON.stringify(error)}}`)
1208779efd5Sopenharmony_ci    });
1218779efd5Sopenharmony_ci  }
1228779efd5Sopenharmony_ci
1238779efd5Sopenharmony_ci  /**
1248779efd5Sopenharmony_ci   * get Missed Call BadgeNumber
1258779efd5Sopenharmony_ci   */
1268779efd5Sopenharmony_ci  public async getMissedBadgeNumber() {
1278779efd5Sopenharmony_ci    if (this.missedBadgeNumber == -1) {
1288779efd5Sopenharmony_ci      this.missedBadgeNumber = <number> await sharedPreferencesUtils.getFromPreferences(KEY_MISSED_BADGE_NUM, -1);
1298779efd5Sopenharmony_ci    }
1308779efd5Sopenharmony_ci    return this.missedBadgeNumber;
1318779efd5Sopenharmony_ci  }
1328779efd5Sopenharmony_ci
1338779efd5Sopenharmony_ci  /**
1348779efd5Sopenharmony_ci   * cancel Missed Call Notification By NotificationId
1358779efd5Sopenharmony_ci   *
1368779efd5Sopenharmony_ci   * @param id Notification Id
1378779efd5Sopenharmony_ci   */
1388779efd5Sopenharmony_ci  public async cancelNotificationById(id: number, count: number) {
1398779efd5Sopenharmony_ci    HiLog.i(TAG, 'cancelNotificationById:' + id)
1408779efd5Sopenharmony_ci    Notification.cancel(id, this.label).catch(error => {
1418779efd5Sopenharmony_ci      HiLog.e(TAG, `cancelNotificationById,err ${JSON.stringify(error)}}`)
1428779efd5Sopenharmony_ci    });
1438779efd5Sopenharmony_ci    let badgeNumber = await this.getMissedBadgeNumber();
1448779efd5Sopenharmony_ci    badgeNumber -= count;
1458779efd5Sopenharmony_ci    if (badgeNumber >= 0) {
1468779efd5Sopenharmony_ci      this.setMissedBadgeNumber(badgeNumber);
1478779efd5Sopenharmony_ci    }
1488779efd5Sopenharmony_ci  }
1498779efd5Sopenharmony_ci
1508779efd5Sopenharmony_ci  private constructor() {
1518779efd5Sopenharmony_ci  }
1528779efd5Sopenharmony_ci
1538779efd5Sopenharmony_ci  private getContext() {
1548779efd5Sopenharmony_ci    if (this.context && this.context != undefined) {
1558779efd5Sopenharmony_ci      return this.context;
1568779efd5Sopenharmony_ci    }
1578779efd5Sopenharmony_ci    return globalThis.context;
1588779efd5Sopenharmony_ci  }
1598779efd5Sopenharmony_ci
1608779efd5Sopenharmony_ci  private async getMissedCallNotifyDatas() {
1618779efd5Sopenharmony_ci    HiLog.i(TAG, `getMissedCallNotifyDatas in`)
1628779efd5Sopenharmony_ci    let result: Array<MissedCallNotifyData> = [];
1638779efd5Sopenharmony_ci    const notifications: Array<Notification.NotificationRequest> =
1648779efd5Sopenharmony_ci      await Notification.getAllActiveNotifications()
1658779efd5Sopenharmony_ci    for (let notify of notifications) {
1668779efd5Sopenharmony_ci      if (notify.groupName == GROUP_NAME && notify.extraInfo) {
1678779efd5Sopenharmony_ci        result.push(<MissedCallNotifyData> notify.extraInfo);
1688779efd5Sopenharmony_ci      }
1698779efd5Sopenharmony_ci    }
1708779efd5Sopenharmony_ci    HiLog.i(TAG, `getMissedCallNotifyDatas result: ${result.length}`)
1718779efd5Sopenharmony_ci    return result;
1728779efd5Sopenharmony_ci  }
1738779efd5Sopenharmony_ci
1748779efd5Sopenharmony_ci  private async sendNotification(missedCallData: MissedCallNotifyData) {
1758779efd5Sopenharmony_ci    const {id, displayName, count, createTime, ringDuration} = missedCallData;
1768779efd5Sopenharmony_ci    sharedPreferencesUtils.saveToPreferences(KEY_ID, id);
1778779efd5Sopenharmony_ci    sharedPreferencesUtils.saveToPreferences(KEY_DISPLAY_NAME, displayName);
1788779efd5Sopenharmony_ci    sharedPreferencesUtils.saveToPreferences(KEY_COUNT, count);
1798779efd5Sopenharmony_ci    sharedPreferencesUtils.saveToPreferences(KEY_CREATE_TIME, createTime);
1808779efd5Sopenharmony_ci    sharedPreferencesUtils.saveToPreferences(KEY_RING_DURATION, ringDuration)
1818779efd5Sopenharmony_ci    HiLog.i(TAG, `sendNotification in id:${id}, count:${count}, createTime:${createTime}`)
1828779efd5Sopenharmony_ci    let str_text = this.getContext()?.resourceManager.getStringSync($r('app.string.contacts_ring_times')) +
1838779efd5Sopenharmony_ci    ringDuration + this.getContext()?.resourceManager.getStringSync($r('app.string.contacts_time_sec'));
1848779efd5Sopenharmony_ci    if (ringDuration === 0) {
1858779efd5Sopenharmony_ci      str_text = $r('app.string.missed_call')
1868779efd5Sopenharmony_ci    }
1878779efd5Sopenharmony_ci    const notificationRequest: Notification.NotificationRequest = {
1888779efd5Sopenharmony_ci      content: {
1898779efd5Sopenharmony_ci        contentType: Notification.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
1908779efd5Sopenharmony_ci        normal: {
1918779efd5Sopenharmony_ci          title: count > 1 ? `${displayName} (${count})` : displayName,
1928779efd5Sopenharmony_ci          text: str_text,
1938779efd5Sopenharmony_ci          additionalText: missedCallData.phoneNumber
1948779efd5Sopenharmony_ci        },
1958779efd5Sopenharmony_ci      },
1968779efd5Sopenharmony_ci      id: id,
1978779efd5Sopenharmony_ci      label: this.label,
1988779efd5Sopenharmony_ci      groupName: GROUP_NAME,
1998779efd5Sopenharmony_ci      slotType: Notification.SlotType.SOCIAL_COMMUNICATION,
2008779efd5Sopenharmony_ci      deliveryTime: new Date().getTime(),
2018779efd5Sopenharmony_ci      extraInfo: missedCallData
2028779efd5Sopenharmony_ci    }
2038779efd5Sopenharmony_ci
2048779efd5Sopenharmony_ci    let wantAgentObj = await this.getWantAgent(missedCallData, 'notification.event.click');
2058779efd5Sopenharmony_ci    notificationRequest.wantAgent = wantAgentObj;
2068779efd5Sopenharmony_ci    notificationRequest.actionButtons = [];
2078779efd5Sopenharmony_ci    for (const key of Object.keys(actionBtnMaps)) {
2088779efd5Sopenharmony_ci      const wantAgent = await this.getWantAgent(missedCallData, key);
2098779efd5Sopenharmony_ci      const title = this.getContext()?.resourceManager.getStringSync(actionBtnMaps[key]);
2108779efd5Sopenharmony_ci      notificationRequest.actionButtons.push({
2118779efd5Sopenharmony_ci        title: title,
2128779efd5Sopenharmony_ci        wantAgent: wantAgent
2138779efd5Sopenharmony_ci      });
2148779efd5Sopenharmony_ci    }
2158779efd5Sopenharmony_ci    notificationRequest.removalWantAgent = await this.createWantAgentForCommonEvent(missedCallData, 'notification.event.cancel');
2168779efd5Sopenharmony_ci    Notification.publish(notificationRequest).then(() => {
2178779efd5Sopenharmony_ci      HiLog.i(TAG, '===>publish promise success req.id : ' + notificationRequest.id);
2188779efd5Sopenharmony_ci    }).catch((err) => {
2198779efd5Sopenharmony_ci      HiLog.e(TAG, '===>publish promise failed because ' + JSON.stringify(err));
2208779efd5Sopenharmony_ci    });
2218779efd5Sopenharmony_ci    HiLog.i(TAG, 'sendNotification end')
2228779efd5Sopenharmony_ci  }
2238779efd5Sopenharmony_ci
2248779efd5Sopenharmony_ci  /**
2258779efd5Sopenharmony_ci   * send Unread Call  Notification
2268779efd5Sopenharmony_ci   */
2278779efd5Sopenharmony_ci  public async sendUnreadCallNotification(map: Map<string, string>) {
2288779efd5Sopenharmony_ci    let id: number = <number> await sharedPreferencesUtils.getFromPreferences(KEY_ID, -1);
2298779efd5Sopenharmony_ci    let displayName: string = <string> await  sharedPreferencesUtils.getFromPreferences(KEY_DISPLAY_NAME, '');
2308779efd5Sopenharmony_ci    let count: number = <number> await  sharedPreferencesUtils.getFromPreferences(KEY_COUNT, -1);
2318779efd5Sopenharmony_ci    let createTime: number = <number> await  sharedPreferencesUtils.getFromPreferences(KEY_CREATE_TIME, -1);
2328779efd5Sopenharmony_ci    let ringDuration: number = <number> await  sharedPreferencesUtils.getFromPreferences(KEY_RING_DURATION, -1);
2338779efd5Sopenharmony_ci    let missCallData = map.get('missedPhoneJson')
2348779efd5Sopenharmony_ci    const parameters = JSON.parse(JSON.stringify(missCallData));
2358779efd5Sopenharmony_ci    for (let i = 0; i < parameters.phoneNumberList.length; i++) {
2368779efd5Sopenharmony_ci      const missedPhoneNumber = parameters.phoneNumberList[i]
2378779efd5Sopenharmony_ci      const missedNum = parameters.countList[i]
2388779efd5Sopenharmony_ci      if (i === (parameters.phoneNumberList.length -1)) {
2398779efd5Sopenharmony_ci        this.UnReadMissedCallData = {
2408779efd5Sopenharmony_ci          phoneNumber: missedPhoneNumber,
2418779efd5Sopenharmony_ci          displayName: missedPhoneNumber,
2428779efd5Sopenharmony_ci          id: i,
2438779efd5Sopenharmony_ci          createTime: createTime,
2448779efd5Sopenharmony_ci          count: count,
2458779efd5Sopenharmony_ci          ringDuration: ringDuration
2468779efd5Sopenharmony_ci        }
2478779efd5Sopenharmony_ci      } else {
2488779efd5Sopenharmony_ci        this.UnReadMissedCallData = {
2498779efd5Sopenharmony_ci          phoneNumber: missedPhoneNumber,
2508779efd5Sopenharmony_ci          displayName: missedPhoneNumber,
2518779efd5Sopenharmony_ci          id: i,
2528779efd5Sopenharmony_ci          createTime: createTime,
2538779efd5Sopenharmony_ci          count: count,
2548779efd5Sopenharmony_ci          ringDuration: 0
2558779efd5Sopenharmony_ci        }
2568779efd5Sopenharmony_ci      }
2578779efd5Sopenharmony_ci      this.sendNotification(this.UnReadMissedCallData);
2588779efd5Sopenharmony_ci    }
2598779efd5Sopenharmony_ci  }
2608779efd5Sopenharmony_ci
2618779efd5Sopenharmony_ci  private setMissedBadgeNumber(newBadgeNum: number) {
2628779efd5Sopenharmony_ci    HiLog.i(TAG, 'setMissedBadgeNumber :' + newBadgeNum);
2638779efd5Sopenharmony_ci    this.missedBadgeNumber = newBadgeNum;
2648779efd5Sopenharmony_ci    Notification.setBadgeNumber(newBadgeNum);
2658779efd5Sopenharmony_ci    sharedPreferencesUtils.saveToPreferences(KEY_MISSED_BADGE_NUM, newBadgeNum);
2668779efd5Sopenharmony_ci  }
2678779efd5Sopenharmony_ci
2688779efd5Sopenharmony_ci  /**
2698779efd5Sopenharmony_ci   * create wantAgent for common event
2708779efd5Sopenharmony_ci   *
2718779efd5Sopenharmony_ci   * @param mAction
2728779efd5Sopenharmony_ci   * @return return the created WantAgent object.
2738779efd5Sopenharmony_ci   */
2748779efd5Sopenharmony_ci  private async createWantAgentForCommonEvent(missedCallData, action?: string) {
2758779efd5Sopenharmony_ci    return await WantAgent.getWantAgent({
2768779efd5Sopenharmony_ci      wants: [{ action: 'contact.event.CANCEL_MISSED', parameters: {
2778779efd5Sopenharmony_ci        action: action,
2788779efd5Sopenharmony_ci        missedCallData: missedCallData
2798779efd5Sopenharmony_ci      }, }],
2808779efd5Sopenharmony_ci      operationType: WantAgent.OperationType.SEND_COMMON_EVENT,
2818779efd5Sopenharmony_ci      requestCode: 0
2828779efd5Sopenharmony_ci    })
2838779efd5Sopenharmony_ci  }
2848779efd5Sopenharmony_ci
2858779efd5Sopenharmony_ci  private getWantAgent(missedCallData: MissedCallNotifyData, action: string) {
2868779efd5Sopenharmony_ci    let data: any = {}
2878779efd5Sopenharmony_ci    data.action = action,
2888779efd5Sopenharmony_ci    data.missedCallData = missedCallData
2898779efd5Sopenharmony_ci    if (action == 'notification.event.dialBack') {
2908779efd5Sopenharmony_ci      HiLog.i(TAG, 'getWantAgent add page_flag_edit_before_calling')
2918779efd5Sopenharmony_ci      return this.createWantAgentForCommonEvent(missedCallData, action);
2928779efd5Sopenharmony_ci    }
2938779efd5Sopenharmony_ci    return WantAgent.getWantAgent({
2948779efd5Sopenharmony_ci      wants: [{
2958779efd5Sopenharmony_ci                deviceId: '',
2968779efd5Sopenharmony_ci                bundleName: BUNDLE_NAME,
2978779efd5Sopenharmony_ci                abilityName: ABILITY_NAME,
2988779efd5Sopenharmony_ci                uri: '',
2998779efd5Sopenharmony_ci                type: 'phone',
3008779efd5Sopenharmony_ci                parameters: data,
3018779efd5Sopenharmony_ci                entities: []
3028779efd5Sopenharmony_ci              }],
3038779efd5Sopenharmony_ci      requestCode: 0,
3048779efd5Sopenharmony_ci      operationType: WantAgent.OperationType.START_ABILITY,
3058779efd5Sopenharmony_ci      wantAgentFlags: [WantAgent.WantAgentFlags.ONE_TIME_FLAG]
3068779efd5Sopenharmony_ci    });
3078779efd5Sopenharmony_ci  }
3088779efd5Sopenharmony_ci}