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 router from "@system.router"; 16import ConListController from "./conversationListController"; 17import DeviceUtil from "../../utils/DeviceUtil"; 18import HiLog from "../../utils/HiLog" 19import { DeleteDialog } from "../../views/MmsDialogs"; 20import { MmsListItem } from "../../views/MmsListItem"; 21import { MoreMenu } from "../../views/MmsMenu"; 22 23const TAG = "ConversationList"; 24 25@Component 26export default struct ConversationList { 27 @Link @Watch("changeSelectState") mConListCtrl: ConListController; 28 private dialogAlignment: DialogAlignment = DeviceUtil.isTablet() ? DialogAlignment.Center : DialogAlignment.Bottom; 29 private dialogOffset: Offset = DeviceUtil.isTablet() ? { dx: 0, dy: 0 } : { dx: 0, dy: -12 }; 30 private dialogGridCount: number = 4; 31 delDialogController: CustomDialogController = null; 32 @State mIsMultipleSelectState: boolean = false; 33 @Provide menuItems:any = []; 34 35 changeSelectState() { 36 this.mIsMultipleSelectState = this.mConListCtrl.isMultipleSelectState; 37 this.menuItems = [ 38 { 39 value: $r("app.string.delete"), 40 action: () => { 41 this.mConListCtrl.showMultipleSelectView(); 42 }, 43 enabled: true 44 }, 45 { 46 value: $r("app.string.markAllAsRead"), 47 action: () => { 48 this.mConListCtrl.clickToMarkAllAsRead(); 49 }, 50 enabled: this.mConListCtrl.unreadTotal == 0 ? false : true 51 }, 52 { 53 value: $r("app.string.settings"), 54 action: () => { 55 this.mConListCtrl.jumpToSettingsPage(); 56 }, 57 enabled: true 58 } 59 ]; 60 // @ts-ignore 61 this.forceCompleteRerender(true) // recusvise 62 } 63 64 /** 65 * The function executes after a new instance of the custom component is created and before its build function 66 * is executed. 67 * You can change the state variable in the aboutToAppear function, and these changes will take effect in 68 * subsequent executions of the build function. 69 */ 70 aboutToAppear() { 71 this.delDialogController = new CustomDialogController({ 72 builder: DeleteDialog({ 73 cancel: () => { 74 this.mConListCtrl.deleteDialogCancel() 75 }, 76 confirm: () => { 77 this.mConListCtrl.deleteDialogConfirm() 78 }, 79 msg: this.mConListCtrl.strMsgDeleteDialogTip, 80 hasLockMsg: this.mConListCtrl.hasLockMsg, 81 setSelectLock: () => { 82 this.mConListCtrl.setSelectLock() 83 }, 84 isSelectLockMsg: this.mConListCtrl.isSelectLockMsg, 85 setSelectLockChange: (isOn: boolean) => { 86 this.mConListCtrl.setSelectLockChange(isOn) 87 } 88 }), 89 autoCancel: false, 90 alignment: this.dialogAlignment, 91 offset: this.dialogOffset, 92 gridCount: this.dialogGridCount 93 }); 94 95 this.mConListCtrl.registerDataChangeObserver(this.onContactChange, getContext(this)); 96 } 97 98 onContactChange = () => { 99 this.mConListCtrl.messageList = []; 100 this.mConListCtrl.requestItem(); 101 } 102 103 /** 104 * Function executes before custom component destructor consumption. 105 * Allow changes to state variables in the aboutToDisappear function, especially changes to the @Link variable, 106 * can cause erratic application behavior. 107 */ 108 aboutToDisappear() { 109 this.mConListCtrl.unregisterDataChangeObserver(this.onContactChange, getContext(this)) 110 } 111 112 build() { 113 Stack(){ 114 Flex({ 115 direction: FlexDirection.Column, 116 justifyContent: FlexAlign.Start, 117 alignItems: ItemAlign.Start 118 }) { 119 Column() { 120 // Menu Bar 121 Row() { 122 if (!this.mConListCtrl.isMultipleSelectState) { 123 Blank() 124 Image($rawfile("icon/ic_public_add.svg")) 125 .width($r("app.float.icon_side_length_medium")) 126 .height($r("app.float.icon_side_length_medium")) 127 .onClick(() => { 128 // The page for creating an SMS message is displayed. 129 router.push( 130 { 131 uri: "pages/conversation/conversation", 132 params: { 133 isNewMsg: true 134 } 135 }) 136 }) 137 Column() { 138 MoreMenu() 139 } 140 .margin({ left: $r("app.float.action_bar_space") }) 141 } else { 142 Image($rawfile("icon/ic_public_cancel.svg")).height("24vp").width("24vp") 143 .onClick(() => { 144 this.mConListCtrl.onBackPress() 145 }) 146 Text(this.mConListCtrl.conversationSelectedNumber === 0 ? 147 $r("app.string.msg_unselected_tip") : 148 $r("app.string.msg_selected_tip", this.mConListCtrl.conversationSelectedNumber)) 149 .fontSize("20fp") 150 .fontWeight(FontWeight.Bold) 151 .margin({ left: 16 }) 152 } 153 } 154 .width("100%") 155 .height($r("app.float.action_bar_height")) 156 157 // Title bar 158 Column() { 159 if (!this.mConListCtrl.isMultipleSelectState) { 160 Row() { 161 Text($r("app.string.messages")) 162 .fontSize($r("app.float.list_title_font_size_large")) 163 .fontColor($r("sys.color.ohos_id_color_foreground")) 164 .fontWeight(FontWeight.Bold) 165 .lineHeight(41) 166 }.margin({ top: 8 }) 167 168 // Unread Message 169 Text($r("app.string.unread_messages", String(this.mConListCtrl.unreadTotal))) 170 .fontSize($r("sys.float.ohos_id_text_size_over_line")) 171 .fontColor($r("sys.color.ohos_id_color_text_secondary")) 172 .fontWeight(FontWeight.Regular) 173 .margin({ top: 2 }) 174 .visibility(this.mConListCtrl.unreadTotal == 0 ? Visibility.None : Visibility.Visible) 175 } 176 } 177 .height(this.mConListCtrl.unreadTotal == 0 ? 56 : $r("app.float.message_bar_height")) 178 .visibility(this.mConListCtrl.isMultipleSelectState 179 ? Visibility.None : Visibility.Visible) 180 } 181 .alignItems(HorizontalAlign.Start) 182 .flexShrink(0) 183 184 if (!(this.mConListCtrl.hasNoOrdinaryMsg && !(this.mConListCtrl.hasAggregate && this.mConListCtrl.hasInfoMsg 185 && this.mConListCtrl.isSearchStatus))) { 186 Column() { 187 //Search box 188 // @ts-ignore 189 Row() { 190 if (this.mConListCtrl.messageList.length != 0) { 191 Image($rawfile("icon/ic_message_search.svg")) 192 .width(17) 193 .height(18) 194 .fillColor($r("sys.color.ohos_id_color_activated")) 195 .margin({ left: 11.5 }) 196 197 Text("搜索联系人") 198 .fontSize("16fp") 199 .fontColor($r("sys.color.ohos_id_color_text_secondary")) 200 .margin({ left: 7.5 }) 201 } 202 } 203 .visibility(Visibility.None) 204 .height(40) 205 .width("100%") 206 .margin({ top: 8, bottom: 8 }) 207 .borderWidth(1.5) 208 .borderRadius(20) 209 .borderColor("#33182431") 210 211 List() { 212 if (this.mConListCtrl.hasAggregate && this.mConListCtrl.hasInfoMsg 213 && this.mConListCtrl.isSearchStatus) { 214 ListItem() { 215 Column() { 216 Row() { 217 Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center }) { 218 if (this.mConListCtrl.unreadTotalOfInfo > 0) { 219 Text(this.mConListCtrl.unreadTotalOfInfo < 100 ? 220 this.mConListCtrl.unreadTotalOfInfo.toString() : "99+") 221 .fontSize(10) 222 .align(Alignment.Center) 223 .padding({ left: 5, right: 5 }) 224 .height(20) 225 .backgroundColor($r("sys.color.ohos_id_color_badge_red")) 226 .fontColor($r("sys.color.ohos_id_color_background")) 227 .zIndex(2) 228 .position({ x: "60%", y: "8%" }) 229 .border({ 230 width: 2, 231 color: $r("sys.color.ohos_id_color_background"), 232 radius: 50 233 }) 234 } 235 Image($rawfile("icon/entrance_icon01.svg")) 236 .width("40vp") 237 .height("40vp") 238 }.width("40vp").height("64vp") 239 240 Column() { 241 Row() { 242 Text($r("app.string.infoMessages")) 243 .fontSize('16fp') 244 .fontColor($r("sys.color.ohos_id_color_text_primary")) 245 .fontWeight(FontWeight.Medium) 246 Blank() 247 if (this.mConListCtrl.unreadTotalOfInfo > 0) { 248 Text(this.mConListCtrl.unreadTotalOfInfo + "") 249 .height("64vp") 250 .margin({ 251 right: $r("app.float.settings_item_status_title_margin_right") 252 }) 253 .fontSize($r("app.float.settings_item_secondary_title_font_size")) 254 .fontWeight(FontWeight.Regular) 255 .fontColor($r("sys.color.ohos_id_color_text_secondary")) 256 Image($rawfile("icon/ic_next.svg")) 257 .width($r("app.float.settings_item_next_image_width")) 258 .height($r("app.float.settings_item_next_image_height")) 259 } 260 } 261 .width("100%") 262 .height("100%") 263 .margin({ left: "4vp" }) 264 }.layoutWeight(1) 265 .height("100%") 266 .padding({ left: "12vp" }) 267 }.height("64vp") 268 .width("100%") 269 .onClick(() => { 270 this.mConListCtrl.clickToInfoMessages(this.mConListCtrl.hasAggregate, 271 this.mConListCtrl.hasInfoMsg,this.mConListCtrl.isSearchStatus) 272 }) 273 } 274 }.opacity(this.mConListCtrl.isMultipleSelectState ? 0.4 : 1) 275 } 276 277 LazyForEach(this.mConListCtrl.conversationListDataSource, (item: any, index: number) => { 278 ListItem() { 279 MmsListItem({ 280 item: item, 281 isShowHead: this.mConListCtrl.isShowContactHeadIcon, 282 isMultipleSelectState: this.mIsMultipleSelectState, 283 onClickHead: (event: ClickEvent) => { 284 this.mConListCtrl.clickToGroupDetail(item.index); 285 }, 286 onClickBody: (event: ClickEvent) => { 287 this.mConListCtrl.clickInfoToConversation(item.index); 288 }, 289 onItemLongPress: (event: GestureEvent) => { 290 this.mConListCtrl.conversationLongPress(item.index); 291 }, 292 onTouchStart: (event: GestureEvent) => { 293 this.mConListCtrl.touchStart(event, item.index); 294 }, 295 onTouchUpdate: (event: GestureEvent) => { 296 this.mConListCtrl.touchMove(event, item.index); 297 // @ts-ignore 298 this.forceCompleteRerender(true) // recusvise 299 }, 300 onTouchEnd: (event: GestureEvent) => { 301 this.mConListCtrl.touchEnd(event, item.index); 302 // @ts-ignore 303 this.forceCompleteRerender(true) // recusvise 304 }, 305 onClickFirstSlipBtn: (event: ClickEvent) => { //Read 306 this.mConListCtrl.markAllAsReadByIndex(item.index); 307 }, 308 onClickSecondSlipBtn: (event: ClickEvent) => { //Delete 309 this.mConListCtrl.deleteAction(item.index); 310 this.delDialogController.open(); 311 } 312 }) 313 }.width("100%") 314 .height("64vp") 315 }, (item: any) => JSON.stringify(item)) 316 } 317 .edgeEffect(EdgeEffect.Spring) 318 .width("100%") 319 .align(Alignment.Top) 320 .divider({ 321 strokeWidth: 1, 322 startMargin: this.mConListCtrl.isShowContactHeadIcon ? 52 : 12, 323 endMargin: 0 324 }) 325 .flexShrink(1) 326 327 Blank() 328 329 /*Select All Delete button at the bottom*/ 330 if (this.mConListCtrl.isMultipleSelectState) { 331 Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) { 332 Column() { 333 Image($rawfile("icon/ic_public_delete.svg")).height(24).width(24) 334 Text($r("app.string.delete")).fontSize(10).margin({ top: 3 }).lineHeight(13) 335 } 336 .width("50%") 337 .onClick(() => { 338 this.mConListCtrl.clickConversationDelete(); 339 this.delDialogController.open(); 340 }) 341 .enabled(!(this.mConListCtrl.conversationSelectedNumber === 0)) 342 .opacity(this.mConListCtrl.conversationSelectedNumber == 0 ? 0.5 : 1) 343 .alignItems(HorizontalAlign.Center) 344 345 Column() { 346 Image(this.mConListCtrl.isConversationCheckAll ? 347 $rawfile("icon/ic_select_all_filled.svg") : $rawfile("icon/ic_select_all.svg")) 348 .height(24).width(24) 349 Text(this.mConListCtrl.isConversationCheckAll ? $r("app.string.msg_deselect_all") 350 : $r("app.string.msg_select_all")) 351 .fontSize(10) 352 .margin({ top: 3 }) 353 .lineHeight(13) 354 .fontColor(this.mConListCtrl.isConversationCheckAll ? 355 $r("sys.color.ohos_id_color_bottom_tab_text_on") : 356 $r("sys.color.ohos_id_color_bottom_tab_text_off")) 357 } 358 .width("50%") 359 .onClick(() => { 360 this.mConListCtrl.clickConversationCheckAll() 361 }) 362 .alignItems(HorizontalAlign.Center) 363 } 364 .width("100%") 365 .height(56) 366 .padding({ 367 left: $r("app.float.menu_layout_padding_left"), 368 right: $r("app.float.menu_layout_padding_right") 369 }) 370 .flexBasis(56) 371 .flexShrink(0) 372 .backgroundColor($r("sys.color.ohos_id_color_background")) 373 } 374 } 375 .width("100%") 376 .height("100%") 377 } 378 } 379 .width("100%") 380 .height("100%") 381 if (this.mConListCtrl.hasNoOrdinaryMsg && !(this.mConListCtrl.hasAggregate && this.mConListCtrl.hasInfoMsg 382 && this.mConListCtrl.isSearchStatus)) { 383 EmptyView().hitTestBehavior(HitTestMode.Transparent) 384 } 385 } 386 .width("100%") 387 .height("100%") 388 } 389} 390 391@Component 392struct EmptyView { 393 394 build() { 395 Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 396 Column() { 397 Image($rawfile("icon/ic_massage_m.svg")) 398 .width($r("app.float.empty_image_width")) 399 .height($r("app.float.empty_image_height")) 400 Text($r("app.string.noMessages")) 401 .margin({ top: $r("app.float.empty_text_top_margin") }) 402 .fontWeight(FontWeight.Regular) 403 .fontFamily("HarmonyHeiTi") 404 .fontSize($r("app.float.conversation_list_no_message_fs")) 405 .fontColor($r("sys.color.ohos_id_color_text_tertiary")) 406 } 407 // .margin({ top: '40%' }) 408 .offset({ y: -60 }) 409 } 410 .height("100%") 411 .width("100%") 412 } 413}