• 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 contractService from "./ContractService";
21import commonService from "./CommonService";
22import telephoneUtils from "../utils/TelephoneUtil";
23import LooseObject from "../data/LooseObject"
24
25let conversationListModel = new ConversationListModel();
26const TAG = "ConversationListService";
27
28export default {
29    /**
30     * Querying list data
31     *
32     * @param actionData
33     * @callback callback
34     */
35    querySessionList(actionData, callback) {
36        // Querying Data Lists
37        let result: LooseObject = {};
38        let queryPromise = conversationListModel.querySessionList(actionData);
39        // Obtains the total number of records.
40        let countPromise = conversationListModel.countSessionList(actionData);
41        // Check whether the notification information exists.
42        let notificationPromise = new Promise((resolve) => {
43            this.judgeIsNotificationData(res => {
44                resolve(res);
45            });
46        });
47        Promise.all([queryPromise, countPromise, notificationPromise]).then((res) => {
48            result.code = common.int.SUCCESS;
49            let telephones = [];
50            let messageList = this.convertSessionList(res[0].response, telephones);
51            result.total = res[1].total;
52            result.hasInfoMsg = res[2];
53            HiLog.i(TAG, "querySessionList, messageList length=" + messageList.length
54            + ", total=" + result.total + ", hasInfoMsg=" + result.hasInfoMsg);
55            this.dealContactsName(telephones, actionData, messageList, sessionList => {
56                HiLog.i(TAG, "querySessionList, dealContactsName len=" + sessionList.length);
57                result.response = sessionList;
58                callback(result);
59            });
60        }).catch((err) => {
61            HiLog.e(TAG, "querySessionList, error: " + JSON.stringify(err.message));
62            result.code = common.int.FAILURE;
63            callback(result);
64        });
65    },
66
67    convertSessionList(sessionList, telephones) {
68        let messageList = [];
69        for (let session of sessionList) {
70            let item: LooseObject = {};
71            item.name = common.string.EMPTY_STR;
72            item.contactsNum = session.contactsNum;
73            item.content = session.content;
74            item.countOfUnread = session.unreadCount;
75            if (session.smsType == 0) {
76                item.icon = "icon/user_avatar_full_fill.svg";
77            } else {
78                item.icon = "icon/entrance_icon01.svg";
79            }
80            item.smsType = session.smsType;
81            item.isCbChecked = false;
82            item.isLock = false;
83            item.sendingFailed = session.sendStatus == common.int.SEND_MESSAGE_FAILED ? true : false;
84            item.telephone = session.telephone;
85            if (item.contactsNum > 1) {
86                let telephoneSplit = item.telephone.split(common.string.COMMA);
87                for (let item of telephoneSplit) {
88                    telephones.push(item);
89                }
90            } else {
91                telephones.push(item.telephone);
92            }
93            item.telephoneFormat = session.telephoneFormat;
94            item.threadId = session.id;
95            item.timeMillisecond = session.time;
96            item.isDraft = session.hasDraft == 1 ? true : false;
97            item.isLock = session.hasLock == 1 ? true : false;
98            item.time = common.string.EMPTY_STR;
99            item.messageCount = session.messageCount;
100            item.hasMms = session.hasMms == 1 ? true : false;
101            item.hasAttachment = session.hasAttachment == 1 ? true : false;
102            messageList.push(item);
103        }
104        return messageList;
105    },
106
107    dealContactsName(telephones, actionData, sessionLists, callback) {
108        actionData.telephones = telephones;
109        if (telephones.length == 0) {
110            HiLog.w(TAG, "dealContactsName, has no telephones");
111            callback(sessionLists);
112            return;
113        }
114        contractService.queryContactDataByTelephone(actionData, contacts => {
115            if (contacts.length == 0) {
116                HiLog.w(TAG, "dealContactsName, has no contacts");
117                callback(sessionLists);
118            } else {
119                // Convert the result to Map, key: mobile number, value: name
120                let telephoneMap = this.getTelephoneMap(contacts);
121                this.buildName(sessionLists, telephoneMap);
122                callback(sessionLists);
123            }
124        });
125    },
126
127    getTelephoneMap(contacts) {
128        let telephoneMap = new Map();
129        for (let item of contacts) {
130            if (item.displayName == common.string.EMPTY_STR) {
131                telephoneMap.set(item.detailInfo, item.detailInfo);
132            } else {
133                telephoneMap.set(item.detailInfo, item.displayName);
134            }
135        }
136        return telephoneMap;
137    },
138
139    buildName(sessionLists, telephoneMap) {
140        // Match the result based on the mobile number.
141        for (let session of sessionLists) {
142            // Indicates the combination of multiple names. The names need to be displayed in combination.
143            if (session.contactsNum > 1) {
144                this.dealMultiName(session, telephoneMap);
145            } else if (telephoneMap.has(session.telephone)) {
146                session.name = telephoneMap.get(session.telephone);
147            }
148        }
149    },
150
151    dealMultiName(session, telephoneMap) {
152        let telephones = session.telephone.split(common.string.COMMA);
153        let name = common.string.EMPTY_STR;
154        for (let telephone of telephones) {
155            if (telephoneMap.has(telephone)) {
156                name = name + telephoneMap.get(telephone) + common.string.COMMA;
157            } else {
158                name = name + telephone + common.string.COMMA;
159            }
160        }
161        session.name = name.substring(0, name.length - 1);
162    },
163
164    /**
165     * Check whether notification data exists.
166     *
167     * @callback callback
168     */
169    judgeIsNotificationData(callback) {
170        let param = {
171            numberType: 1,
172            limit: 1,
173            page: 1
174        };
175        this.querySessionByNumberType(param, res => {
176            if (res.code == common.int.SUCCESS && res.response.length > 0) {
177                callback(true);
178            } else {
179                callback(false);
180            }
181        });
182    },
183
184    /**
185     * statistical data
186     *
187     * @param actionData
188     * @callBack callBack
189     */
190    statisticalData(actionData, callBack) {
191        let normalPromise = new Promise<LooseObject>((resolve) => {
192            conversationListModel.statisticalData(actionData, res => {
193                let result: LooseObject = {};
194                result.code = res.code;
195                if (res.code == common.int.SUCCESS) {
196                    result.response = res.abilityResult;
197                    resolve(result.response);
198                } else {
199                    HiLog.w(TAG, "statisticalData, failed");
200                }
201            });
202        });
203        let notifyPromise = new Promise<number>((resolve) => {
204            conversationService.statisticsUnreadNotify(actionData, res => {
205                resolve(res);
206            });
207        });
208        Promise.all([normalPromise, notifyPromise]).then(res => {
209            let normalResult = res[0];
210            let notifyResult = res[1];
211            let response = {
212                "totalListCount": normalResult.totalListCount,
213                "unreadCount": (normalResult.totalListCount - notifyResult),
214                "unreadTotalOfInfo": notifyResult
215            }
216            let result = {
217                code: common.int.SUCCESS,
218                response: response
219            }
220            callBack(result);
221        }).catch(err => {
222            HiLog.e(TAG, "statisticalData, failed: " + JSON.stringify(err));
223            let result = {
224                code: common.int.FAILURE
225            }
226            callBack(result);
227        });
228    },
229
230    /**
231     * Delete data based on the primary key id.
232     *
233     * @param threadIds Session ID
234     */
235    deleteMessageById(actionData) {
236        // Deletes data from the session list.
237        conversationListModel.deleteMessageById(actionData.threadIds);
238        // Deletes data from the information list.
239        conversationService.deleteMessageBySessionIds(actionData);
240    },
241
242    /**
243     * Delete data based on the primary key id.
244     *
245     * @param threadIds Session ID
246     */
247    deleteMessageBySessionId(threadIds) {
248        // Deletes data from the session list.
249        conversationListModel.deleteMessageById(threadIds);
250        globalThis.needToUpdate = true;
251    },
252
253    /**
254     * Update data based on the primary key id.
255     *
256     * @param threadIds Session ID
257     * @param valueBucket
258     */
259    updateById(threadIds, valueBucket) {
260        conversationListModel.updateById(threadIds, valueBucket);
261        globalThis.needToUpdate = true;
262    },
263
264    /**
265     * Marking a read SMS message
266     *
267     * @param actionData
268     */
269    markAllAsRead(actionData) {
270        if (actionData.threadIds.length == 0) {
271            return;
272        }
273        // Tag on session list read
274        conversationListModel.markAllAsRead(actionData.threadIds, actionData.valueBucket);
275        // SMS message read
276        conversationService.markAllAsRead(actionData);
277    },
278
279    /**
280     * Updates all unread information to read.
281     *
282     * @param actionData
283     */
284    markAllToRead(actionData) {
285        conversationListModel.markAllToRead(actionData.smsType);
286        conversationService.markAllToRead(actionData);
287    },
288
289    /**
290     * Add a new session list
291     *
292     * @param valueBucket New data
293     * @callback callback
294     */
295    insertSession(valueBucket, callback) {
296        conversationListModel.insertSession(valueBucket, res => {
297            callback(res);
298        });
299    },
300
301    /**
302     * Adding a session draft list
303     *
304     * @param valueBucket New Data
305     * @callback callback
306     */
307    insertSessionDraft(actionData, callback) {
308        let param = this.dealSendResults(actionData);
309        // Check whether a session list has been created
310        this.querySessionByTelephone(param.telephone, res => {
311            let response = res.response;
312            if(res.code == common.int.SUCCESS && response.id <= 0) {
313                // If you modify the recipient in draft state and save the modification again, you need to delete the
314                // unnecessary session draft before modification.
315                if (actionData.threadId != 0) {
316                    conversationListModel.deleteMessageById([actionData.threadId]);
317                }
318                this.dealInsertSession(param, actionData, callback);
319            } else {
320                this.deleteDraftDataOrUpdate(actionData, response, param, callback);
321            }
322            globalThis.needToUpdate = true;
323        });
324    },
325
326    dealInsertSession(param, actionData, callback) {
327        let valueBucket = {
328            "telephone": param.telephone,
329            "content": param.content,
330            "contacts_num": param.contractsNum,
331            "sms_type": param.smsType,
332            "unread_count": 0,
333            "sending_status": 1,
334            "has_draft": 1,
335            "time": param.timestamp,
336            "has_mms": param.hasMms,
337            "has_attachment": param.hasAttachment,
338        }
339        this.insertSession(valueBucket, sessionResult => {
340            // Invoke the SMS database to insert SMS messages.
341            let sessionId = sessionResult.rowId;
342            conversationService.dealInsertMessageDetail(param, actionData, sessionId, res => {
343                callback();
344            });
345        });
346    },
347
348    deleteDraftDataOrUpdate(actionData, response, param, callback) {
349        if (actionData.groupId > 0) {
350            let groupIds = [actionData.groupId];
351            actionData.groupIds = groupIds;
352            // Delete the original draft first.
353            conversationService.deleteMessageByGroupIds(actionData);
354        }
355        if (actionData.content != common.string.EMPTY_STR || actionData.mmsSource.length > 0) {
356            // Save New Draft
357            this.updateDraftData(response, param, actionData, callback);
358        } else {
359            callback();
360        }
361    },
362
363    updateDraftData(response, param, actionData, callback) {
364        let sessionId = response.id;
365        // Invoke the SMS database to insert SMS messages.
366        let threadIds = [sessionId];
367        let time = new Date();
368        let valueBucket = {
369            "content": param.content,
370            "has_draft": 1,
371            "time": time.getTime(),
372            "has_attachment": param.hasAttachment,
373            "has_mms": param.hasMms,
374        }
375        this.updateById(threadIds, valueBucket);
376        conversationService.dealInsertMessageDetail(param, actionData, sessionId, res => {
377            callback();
378        });
379    },
380
381    dealSendResults(actionData) {
382        let contractsNum = 1;
383        let telephone = common.string.EMPTY_STR;
384        if (actionData.isNewMsg) {
385            let selectContacts = actionData.selectContacts;
386            if (selectContacts.length > 1) {
387                for (let contact of selectContacts) {
388                    telephone = telephone + contact.telephone + common.string.COMMA;
389                }
390                // If it fails, then the session list turns out to be a failure.
391                telephone = telephone.substring(0, telephone.length - 1);
392                contractsNum = selectContacts.length;
393            } else if (selectContacts.length == 1) {
394                telephone = selectContacts[0]?.telephone;
395            }
396            let receiveContactValue = actionData.receiveContactValue;
397            if (receiveContactValue != common.string.EMPTY_STR) {
398                telephone = actionData.receiveContactValue;
399            }
400        } else {
401            telephone = actionData.telephone;
402        }
403        let smsType = 0;
404        if (contractsNum == 1 && telephoneUtils.judgeIsInfoMsg(telephone)) {
405            smsType = 1;
406        }
407        let sendResult = {
408            telephone: telephone,
409            content: actionData.content,
410            sendStatus: common.int.SEND_DRAFT
411        }
412        actionData.sendResults = [sendResult];
413        let timestamp = new Date().getTime();
414        let result: LooseObject = {};
415        result.contractsNum = contractsNum;
416        result.telephone = telephoneUtils.dealTelephoneSort(telephone);
417        result.content = actionData.content;
418        if (actionData.isMms) {
419            result.content = commonService.getMmsContent(actionData.mmsSource);
420        }
421        result.sendStatus = 1;
422        result.smsType = smsType;
423        result.timestamp = timestamp;
424        result.hasMms = actionData.isMms ? 1 : 0;
425        result.hasAttachment = actionData.hasAttachment ? 1 : 0;
426        return result;
427    },
428
429    /**
430     * Querying the session list by mobile number
431     *
432     * @param actionData
433     * @callback callback
434     */
435    querySessionByNumberType(actionData, callback) {
436        let result: LooseObject = {};
437        let queryPromise = conversationListModel.querySessionList(actionData);
438        Promise.all([queryPromise]).then((res) => {
439            result.code = common.int.SUCCESS;
440            result.response = res[0].response;
441            HiLog.i(TAG, "querySessionList SUCCESS. len=" + result.response.length);
442            callback(result);
443        }).catch((err) => {
444            HiLog.e(TAG, "querySessionByNumberType, error: " + JSON.stringify(err.message));
445            result.code = common.int.FAILURE;
446            callback(result);
447        });
448    },
449
450    /**
451     * Querying the session list by mobile number
452     *
453     * @param telephone
454     * @callback callback
455     */
456    querySessionByTelephone(telephone, callback) {
457        let result: LooseObject = {};
458        if (telephone == null) {
459            HiLog.w(TAG, "querySesByTele, telephone == null")
460            result.code = common.int.FAILURE;
461            callback(result);
462        } else {
463            HiLog.i(TAG, "querySesByTele, telephone != null")
464            let queryPromise = conversationListModel.querySessionByTelephone(telephone);
465            Promise.all([queryPromise]).then((res) => {
466                result.code = common.int.SUCCESS;
467                result.response = res[0];
468                callback(result);
469            }).catch((err) => {
470                HiLog.e(TAG, "querySesByTele, error: " + JSON.stringify(err.message));
471                result.code = common.int.FAILURE;
472                callback(result);
473            });
474        }
475    },
476
477    /**
478     * Querying the session list by mobile number
479     *
480     * @param telephone
481     * @callback callback
482     */
483    querySessionById(threadId, callback) {
484        let result: LooseObject = {};
485        HiLog.i(TAG, "querySessionById, threadId:" + threadId);
486        let queryPromise = conversationListModel.querySessionById(threadId);
487        Promise.all([queryPromise]).then((res) => {
488            result.code = common.int.SUCCESS;
489            result.response = res[0];
490            callback(result);
491        }).catch((err) => {
492            HiLog.e(TAG, "querySessionById, error: " + JSON.stringify(err.message));
493            result.code = common.int.FAILURE;
494            callback(result);
495        });
496    },
497
498    deleteMessageBySessionIdsAndLock(actionData) {
499        conversationService.deleteMessageBySessionIdsAndLock(actionData);
500    },
501
502    dealMessageLockContent(actionData, callback) {
503        let threadIds = actionData.threadIds;
504        let length = threadIds.length;
505        let count = 0;
506        for (let id of threadIds) {
507            actionData.threadId = id;
508            if (!actionData.isMessageDetail) {
509                actionData.hasLock = 1;
510            }
511            conversationService.queryMessageDetail(actionData, res => {
512                if (res.code == common.int.SUCCESS && res.response.length > 0) {
513                    count++;
514                    actionData.mmsList = res.response;
515                    this.updateLastItemContent(actionData);
516                }
517                if (count == length) {
518                    callback(common.int.SUCCESS);
519                }
520            });
521        }
522    },
523
524    updateLastItemContent(actionData) {
525        let length = actionData.mmsList.length;
526        let item = actionData.mmsList[length - 1];
527        let content = item.content || '';
528        let threadIds = [actionData.threadId];
529        let hasAttachment = false;
530        if (item.isMsm) {
531            content = commonService.getMmsContent(item.mms);
532            hasAttachment = true;
533        }
534        let valueBucket = {
535            "content": content,
536            "sending_status": item.sendStatus,
537            "has_mms": item.isMsm ? 1 : 0,
538            "has_attachment": hasAttachment ? 1 : 0,
539            "message_count": length,
540            "unread_count": 0
541        };
542        this.updateById(threadIds, valueBucket);
543    },
544
545    /**
546     * Search message with text
547     *
548     * @param actionData
549     * @callback callback
550     */
551    searchMessageWithLike(actionData, callback) {
552        // Session Details Search Data
553        let searchText = actionData.inputValue;
554        let sessionListPromise = new Promise((resolve, reject) => {
555            this.searchSessionByTelephone(actionData, res => {
556                if (res.code === common.int.SUCCESS) {
557                    resolve(res.response);
558                } else {
559                    reject(res.code);
560                }
561            });
562        });
563        // Information List Search Data
564        let contentListPromise = new Promise((resolve, reject) => {
565            conversationService.searchMessageByContent(actionData, res => {
566                if (res.code === common.int.SUCCESS) {
567                    resolve(res.response);
568                } else {
569                    reject(res.code);
570                }
571            });
572        });
573        let resultMap: LooseObject = {};
574        let result: LooseObject = {};
575        Promise.all([sessionListPromise, contentListPromise]).then((res) => {
576            result.code = common.int.SUCCESS;
577            resultMap.sessionList = res[0];
578            resultMap.contentList = res[1];
579            result.resultMap = resultMap;
580            result.search = searchText;
581            callback(result);
582        }).catch((err) => {
583            HiLog.e(TAG, "searchMessageWithLike, error: " + JSON.stringify(err.message));
584            result.code = common.int.FAILURE;
585            callback(result);
586        });
587    },
588
589    /**
590     * Fuzzy match of the session list based on the mobile number
591     *
592     * @param actionData
593     * @callback callback
594     */
595    async searchSessionByTelephone(actionData, callback) {
596        let result: LooseObject = {};
597        let telephone = actionData.inputValue;
598        let numberType = actionData.numberType;
599        let queryPromise = conversationListModel.searchSessionByTelephone(telephone, numberType);
600        queryPromise.then((res) => {
601            result.code = common.int.SUCCESS;
602            let telephones = [];
603            let messageList = this.convertSessionList(res, telephones);
604            this.dealContactsName(telephones, actionData, messageList, sessionList => {
605                result.response = this.dealSessionLikeData(sessionList);
606                callback(result);
607            });
608        }).catch((err) => {
609            HiLog.e(TAG, "searchSessionByTelephone, error: " + JSON.stringify(err.message));
610            result.code = common.int.FAILURE;
611            callback(result);
612        });
613    },
614
615    dealSessionLikeData(mmList) {
616        let sessionList = [];
617        for (let item of mmList) {
618            let map: LooseObject = {}
619            map.name = item.name;
620            map.threadId = item.threadId;
621            map.telephone = item.telephone;
622            map.telephoneFormat = item.telephoneFormat;
623            map.contactsNum = item.contactsNum;
624            map.isDraft = item.isDraft;
625            let names = item.name.split(common.string.COMMA);
626            let telephones = item.telephone.split(common.string.COMMA);
627            let telephoneFormats = item.telephoneFormat.split(common.string.COMMA);
628            let nameFormatter = common.string.EMPTY_STR;
629            let index = 0;
630            for (let name of names) {
631                nameFormatter += (name == null || name == common.string.EMPTY_STR ? telephones[index] : name);
632                nameFormatter += "<";
633                nameFormatter += telephoneFormats[index];
634                nameFormatter += ">";
635                if (index < telephones.length - 1) {
636                    nameFormatter += common.string.COMMA;
637                }
638                index++;
639            }
640            map.nameFormatter = nameFormatter;
641            map.date = common.string.EMPTY_STR;
642            map.time = common.string.EMPTY_STR;
643            map.timeMillisecond = item.timeMillisecond;
644            map.size = item.messageCount;
645            map.icon = item.icon;
646            sessionList.push(map);
647        }
648        return sessionList;
649    }
650}