• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 HiLog from '../utils/HiLog';
17import common from '../data/commonData';
18import ConversationListModel from '../model/ConversationListModel';
19import ConversationService from './ConversationService';
20import ContactService from './ContactsService';
21import commonService from './CommonService';
22import telephoneUtils from '../utils/TelephoneUtil';
23import LooseObject from '../data/LooseObject'
24
25const TAG = "ConversationListService";
26
27export default class ConversationListService {
28  private static instance: ConversationListService;
29  private conversationListModel: ConversationListModel = new ConversationListModel();
30
31  private constructor() {
32  }
33
34  public static getInstance(): ConversationListService {
35    if (ConversationListService.instance == null) {
36      ConversationListService.instance = new ConversationListService();
37    }
38    return ConversationListService.instance;
39  }
40
41  public insertSession(valueBucket, callback, context): void {
42    let mmsContext = context ? context : globalThis.mmsContext;
43    if (globalThis.DataWorker != null) {
44      globalThis.DataWorker.sendRequest(common.RUN_IN_WORKER_METHOD.insertSession, {
45        valueBucket: valueBucket,
46        context: mmsContext
47      }, res => {
48        if (callback) {
49          callback(res);
50        }
51      });
52    } else {
53      this.conversationListModel.insertSession(valueBucket, callback, mmsContext);
54    }
55    globalThis.needToUpdate = true;
56  }
57
58  public deleteSessionByCondition(actionData, callback, context): void {
59    let mmsContext = context ? context : globalThis.mmsContext;
60    if (globalThis.DataWorker != null) {
61      globalThis.DataWorker.sendRequest(common.RUN_IN_WORKER_METHOD.deleteSessionByCondition, {
62        actionData: actionData,
63        context: mmsContext
64      }, res => {
65        if (callback) {
66          callback(res);
67        }
68      });
69    } else {
70      this.conversationListModel.deleteSessionByCondition(actionData, callback, mmsContext);
71    }
72    globalThis.needToUpdate = true;
73  }
74
75  public updateSessionByCondition(actionData, valueBucket, callback, context): void {
76    let mmsContext = context ? context : globalThis.mmsContext;
77    if (globalThis.DataWorker != null) {
78      globalThis.DataWorker.sendRequest(common.RUN_IN_WORKER_METHOD.updateSessionByCondition, {
79        actionData: actionData,
80        valueBucket: valueBucket,
81        context: mmsContext
82      }, res => {
83        if (callback) {
84          callback(res);
85        }
86      });
87    } else {
88      this.conversationListModel.updateSessionByCondition(actionData, valueBucket, callback, mmsContext);
89    }
90    globalThis.needToUpdate = true;
91  }
92
93  public querySessionByCondition(actionData, callback, context): void {
94    let mmsContext = context ? context : globalThis.mmsContext;
95    if (globalThis.DataWorker != null) {
96      globalThis.DataWorker.sendRequest(common.RUN_IN_WORKER_METHOD.querySessionByCondition, {
97        actionData: actionData,
98        context: mmsContext
99      }, res => {
100        callback(res);
101      });
102    } else {
103      this.conversationListModel.querySessionByCondition(actionData, callback, mmsContext);
104    }
105  }
106
107  public querySessionSizeByCondition(actionData, callback, context): void {
108    let mmsContext = context ? context : globalThis.mmsContext;
109    if (globalThis.DataWorker != null) {
110      globalThis.DataWorker.sendRequest(common.RUN_IN_WORKER_METHOD.querySessionSizeByCondition, {
111        actionData: actionData,
112        context: mmsContext
113      }, res => {
114        callback(res);
115      });
116    } else {
117      this.conversationListModel.querySessionSizeByCondition(actionData, callback, mmsContext);
118    }
119  }
120
121  public async getSessionListSize(actionData, context): Promise<number> {
122    let condition: LooseObject = {};
123    condition.smsType = actionData.smsType;
124    let result: Promise<number> = new Promise((resolve) => {
125      this.querySessionSizeByCondition(condition, res => {
126        let size: number = 0;
127        if (res.code == common.int.SUCCESS && res.abilityResult != null) {
128          size = res.abilityResult;
129        }
130        resolve(size);
131      }, context);
132    });
133    return result;
134  }
135
136  public getSessionListResult(actionData, context): Promise<LooseObject> {
137    let result: Promise<LooseObject> = new Promise((resolve) => {
138      this.querySessionByCondition(actionData, res => {
139        let result: LooseObject = {
140          "messageList": [],
141          "telephones": []
142        };
143        if (res.code == common.int.SUCCESS && res.abilityResult != null) {
144          result = this.getConvertSessionListResult(res.abilityResult);
145        }
146        resolve(result);
147      }, context)
148    });
149    return result;
150  }
151
152  public isExistNoticeMessage(context): Promise<boolean> {
153    let result: Promise<boolean> = new Promise((resolve) => {
154      let actionData: LooseObject = {};
155      actionData.smsType = common.sms_type.NOTICE;
156      this.querySessionSizeByCondition(actionData, res => {
157        let isExistNoticeMessage: boolean = false;
158        if (res.code == common.int.SUCCESS && res.abilityResult != null && res.abilityResult > 0) {
159          isExistNoticeMessage = true;
160        }
161        resolve(isExistNoticeMessage);
162      }, context);
163    });
164    return result;
165  }
166
167  public querySessionList(actionData, callback, context): void {
168    let result: LooseObject = {};
169    let queryPromise: Promise<LooseObject> = this.getSessionListResult(actionData, context);
170    let countPromise: Promise<number> = this.getSessionListSize(actionData, context);
171    let noticePromise: Promise<boolean> = this.isExistNoticeMessage(context);
172    Promise.all([queryPromise, countPromise, noticePromise]).then(res => {
173      result.code = common.int.SUCCESS;
174      result.total = res[1];
175      result.hasInfoMsg = res[2];
176      result.response = [];
177      HiLog.i(TAG, "querySessionList, sessionList.length: " + res[0].messageList.length + ", total=" + result.total
178      + ", hasInfoMsg=" + result.hasInfoMsg);
179      if (result.total > 0) {
180        this.dealContactsName(res[0].telephones, actionData, res[0].messageList, res => {
181          result.response = res;
182          callback(result);
183        }, context);
184      } else {
185        callback(result);
186      }
187    }).catch(error => {
188      HiLog.e(TAG, "querySessionList, error: " + JSON.stringify(error));
189      result.code = common.int.FAILURE;
190      callback(result);
191    });
192  }
193
194  private getConvertSessionListResult(sessionList): LooseObject {
195    let result: LooseObject = {
196      "messageList": [],
197      "telephones": []
198    };
199    if (sessionList == null) {
200      return result;
201    }
202    let messageList: Array<LooseObject> = [];
203    let telephones: Array<LooseObject> = [];
204    for (let session of sessionList) {
205      let item: LooseObject = {};
206      item.name = common.string.EMPTY_STR;
207      item.contactsNum = session.contactsNum;
208      item.content = session.content;
209      item.countOfUnread = session.unreadCount;
210      if (session.smsType == common.sms_type.COMMON) {
211        item.icon = "icon/user_avatar_full_fill.svg";
212      } else {
213        item.icon = "icon/entrance_icon01.svg";
214      }
215      item.smsType = session.smsType;
216      item.isCbChecked = false;
217      item.isLock = false;
218      item.sendingFailed = session.sendStatus == common.int.SEND_MESSAGE_FAILED ? true : false;
219      item.telephone = session.telephone;
220      if (item.contactsNum > 1) {
221        let telephoneSplit = item.telephone.split(common.string.COMMA);
222        for (let item of telephoneSplit) {
223          telephones.push(item);
224        }
225      } else {
226        telephones.push(item.telephone);
227      }
228      item.telephoneFormat = session.telephoneFormat;
229      item.threadId = session.id;
230      item.timeMillisecond = session.time;
231      item.isDraft = session.hasDraft == 1 ? true : false;
232      item.isLock = session.hasLock == 1 ? true : false;
233      item.time = common.string.EMPTY_STR;
234      item.messageCount = session.messageCount;
235      item.hasMms = session.hasMms == 1 ? true : false;
236      item.hasAttachment = session.hasAttachment == 1 ? true : false;
237      messageList.push(item);
238    }
239    result.messageList = messageList;
240    result.telephones = telephones;
241    return result;
242  }
243
244  private dealContactsName(telephones, actionData, sessionLists, callback, context) {
245    if (telephones.length == 0) {
246      HiLog.w(TAG, "dealContactsName, has no telephones");
247      callback(sessionLists);
248      return;
249    }
250    actionData.telephones = telephones;
251    actionData.hasDelete = "0";
252    ContactService.getInstance().queryContactDataByCondition(actionData, res => {
253      if (res.code == common.int.FAILURE || res.abilityResult.length == 0) {
254        HiLog.w(TAG, "dealContactsName, has no contacts");
255        callback(sessionLists);
256      } else {
257        callback(this.buildSessionNames(res.abilityResult, sessionLists));
258      }
259    }, context);
260  }
261
262  private buildSessionNames(contacts, sessionLists) {
263    let telephoneMap = new Map();
264    for (let item of contacts) {
265      if (item.displayName == common.string.EMPTY_STR) {
266        telephoneMap.set(item.detailInfo, item.detailInfo);
267      } else {
268        telephoneMap.set(item.detailInfo, item.displayName);
269      }
270    }
271    for (let session of sessionLists) {
272      if (session.contactsNum > 1) {
273        this.dealMultiName(session, telephoneMap);
274      } else if (telephoneMap.has(session.telephone)) {
275        session.name = telephoneMap.get(session.telephone);
276      }
277    }
278    return sessionLists;
279  }
280
281  private dealMultiName(session, telephoneMap): void {
282    let telephones: Array<string> = session.telephone.split(common.string.COMMA);
283    let name: string = common.string.EMPTY_STR;
284    for (let telephone of telephones) {
285      if (telephoneMap.has(telephone)) {
286        name = name + telephoneMap.get(telephone) + common.string.COMMA;
287      } else {
288        name = name + telephone + common.string.COMMA;
289      }
290    }
291    session.name = name.substring(0, name.length - 1);
292  }
293
294  public statisticalData(callBack, context): void {
295    let normalPromise = new Promise<LooseObject>((resolve) => {
296      ConversationService.getInstance().statisticalData(res => {
297        if (res.code == common.int.SUCCESS) {
298          resolve(res.abilityResult);
299        } else {
300          HiLog.w(TAG, "statisticalData, failed");
301        }
302      }, context);
303    });
304    let notifyPromise = new Promise<number>((resolve) => {
305      ConversationService.getInstance().statisticsUnreadNotify(res => {
306        resolve(res);
307      }, context);
308    });
309    let result: LooseObject = {};
310    Promise.all([normalPromise, notifyPromise]).then(res => {
311      let normalResult: LooseObject = res[0];
312      let notifyResult: number = res[1];
313      result.code = common.int.SUCCESS;
314      let response: LooseObject = {};
315      response.totalListCount = normalResult.totalListCount;
316      response.unreadCount = normalResult.totalListCount - notifyResult;
317      response.unreadTotalOfInfo = notifyResult;
318      result.response = response;
319      callBack(result);
320    }).catch(error => {
321      HiLog.e(TAG, "statisticalData, failed: " + JSON.stringify(error));
322      result.code = common.int.FAILURE;
323      callBack(result);
324    });
325  }
326
327  public deleteMessageById(actionData, callback, context): void {
328    // Deletes data from the session list.
329    this.deleteSessionByCondition(actionData, callback, context);
330    // Deletes data from the information list.
331    ConversationService.getInstance().deleteSmsMmsInfoByCondition(actionData, null, null);
332  }
333
334  public markAllToRead(actionData) {
335    actionData.unreadCount_greaterThan = 0;
336    let sessionValueBucket: LooseObject = {
337      "unread_count": 0
338    };
339    this.updateSessionByCondition(actionData, sessionValueBucket, null, null);
340
341    actionData.hasRead = common.is_read.UN_READ;
342    let smsMmsInfoValueBucket: LooseObject = {
343      "is_read": common.is_read.READ
344    };
345    ConversationService.getInstance().updateSmsMmsInfoByCondition(actionData, smsMmsInfoValueBucket, null, null);
346  }
347
348  /**
349   * Adding a session draft list
350   *
351   * @param valueBucket New Data
352   * @callback callback
353   */
354  public insertSessionDraft(actionData, callback, context): void {
355    let param: LooseObject = this.dealSendResults(actionData);
356    // Check whether a session list has been created
357    this.querySessionByTelephone(param.telephone, res => {
358      if (res.code == common.int.SUCCESS && res.response.id <= 0) {
359        // If you modify the recipient in draft state and save the modification again, you need to delete the
360        // unnecessary session draft before modification.
361        if (actionData.threadId != 0 && actionData.isDraft) {
362          this.deleteSessionByCondition(actionData, null, null);
363        }
364        this.dealInsertSession(param, actionData, callback, context);
365      } else {
366        this.deleteDraftDataOrUpdate(actionData, res.response, param, callback, context);
367      }
368      globalThis.needToUpdate = true;
369    }, context);
370  }
371
372  public dealInsertSession(param, actionData, callback, context): void {
373    let valueBucket: LooseObject = {
374      "telephone": param.telephone,
375      "content": param.content,
376      "contacts_num": param.contactsNum,
377      "sms_type": param.smsType,
378      "unread_count": 0,
379      "sending_status": common.int.SEND_MESSAGE_SENDING,
380      "has_draft": common.has_draft.HAVE,
381      "time": param.timestamp,
382      "has_mms": param.hasMms,
383      "has_attachment": param.hasAttachment,
384    }
385    this.insertSession(valueBucket, sessionResult => {
386      // Invoke the SMS database to insert SMS messages.
387      let sessionId: number = sessionResult.abilityResult;
388      ConversationService.getInstance().dealInsertMessageDetail(param, actionData, sessionId, res => {
389        callback();
390      }, context);
391    }, context);
392  }
393
394  public deleteDraftDataOrUpdate(actionData, response, param, callback, context): void {
395    if (actionData.groupId > 0) {
396      ConversationService.getInstance().deleteSmsMmsInfoByCondition(actionData, null, null);
397    }
398    if (actionData.content != common.string.EMPTY_STR || actionData.mmsSource.length > 0) {
399      // Save New Draft
400      this.updateDraftData(response, param, actionData, callback, context);
401    } else {
402      if (callback) {
403        callback();
404      }
405    }
406  }
407
408  public updateDraftData(response, param, actionData, callback, context): void {
409    let valueBucket: LooseObject = {
410      "content": param.content,
411      "has_draft": common.has_draft.HAVE,
412      "time": new Date().getTime(),
413      "has_attachment": param.hasAttachment,
414      "has_mms": param.hasMms,
415    }
416    if (response == undefined || response == null) {
417      return
418    }
419    let sessionId: number = response.id;
420    let condition: LooseObject = {};
421    condition.threadId = sessionId;
422    this.updateSessionByCondition(condition, valueBucket, null, null);
423    ConversationService.getInstance().dealInsertMessageDetail(param, actionData, sessionId, res => {
424      if (callback) {
425        callback();
426      }
427    }, context);
428  }
429
430  public dealSendResults(actionData): LooseObject {
431    let contactsNum: number = 1;
432    let telephone: string = common.string.EMPTY_STR;
433    if (actionData.isNewMsg) {
434      let selectContacts = actionData.selectContacts;
435      if (selectContacts.length > 1) {
436        for (let contact of selectContacts) {
437          telephone = telephone + contact.telephone + common.string.COMMA;
438        }
439        // If it fails, then the session list turns out to be a failure.
440        telephone = telephone.substring(0, telephone.length - 1);
441        contactsNum = selectContacts.length;
442      } else if (selectContacts.length == 1) {
443        telephone = selectContacts[0]?.telephone;
444      }
445      let receiveContactValue = actionData.receiveContactValue;
446      if (receiveContactValue != common.string.EMPTY_STR) {
447        telephone = actionData.receiveContactValue;
448      }
449    } else {
450      telephone = actionData.telephone;
451    }
452    let smsType: number = common.sms_type.COMMON;
453    if (contactsNum == 1 && telephoneUtils.judgeIsInfoMsg(telephone)) {
454      smsType = common.sms_type.NOTICE;
455    }
456    let sendResult: LooseObject = {
457      telephone: telephone,
458      content: actionData.content,
459      sendStatus: common.int.SEND_DRAFT
460    }
461    actionData.sendResults = [sendResult];
462    let timestamp = new Date().getTime();
463    let result: LooseObject = {};
464    result.contactsNum = contactsNum;
465    result.telephone = telephoneUtils.dealTelephoneSort(telephone);
466    result.content = actionData.content;
467    if (actionData.isMms) {
468      result.content = commonService.getMmsContent(actionData.mmsSource);
469    }
470    result.sendStatus = common.int.SEND_MESSAGE_SENDING;
471    result.smsType = smsType;
472    result.timestamp = timestamp;
473    result.hasMms = actionData.isMms ? 1 : 0;
474    result.hasAttachment = actionData.hasAttachment ? 1 : 0;
475
476    return result;
477  }
478
479  public querySessionByTelephone(telephone, callback, context): void {
480    let result: LooseObject = {};
481    if (telephone == null) {
482      HiLog.w(TAG, "querySessionByTelephone, telephone is null!");
483      result.code = common.int.FAILURE;
484      callback(result);
485    } else {
486      HiLog.i(TAG, "querySessionByTelephone, telephone != null");
487      let actionData: LooseObject = {};
488      actionData.telephone = telephone;
489      this.querySessionByCondition(actionData, res => {
490        if (res.code == common.int.FAILURE) {
491          callback(res);
492        } else {
493          result.code = common.int.SUCCESS;
494          result.response = res.abilityResult[0];
495          callback(result);
496        }
497      }, context);
498    }
499  }
500
501  public dealMessageLockContent(actionData, callback, context): void {
502    let threadIds = actionData.threadIds;
503    let length: number = threadIds.length;
504    let count: number = 0;
505    for (let id of threadIds) {
506      actionData.threadId = id;
507      if (!actionData.isMessageDetail) {
508        actionData.hasLock = 1;
509      }
510      ConversationService.getInstance().queryMessageDetail(actionData, res => {
511        if (res.code == common.int.SUCCESS && res.response.length > 0) {
512          count++;
513          actionData.mmsList = res.response;
514          this.updateLastItemContent(actionData, null, null);
515        }
516        if (count == length) {
517          callback(common.int.SUCCESS);
518        }
519      }, context);
520    }
521  }
522
523  public updateLastItemContent(actionData, callback, context): void {
524    let valueBucket: LooseObject = {
525      "content": common.string.EMPTY_STR,
526      "sending_status": common.int.SEND_MESSAGE_FAILED,
527      "has_mms": common.has_mms.NO,
528      "has_attachment": common.has_attachment.NO,
529      "message_count": 0,
530      "unread_count": 0
531    };
532    let length: number = actionData.mmsList.length;
533    if (length > 0) {
534      let item: LooseObject = actionData.mmsList[length - 1];
535      valueBucket.content = item.isMsm ? commonService.getMmsContent(item.mms) : item.content;
536      valueBucket.sending_status = item.sendStatus;
537      valueBucket.has_mms = item.isMsm ? common.has_mms.HAVE : common.has_mms.NO;
538      valueBucket.has_attachment = item.isMsm ? common.has_attachment.HAVE : common.has_attachment.NO;
539      valueBucket.message_count = length;
540    }
541    let condition: LooseObject = {
542      threadId: actionData.threadId
543    };
544    this.updateSessionByCondition(condition, valueBucket, callback, context);
545  }
546}