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_ci 168779efd5Sopenharmony_ciimport ICallLogService from './ICallLogService'; 178779efd5Sopenharmony_ciimport { CallLog } from './entity/CallLog'; 188779efd5Sopenharmony_ciimport { CallType } from './entity/CallLog'; 198779efd5Sopenharmony_ciimport { ArrayUtil } from '../../../../../common/src/main/ets/util/ArrayUtil'; 208779efd5Sopenharmony_ciimport MergedCallLog from './entity/MergedCallLog'; 218779efd5Sopenharmony_ciimport { StringUtil } from '../../../../../common/src/main/ets/util/StringUtil'; 228779efd5Sopenharmony_ciimport { MergeRule } from './CallLogSetting'; 238779efd5Sopenharmony_ciimport StringFormatUtil from '../../../../../entry/src/main/ets/util/StringFormatUtil'; 248779efd5Sopenharmony_ci 258779efd5Sopenharmony_ciexport class CallLogService implements ICallLogService { 268779efd5Sopenharmony_ci private static instance: CallLogService; 278779efd5Sopenharmony_ci private mergeRule: MergeRule; 288779efd5Sopenharmony_ci private context: Context; 298779efd5Sopenharmony_ci 308779efd5Sopenharmony_ci private constructor() { 318779efd5Sopenharmony_ci } 328779efd5Sopenharmony_ci 338779efd5Sopenharmony_ci /* 348779efd5Sopenharmony_ci * init if Call From serviceAbility globalThis.context is Null 358779efd5Sopenharmony_ci *@param ctx Context used for dataShare 368779efd5Sopenharmony_ci */ 378779efd5Sopenharmony_ci init(ctx: Context) { 388779efd5Sopenharmony_ci this.context = ctx; 398779efd5Sopenharmony_ci } 408779efd5Sopenharmony_ci 418779efd5Sopenharmony_ci public static getInstance(): CallLogService { 428779efd5Sopenharmony_ci if (!CallLogService.instance) { 438779efd5Sopenharmony_ci CallLogService.instance = new CallLogService(); 448779efd5Sopenharmony_ci } 458779efd5Sopenharmony_ci return CallLogService.instance; 468779efd5Sopenharmony_ci } 478779efd5Sopenharmony_ci 488779efd5Sopenharmony_ci setMergeRule(mergeRule: MergeRule) { 498779efd5Sopenharmony_ci this.mergeRule = mergeRule; 508779efd5Sopenharmony_ci } 518779efd5Sopenharmony_ci 528779efd5Sopenharmony_ci mergeCallLogs(callLogs: CallLog[]) { 538779efd5Sopenharmony_ci if (this.getMergeRule() === MergeRule.CONTACT) { 548779efd5Sopenharmony_ci return this.mergeByContact(callLogs); 558779efd5Sopenharmony_ci } else { 568779efd5Sopenharmony_ci return this.mergeByTime(callLogs); 578779efd5Sopenharmony_ci } 588779efd5Sopenharmony_ci } 598779efd5Sopenharmony_ci 608779efd5Sopenharmony_ci mergeMissedCalls(callLogs: CallLog[]) { 618779efd5Sopenharmony_ci let mergeRule = this.getMergeRule(); 628779efd5Sopenharmony_ci let callLogList: CallLog[] = []; 638779efd5Sopenharmony_ci let missedList: CallLog[] = []; 648779efd5Sopenharmony_ci for (let callLog of callLogs) { 658779efd5Sopenharmony_ci callLogList.push(callLog); 668779efd5Sopenharmony_ci if (callLog.callType == CallType.MISSED || 678779efd5Sopenharmony_ci callLog.callType == CallType.REJECTED) { 688779efd5Sopenharmony_ci //Filtering Missed Call Data 698779efd5Sopenharmony_ci missedList.push(callLog); 708779efd5Sopenharmony_ci let timeList = []; 718779efd5Sopenharmony_ci // Filtering by Contact Missed Calls and Redialing 728779efd5Sopenharmony_ci if (mergeRule === MergeRule.CONTACT) { 738779efd5Sopenharmony_ci for (let k = 0; k < missedList.length; k++) { 748779efd5Sopenharmony_ci let missedPhone = missedList[k].phoneNumber; 758779efd5Sopenharmony_ci for (let i = 0; i < callLogList.length; i++) { 768779efd5Sopenharmony_ci let allSpecialPhone = callLogList[i].phoneNumber; 778779efd5Sopenharmony_ci if (missedPhone == allSpecialPhone) { 788779efd5Sopenharmony_ci let timeNumber = callLogList[i].createTime; 798779efd5Sopenharmony_ci let obj = { 808779efd5Sopenharmony_ci 'id': i, 818779efd5Sopenharmony_ci 'timeObj': timeNumber, 828779efd5Sopenharmony_ci }; 838779efd5Sopenharmony_ci timeList.push(obj); 848779efd5Sopenharmony_ci let max = timeList[0].timeObj; 858779efd5Sopenharmony_ci for (let j = 0; j < timeList.length; j++) { 868779efd5Sopenharmony_ci if (timeList[j].timeObj > max) { 878779efd5Sopenharmony_ci max = timeList[j].timeObj; 888779efd5Sopenharmony_ci let n = timeList[j].id; 898779efd5Sopenharmony_ci if (callLogList[n].callType == CallType.OUT) { 908779efd5Sopenharmony_ci missedList.splice(k, 1); 918779efd5Sopenharmony_ci } 928779efd5Sopenharmony_ci } else { 938779efd5Sopenharmony_ci let m = timeList[0].id; 948779efd5Sopenharmony_ci if (callLogList[m].callType == CallType.OUT) { 958779efd5Sopenharmony_ci missedList.splice(k, 1); 968779efd5Sopenharmony_ci } 978779efd5Sopenharmony_ci } 988779efd5Sopenharmony_ci } 998779efd5Sopenharmony_ci } 1008779efd5Sopenharmony_ci } 1018779efd5Sopenharmony_ci } 1028779efd5Sopenharmony_ci } 1038779efd5Sopenharmony_ci } 1048779efd5Sopenharmony_ci } 1058779efd5Sopenharmony_ci if (mergeRule === MergeRule.CONTACT) { 1068779efd5Sopenharmony_ci return this.mergeByContact(missedList); 1078779efd5Sopenharmony_ci } else { 1088779efd5Sopenharmony_ci return this.mergeByTime(missedList); 1098779efd5Sopenharmony_ci } 1108779efd5Sopenharmony_ci } 1118779efd5Sopenharmony_ci 1128779efd5Sopenharmony_ci /** 1138779efd5Sopenharmony_ci * In the case of merging by time, the post-processing of the call record 1148779efd5Sopenharmony_ci * service data is optimized based on the original call record data. 1158779efd5Sopenharmony_ci * @param callLogList 1168779efd5Sopenharmony_ci * @return 1178779efd5Sopenharmony_ci */ 1188779efd5Sopenharmony_ci private mergeByTime(callLogList: CallLog[]) { 1198779efd5Sopenharmony_ci let resultList = []; 1208779efd5Sopenharmony_ci if (ArrayUtil.isEmpty(callLogList)) { 1218779efd5Sopenharmony_ci return resultList; 1228779efd5Sopenharmony_ci } 1238779efd5Sopenharmony_ci // Call records are cached from the first record. 1248779efd5Sopenharmony_ci let tempElement = new MergedCallLog(callLogList[0]); 1258779efd5Sopenharmony_ci // Indicates the creation time of the latest record. 1268779efd5Sopenharmony_ci // After call records are merged, the time is displayed. 1278779efd5Sopenharmony_ci let tempCallTime = callLogList[0].createTime; 1288779efd5Sopenharmony_ci // Type of the call record that retains the latest record. 1298779efd5Sopenharmony_ci // This type is displayed after the call record is combined. 1308779efd5Sopenharmony_ci let tempCallType = callLogList[0].callType; 1318779efd5Sopenharmony_ci let num = 1; 1328779efd5Sopenharmony_ci let ids = []; 1338779efd5Sopenharmony_ci ids.push(callLogList[0].id); 1348779efd5Sopenharmony_ci for (let i = 1; i < callLogList.length; i++) { 1358779efd5Sopenharmony_ci let element = callLogList[i]; 1368779efd5Sopenharmony_ci // Whether the cached field needs to be combined with the current field 1378779efd5Sopenharmony_ci if (this.callLogMergeCheck(tempElement, element)) { 1388779efd5Sopenharmony_ci num++; 1398779efd5Sopenharmony_ci // Put the latest record ID into the merged array. 1408779efd5Sopenharmony_ci ids.push(element.id); 1418779efd5Sopenharmony_ci } else { 1428779efd5Sopenharmony_ci //If the latest data is inconsistent with the cached data, 1438779efd5Sopenharmony_ci // replace the num and ids data in the cached data and 1448779efd5Sopenharmony_ci // save the cached data to the result set. 1458779efd5Sopenharmony_ci tempElement.count = num; 1468779efd5Sopenharmony_ci tempElement.ids = ids; 1478779efd5Sopenharmony_ci // Displays the creation time of the latest saved record. 1488779efd5Sopenharmony_ci tempElement.createTime = this.formatTime(tempCallTime); 1498779efd5Sopenharmony_ci tempElement.callType = tempCallType; 1508779efd5Sopenharmony_ci resultList.push(tempElement); 1518779efd5Sopenharmony_ci /* Reset num and ids to the latest count and record, 1528779efd5Sopenharmony_ci and reset tempCallTime to the latest creation time of the next record.*/ 1538779efd5Sopenharmony_ci num = 1; 1548779efd5Sopenharmony_ci ids = []; 1558779efd5Sopenharmony_ci tempCallTime = element.createTime; 1568779efd5Sopenharmony_ci tempCallType = element.callType; 1578779efd5Sopenharmony_ci ids.push(element.id); 1588779efd5Sopenharmony_ci } 1598779efd5Sopenharmony_ci tempElement = new MergedCallLog(element); 1608779efd5Sopenharmony_ci } 1618779efd5Sopenharmony_ci /* Put the last piece of cached data into the result set*/ 1628779efd5Sopenharmony_ci if (tempElement != null) { 1638779efd5Sopenharmony_ci tempElement.count = num; 1648779efd5Sopenharmony_ci tempElement.ids = ids; 1658779efd5Sopenharmony_ci tempElement.createTime = this.formatTime(tempCallTime); 1668779efd5Sopenharmony_ci tempElement.callType = tempCallType; 1678779efd5Sopenharmony_ci resultList.push(tempElement); 1688779efd5Sopenharmony_ci } 1698779efd5Sopenharmony_ci return resultList; 1708779efd5Sopenharmony_ci } 1718779efd5Sopenharmony_ci 1728779efd5Sopenharmony_ci /** 1738779efd5Sopenharmony_ci * In the case of merging by contact, the post-processing 1748779efd5Sopenharmony_ci * of the call record service data is optimized based on the original call record data. 1758779efd5Sopenharmony_ci * 1768779efd5Sopenharmony_ci * @param {Array} callLogList 1778779efd5Sopenharmony_ci * @return {Array} callLogList 1788779efd5Sopenharmony_ci */ 1798779efd5Sopenharmony_ci private mergeByContact(callLogs: CallLog[]) { 1808779efd5Sopenharmony_ci let resultList = []; 1818779efd5Sopenharmony_ci if (ArrayUtil.isEmpty(callLogs)) { 1828779efd5Sopenharmony_ci return resultList; 1838779efd5Sopenharmony_ci } 1848779efd5Sopenharmony_ci let contactTempMap = new Map(); 1858779efd5Sopenharmony_ci let phoneNumberMap = new Map(); 1868779efd5Sopenharmony_ci for (let i = 0; i < callLogs.length; i++) { 1878779efd5Sopenharmony_ci let element = new MergedCallLog(callLogs[i]); 1888779efd5Sopenharmony_ci element.createTime = this.formatTime(callLogs[i].createTime); 1898779efd5Sopenharmony_ci // In the case of merging by contact, the combined record entry is fixed to 1. 1908779efd5Sopenharmony_ci element.count = 1; 1918779efd5Sopenharmony_ci // In the case of merging by contact, the IDs of 1928779efd5Sopenharmony_ci // the merging record are fixed to the ID of the record. 1938779efd5Sopenharmony_ci element.ids = [callLogs[i].id]; 1948779efd5Sopenharmony_ci // Call records without contacts are combined by phone number. 1958779efd5Sopenharmony_ci if (StringUtil.isEmpty(element.quickSearchKey)) { 1968779efd5Sopenharmony_ci if (!phoneNumberMap.has(element.phoneNumber)) { 1978779efd5Sopenharmony_ci resultList.push(element); 1988779efd5Sopenharmony_ci phoneNumberMap.set(element.phoneNumber, callLogs[i].phoneNumber); 1998779efd5Sopenharmony_ci } 2008779efd5Sopenharmony_ci } else { // Call records with contacts are merged by contact. 2018779efd5Sopenharmony_ci let isContactKey = contactTempMap.has(element.quickSearchKey); 2028779efd5Sopenharmony_ci if (!isContactKey) { 2038779efd5Sopenharmony_ci resultList.push(element); 2048779efd5Sopenharmony_ci contactTempMap.set(element.quickSearchKey, callLogs[i].quickSearchKey); 2058779efd5Sopenharmony_ci } 2068779efd5Sopenharmony_ci } 2078779efd5Sopenharmony_ci } 2088779efd5Sopenharmony_ci return resultList; 2098779efd5Sopenharmony_ci } 2108779efd5Sopenharmony_ci 2118779efd5Sopenharmony_ci /** 2128779efd5Sopenharmony_ci * Obtain the call time. 2138779efd5Sopenharmony_ci * 2148779efd5Sopenharmony_ci * @param date Call record creation timestamp 2158779efd5Sopenharmony_ci * @return {object} Talk time 2168779efd5Sopenharmony_ci */ 2178779efd5Sopenharmony_ci private formatTime(date) { 2188779efd5Sopenharmony_ci let result; 2198779efd5Sopenharmony_ci // If the value is not a number, the value is not parsed. 2208779efd5Sopenharmony_ci if (isNaN(date)) { 2218779efd5Sopenharmony_ci return date; 2228779efd5Sopenharmony_ci } 2238779efd5Sopenharmony_ci let timestamp = parseInt(date) * 1000; 2248779efd5Sopenharmony_ci let callTime = new Date(timestamp); 2258779efd5Sopenharmony_ci let now = new Date(); 2268779efd5Sopenharmony_ci if (callTime.getTime() > now.getTime()) { 2278779efd5Sopenharmony_ci result = callTime.getFullYear() + '/' + (callTime.getMonth() + 1) + '/' + callTime.getDate(); 2288779efd5Sopenharmony_ci } else if (callTime.getFullYear() == now.getFullYear()) { 2298779efd5Sopenharmony_ci if (callTime.getMonth() == now.getMonth()) { 2308779efd5Sopenharmony_ci // Same month of the same year 2318779efd5Sopenharmony_ci let timeDiff = parseInt(((now.getTime() - callTime.getTime()) / 60000).toString()); 2328779efd5Sopenharmony_ci let dayDiff = now.getDate() - callTime.getDate(); 2338779efd5Sopenharmony_ci let hour = callTime.getHours().toString(); 2348779efd5Sopenharmony_ci let minutes = callTime.getMinutes() < 10 ? '0' + callTime.getMinutes() : callTime.getMinutes().toString(); 2358779efd5Sopenharmony_ci if (dayDiff == 0) { 2368779efd5Sopenharmony_ci // 同天 2378779efd5Sopenharmony_ci if (timeDiff == 0) { 2388779efd5Sopenharmony_ci result = $r("app.string.justNow"); 2398779efd5Sopenharmony_ci } else if (timeDiff < 60) { 2408779efd5Sopenharmony_ci result = $r("app.string.minutesAgo", timeDiff); 2418779efd5Sopenharmony_ci } else { 2428779efd5Sopenharmony_ci let timeDetail: any = {}; 2438779efd5Sopenharmony_ci if (parseInt(StringFormatUtil.judgeSysTime(this.context)) == 12) { 2448779efd5Sopenharmony_ci timeDetail.time = StringFormatUtil.getDayMessage(hour, minutes); 2458779efd5Sopenharmony_ci } else { 2468779efd5Sopenharmony_ci timeDetail.time = $r("app.string.time_normal", hour, minutes); 2478779efd5Sopenharmony_ci } 2488779efd5Sopenharmony_ci result = timeDetail.time 2498779efd5Sopenharmony_ci } 2508779efd5Sopenharmony_ci } else if (dayDiff == 1) { 2518779efd5Sopenharmony_ci result = $r("app.string.yesterday"); 2528779efd5Sopenharmony_ci } else { 2538779efd5Sopenharmony_ci result = (callTime.getMonth() + 1) + '/' + callTime.getDate(); // 'MM/dd' 2548779efd5Sopenharmony_ci } 2558779efd5Sopenharmony_ci } else { 2568779efd5Sopenharmony_ci result = (callTime.getMonth() + 1) + '/' + callTime.getDate(); 2578779efd5Sopenharmony_ci } 2588779efd5Sopenharmony_ci } else { 2598779efd5Sopenharmony_ci // 'yyyy/MM/dd' 2608779efd5Sopenharmony_ci result = callTime.getFullYear() + '/' + (callTime.getMonth() + 1) + '/' + callTime.getDate(); 2618779efd5Sopenharmony_ci } 2628779efd5Sopenharmony_ci return result; 2638779efd5Sopenharmony_ci } 2648779efd5Sopenharmony_ci 2658779efd5Sopenharmony_ci /** 2668779efd5Sopenharmony_ci * Checks whether two call records need to be combined when the call records are combined by time. 2678779efd5Sopenharmony_ci * If the call records need to be combined, true is returned. Otherwise, false is returned. 2688779efd5Sopenharmony_ci * 2698779efd5Sopenharmony_ci * @param oldElement Call records before merging 2708779efd5Sopenharmony_ci * @param newElement Combined call records 2718779efd5Sopenharmony_ci * @return 2728779efd5Sopenharmony_ci */ 2738779efd5Sopenharmony_ci private callLogMergeCheck(oldElement: MergedCallLog, newElement: CallLog) { 2748779efd5Sopenharmony_ci /* Merge Rules: 2758779efd5Sopenharmony_ci 1. The phone numbers are combined only when the phone numbers are the same. 2768779efd5Sopenharmony_ci 2. If the number is the same and the call type is 1, 2, 3, or 5, 2778779efd5Sopenharmony_ci the call is combined. Types 1, 2, 3, and 5 are not combined. 2788779efd5Sopenharmony_ci */ 2798779efd5Sopenharmony_ci if (oldElement.phoneNumber.trim() == newElement.phoneNumber.trim()) { 2808779efd5Sopenharmony_ci if (oldElement.callType == CallType.IN || oldElement.callType == CallType.OUT) { 2818779efd5Sopenharmony_ci if (newElement.callType == CallType.IN || newElement.callType == CallType.OUT) { 2828779efd5Sopenharmony_ci return true; 2838779efd5Sopenharmony_ci } 2848779efd5Sopenharmony_ci return false; 2858779efd5Sopenharmony_ci } 2868779efd5Sopenharmony_ci if (newElement.callType == CallType.MISSED || newElement.callType == CallType.REJECTED) { 2878779efd5Sopenharmony_ci return true; 2888779efd5Sopenharmony_ci } 2898779efd5Sopenharmony_ci } 2908779efd5Sopenharmony_ci return false; 2918779efd5Sopenharmony_ci } 2928779efd5Sopenharmony_ci 2938779efd5Sopenharmony_ci private getMergeRule() { 2948779efd5Sopenharmony_ci return this.mergeRule; 2958779efd5Sopenharmony_ci } 2968779efd5Sopenharmony_ci}