• 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 router from '@ohos.router';
17import prompt from '@system.prompt';
18import { StringUtil } from '../../../../../../../common/src/main/ets/util/StringUtil';
19import { HiLog } from '../../../../../../../common/src/main/ets/util/HiLog';
20import { ArrayUtil } from '../../../../../../../common/src/main/ets/util/ArrayUtil';
21import { CallLogRepository } from '../../../../../../../feature/call/src/main/ets/repo/CallLogRepository';
22import { CallType, CallLog } from '../../../../../../../feature/call/src/main/ets/entity/CallLog';
23import { PhoneNumber } from '../../../../../../../feature/phonenumber/src/main/ets/PhoneNumber';
24import { ContactRepository } from '../../../../../../../feature/contact/src/main/ets/repo/ContactRepository';
25import { House } from '../../../../../../../feature/contact/src/main/ets/contract/House';
26import { Relation } from '../../../../../../../feature/contact/src/main/ets/contract/Relation';
27import { Phone } from '../../../../../../../feature/contact/src/main/ets/contract/Phone';
28import { Email } from '../../../../../../../feature/contact/src/main/ets/contract/Email';
29import { Birthday } from '../../../../../../../feature/contact/src/main/ets/contract/Birthday';
30import { Aim } from '../../../../../../../feature/contact/src/main/ets/contract/Aim';
31import MorandiColor from '../../../model/bean/MorandiColor';
32import ContactAbilityModel from '../../../model/ContactAbilityModel';
33import DetailCallLogDataSource from '../../../model/bean/DetailCallLogDataSource';
34import EnvironmentProp from '../../../feature/EnvironmentProp';
35import StringFormatUtil from '../../../util/StringFormatUtil'
36
37const TAG = 'DetailPresenter';
38
39export default class DetailPresenter {
40  private static sInstance: DetailPresenter;
41  /** UI parameters */
42  moreMenuOptions: Resource[] = [$r('app.string.delete_contact')];
43  isFavorite: boolean = false;
44  showNameLastMenu: string = '';
45  lastUsedSlotId: number = -1;
46
47  /** Display parameters */
48  sourceHasId: boolean = false;
49  sourceHasPhone: boolean = false;
50  phoneNumberShow: string = '';
51  contactId: number;
52  isNewNumber: boolean = true;
53  isNewDetail: boolean = false;
54  topbarBackgroundColor: ResourceColor = Color.Transparent;
55  newNumberBgColor: string = '';
56  detailsColor: string = '';
57  isFavorited : string = '0'
58  /** detail parameters */
59  contactForm: any = {
60    contactId: -1,
61    display_name: '',
62    photoFirstName: '',
63    company: '',
64    position: '',
65    phones: [],
66    emails: [],
67    aims: [],
68    nickname: [],
69    websites: [],
70    houses: [],
71    events: [],
72    remarks: [],
73    relationships: [],
74    numRecords: [],
75    portraitColor: '',
76    detailsBgColor: '',
77    favorite: 0
78  };
79  detailCallLogDataSource: DetailCallLogDataSource = new DetailCallLogDataSource();
80  /** Contact Temporary */
81  contacts: { [key: string]: any } = {};
82
83  private constructor() {
84  }
85
86  public static getInstance(): DetailPresenter {
87    if (DetailPresenter.sInstance == null) {
88      DetailPresenter.sInstance = new DetailPresenter();
89    }
90    return DetailPresenter.sInstance;
91  }
92
93  async aboutToAppear() {
94    // Groups, favorites, contact lists,new contacts.
95    if (this.sourceHasId) {
96      HiLog.i(TAG, 'onShow:sourceHasId');
97      this.contactForm = {
98        display_name: '',
99        photoFirstName: '',
100        company: '',
101        position: '',
102        phones: [],
103        emails: [],
104        aims: [],
105        nickname: [],
106        websites: [],
107        houses: [],
108        events: [],
109        remarks: [],
110        relationships: [],
111        numRecords: [],
112        portraitColor: '',
113        detailsBgColor: '',
114        favorite: 0
115      };
116      let requestData = {
117        contactId: this.contactId
118      };
119      this.isNewNumber = false;
120      this.getContactDetail(requestData);
121    } else if (this.sourceHasPhone) {
122      // call log, mms.
123      HiLog.i(TAG, 'onShow:sourceHasPhone');
124      this.contactForm = {
125        display_name: '',
126        photoFirstName: '',
127        company: '',
128        position: '',
129        phones: [],
130        emails: [],
131        aims: [],
132        nickname: [],
133        websites: [],
134        houses: [],
135        events: [],
136        remarks: [],
137        relationships: [],
138        numRecords: [],
139        portraitColor: '',
140        detailsBgColor: '',
141        favorite: 0
142      };
143      /** Query the contact ID based on the phone number.
144       If a contact exists,the contact details are displayed based on the first contact ID.*/
145      globalThis.DataWorker.sendRequest('getIdByTelephone', {
146        context: globalThis.context,
147        phoneNumber: this.phoneNumberShow
148      }, (contactId) => {
149        if (!ArrayUtil.isEmpty(contactId)) {
150          HiLog.i(TAG, 'contactid is exist');
151          // If a contact exists, set isNewNumber to false.
152          this.isNewNumber = false;
153          let requestData = {
154            contactId: contactId[0]
155          };
156          this.getContactDetail(requestData);
157        }
158        if (this.isNewNumber) {
159          // If the contact ID does not exist, the new number is used.
160          this.getNewNumCallLog();
161        }
162      });
163    }
164    this.registerCallLogObsever();
165    this.isNewNumber = true;
166  }
167
168  aboutToDisappear() {
169    HiLog.i(TAG, 'ContactDetail aboutToDisappear!');
170  }
171
172  registerCallLogObsever() {
173    CallLogRepository.getInstance().registerDataChangeObserver(() => {
174      this.refresh();
175    });
176  }
177
178  refresh() {
179    HiLog.i(TAG, 'refresh call log!');
180    if (this.contactId != undefined) {
181      this.getContactCallLog();
182    } else {
183      this.getNewNumCallLog();
184    }
185  }
186
187  getContactDetail(data) {
188    HiLog.i(TAG, 'get ContactDetail by id');
189    globalThis.DataWorker.sendRequest('getContactById', {
190      context: globalThis.context,
191      contactId: data.contactId
192    }, result => {
193      if (StringUtil.isEmpty(result)) {
194        // If the contact cannot be obtained based on the specified ID, the new number is used.
195        this.getNewNumCallLog();
196        return;
197      }
198      this.contactId = result.data.id;
199      this.contacts = result.data;
200      this.contactForm.portraitColor = MorandiColor.Color[Math.abs(parseInt(result.data.id, 10)) % 6];
201      this.contactForm.detailsBgColor = MorandiColor.detailColor[Math.abs(parseInt(result.data.id, 10)) % 6];
202      this.detailsColor = MorandiColor.detailColor[Math.abs(parseInt(result.data.id, 10)) % 6];
203      this.isFavorited = this.contacts.favorite;
204      this.dealDetailsData();
205    });
206  }
207
208  dealDetailsData() {
209    HiLog.i(TAG, 'deal detail data');
210    this.getLabelNameByTypeId();
211    this.dealContactsToForm();
212    this.getContactCallLog();
213  }
214
215  getLabelNameByTypeId() {
216    if (this.contacts.hasOwnProperty('phones') && this.contacts.phones.length > 0) {
217      this.contacts.phones.forEach((element) => {
218        element.labelName = Phone.getTypeLabelResource(parseInt(element.numType, 10));
219        element.phoneAddress = (element.phoneAddress == 'N' || StringUtil.isEmpty(element.phoneAddress)) ?
220        $r('app.string.unknown') : element.phoneAddress;
221      });
222    }
223    if (this.contacts.hasOwnProperty('emails') && this.contacts.emails.length > 0) {
224      this.contacts.emails.forEach((element) => {
225        element.labelName = Email.getTypeLabelResource(parseInt(element.emailType, 10));
226      });
227    }
228    if (this.contacts.hasOwnProperty('aims') && this.contacts.aims.length > 0) {
229      this.contacts.aims.forEach((element) => {
230        element.labelName = Aim.getTypeLabelResource(parseInt(element.aimType, 10));
231      });
232    }
233    if (this.contacts.hasOwnProperty('houses') && this.contacts.houses.length > 0) {
234      this.contacts.houses.forEach((element) => {
235        element.labelName = House.getTypeLabelResource(parseInt(element.houseType, 10));
236      });
237    }
238    if (this.contacts.hasOwnProperty('events') && this.contacts.events.length > 0) {
239      this.contacts.events.forEach((element) => {
240        element.labelName = Birthday.getTypeLabelResource(parseInt(element.eventType, 10));
241      });
242    }
243    if (this.contacts.hasOwnProperty('relationships') && this.contacts.relationships.length > 0) {
244      this.contacts.relationships.forEach((element) => {
245        element.labelName = Relation.getTypeLabelResource(parseInt(element.associatedType, 10));
246      });
247    }
248  }
249
250  dealContactsToForm() {
251    let newContact = this.contacts;
252    this.contactForm.display_name = (newContact.display_name && newContact.display_name.length > 0)
253      ? newContact.display_name : $r('app.string.noName');
254    this.contactForm.photoFirstName = (newContact.photoFirstName && newContact.photoFirstName.length > 0)
255      ? newContact.photoFirstName.toUpperCase() : '-1';
256    this.contactForm.company = (newContact.company && newContact.company.length > 0)
257      ? newContact.company : '';
258    this.contactForm.position = (newContact.position && newContact.position.length > 0)
259      ? newContact.position : '';
260    if (newContact.phones && newContact.phones.length > 0) {
261      for (let item of newContact.phones) {
262        let itemtemp = {
263          id: item.id,
264          data: PhoneNumber.fromString(item.num).getNumber(),
265          num: item.num,
266          type: item.numType,
267          phoneAddress: item.phoneAddress,
268          labelName: item.labelName
269        }
270        if (this.contactForm.phones) {
271          this.contactForm.phones.push(itemtemp);
272        } else {
273          this.contactForm.phones = [itemtemp];
274        }
275      }
276    }
277    if (newContact.emails && newContact.emails.length > 0) {
278      for (let item of newContact.emails) {
279        let itemtemp = {
280          id: item.id,
281          data: item.address,
282          type: item.emailType,
283          labelName: item.labelName
284        }
285        if (this.contactForm.emails) {
286          this.contactForm.emails.push(itemtemp);
287        } else {
288          this.contactForm.emails = [itemtemp];
289        }
290      }
291    }
292    if (newContact.aims && newContact.aims.length > 0) {
293      for (let item of newContact.aims) {
294        let itemtemp = {
295          id: item.aimId,
296          data: item.aimName,
297          type: item.aimType,
298          labelName: item.labelName
299        }
300        if (this.contactForm.aims) {
301          this.contactForm.aims.push(itemtemp);
302        } else {
303          this.contactForm.aims = [itemtemp];
304        }
305      }
306    }
307    if (newContact.nickname && newContact.nickname.length > 0) {
308      let itemtemp = {
309        id: 0,
310        data: newContact.nickname,
311        labelName: $r('app.string.nickname')
312      }
313      this.contactForm.nickname = [itemtemp];
314    }
315    if (newContact.websites && newContact.websites.length > 0) {
316      let itemtemp = {
317        id: 0,
318        data: newContact.websites[0],
319        labelName: $r('app.string.website')
320      }
321      this.contactForm.websites = [itemtemp];
322    }
323    if (newContact.houses && newContact.houses.length > 0) {
324      for (let item of newContact.houses) {
325        let itemtemp = {
326          id: item.houseId,
327          data: item.houseName,
328          type: item.houseType,
329          labelName: item.labelName
330        }
331        if (this.contactForm.houses) {
332          this.contactForm.houses.push(itemtemp);
333        } else {
334          this.contactForm.houses = [itemtemp];
335        }
336      }
337    }
338    if (newContact.events && newContact.events.length > 0) {
339      for (let item of newContact.events) {
340        let itemtemp = {
341          id: item.id,
342          data: item.data,
343          type: item.eventType,
344          labelName: item.labelName
345        }
346        if (this.contactForm.events) {
347          this.contactForm.events.push(itemtemp);
348        } else {
349          this.contactForm.events = [itemtemp];
350        }
351      }
352    }
353    if (newContact.remarks && newContact.remarks.length > 0) {
354      let itemtemp = {
355        id: 0,
356        data: newContact.remarks,
357        labelName: $r('app.string.remarks')
358      }
359      this.contactForm.remarks = [itemtemp];
360    }
361    if (newContact.relationships && newContact.relationships.length > 0) {
362      for (let item of this.contacts.relationships) {
363        let itemtemp = {
364          id: item.id,
365          data: item.name,
366          type: item.associatedType,
367          labelName: item.labelName
368        }
369        if (this.contactForm.relationships) {
370          this.contactForm.relationships.push(itemtemp);
371        } else {
372          this.contactForm.relationships = [itemtemp];
373        }
374      }
375    }
376  }
377
378  async getContactCallLog() {
379    HiLog.i(TAG, 'get Contact CallLog');
380    if (!ArrayUtil.isEmpty(this.contactForm.phones)) {
381      let numbers: Set<string> = new Set();
382      this.contactForm.phones.forEach(element => {
383        numbers.add(`${element.data}`.replace(/\s+/g, ''));
384      });
385      /* All call records of all phone numbers of the contact are obtained. */
386      globalThis.DataWorker.sendRequest('findByNumberIn', {
387        context: globalThis.context,
388        numbers: Array.from(numbers)
389      }, (resultList) => {
390        /* Encapsulate the attributes required on the detail page based on the obtained raw call record data. */
391        if (!ArrayUtil.isEmpty(resultList)) {
392          this.lastUsedSlotId = resultList[0].simId;
393        } else {
394          this.lastUsedSlotId = -1;
395        }
396        this.detailCallLogDataSource.refresh(this.getDetailMessage(resultList));
397      });
398      /* Encapsulate the attributes required on the detail page based on the obtained raw call record data. */
399    }
400    // Processing Initialization Data
401    this.showNameLastMenu = (this.contactForm.display_name && this.contactForm.display_name.length > 6)
402      ? this.subStringWithEllipsis(this.contactForm.display_name, 7) : this.contactForm.display_name;
403  }
404
405  // Obtains call records and assembles parameters when the call is not a contact.
406  async getNewNumCallLog() {
407    this.isNewDetail = true;
408    HiLog.i(TAG, 'get new number call log');
409    let numbers: any = [this.phoneNumberShow.replace(/\s+/g, '')];
410    let formatNum = PhoneNumber.fromString(this.phoneNumberShow).getNumber();
411    this.contactForm.display_name = formatNum;
412    /* Creating a Contact Phone List Object */
413    let itemtemp = {
414      id: 0,
415      data: formatNum,
416      num: this.phoneNumberShow,
417      type: 1,
418      labelName: $r('app.string.phone_type_mobile'),
419      phoneAddress: $r('app.string.unknown')
420    }
421    this.contactForm.phones = [itemtemp];
422    this.contactForm.portraitColor = MorandiColor.Color[0];
423    this.contactForm.detailsBgColor = MorandiColor.detailColor[0];
424    this.newNumberBgColor = MorandiColor.detailColor[0];
425    globalThis.DataWorker.sendRequest('findByNumberIn', {
426      context: globalThis.context,
427      numbers: numbers
428    }, (resultList) => {
429      /* Encapsulate the attributes required on the detail page based on the obtained raw call record data. */
430      if (!ArrayUtil.isEmpty(resultList)) {
431        this.lastUsedSlotId = resultList[0].simId;
432      } else {
433        this.lastUsedSlotId = -1;
434      }
435      this.detailCallLogDataSource.refresh(this.getDetailMessage(resultList));
436    });
437    if (this.detailCallLogDataSource.totalCount() > 0) {
438      let bgColorId = Math.abs(parseInt(this.detailCallLogDataSource.getData(0).callLog.id, 10));
439      this.contactForm.portraitColor = MorandiColor.Color[bgColorId % 6];
440      this.contactForm.detailsBgColor = MorandiColor.detailColor[bgColorId % 6];
441      this.newNumberBgColor = MorandiColor.detailColor[bgColorId % 6];
442    }
443  }
444
445  /**
446   * Data required for converting the original
447   * callLogList content into call record details
448   *
449   * @param {Array} originList Original Call List
450   * @return {Array} resultList
451   */
452  getDetailMessage(originList: CallLog[]) {
453    let resultList = [];
454    if (ArrayUtil.isEmpty(originList)) {
455      return resultList;
456    }
457    originList.forEach(element => {
458      let callTimeDetail = this.getTimeDetailByCallTime(element);
459      let contactDetailCallsItem = {
460        id: element.id.toString(),
461        phone: element.phoneNumber,
462        name: element.displayName,
463        callTime: element.createTime.toString(),
464        callType: element.callType,
465        callTag: element.numberLocation,
466        simType: element.simType.toString(),
467        simId: element.simId,
468        isHd: element.isHD,
469        ringTime: element.ringDuration,
470        formatNumber: element.formattedNumber,
471        talkTime: this.getTalkTimeMessage(element),
472        dateDetail: callTimeDetail.date,
473        timeDetail: callTimeDetail.time
474      };
475      resultList.push(contactDetailCallsItem)
476    });
477    return resultList;
478  }
479
480  /**
481   * Obtain the call details of the call record according to the call record.
482   *
483   * @param {Object} callLogElement Call log
484   * @return {string} resultMessage Status information
485   */
486  getTalkTimeMessage(callLogElement: CallLog) {
487    let resultMessage: Resource | string = null;
488    switch (callLogElement.callType) {
489      case CallType.IN:
490        resultMessage = this.getDescriptionByDuration(callLogElement.talkDuration);
491        break;
492      case CallType.OUT:
493        resultMessage = callLogElement.talkDuration == 0
494          ? $r('app.string.blockCall') : this.getDescriptionByDuration(callLogElement.talkDuration);
495        break;
496      case CallType.MISSED:
497        resultMessage = this.getDescriptionByDuration(callLogElement.ringDuration);
498        break;
499      case CallType.REJECTED:
500        resultMessage = $r('app.string.reject');
501        break;
502      default:
503        resultMessage = '';
504        break;
505    }
506    return resultMessage;
507  }
508
509  /**
510   * Obtains the call duration based on the specified timestamp. The unit is s.
511   *
512   * @param {number} timeDuration
513   * @return {Object} Return time unit
514   */
515  getDescriptionByDuration(timeDuration) {
516    let seconds = parseInt(timeDuration);
517    if (seconds < 60) {
518      // Less than one minute
519      return $r('app.string.secondsFormat', seconds);
520    } else {
521      let minutes = Math.floor(seconds / 60);
522      if (minutes < 60) {
523        // Within an hour
524        return $r('app.string.minutesSecondsFormat', minutes, seconds % 60);
525      } else {
526        let hours = Math.floor(minutes / 60);
527        return $r('app.string.hourMinutesSecondsFormat', hours, minutes % 60, seconds % 3600 % 60);
528      }
529    }
530  }
531
532  /**
533   * Obtain the time details based on the call record generation time.
534   *
535   * @param {number} callTime Initial Talk Time
536   * @return {string} timeDetail Talk time after processing
537   */
538  getTimeDetailByCallTime(element: CallLog) {
539    let callTime = element.createTime.toString();
540    let callLogTime = new Date(parseInt(callTime, 10) * 1000);
541    // time detail
542    let year = callLogTime.getFullYear();
543    let mounth = callLogTime.getMonth() + 1;
544    let day = callLogTime.getDate();
545    let hour = callLogTime.getHours().toString();
546    let minutes = callLogTime.getMinutes() < 10 ? '0' + callLogTime.getMinutes() : callLogTime.getMinutes().toString();
547    // description
548    let now = new Date();
549    let timeDetail: any = {};
550    if (parseInt(StringFormatUtil.judgeSysTime()) == 12) {
551      timeDetail.time = StringFormatUtil.getDayMessage(hour, minutes);
552    } else {
553      timeDetail.time = $r('app.string.time_normal', hour, minutes);
554    }
555    if (now.getFullYear() - callLogTime.getFullYear() == 0) {
556      if (now.getMonth() - callLogTime.getMonth() == 0) {
557        if (now.getDate() - callLogTime.getDate() == 0) {
558          timeDetail.date = '';
559          return timeDetail;
560        }
561      }
562      timeDetail.date = $r('app.string.monthDay', mounth, day);
563    } else {
564      timeDetail.date = $r('app.string.yearMonthDay', year, mounth, day);
565    }
566    return timeDetail;
567  }
568
569  // Edit Contact
570  updateContact() {
571    let phoneNumbers = [{
572                          'phoneNumber': '',
573                          'phoneAddress': ''
574                        }];
575    if (this.isNewNumber) {
576      phoneNumbers[0].phoneNumber = this.phoneNumberShow;
577      phoneNumbers[0].phoneAddress = this.contactForm?.phones[0]?.phoneAddress;
578    }
579    let upDataShow = false;
580    if (this.contactId != undefined) {
581      upDataShow = true
582    }
583    router.replace({
584      url: 'pages/contacts/accountants/Accountants',
585      params: {
586        updataShow: upDataShow,
587        contactId: this.contacts.id,
588        phoneNumbers: phoneNumbers
589      },
590    });
591  }
592
593  clearAllCallLog() {
594    let id = '';
595    let ids = [];
596    for (let index = 0; index < this.detailCallLogDataSource.totalCount(); index++) {
597      id = this.detailCallLogDataSource.getData(index).callLog.id;
598      ids.push(id);
599    }
600    this.removeCallLog(ids);
601  }
602
603  // Delete call records based on the ID set.
604  removeCallLog(ids) {
605    HiLog.i(TAG, 'removeCallLog');
606    globalThis.DataWorker.sendRequest('deleteCallLogsById', {
607      context: globalThis.context,
608      ids: ids
609    }, (data) => {
610      HiLog.i(TAG, 'removeCallLog Success');
611    });
612  }
613
614  // Deleting a contact
615  deleteContact() {
616    AlertDialog.show({
617      message: $r('app.string.delete_contact_sure'),
618      alignment: EnvironmentProp.isTablet() ? DialogAlignment.Center : DialogAlignment.Bottom,
619      autoCancel: true,
620      primaryButton: {
621        value: $r('app.string.dialog_cancel'),
622        action: () => {
623        }
624      },
625      secondaryButton: {
626        value: $r('app.string.dialog_delete'),
627        fontColor: $r('sys.color.ohos_id_color_handup'),
628        action: () => {
629          HiLog.i(TAG, 'delete contact')
630          this.doDeleteContact();
631        }
632      },
633      cancel: () => {
634        HiLog.i(TAG, 'Closed callbacks')
635      },
636      offset: {
637        dx: 0, dy: -52
638      },
639      gridCount: 4
640    })
641  }
642
643  // Delete a contact
644  doDeleteContact() {
645    globalThis.DataWorker.sendRequest('deleteContactById', {
646      context: globalThis.context,
647      contactId: this.contactId
648    }, (result) => {
649      if (result == 0 || result == undefined) {
650        HiLog.i(TAG, 'doDeleteContact succ');
651      } else {
652        HiLog.i(TAG, `doDeleteContact Failed ${JSON.stringify(result)}`);
653        prompt.showToast({
654          message: 'contactDetail Failed to delete data.'
655        });
656      }
657    });
658    router.back();
659  }
660
661  // Sending Messages
662  sendMessage(phoneNumber, formatnum, name) {
663    PhoneNumber.fromString(phoneNumber).sendMessage(formatnum, name);
664  }
665
666  changeTopBarBackgroundColor(isTopForItem) {
667    if (isTopForItem) {
668      this.topbarBackgroundColor = Color.White;
669    } else {
670      this.topbarBackgroundColor = Color.Transparent;
671    }
672  }
673
674  getTopBarBackgroundColor() {
675    return this.topbarBackgroundColor;
676  }
677
678  // Truncates the first five characters of the string plus..
679  subStringWithEllipsis(str, len) {
680    let newLength = 0;
681    let newStr = '';
682    let chineseRegex = /[^\x00-\xff]/g;
683    let singleChar = '';
684    let strLength = str.replace(chineseRegex, '**').length;
685    for (let i = 0; i < strLength; i++) {
686      singleChar = str.charAt(i).toString();
687      if (singleChar.match(chineseRegex) != null) {
688        newLength += 2;
689      } else {
690        newLength++;
691      }
692      if (newLength > len) {
693        break;
694      }
695      newStr += singleChar;
696    }
697    newStr += '..'
698    return newStr;
699  }
700
701  getSettingsMenus() {
702    let tmpMoreMenu = [];
703    this.moreMenuOptions.forEach(element => {
704      tmpMoreMenu.push({});
705    });
706    let mMoreMenu: Array<{
707      value: string,
708      action: () => void
709    }> = [{
710            value: '',
711            action: () => {
712            }
713          }];
714    mMoreMenu = tmpMoreMenu;
715    this.moreMenuOptions.forEach((element, i) => {
716      globalThis.context.resourceManager.getString(element.id, (err, typeName) => {
717        mMoreMenu[i] = {
718          value: typeName,
719          action: () => {
720            switch (i) {
721              case 0:
722                this.deleteContact();
723                break;
724            }
725          }
726        };
727      });
728    });
729    return mMoreMenu;
730  }
731
732  updateFavorite(favoriteStatus: number) {
733    HiLog.i(TAG, 'updateFavorite start.');
734    let favoriteForm: any = {}
735    favoriteForm.id = this.contactId;
736    favoriteForm.favorite = favoriteStatus;
737    globalThis.DataWorker.sendRequest('updateFavorite', {
738      context: globalThis.context,
739      favoriteForm: JSON.stringify(favoriteForm)
740    }, (arg) => {
741      HiLog.i(TAG, 'updateFavorite success.');
742    })
743  }
744
745  saveExistingContact() {
746    HiLog.i(TAG, 'updateFavorite start.');
747    router.replaceUrl({
748      url: 'pages/contacts/batchselectcontacts/SingleSelectContactPage',
749      params: {
750        phoneNumberShow: this.phoneNumberShow,
751        contactForm: this.contactForm,
752        contactId: this.contactId,
753        contactsId: this.contacts.id,
754        phones: this.contactForm.phones,
755        editContact: 0,
756        selectType: 0
757      }
758    });
759  }
760}