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