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 DeviceUtil from "../../utils/DeviceUtil"; 16import InfoMsgController from "./InfoMsgController"; 17import { DeleteDialog } from "../../views/MmsDialogs"; 18import { MmsListItem } from "../../views/MmsListItem"; 19import { MoreMenu } from "../../views/MmsMenu"; 20import WantUtil from "../../utils/WantUtil"; 21 22@Entry 23@Component 24export default struct InfoMsg { 25 @StorageLink("InfoMsgController") @Watch("changeSelectState") mInfoMsgCtrl: InfoMsgController = InfoMsgController.getInstance(); 26 @State mIsMultipleSelectState : boolean = false; 27 @State misShowContactHeadIcon : boolean = true; 28 private gridColumns: GridRowColumnOption = { sm: 4, md: 8, lg: 12 }; 29 private girdSpan: GridColColumnOption = { sm: 4, md: 8, lg: 12 }; 30 private gridGutter: string = "24vp"; 31 private gridMargin: string = "24vp"; 32 private dialogGridCount: number = 4; 33 private dialogAlignment: DialogAlignment = DeviceUtil.isTablet() ? DialogAlignment.Center : DialogAlignment.Bottom; 34 private dialogOffset: Offset = DeviceUtil.isTablet() ? { dx: 0, dy: 0 } : { dx: 0, dy: -12 }; 35 delDialogController: CustomDialogController = new CustomDialogController({ 36 builder: DeleteDialog({ 37 cancel: () => { 38 this.mInfoMsgCtrl.delDialogShow = false; 39 this.mInfoMsgCtrl.deleteDialogCancel() 40 }, 41 confirm: () => { 42 this.mInfoMsgCtrl.delDialogShow = false; 43 this.mInfoMsgCtrl.deleteDialogConfirm() 44 }, 45 msg: this.mInfoMsgCtrl.strMsgDeleteDialogTip, 46 hasLockMsg: this.mInfoMsgCtrl.hasLockMsg, 47 setSelectLock: () => { 48 this.mInfoMsgCtrl.setSelectLock() 49 }, 50 isSelectLockMsg: this.mInfoMsgCtrl.isSelectLockMsg, 51 setSelectLockChange: (isOn: boolean) => { 52 this.mInfoMsgCtrl.setSelectLockChange(isOn) 53 } 54 }), 55 autoCancel: false, 56 alignment: this.dialogAlignment, 57 offset: this.dialogOffset, 58 gridCount: this.dialogGridCount 59 }) 60 @Provide menuItems: Array<any> = [ 61 { 62 value: $r("app.string.delete"), 63 action: () => { 64 this.mInfoMsgCtrl.selectInMoreMenu(1); 65 }, 66 enabled: true 67 } 68// , 69// { 70// value: $r("app.string.blocked"), 71// action: () => { 72// this.mInfoMsgCtrl.selectInMoreMenu(2); 73// }, 74// enabled: true 75// } 76 ]; 77 78 changeSelectState() { 79 this.mIsMultipleSelectState = this.mInfoMsgCtrl.isMultipleSelectState 80 this.misShowContactHeadIcon = this.mInfoMsgCtrl.isShowContactHeadIcon 81 // @ts-ignore 82 this.forceCompleteRerender(true) // recusvise 83 } 84 85 /** 86 * The function executes after a new instance of the custom component is created and before its build function 87 * is executed. 88 * Allows state variables to be changed in the aboutToAppear function, and these changes will take effect in 89 * subsequent executions of the build function. 90 */ 91 aboutToAppear() { 92 this.mInfoMsgCtrl.onInit() 93 } 94 /** 95 * Function executes before custom component destructor consumption. 96 * Allow changes to state variables in the aboutToDisappear function, especially changes to the @Link variable, 97 * can cause erratic application behavior. 98 */ 99 aboutToDisappear() { 100 } 101 /** 102 * Triggers once when this page is displayed. In scenarios such as routing and application access to the 103 * foreground and background, only customized components modified by @Entry take effect. 104 */ 105 onPageShow() { 106 this.mInfoMsgCtrl.onShow(); 107 WantUtil.getWant(); 108 } 109 /** 110 * Triggers once when this page disappears. In scenarios such as routing and application access to the foreground 111 * and background, only customized components modified by @Entry take effect. 112 */ 113 onPageHide() { 114 this.mInfoMsgCtrl.onHide() 115 } 116 /** 117 * Triggered when a user clicks the back button. Only the customized component modified by @Entry takes effect. 118 * If true is returned, the page processes the return logic and does not route the page 119 * 返If false is returned, the default return logic is used. 120 * If no value is returned, the value is treated as false. 121 */ 122 onBackPress() { 123 // Key returned by the system. The value true indicates interception. 124 if (this.mInfoMsgCtrl.delDialogShow) { 125 this.delDialogController.close(); 126 this.mInfoMsgCtrl.delDialogShow = false; 127 return true; 128 } 129 if (this.mInfoMsgCtrl.isMultipleSelectState) { 130 for (let element of this.mInfoMsgCtrl.messageList) { 131 element.isCbChecked = false; 132 } 133 this.mInfoMsgCtrl.isMultipleSelectState = false; 134 this.mInfoMsgCtrl.showToolBar = true; 135 return true; 136 } 137 return false; 138 } 139 140 build() { 141 GridRow({ columns: this.gridColumns, gutter: this.gridGutter }) { 142 GridCol({ span: this.girdSpan }) { 143 //Notification Information 144 Column() { 145 if (this.mIsMultipleSelectState) { 146 //Multi-Select Status Title 147 Flex({ direction: FlexDirection.Column }) { 148 Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) { 149 Image($rawfile("icon/ic_public_cancel.svg")) 150 .width("24vp") 151 .height("24vp") 152 .onClick(() => { 153 this.onBackPress() 154 }) 155 Text(this.mInfoMsgCtrl.conversationSelectedNumber == 0 ? 156 $r("app.string.msg_unselected_tip") : 157 $r("app.string.msg_selected_tip", this.mInfoMsgCtrl.conversationSelectedNumber)) 158 .padding({ left: "16vp" }) 159 .fontSize("20fp") 160 .fontWeight(FontWeight.Bold) 161 } 162 .height("56vp") 163 } 164 .width("100%") 165 .height("56vp") 166 } else if (!this.mInfoMsgCtrl.searchStatus) { 167 //Header Row 168 Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) { 169 Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) { 170 Image($rawfile("icon/ic_message_back.svg")) 171 .width("24vp") 172 .height("24vp") 173 .onClick(() => { 174 this.mInfoMsgCtrl.back() 175 }) 176 Text($r("app.string.infoMessages")) 177 .padding({ left: "16vp" }) 178 .fontSize("20fp") 179 .fontWeight(FontWeight.Bold) 180 } 181 .height("56vp") 182 } 183 .width("100%") 184 .height("56vp") 185 } 186 187 Row() { 188 //Back button 189 if (this.mInfoMsgCtrl.isShowSearchBack) { 190 Image($rawfile("icon/ic_message_back.svg")) 191 .width(24) 192 .height(24) 193 .onClick((event: ClickEvent) => { 194 this.mInfoMsgCtrl.clickSearchBack(); 195 }) 196 } 197 //Search box 198 // @ts-ignore 199 Search({ value: this.mInfoMsgCtrl.inputValueOfSearch, placeholder: "搜索通知信息" }) 200 .layoutWeight(1) 201 .height("40vp") 202 .border({ radius: "20vp" }) 203 .enabled(!this.mIsMultipleSelectState) 204 .backgroundColor($r("sys.color.ohos_id_color_text_field_bg")) 205 .onChange((value: string) => { 206 this.mInfoMsgCtrl.clickToSearch(value); 207 }) 208 .onSubmit((value: string) => { 209 this.mInfoMsgCtrl.clickToSearch(value); 210 }) 211 } 212 .visibility(Visibility.None) 213 .width("100%") 214 .height("56vp") 215 .padding({ left: 24, right: 24 }) 216 .alignItems(VerticalAlign.Center) 217 218 //SMS message display list 219 Stack({ alignContent: Alignment.Top }) { 220 Column() { 221 List({ initialIndex: 0 }) { 222 if (this.mInfoMsgCtrl.isSearchStatus) { 223 LazyForEach(this.mInfoMsgCtrl.conversationListDataSource, (item, index) => { 224 //A real list of information 225 ListItem() { 226 MmsListItem({ 227 item: item, 228 isShowHead: this.misShowContactHeadIcon, 229 isMultipleSelectState: this.mIsMultipleSelectState, 230 onClickHead: (event: ClickEvent) => { 231 this.mInfoMsgCtrl.clickToGroupDetail(item.index); 232 }, 233 onClickBody: (event: ClickEvent) => { 234 this.mInfoMsgCtrl.clickInfoToConversation(item.index); 235 }, 236 onItemLongPress: (event: GestureEvent) => { 237 this.mInfoMsgCtrl.conversationLongPress(item.index) 238 }, 239 onTouchStart: (event: GestureEvent) => { 240 this.mInfoMsgCtrl.touchStart(event, item.index); 241 }, 242 onTouchUpdate: (event: GestureEvent) => { 243 this.mInfoMsgCtrl.touchMove(event, item.index); 244 }, 245 onTouchEnd: (event: GestureEvent) => { 246 this.mInfoMsgCtrl.touchEnd(event, item.index); 247 // @ts-ignore 248 this.forceCompleteRerender(true) // recusvise 249 }, 250 onClickFirstSlipBtn: (event: ClickEvent) => { 251 this.mInfoMsgCtrl.markAllAsReadByIndex(item.index); 252 }, 253 onClickSecondSlipBtn: (event: ClickEvent) => { 254 this.mInfoMsgCtrl.deleteAction(item.index); 255 this.delDialogController.open(); 256 this.mInfoMsgCtrl.delDialogShow = true; 257 } 258 }) 259 } 260 .width("100%") 261 .height("64vp") 262 .alignSelf(ItemAlign.Start) 263 }, item => JSON.stringify(item)) 264 } 265 } 266 .align(Alignment.Top) 267 .cachedCount(this.mInfoMsgCtrl.limit) 268 .edgeEffect(EdgeEffect.Spring) 269 .width("100%") 270 .divider({ 271 strokeWidth: 1, 272 startMargin: this.mInfoMsgCtrl.isShowContactHeadIcon ? 52 : 12, 273 endMargin: 0 274 }) 275 }.width("100%") 276 //Search Above 277 //SMS Search Session Item 278 //Left avatar 279 //Information on the right 280 //Name and date above 281 //Details of the information below 282 //intermediate spacing line 283 //Number of barcodes in the search information list 284 //Search Information List 285 //Left avatar 286 //Information on the right 287 //Name and date above 288 //Details of the information below 289 //If there is no session information, that is, {{total}} is 0, a blank image is displayed. 290 //Show Search Status 291 if (this.mInfoMsgCtrl.isSearchCoverage) { 292 //Display of layers for search 293 Flex() 294 .width("100%") 295 .height("100%") 296 .opacity(0.2) 297 .backgroundColor(Color.Gray) 298 .onTouch((event: TouchEvent) => { 299 if (event.type === TouchType.Down) { 300 this.mInfoMsgCtrl.searchCoverageClick() 301 } 302 }) 303 } 304 } 305 .flexShrink(1) 306 307 Blank() 308 309 //Single session press and hold option 310 if (this.mInfoMsgCtrl.isMultipleSelectState) { 311 Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) { 312 //Delete 313 Flex({ 314 direction: FlexDirection.Column, 315 justifyContent: FlexAlign.Center, 316 alignItems: ItemAlign.Center 317 }) { 318 Image($rawfile(this.mInfoMsgCtrl.svgDelete)) 319 .width("24vp") 320 .height("24vp") 321 .margin({ top: "3vp" }) 322 Text($r("app.string.delete")) 323 .fontSize("10fp") 324 .fontWeight(FontWeight.Medium) 325 .fontFamily("HarmonyHeiTi") 326 .margin({ top: 3 }) 327 } 328 .width("50%") 329 .opacity(this.mInfoMsgCtrl.checkSelectedNumberIsEmpty() ? 0.4 : 1) 330 .onClick(() => { 331 if (!this.mInfoMsgCtrl.checkSelectedNumberIsEmpty()) { 332 this.mInfoMsgCtrl.clickConversationDelete() 333 this.delDialogController.open() 334 this.mInfoMsgCtrl.delDialogShow = true; 335 } 336 }) 337 //Select All 338 Flex({ 339 direction: FlexDirection.Column, 340 justifyContent: FlexAlign.Center, 341 alignItems: ItemAlign.Center 342 }) { 343 Image($rawfile(this.mInfoMsgCtrl.isConversationCheckAll ? 344 "icon/ic_select_all_filled.svg" : 345 "icon/ic_select_all.svg")) 346 .width("24vp") 347 .height("24vp") 348 .margin({ top: "3vp" }) 349 Text(this.mInfoMsgCtrl.strCheckBoxSelectTip) 350 .fontSize("10fp") 351 .fontColor(this.mInfoMsgCtrl.isConversationCheckAll ? 352 $r("sys.color.ohos_id_color_bottom_tab_text_on") : 353 $r("sys.color.ohos_id_color_bottom_tab_text_off")) 354 .fontWeight(FontWeight.Medium) 355 .fontFamily("HarmonyHeiTi") 356 .margin({ top: 3 }) 357 } 358 .width("50%") 359 .onClick(() => { 360 this.mInfoMsgCtrl.clickConversationCheckAll() 361 }) 362 } 363 .width("100%") 364 .height(56) 365 .padding({ left: $r("app.float.menu_layout_padding_left"), 366 right: $r("app.float.menu_layout_padding_right") }) 367 .flexBasis(56) 368 .flexShrink(0) 369 } 370 371 //All read and more 372 if (!this.mInfoMsgCtrl.isMultipleSelectState && this.mInfoMsgCtrl.showToolBar) { 373 Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) { 374 //All read 375 Flex({ 376 direction: FlexDirection.Column, 377 justifyContent: FlexAlign.Center, 378 alignItems: ItemAlign.Center 379 }) { 380 Image($rawfile("icon/ic_allread.svg")) 381 .width("24vp") 382 .height("24vp") 383 .margin({ top: "3vp" }) 384 Text($r("app.string.markAllAsRead")) 385 .fontSize($r("sys.float.ohos_id_text_size_caption")) 386 .fontWeight(FontWeight.Medium) 387 .fontColor($r("sys.color.ohos_id_color_toolbar_text")) 388 } 389 .width("50%") 390 .opacity(this.mInfoMsgCtrl.unreadTotalOfInfo == 0 ? 0.4 : 1) 391 .onClick(() => { 392 this.mInfoMsgCtrl.clickToMarkAllAsReadForInfo() 393 }) 394 //more 395 Flex({ 396 direction: FlexDirection.Column, 397 justifyContent: FlexAlign.Center, 398 alignItems: ItemAlign.Center 399 }) { 400 MoreMenu({ 401 menuText: $r("app.string.more") 402 }) 403 } 404 .width("50%") 405 } 406 .width("100%") 407 .height(56) 408 .padding({ left: $r("app.float.menu_layout_padding_left"), 409 right: $r("app.float.menu_layout_padding_right") }) 410 .flexBasis(56) 411 .flexShrink(0) 412 } 413 //Setting the background of the navigation bar 414 //Delete pop-up dialog box 415 } 416 .width("100%") 417 .height("100%") 418 } 419 } 420 .margin({ left: this.gridMargin }) 421 } 422}