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 */ 15import prompt from "@system.prompt"; 16 17import HiLog from "../../utils/HiLog"; 18import common from "../../data/commonData"; 19import ContactsService from "../../service/ContactsService"; 20import commonService from "../../service/CommonService" 21import commonCtrl from "../../pages/conversation/common" 22import LooseObject from "../../data/LooseObject" 23 24const TAG = "ReceiveController"; 25 26export default class ReceiveController { 27 private static sInstance: ReceiveController; 28 commonCtrl = commonCtrl.getInstance(); 29 refresh: boolean = false; 30 // Recipient information (selected) 31 selectContacts: Array<any> = []; 32 contacts: Array<any> = []; 33 // Recipient list information (all) 34 contactsTemp: Array<any> = []; 35 // Recipient Content 36 myText: string = ''; 37 // true: focus editing status (gray); false: no focus (blue) 38 isInputStatus: boolean = true; 39 // true Show Search List 40 isShowSearch: boolean = true; 41 strSelectContact: string = ''; 42 styleTextarea: string = "select-contact-textarea"; 43 hasBlur: boolean = false; 44 // List pagination, number of pages 45 page: number = 0; 46 // List pagination, quantity 47 limit: number = 10; 48 // Total number of contacts 49 totalMessage: number = 0; 50 51 static getInstance() { 52 if (ReceiveController.sInstance == null) { 53 ReceiveController.sInstance = new ReceiveController(); 54 } 55 return ReceiveController.sInstance; 56 } 57 58 onInit(call) { 59 HiLog.i(TAG, "onInit()") 60 // this.$watch("paramContact", "onPropertyChange"); 61 this.selectContacts = this.commonCtrl.paramContact.transmitContacts; 62 if (this.selectContacts.length > 0) { 63 let that = this; 64 setTimeout(function () { 65 that.setContactValue(call); 66 }, 200); 67 this.isShowSearch = false; 68 this.setInputStatus(false); 69 } 70 this.requestItem() 71 this.refresh = !this.refresh; 72 } 73 74 onBackPress() { 75 this.InputTextClear(); 76 return true; 77 } 78 79 InputTextClear() { 80 this.myText = ""; 81 this.setInputStatus(true); 82 this.commonCtrl.paramContact.transmitContacts = []; 83 HiLog.i(TAG,"InputTextClear") 84 } 85 86 requestItem() { 87 let count = this.page * this.limit; 88 if (this.page === 0) { 89 this.page++; 90 this.queryContacts(); 91 } else if (count < this.totalMessage && this.contacts.length > (this.page - 1) * this.limit) { 92 // The restriction on Contacts is to prevent multiple refresh requests during initialization. 93 this.page++; 94 this.queryContacts(); 95 } 96 } 97 98 queryContacts() { 99 let actionData = { 100 page: this.page, 101 limit: this.limit 102 }; 103 // Querying Contacts 104 ContactsService.getInstance().queryContact(actionData, contacts => { 105 if (common.int.SUCCESS == contacts.code) { 106 let response = this.contacts.concat(contacts.response); 107 this.contacts = []; 108 this.contacts = response; 109 this.contactsTemp = this.contacts.slice(0); 110 } else { 111 HiLog.w(TAG, "queryContacts, fail"); 112 } 113 }, null); 114 // Number of statistics 115 ContactsService.getInstance().queryContactSizeByCondition(actionData, res => { 116 if (res.code == common.int.SUCCESS) { 117 this.totalMessage = res.abilityResult; 118 } 119 }, null); 120 } 121 122 searchContacts(textValue, callback) { 123 HiLog.i(TAG, "searchContacts start"); 124 let actionData = { 125 telephone: textValue, 126 }; 127 ContactsService.getInstance().queryContactViewByCondition(actionData, res => { 128 if (res.code == common.int.SUCCESS) { 129 this.contacts = res.abilityResult; 130 } else { 131 HiLog.w(TAG, "searchContacts fail"); 132 } 133 callback(res.code); 134 }, null); 135 } 136 137 // Filter search terms to match contacts 138 filterContacts(textValue) { 139 try { 140 this.contacts = this.contactsTemp.filter((contact) => { 141 if (contact.contactName && contact.contactName.toLowerCase().search(textValue) != -1) { 142 HiLog.i(TAG, "filterContacts, contactName"); 143 return true; 144 } else if (contact.telephone && contact.telephone.toLowerCase().search(textValue) != -1) { 145 HiLog.i(TAG, "filterContacts, telephone"); 146 return true; 147 } 148 return false; 149 }); 150 } catch (Error) { 151 HiLog.i(TAG, `error message: ${JSON.stringify(Error)}`); 152 } 153 } 154 155 isPhoneNumber(str) { 156 // Determine whether the value is a number. 157 let reg = /^\d{1,}$/; 158 let pattern = new RegExp(reg); 159 return pattern.test(str); 160 } 161 162 setInputStatus(flag) { 163 this.isInputStatus = flag; 164 if (!flag) { 165 this.strSelectContact = this.setShowContactName(); 166 } 167 } 168 169 checkReceive(call) { 170 HiLog.i(TAG, "checkReceive, isInputStatus: " + this.isInputStatus); 171 if (this.myText.trim() == common.string.EMPTY_STR) { 172 this.strSelectContact = this.setShowContactName(); 173 this.isShowSearch = false; 174 return; 175 } 176 this.hasBlur = true; 177 if (this.isPhoneNumber(this.myText)) { 178 // Get information from the contact list 179 let that = this; 180 let selectContact: LooseObject = {}; 181 let hasSelect = false; 182 for (let index in this.contacts) { 183 let contact = this.contacts[index]; 184 if (contact.telephone == that.myText) { 185 selectContact.headImage = "icon/user_avatar_full_fill.svg"; 186 selectContact.contactName = contact.contactName; 187 selectContact.telephone = contact.telephone; 188 selectContact.telephoneFormat = contact.telephone; 189 selectContact.select = false; 190 hasSelect = true; 191 break; 192 } 193 } 194 if (!hasSelect) { 195 selectContact.headImage = common.string.EMPTY_STR; 196 selectContact.contactName = common.string.EMPTY_STR; 197 selectContact.telephone = that.myText; 198 selectContact.telephoneFormat = that.myText; 199 selectContact.select = false; 200 } 201 HiLog.i(TAG, "checkReceive, isPhoneNumber yes"); 202 this.selectContacts.push(selectContact); 203 this.refresh = !this.refresh; 204 this.setInputStatus(false); 205 this.isShowSearch = false; 206 this.setContactValue(call); 207 } else { 208 HiLog.i(TAG, "checkReceive, isPhoneNumber no"); 209 prompt.showToast({ 210 // Invalid Recipient 211 // @ts-ignore 212 message: $r("app.string.invalid_receive", this.myText), 213 duration: 1000, 214 }); 215 this.myText = ""; 216 this.isShowSearch = true; 217 this.setContactValue(call); 218 } 219 } 220 221 searchChange(text, call) { 222 HiLog.d(TAG, "searchChange, start"); 223 if (this.checkSingle()) { 224 this.setInputStatus(false); 225 this.isShowSearch = false; 226 return; 227 } 228 this.myText = text; 229 if (!this.isInputStatus) { 230 HiLog.w(TAG, "searchChange, isInputStatus false"); 231 return; 232 } 233 this.searchContacts(this.myText, code => { 234 if (code == common.int.SUCCESS && this.myText.trim() != "") { 235 this.setContactValue(call); 236 this.dealSearchData(); 237 this.setContactValue(call); 238 } else { 239 this.setContactValue(call); 240 } 241 }); 242 } 243 244 dealSearchData() { 245 if (this.myText.trim() == "") { 246 this.contacts = this.contactsTemp.slice(0); 247 // this.$element("receiveTxt").focus({ 248 // focus: true 249 // }); 250 } else { 251 let textValue = this.myText.trim().toLowerCase(); 252 // Filtering logic 253 this.filterContacts(textValue); 254 } 255 } 256 257 setContactValue(call) { 258 // Send recipient information to the invoked parent component. 259 call({ 260 // Select the content of the text box before the contact. 261 contactValue: this.myText, 262 // Selected recipient information 263 selectContacts: this.selectContacts, 264 // Whether the focus is lost 265 hasBlur: this.hasBlur 266 }); 267 } 268 269 addContact(index, call) { 270 let curItem = this.contacts[index]; 271 if (this.checkSingle()) { 272 return; 273 } 274 if (curItem != undefined && curItem.telephone != undefined && curItem.telephone.toString().trim() == "") { 275 prompt.showToast({ 276 // Invalid Recipient 277 // @ts-ignore 278 message: $r("app.string.invalid_receive", this.myText), 279 duration: 1000, 280 }); 281 return; 282 } 283 this.selectContacts.push(curItem); 284 this.contactsTemp = this.contactsTemp.filter((item) => { 285 if (item.telephone == undefined || curItem.telephone == undefined) { 286 return; 287 } 288 HiLog.w(TAG, "addContact"); 289 return item.telephone != curItem.telephone 290 }); 291 this.contacts.splice(index, 1); 292 HiLog.i(TAG, "addContact, length: " + this.selectContacts.length); 293 this.myText = ''; 294 if (this.selectContacts.length == 1) { 295 this.setInputStatus(false); 296 this.isShowSearch = false; 297 this.setContactValue(call); 298 } else { 299 this.setInputStatus(true); 300 this.isShowSearch = true; 301 this.setContactValue(call); 302 } 303 HiLog.i(TAG, "addContact, isInputStatus: " + this.isInputStatus); 304 } 305 306 setShowContactName() { 307 if (this.selectContacts.length == 0) { 308 return ''; 309 } 310 let myName = this.selectContacts[0]?.contactName?.trim(); 311 if (!myName) { 312 myName = "" 313 } 314 let telephone = this.selectContacts[0]?.telephone 315 if (telephone === undefined || telephone === null) { 316 HiLog.e(TAG, "setShowContactName fail"); 317 return ''; 318 } 319 if (!this.isPhoneNumber(telephone)) { 320 myName = telephone.replace(new RegExp(/e|-|#|\*|\./, "g"), common.string.EMPTY_STR); 321 } else { 322 if (myName == "") { 323 myName = telephone; 324 } 325 } 326 if (this.selectContacts.length >= 2) { 327 // name and other numbers 328 return $r("app.string.and_others", myName, this.selectContacts.length - 1) 329 } else { 330 return myName 331 } 332 } 333 334 myContactFocus() { 335 HiLog.i(TAG, "myContactFocus, start"); 336 this.myText = common.string.EMPTY_STR; 337 this.setInputStatus(true); 338 this.isShowSearch = true; 339 } 340 341 myContactClick() { 342 HiLog.i(TAG, "myContactClick, start"); 343 if (!this.isInputStatus) { 344 this.myText = common.string.EMPTY_STR; 345 this.setInputStatus(true); 346 this.isShowSearch = true; 347 // The TextArea control does not support focus. 348 // this.$element("receiveTxt").focus({ 349 // focus: true 350 // }); 351 } 352 } 353 354 nameClick(idx, call) { 355 HiLog.i(TAG, "click-->" + idx) 356 if (this.selectContacts[idx] == null || this.selectContacts[idx] == undefined) { 357 return; 358 } 359 if (this.selectContacts[idx].select) { 360 let item = this.selectContacts.splice(idx, 1); 361 // Deleted items are added to the collection to be searched. 362 this.contactsTemp.push(item); 363 if (item[0] != undefined && item[0].telephoneFormat != undefined && 364 item[0].telephoneFormat.toString().trim() != "") { 365 this.contacts.push(item[0]); 366 } 367 this.refresh = !this.refresh; 368 this.setContactValue(call); 369 return; 370 } 371 for (let element of this.selectContacts) { 372 element.select = false; 373 } 374 this.selectContacts[idx].select = true; 375 this.refresh = !this.refresh; 376 } 377 378 clickToContacts(call) { 379 var actionData: LooseObject = {}; 380 actionData.pageFlag = common.contactPage.PAGE_FLAG_SINGLE_CHOOSE; 381 this.jumpToContactForResult(actionData, call); 382 } 383 // Tap a contact's avatar to go to the contact details page. 384 titleBarAvatar(index) { 385 var actionData: LooseObject = {}; 386 actionData.phoneNumber = this.contacts[index]?.telephone; 387 actionData.pageFlag = common.contactPage.PAGE_FLAG_CONTACT_DETAILS; 388 this.jumpToContact(actionData); 389 } 390 // Switching to the Contacts app 391 jumpToContact(actionData) { 392 let str = commonService.commonContactParam(actionData); 393 globalThis.mmsContext.startAbility(str).then((data) => { 394 }).catch((error) => { 395 HiLog.i(TAG, "jumpToContact failed"); 396 }); 397 } 398 // Switching to the Contacts app 399 async jumpToContactForResult(actionData, call) { 400 let str = commonService.commonContactParam(actionData); 401 var data = await globalThis.mmsContext.startAbilityForResult(str); 402 if (data.resultCode == 0) { 403 this.dealContactParams(data.want.parameters.contactObjects, call); 404 } 405 } 406 407 dealContactParams(contactObjects, call) { 408 this.selectContacts = []; 409 let params = JSON.parse(contactObjects); 410 if (this.checkSingle()) { 411 return; 412 } 413 for (let element of params) { 414 let selectContact: LooseObject = {}; 415 selectContact.headImage = "icon/user_avatar_full_fill.svg"; 416 selectContact.contactName = element.contactName; 417 selectContact.telephone = element.telephone; 418 selectContact.telephoneFormat = element.telephone; 419 selectContact.select = false; 420 this.selectContacts.push(selectContact); 421 } 422 if (params.length > 1 && this.checkSingle()) { 423 this.selectContacts = []; 424 return; 425 } 426 if (this.selectContacts.length > 0) { 427 this.deleteRepetitionContacts(this.contacts, this.selectContacts); 428 this.setInputStatus(false); 429 this.isShowSearch = false; 430 this.setContactValue(call); 431 } 432 this.commonCtrl.paramContact.isSelectContact = false; 433 this.commonCtrl.paramContact.isNewRecallMessagesFlag = false; 434 } 435 436 deleteRepetitionContacts(contacts, selectContacts) { 437 let indexs = []; 438 let count = 0; 439 for (let item of contacts) { 440 let telephone = item.telephone; 441 for (let selectContact of selectContacts) { 442 if (telephone == selectContact.telephone) { 443 indexs.push(count); 444 break; 445 } 446 } 447 count++; 448 } 449 let selectContactIndexs = []; 450 for (let i = 0; i < selectContacts.length; i++) { 451 let telephone = selectContacts[i].telephone; 452 for (let j = i + 1; j < selectContacts.length; j++) { 453 if (telephone == selectContacts[j].telephone) { 454 selectContactIndexs.push(i); 455 break; 456 } 457 } 458 } 459 if (indexs.length > 0) { 460 for (let index of indexs) { 461 contacts.splice(index, 1); 462 } 463 } 464 if (selectContactIndexs.length > 0) { 465 for (let index of selectContactIndexs) { 466 selectContacts.splice(index, 1); 467 } 468 } 469 } 470 471 // Currently, only one recipient is supported. You can enter only one recipient first. 472 checkSingle() { 473 if (this.selectContacts.length > 0) { 474 prompt.showToast({ 475 // Invalid Recipient 476 // @ts-ignore 477 message: "只支持单个收件人", 478 duration: 1000, 479 }); 480 return true; 481 } else { 482 return false; 483 } 484 } 485}