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 '../../../../../../../common/src/main/ets/util/HiLog';
17import callLogService from '../../../model/calllog/CalllogModel';
18import MorandiColor from '../../../model/bean/MorandiColor';
19import { ArrayUtil } from '../../../../../../../common/src/main/ets/util/ArrayUtil';
20import { StringUtil } from '../../../../../../../common/src/main/ets/util/StringUtil';
21import { ObjectUtil } from '../../../../../../../common/src/main/ets/util/ObjectUtil';
22import ContactAbilityModel from '../../../model/ContactAbilityModel';
23import router from '@ohos.router';
24import BatchSelectRecentSource from '../../../model/bean/BatchSelectRecentSource';
25import BatchSelectContactSource from '../../../model/bean/BatchSelectContactSource';
26import CallLogSetting from '../../../../../../../feature/call/src/main/ets/CallLogSetting'
27import { ContactVo } from '../../../model/bean/ContactVo';
28import AlphabetIndexerPresenter from '../alphabetindex/AlphabetIndexerPresenter';
29
30const TAG = 'BatchSelectContactsPresenter ';
31
32/**
33 * Selecting a contact list by SMS
34 */
35export default class BatchSelectContactsPresenter {
36  private static sInstance: BatchSelectContactsPresenter;
37  sizeType: SizeType = SizeType.LG;
38  selectCount: number = 0;
39  // Recent Call Records
40  callLogTemp: Array<any> = [];
41  contactsList: Array<any> = [];
42  searchContactList: Array<any> = [];
43  groupList: Array<any> = [];
44  emptyViewText: Resource = $r('app.string.no_recent_contacts');
45  controller: TabsController = new TabsController();
46  currentIndex: number = 0;
47  tabTextSrc: string[] | Resource[] = [$r('app.string.recent'), $r('app.string.contact')];
48  tabInfo: TabInfo = new TabInfo(0);
49  contactsInfo: ContactsInfo = new ContactsInfo();
50  // Whether to display the Select All button at the bottom
51  showOption: boolean = false;
52  // Search Keyword
53  searchText: string = '';
54  // Selected data for the current population,key:phone number,value:name and number
55  selectedNumberMap: Map<number, any> = new Map();
56  // Whether to display the search list
57  searchLayoutShow: boolean = false;
58  selectDisabled: boolean = true;
59  isSelectAll: boolean = false;
60  icSelectAll: Resource = $r('app.media.ic_public_select_all');
61  allSelectMessage: Resource = $r('app.string.select_all');
62  allSelectTextStyle: Resource = $r('sys.color.ohos_id_color_primary');
63  initialIndex: number = 0;
64  recentSource: BatchSelectRecentSource = new BatchSelectRecentSource();
65  contactsSource: BatchSelectContactSource = new BatchSelectContactSource();
66  actionData: { [key: string]: any } = {};
67  alphabetIndexPresenter: AlphabetIndexerPresenter = AlphabetIndexerPresenter.getInstance();
68  editContact: number = -1;
69  contactId: number;
70  /** Contact Temporary */
71  callId: string = '';
72  phones: string = '';
73  phoneNumberShow: string = '';
74  isNewNumber: boolean = false;
75  addFavorite: number = -1;
76
77  public static getInstance(): BatchSelectContactsPresenter {
78    if (BatchSelectContactsPresenter.sInstance == null) {
79      BatchSelectContactsPresenter.sInstance = new BatchSelectContactsPresenter();
80    }
81    return BatchSelectContactsPresenter.sInstance;
82  }
83
84  aboutToAppear() {
85    this.initCallLog();
86    this.initContactsList();
87    this.selectCount = 0;
88    this.selectedNumberMap = new Map();
89  }
90
91  aboutToDisappear() {
92  }
93
94  onPageShow() {
95  }
96
97  onPageHide() {
98  }
99
100  backCancel() {
101    if (0 === this.addFavorite) {
102      router.back();
103    } else {
104      this.cancel();
105    }
106  }
107
108  singleBackCancel() {
109    if (0 === this.editContact) {
110      router.replaceUrl({
111        url: 'pages/contacts/details/ContactDetail',
112        params: {
113          sourceHasPhone: true,
114          phoneNumberShow: this.phoneNumberShow
115        }
116      })
117    } else if (1 === this.editContact || 2 === this.editContact) {
118      router.back();
119    } else {
120      this.cancel();
121    }
122  }
123
124  cancel() {
125    let parameters = {
126      contactObjects: ''
127    };
128    let result = {
129      resultCode: 0,
130      want: {
131        parameters: parameters
132      }
133    };
134    // Selecting a contact for creating an SMS message
135    globalThis.context?.terminateSelfWithResult(result)
136      .then((data) => {
137        HiLog.i(TAG, 'terminateSelfWithResult Operation succeeded: ');
138      })
139      .catch((error) => {
140        HiLog.e(TAG, 'Operation failed. Cause: %s', JSON.stringify(error.message));
141      });
142  }
143
144  resetInitialIndex(firstIndex: number) {
145    HiLog.i(TAG, 'resetInitialIndex firstIndex is %s', firstIndex);
146    this.initialIndex = firstIndex;
147  }
148
149  selectBatchContact() {
150    if (0 === this.addFavorite) {
151      this.addFavoriteContacts();
152    } else {
153      this.comfirm()
154    }
155  }
156
157  addFavoriteContacts() {
158    HiLog.i(TAG, 'addFavoriteContacts start.');
159    let checkedList = [];
160    this.contactsList.forEach((value) => {
161      if (value.phoneNumbers.length > 0) {
162        value.phoneNumbers.forEach((values) => {
163          if (values.checked === true) {
164            checkedList.push(value.contactId);
165          }
166        })
167      }
168    })
169    AppStorage.SetOrCreate<Array<string>>('addFavoriteContactData', checkedList);
170    router.back();
171    HiLog.i(TAG, 'addFavoriteContacts end.');
172  }
173
174  comfirm() {
175    let checkedList = [];
176    this.selectedNumberMap.forEach((value) => {
177      checkedList.push(value);
178    });
179    let contacts = this.dealContactName(checkedList);
180    let parameters = {
181      contactObjects: JSON.stringify(contacts)
182    };
183    let result = {
184      resultCode: 0,
185      want: {
186        parameters: parameters
187      }
188    };
189    // Selecting a contact for creating an SMS message
190    globalThis.context?.terminateSelfWithResult(result)
191      .then((data) => {
192        HiLog.i(TAG, 'terminateSelfWithResult Operation succeeded ');
193      })
194      .catch((error) => {
195        HiLog.e(TAG, 'Operation failed. Cause: %s', JSON.stringify(error.message));
196      });
197  }
198
199  /**
200   *   Edit Contact
201   */
202  updateContact(contactId: string) {
203    let upDataShow = false;
204    if (contactId != undefined) {
205      upDataShow = true
206    }
207    router.replaceUrl({
208      url: 'pages/contacts/accountants/Accountants',
209      params: {
210        updataShow: upDataShow,
211        contactId: contactId,
212        callId: this.callId,
213        phones: this.phones,
214        editContact: this.editContact,
215        phoneNumberShow: this.phoneNumberShow
216      },
217    });
218  }
219
220  dealContactSelectId(checkedList) {
221    let contacts = [];
222    for (let item of checkedList) {
223      if (item.phoneNumbers) {
224
225      }
226      let contact = {
227        contactId: item.contactId,
228      };
229      contacts.push(contact);
230    }
231    return contacts;
232  }
233
234  dealContactName(checkedList) {
235    let contacts = [];
236    for (let item of checkedList) {
237      let contact = {
238        contactName: item.name,
239        telephone: item.number
240      };
241      contacts.push(contact);
242    }
243    return contacts;
244  }
245
246  clickSelectAll() {
247    switch (this.tabInfo.tabIndex) {
248      case 0:
249        if (this.tabInfo.recentCount != 0 && this.tabInfo.recentCount === this.tabInfo.recentTotal) {
250          this.tabInfo.allClickedRecent = false;
251          this.unSelectAll();
252        } else {
253          this.tabInfo.allClickedRecent = true;
254          this.selectAll();
255        }
256        break;
257      case 1:
258        if (this.tabInfo.contactsCount != 0 && this.tabInfo.contactsCount === this.tabInfo.contactsTotal) {
259          this.tabInfo.allClickedContacts = false;
260          this.unSelectAll();
261        } else {
262          this.tabInfo.allClickedContacts = true;
263          this.selectAll();
264        }
265        break;
266      case 2:
267        if (this.tabInfo.groupsCount != 0 && this.tabInfo.groupsCount === this.tabInfo.groupsTotal) {
268          this.tabInfo.allClickedGroups = false;
269          this.unSelectAll();
270        } else {
271          this.tabInfo.allClickedGroups = true;
272          this.selectAll();
273        }
274        break;
275      default:
276        break;
277    }
278    this.refreshPageMessage();
279  }
280
281  unSelectAll() {
282    switch (this.tabInfo.tabIndex) {
283      case 0:
284        this.unSelectAllRecentProc();
285        break;
286      case 1:
287        this.unSelectAllContactProc();
288        break;
289      case 2:
290        this.groupList.forEach(element => {
291          element.checked = false;
292        });
293        this.tabInfo.groupsCount = 0;
294        break;
295      default:
296        break;
297    }
298  }
299
300  selectAll() {
301    switch (this.tabInfo.tabIndex) {
302      case 0:
303        this.selectAllRecentProc();
304        break;
305      case 1:
306        this.selectAllContactProc();
307        break;
308      case 2:
309        this.groupList.forEach(element => {
310          element.checked = true;
311        });
312        this.tabInfo.groupsCount = this.tabInfo.groupsTotal;
313        break;
314      default:
315        break;
316    }
317  }
318
319  unSelectAllRecentProc() {
320    this.callLogTemp.forEach(element => {
321      if (element.checked) {
322        element.checked = false;
323        this.deleteSelectedNumber(element.phoneNumber, element.displayName, true, element.quickSearchKey);
324      }
325    });
326    this.recentSource.refresh(this.callLogTemp);
327    this.tabInfo.recentCount = 0;
328  }
329
330  unSelectAllContactProc() {
331    if (this.contactsInfo.searchLayoutShow) {
332      this.contactsInfo.searchContactList.forEach(element => {
333        for (let i = 0; i < element.phoneNumbers.length; i++) {
334          if (element.phoneNumbers[i].checked) {
335            element.phoneNumbers[i].checked = false;
336            this.deleteSelectedNumber(element.phoneNumbers[i].phoneNumber, element.name.fullName, false, element.contactId);
337          }
338        }
339      });
340    } else {
341      this.contactsList.forEach(element => {
342        for (let i = 0; i < element.phoneNumbers.length; i++) {
343          if (element.phoneNumbers[i].checked) {
344            element.phoneNumbers[i].checked = false;
345            this.deleteSelectedNumber(element.phoneNumbers[i].phoneNumber, element.name.fullName, false, element.contactId);
346          }
347        }
348      });
349      this.contactsSource.refresh(this.contactsList);
350    }
351    this.tabInfo.contactsCount = 0;
352  }
353
354  selectAllRecentProc() {
355    this.callLogTemp.forEach(element => {
356      element.checked = true;
357      this.addOrUpdateSelectedNumberMap(element.phoneNumber, element.displayName, true, element.quickSearchKey);
358    });
359    this.recentSource.refresh(this.callLogTemp);
360    this.tabInfo.recentCount = this.tabInfo.recentTotal;
361  }
362
363  selectAllContactProc() {
364    if (this.contactsInfo.searchLayoutShow) {
365      this.contactsInfo.searchContactList.forEach(element => {
366        if (!element.phoneNumbers[0].checked) {
367          element.phoneNumbers[0].checked = true;
368          this.addOrUpdateSelectedNumberMap(element.phoneNumbers[0].phoneNumber, element.name.fullName, false, element.contactId);
369        }
370      });
371    } else {
372      this.contactsList.forEach(element => {
373        if (!element.phoneNumbers[0].checked) {
374          element.phoneNumbers[0].checked = true;
375          this.addOrUpdateSelectedNumberMap(element.phoneNumbers[0].phoneNumber, element.name.fullName, false, element.contactId);
376        }
377      });
378      this.contactsSource.refresh(this.contactsList);
379    }
380    this.tabInfo.contactsCount = this.tabInfo.contactsTotal;
381  }
382
383  onTabChange(tabIndex: number) {
384    HiLog.i(TAG, 'onTabChange tabIndex is %s', tabIndex);
385    this.tabInfo.tabIndex = tabIndex;
386    this.refreshPageMessage();
387  }
388
389  getEmptyText(): Resource {
390    switch (this.tabInfo.tabIndex) {
391      case 0:
392        this.emptyViewText = $r('app.string.no_recent_contacts');
393        break
394      case 1:
395        this.emptyViewText = $r('app.string.no_select_contacts');
396        break
397      case 2:
398        this.emptyViewText = $r('app.string.no_group_contacts');
399        break
400      default:
401        this.emptyViewText = $r('app.string.no_recent_contacts');
402        break
403    }
404    return this.emptyViewText;
405  }
406
407  onRecentItemClicked(index: number) {
408    HiLog.i(TAG, 'onRecentItemClicked index is %s', index);
409    this.checkStateChange(index, {
410      checked: !(this.callLogTemp[index].checked)
411    });
412  }
413
414  onSingleContactItemClick(num: number, name: string, item: ContactVo) {
415    HiLog.i(TAG, 'onSingleContactItemClick in ');
416    this.selectedNumberMap.set(num, {
417      name: name,
418      number: num
419    });
420    if (0 === this.editContact || 1 === this.editContact || 2 === this.editContact) {
421      this.updateContact(item.contactId);
422    } else {
423      this.comfirm();
424    }
425  }
426
427  onContactItemClicked(index: number, indexChild: number) {
428    HiLog.i(TAG, 'onContactItemClicked index is ' + index);
429    HiLog.i(TAG, 'onContactItemClicked indexChild is ' + indexChild);
430    let event = {
431      contactIndex: index,
432      numberIndex: indexChild,
433      checked: this.searchLayoutShow ? !(this.searchContactList[index].phoneNumbers[indexChild].checked)
434                                     : !(this.contactsList[index].phoneNumbers[indexChild].checked)
435    }
436    this.checkStateChange(index, event);
437  }
438
439  checkStateChange(index, event) {
440    HiLog.i(TAG, 'checkStateChange event:  ' + JSON.stringify(event));
441    switch (this.tabInfo.tabIndex) {
442      case 0:
443        this.changeCallLogItemState(index, event);
444        break;
445      case 1:
446        this.changeContactsItemState(index, event);
447        break;
448      default:
449        break;
450    }
451    this.refreshPageMessage();
452  }
453
454  changeContactState(event) {
455    this.checkStateChange(event.contactIndex, event);
456  }
457
458  changeCallLogItemState(index, event) {
459    HiLog.i(TAG, 'changeCallLogItemState event :  ' + JSON.stringify(event));
460    if (this.callLogTemp[index]) {
461      this.callLogTemp[index].checked = event.checked;
462      this.recentSource.refreshSpecificOne(index, event.checked)
463
464      if (this.callLogTemp[index].checked) {
465        this.addOrUpdateSelectedNumberMap(this.callLogTemp[index].phoneNumber, this.callLogTemp[index].displayName, true, this.callLogTemp[index].quickSearchKey);
466        this.tabInfo.recentCount++;
467      } else {
468        this.deleteSelectedNumber(this.callLogTemp[index].phoneNumber, this.callLogTemp[index].displayName, true, this.callLogTemp[index].quickSearchKey);
469        this.tabInfo.recentCount--;
470      }
471    }
472  }
473
474  changeContactsItemState(index, event) {
475    HiLog.i(TAG, 'SHOW changeContactsItemState searchLayoutShow');
476    let contactId = '';
477    if (!this.contactsInfo.searchLayoutShow) {
478      contactId = this.contactsList[index].contactId;
479    } else {
480      contactId = this.contactsInfo.searchContactList[index].contactId;
481    }
482    this.checkContactsCount(event, contactId);
483  }
484
485  checkContactsCount(event, contactId) {
486    HiLog.i(TAG, 'SHOW checkContactsCount searchLayoutShow');
487    if (this.contactsInfo.searchLayoutShow) {
488      this.contactsInfo.searchContactList.forEach(element => {
489        if (contactId == element.contactId) {
490          if (event.checked) {
491            if (!this.checkIfNeedCount(element)) {
492              this.tabInfo.contactsCount++;
493            }
494            element.phoneNumbers[event.numberIndex].checked = true;
495            this.contactsInfo.contactsNumberCount++;
496            this.addOrUpdateSelectedNumberMap(element.phoneNumbers[event.numberIndex].phoneNumber,
497            element.name.fullName, false, element.contactId);
498          } else {
499            element.phoneNumbers[event.numberIndex].checked = false;
500            this.contactsInfo.contactsNumberCount--;
501            if (!this.checkIfNeedCount(element)) {
502              this.tabInfo.contactsCount--;
503            }
504            this.deleteSelectedNumber(element.phoneNumbers[event.numberIndex].phoneNumber, element.name.fullName, false, element.contactId);
505          }
506        }
507      });
508    } else {
509      this.contactsList.forEach(element => {
510        if (contactId == element.contactId) {
511          if (event.checked) {
512            if (!this.checkIfNeedCount(element)) {
513              this.tabInfo.contactsCount++;
514            }
515            element.phoneNumbers[event.numberIndex].checked = true;
516            this.contactsInfo.contactsNumberCount++;
517            this.addOrUpdateSelectedNumberMap(element.phoneNumbers[event.numberIndex].phoneNumber,
518            element.name.fullName, false, element.contactId);
519          } else {
520            element.phoneNumbers[event.numberIndex].checked = false;
521            this.contactsInfo.contactsNumberCount--;
522            if (!this.checkIfNeedCount(element)) {
523              this.tabInfo.contactsCount--;
524            }
525            this.deleteSelectedNumber(element.phoneNumbers[event.numberIndex].phoneNumber, element.name.fullName, false, element.contactId);
526          }
527        }
528      });
529      this.contactsSource.refresh(this.contactsList);
530    }
531  }
532
533  /**
534   * Determines whether the current contact element has an option.
535   *
536   * @param {Object} contact
537   * @return {boolean} true,false
538   */
539  checkIfNeedCount(contact) {
540    if (contact.phoneNumbers.length > 0) {
541      for (let index = 0; index < contact.phoneNumbers.length; index++) {
542        const element = contact.phoneNumbers[index];
543        if (element.checked) {
544          return true;
545        }
546      }
547    } else {
548      return false;
549    }
550  }
551
552  // Header Count Refresh Function
553  refreshPageMessage() {
554    HiLog.i(TAG, 'refreshPageMessage start !')
555    this.selectCount = this.selectedNumberMap.size;
556    if (this.selectedNumberMap.size > 0) {
557      this.selectDisabled = false;
558      this.checkAllClickButtonStyle();
559    } else {
560      this.selectDisabled = true;
561      this.isSelectAll = false;
562      this.changeToUnFullSelect();
563    }
564  }
565
566  /**
567   * Verify the display style of the Select All button.
568   */
569  checkAllClickButtonStyle() {
570    HiLog.i(TAG, 'checkAllClickButtonStyle start , and tabIndex is ' + this.tabInfo.tabIndex);
571    switch (this.tabInfo.tabIndex) {
572      case 0:
573        if (this.tabInfo.recentCount === this.tabInfo.recentTotal) {
574          HiLog.i(TAG, 'checkAllClickButtonStyle recent select all ');
575          this.changeToFullSelect();
576          this.tabInfo.allClickedRecent = true;
577        } else {
578          HiLog.i(TAG, 'checkAllClickButtonStyle recent unselect all ');
579          this.changeToUnFullSelect();
580        }
581        break;
582      case 1:
583        if (this.tabInfo.contactsCount === this.tabInfo.contactsTotal) {
584          HiLog.i(TAG, 'checkAllClickButtonStyle contact select all ');
585          this.changeToFullSelect();
586          this.tabInfo.allClickedContacts = true;
587        } else {
588          HiLog.i(TAG, 'checkAllClickButtonStyle contact unselect all ');
589          this.changeToUnFullSelect();
590        }
591        break;
592      default:
593        break;
594    }
595  }
596
597  changeToFullSelect() {
598    this.icSelectAll = $r('app.media.ic_public_select_all_filled');
599    this.allSelectMessage = $r('app.string.unselect_all');
600    this.allSelectTextStyle = $r('sys.color.ohos_id_color_connected');
601  }
602
603  changeToUnFullSelect() {
604    this.icSelectAll = $r('app.media.ic_public_select_all');
605    this.allSelectMessage = $r('app.string.select_all');
606    this.allSelectTextStyle = $r('sys.color.ohos_id_color_primary');
607  }
608
609  addOrUpdateSelectedNumberMap(number, name, isCalllogs, keyOrId) {
610    HiLog.i(TAG, 'addOrUpdateSelectedNumberMap isCalllogs is ' + isCalllogs + ' , keyOrId is ' + keyOrId);
611    if (StringUtil.isEmpty(number)) {
612      return;
613    }
614    this.selectedNumberMap.set((keyOrId + number.replace(/\s+/g, '')), {
615      name: name,
616      number: number.replace(/\s+/g, '')
617    });
618    this.updataConnectedContact(number, name, isCalllogs, keyOrId, true);
619  }
620
621  deleteSelectedNumber(number, name, isCalllogs, keyOrId) {
622    HiLog.i(TAG, 'deleteSelectedNumber isCalllogs is ' + isCalllogs + ' , keyOrId is ' + keyOrId);
623    if (StringUtil.isEmpty(number)) {
624      return;
625    }
626    this.selectedNumberMap.delete(keyOrId + number.replace(/\s+/g, ''));
627    this.updataConnectedContact(number, name, isCalllogs, keyOrId, false);
628  }
629
630  updataConnectedContact(number, name, isCalllogs, keyOrId, isAdd) {
631    HiLog.i(TAG, 'updataConnectedContact isCalllogs is ' + isCalllogs + ' , keyOrId is ' + keyOrId);
632    if (isCalllogs) {
633      this.contactsList.forEach(element => {
634        if (!ObjectUtil.isEmpty(element) && element.contactId == keyOrId) {
635          for (let i = 0; i < element.phoneNumbers.length; i++) {
636            let childElement = element.phoneNumbers[i];
637            if (!ObjectUtil.isEmpty(childElement) && childElement.phoneNumber == number && element.name.fullName == name) {
638              if (isAdd) {
639                // If the original data does not contain the selected item before modification, the tab count increases by 1.
640                if (!this.checkIfNeedCount(element)) {
641                  this.tabInfo.contactsCount++;
642                }
643                childElement.checked = true;
644                this.contactsInfo.contactsNumberCount++;
645              } else {
646                // After the modification, the tab count decreases by 1 when the original data does not contain the selected item.
647                childElement.checked = false;
648                this.contactsInfo.contactsNumberCount--;
649                if (!this.checkIfNeedCount(element)) {
650                  this.tabInfo.contactsCount--;
651                }
652              }
653            }
654          }
655          return;
656        }
657      });
658      this.contactsSource.refresh(this.contactsList);
659    } else {
660      this.callLogTemp.forEach(element => {
661        if (!ObjectUtil.isEmpty(element) && element.quickSearchKey == keyOrId && element.phoneNumber == number && element.displayName == name) {
662          element.checked = isAdd;
663          if (isAdd) {
664            this.tabInfo.recentCount++;
665          } else {
666            this.tabInfo.recentCount--;
667          }
668          return;
669        }
670      })
671      this.recentSource.refresh(this.callLogTemp);
672    }
673  }
674
675  /**
676   * Obtaining Recent Call Records
677   * */
678  initCallLog() {
679    HiLog.i(TAG, 'initCallLog start !');
680    let tempMap = new Map();
681    let tempList: any[] = [];
682    let favoriteForm: any = {}
683    if (0 === this.addFavorite) {
684      favoriteForm.favorite = 0;
685    } else {
686      favoriteForm.favorite = -1;
687    }
688    globalThis.DataWorker?.sendRequest('getAllCalls', {
689      context: globalThis.context,
690      mergeRule: CallLogSetting.getInstance().getMergeRule(),
691      actionData: this.actionData,
692      favoriteForm: JSON.stringify(favoriteForm)
693    }, (data) => {
694      if (data.hasOwnProperty('callLogList') && !ArrayUtil.isEmpty(data.callLogList)) {
695        HiLog.i(TAG, 'data  has callLogList key');
696        for (let i = 0; i < data.callLogList.length; i++) {
697          let element = data.callLogList[i];
698          let bgColorIndex = parseInt(element.id, 10) % (MorandiColor.Color.length);
699          element.portraitColor = MorandiColor.Color[bgColorIndex];
700          element.suffix = StringUtil.isEmpty(element.displayName) ? '' : element.displayName.substr(element.displayName.length - 1);
701          element.checked = false;
702          // 重复的号码无需显示
703          if (!tempMap.has(StringUtil.removeSpace(element.phoneNumber))) {
704            tempList.push(element);
705            tempMap.set(element.phoneNumber, null);
706          }
707          //Displays the 50 numbers that have generated the latest call records.
708          if (tempList.length > 50) {
709            HiLog.i(TAG, 'callLogList more 50 break!');
710            break;
711          }
712        }
713      }
714      this.callLogTemp = tempList;
715      this.recentSource.refresh(this.callLogTemp);
716      this.tabInfo.recentTotal = this.callLogTemp.length;
717      this.checkOptionState();
718    });
719  }
720
721  /**
722   * Check whether the Select All button at the bottom needs to be displayed.
723   * */
724  checkOptionState() {
725    switch (this.tabInfo.tabIndex) {
726      case 0:
727        ArrayUtil.isEmpty(this.callLogTemp) ? this.showOption = false : this.showOption = true;
728        break;
729      case 1:
730        ArrayUtil.isEmpty(this.contactsList) ? this.showOption = false : this.showOption = true;
731        break;
732      case 2:
733        ArrayUtil.isEmpty(this.groupList) ? this.showOption = false : this.showOption = true;
734        break;
735      default:
736        break;
737    }
738  }
739
740  /*
741   * Initializing Contact List Data
742   */
743  initContactsList() {
744    HiLog.i(TAG, 'initContactsList start!');
745    let favoriteForm: any = {}
746    if (0 === this.addFavorite) {
747      favoriteForm.favorite = 0;
748    } else {
749      favoriteForm.favorite = -1;
750    }
751    favoriteForm.editContact = this.editContact
752    globalThis.DataWorker.sendRequest('getAllContactWithPhoneNumbers', {
753      context: globalThis.context,
754      favoriteForm: JSON.stringify(favoriteForm)
755    }, (resultList) => {
756      HiLog.i(TAG, 'initContactsList resultList success ' + resultList.length);
757      let listTemp: any[] = [];
758      if (!ArrayUtil.isEmpty(resultList)) {
759        for (let element of resultList) {
760          element.name = {};
761          element.name.fullName = element.emptyNameData;
762          element.name.namePrefix = element.namePrefix;
763          element.name.nameSuffix = element.nameSuffix;
764          if (element.phoneNumbers != null && element.phoneNumbers.length > 0) {
765            element.phoneNumbers.forEach(childEle => {
766              childEle.checked = false;
767              childEle.labelName = this.getPhoneLabelNameById(childEle.numType, childEle.phoneNumber);
768              this.initVariableSpan(element);
769            });
770            listTemp.push(element);
771          }
772        }
773        this.contactsList = listTemp;
774        this.contactsSource.refresh(this.contactsList);
775        this.tabInfo.contactsTotal = this.contactsList.length;
776        this.contactsInfo.contactsListTotal = this.contactsList.length;
777        this.alphabetIndexPresenter.initContactList(this.contactsList);
778      } else {
779        HiLog.e(TAG, 'select contact list is empty!' + JSON.stringify(this.contactsList));
780        this.contactsSource.refresh(this.contactsList);
781        HiLog.e(TAG, 'select contact list is empty!');
782      }
783    });
784  }
785
786
787  /**
788   * Assign a custom attribute to prepare for later variable font searches
789   *
790   * @param {Object} item contacts data
791   */
792  initVariableSpan(item) {
793    // Initialize Variable Names
794    let matchString = StringUtil.getMatchedString(item.emptyNameData, this.searchText);
795    if (StringUtil.isEmpty(matchString) || StringUtil.isEmpty(this.searchText.trim())) {
796      item.name.searchTextStart = '';
797      item.name.searchTextMiddle = '';
798      item.name.searchTextEnd = item.emptyNameData;
799    } else {
800      let name = item.emptyNameData;
801      let index = name.indexOf(matchString);
802      item.name.searchTextStart = name.substr(0, index);
803      item.name.searchTextMiddle = name.substr(index, matchString.length);
804      item.name.searchTextEnd = name.substr(index + matchString.length);
805    }
806    // Initialize Variable Numbers
807    for (let i = 0; i < item.phoneNumbers.length; i++) {
808      let phoneNumber = item.phoneNumbers[i].phoneNumber;
809      let matchStringPhone = StringUtil.getMatchedString(phoneNumber, this.searchText);
810      if (StringUtil.isEmpty(matchStringPhone) || StringUtil.isEmpty(this.searchText.trim())) {
811        item.phoneNumbers[i].startPhone = '';
812        item.phoneNumbers[i].middlePhone = '';
813        item.phoneNumbers[i].endPhone = phoneNumber;
814      } else {
815        let phoneIndex = phoneNumber.indexOf(matchStringPhone);
816        item.phoneNumbers[i].startPhone = phoneNumber.substr(0, phoneIndex);
817        item.phoneNumbers[i].middlePhone = phoneNumber.substr(phoneIndex, matchStringPhone.length);
818        item.phoneNumbers[i].endPhone = phoneNumber.substr(phoneIndex + matchStringPhone.length);
819      }
820    }
821  }
822
823  getPhoneLabelNameById(phoneLabelId: string, phoneNumber) {
824    let labelName: Resource;
825    switch (parseInt(phoneLabelId, 10)) {
826      case 1:
827        labelName = $r('app.string.phone_type_mobile_expansion', phoneNumber);
828        break;
829      case 2:
830        labelName = $r('app.string.phone_type_home_expansion', phoneNumber);
831        break;
832      case 3:
833        labelName = $r('app.string.phone_type_work_expansion', phoneNumber);
834        break;
835      case 4:
836        labelName = $r('app.string.phone_type_fax_work_expansion', phoneNumber);
837        break;
838      case 5:
839        labelName = $r('app.string.phone_type_fax_home_expansion', phoneNumber);
840        break;
841      case 6:
842        labelName = $r('app.string.phone_type_pager_expansion', phoneNumber);
843        break;
844      case 7:
845        labelName = $r('app.string.phone_type_other_expansion', phoneNumber);
846        break;
847      case 12:
848        labelName = $r('app.string.phone_type_main_expansion', phoneNumber);
849        break;
850      case 99:
851        labelName = $r('app.string.phone_type_custom_expansion', phoneNumber);
852        break;
853      default:
854        break;
855    }
856    return labelName;
857  }
858}
859
860export class TabInfo {
861  tabIndex: number = 0;
862  recentTotal: number = 0;
863  contactsTotal: number = 0;
864  groupsTotal: number = 0;
865  // Select All Clicked
866  allClickedRecent: boolean = false;
867  allClickedContacts: boolean = false;
868  allClickedGroups: boolean = false;
869  // Count on each tab page
870  recentCount: number = 0;
871  contactsCount: number = 0;
872  groupsCount: number = 0;
873  refreshGroupItemState: boolean = false;
874
875  constructor(tabIndex: number) {
876    this.tabIndex = tabIndex;
877  }
878}
879
880/**
881 * Data related to the contact list
882 */
883export class ContactsInfo {
884  searchContactList = [];
885  // List of selected contacts, which will be used for big data.
886  selectedContactMap = new Map();
887  // Whether to display the search page
888  searchLayoutShow: boolean = false;
889  // Number of Matched Search Records
890  searchPhoneNum: number = 0;
891  // Indicates whether to search a list.
892  showSearchList: boolean = false;
893  // Display Default Number
894  showDefaultNumber: boolean = true;
895  // Indicates whether to display the child number list.
896  showNumberList: boolean = true;
897  // Display primary number check box
898  phoneCheckShow: boolean = true;
899  // Display child number list check box
900  childPhoneCheckShow: boolean = true;
901  contactsListCount: number = 0;
902  contactsListTotal: number = 0;
903  // Count of selected numbers in the contact list
904  contactsNumberCount: number = 0;
905
906  constructor() {
907  }
908}