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 FolderData from '@ohos/utils/src/main/ets/default/model/databaseModel/FolderData' 17import NoteData from '@ohos/utils/src/main/ets/default/model/databaseModel/NoteData' 18import { 19 SysDefFolderUuid, 20 TableName, 21 FolderType, 22 FolderTableColumn, 23 NoteTableColumn, 24 Delete, 25 DeleteFileType 26} from '@ohos/utils/src/main/ets/default/model/databaseModel/EnumData' 27import { NewOrEditFolderDialog, DeleteDialog } from './CusDialogComp' 28import RdbStoreUtil from '@ohos/utils/src/main/ets/default/baseUtil/RdbStoreUtil' 29import FolderUtil from '@ohos/utils/src/main/ets/default/baseUtil/FolderUtil' 30import NoteUtil from '@ohos/utils/src/main/ets/default/baseUtil/NoteUtil' 31import { LogUtil } from '@ohos/utils/src/main/ets/default/baseUtil/LogUtil' 32import webview from '@ohos.web.webview'; 33 34// Folder list component 35@Component 36export struct FolderListComp { 37 @StorageLink('AllFolderArray') AllFolderArray: FolderData[] = AppStorage.Link('AllFolderArray') 38 @Consume('SectionStatus') sectionStatus: number 39 @Consume('ExpandStatus') expandStatus: boolean // 笔记本折叠展开状态 40 @StorageLink('breakPoint') breakPoints: string = 'lg' 41 controllerShow: webview.WebviewController = new webview.WebviewController(); 42 TAG = "FolderListComp" 43 @Consume('AsideWidth') asideWidth: number 44 45 build() { 46 Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.SpaceBetween }) { 47 Column() { 48 Column() { 49 Image($r("app.media.suojin")) 50 .height(24) 51 .width(24) 52 .responseRegion({ x: -15.0, y: -15.0, width: 54, height: 54 }) 53 .onClick(() => { 54 if (this.breakPoints == 'sm' || this.breakPoints == 'md') { 55 animateTo({ duration: 200 }, () => { 56 this.expandStatus = !this.expandStatus 57 }) 58 } else { 59 this.asideWidth = 0 60 this.sectionStatus = (this.sectionStatus == 3 ? 2 : 3) 61 // save continue data 62 AppStorage.SetOrCreate<number>('ContinueSection', this.sectionStatus) 63 LogUtil.info(this.TAG, "FolderListComp, set continue section success") 64 } 65 }) 66 } 67 .alignItems(HorizontalAlign.Start) 68 .width("100%") 69 .margin({ top: 28 }) 70 .padding({ left: 24 }) 71 .flexGrow(1) 72 73 NoteAndCreateComp() 74 // center 75 List() { 76 ForEach(this.AllFolderArray, (folderItem: FolderData) => { 77 ListItem() { 78 if (!FolderUtil.isBottomFixedFolder(folderItem)) { 79 FolderItemComp({ folderItem: folderItem, controllerShow: this.controllerShow }) 80 } 81 } 82 }, folderItem => folderItem.name.toString()) 83 } 84 .width('100%') 85 .height(500) 86 .margin({ bottom: 120 }) 87 .padding({ left: 12, right: 12 }) 88 .flexGrow(1) 89 } 90 91 92 Column() { 93 FolderItemComp({ 94 folderItem: FolderUtil.getFolderData(AppStorage.Get('AllFolderArray'), SysDefFolderUuid.MyFavorites), 95 controllerShow: this.controllerShow 96 }) 97 FolderItemComp({ 98 folderItem: FolderUtil.getFolderData(AppStorage.Get('AllFolderArray'), SysDefFolderUuid.RecentDeletes), 99 controllerShow: this.controllerShow 100 }) 101 } 102 .backgroundColor($r("app.color.folderlist_bgcolor_f1f3f5")) 103 .flexGrow(0) 104 .width("100%") 105 .padding({ left: 12, right: 12, bottom: 24 }) 106 } 107 .height("100%") 108 .backgroundColor($r('app.color.folder_color_d6d6d6')) 109 .backgroundBlurStyle(BlurStyle.Thick) 110 } 111 112 aboutToAppear(): void { 113 LogUtil.info(this.TAG, "aboutToAppear") 114 } 115 116 aboutToDisappear(): void { 117 LogUtil.info(this.TAG, "aboutToDisappear") 118 } 119} 120 121@Component 122export struct NoteAndCreateComp { 123 @StorageLink('AllFolderArray') AllFolderArray: FolderData[] = AppStorage.Link('AllFolderArray') 124 @Consume('SelectedColor') selectedColor: string 125 @Consume('PortraitModel') portraitModel: boolean 126 folderCreateDialogCtl: CustomDialogController = new CustomDialogController({ 127 builder: NewOrEditFolderDialog({ confirm: this.onCreateConfirm.bind(this), dialogType: 0 }), 128 alignment: DialogAlignment.Center, 129 autoCancel: false, 130 customStyle: true, 131 }) 132 folderCreateDialogCtlBottom: CustomDialogController = new CustomDialogController({ 133 builder: NewOrEditFolderDialog({ confirm: this.onCreateConfirm.bind(this), dialogType: 0 }), 134 alignment: DialogAlignment.Bottom, 135 autoCancel: false, 136 customStyle: true, 137 }) 138 139 aboutToDisappear() { 140 this.folderCreateDialogCtl = null 141 this.folderCreateDialogCtlBottom = null 142 } 143 144 onCreateConfirm(color: string, name: string) { 145 let folderData = new FolderData(0, name, new Date().getTime() + "", color, FolderType.CusDef, Delete.No, new Date().getTime(), new Date().getTime()) // 新的的笔记本都是自定义类型 type为1 146 this.AllFolderArray.push(folderData) 147 // insert folder to db 148 RdbStoreUtil.insert(TableName.FolderTable, folderData.toFolderObject(), null) 149 AppStorage.SetOrCreate('isUpdate', true) 150 } 151 152 build() { 153 Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceBetween }) { 154 Row() { 155 Text($r("app.string.note")) 156 .fontSize(20) 157 .fontWeight(FontWeight.Bold) 158 }.width(102) 159 160 Row() { 161 Text($r("app.string.create")) 162 .fontSize(14) 163 .fontColor($r("app.color.text_color_f86d05")) 164 .onClick(() => { 165 this.selectedColor = "#e84026" // 新建的时候选中第一个颜色 166 if (this.portraitModel) { 167 this.folderCreateDialogCtlBottom.open() 168 } else { 169 this.folderCreateDialogCtl.open() 170 } 171 }).padding({ right: 0 }) 172 }.width(50) 173 }.width("100%") 174 .margin({ top: 8 }) 175 .padding({ left: 24 }) 176 .height(56) 177 } 178} 179 180@Component 181struct FolderItemComp { 182 @State folderItem: FolderData = new FolderData(0, "", new Date().getTime() + "", "", FolderType.CusDef, Delete.No, new Date().getTime(), new Date().getTime()) 183 @StorageLink('AllNoteArray') AllNoteArray: NoteData[] = [] 184 @StorageLink('AllFolderArray') AllFolderArray: FolderData[] = [] 185 @StorageLink('CheckedNoteArray') CheckedNoteArray: NoteData[] = [] 186 @Consume('SelectedFolderData') selectedFolderData: FolderData 187 @Consume('SelectedNoteData') selectedNoteData: NoteData 188 @Consume('RefreshFlag') refreshFlag: number 189 @Consume('Longpress') longpress: boolean 190 @Consume('SelectedColor') selectedColor: string 191 @Consume('PortraitModel') portraitModel: boolean 192 controllerShow: WebviewController 193 @State isLongPress: boolean = false 194 TAG = "FolderItemComp" 195 @StorageLink('isUpdate') isUpdate: boolean = false 196 // Folder Edit Dialog 197 folderEditDialogCtl: CustomDialogController = new CustomDialogController({ 198 builder: NewOrEditFolderDialog({ 199 editFolderUuid: this.folderItem.uuid, 200 confirm: this.onEditConfirm.bind(this), 201 dialogType: 1 202 }), 203 alignment: DialogAlignment.Center, 204 autoCancel: false, 205 customStyle: true, 206 }) 207 // Folder Edit Dialog for portrait model 208 folderEditDialogCtlBottom: CustomDialogController = new CustomDialogController({ 209 builder: NewOrEditFolderDialog({ 210 editFolderUuid: this.folderItem.uuid, 211 confirm: this.onEditConfirm.bind(this), 212 dialogType: 1 213 }), 214 alignment: DialogAlignment.Bottom, 215 autoCancel: false, 216 customStyle: true, 217 }) 218 219 aboutToDisappear() { 220 this.folderEditDialogCtl = null 221 this.folderEditDialogCtlBottom = null 222 this.folderDeleteDialogCtl = null 223 this.folderDeleteDialogCtlBottom = null 224 this.folderCreateDialogCtl = null 225 this.folderCreateDialogCtlBottom = null 226 } 227 228 // Folder Edit Callback 229 onEditConfirm(color: string, name: string) { 230 this.folderItem.color = color 231 this.folderItem.name = name 232 this.folderItem.folder_type = FolderType.CusDef 233 // update folder to db 234 let predicates_folder = RdbStoreUtil.getRdbPredicates(TableName.FolderTable) 235 predicates_folder.equalTo(FolderTableColumn.Uuid, this.folderItem.uuid) 236 RdbStoreUtil.update(this.folderItem.toFolderObject(), predicates_folder, null) 237 this.isUpdate = true 238 } 239 // Folder Delete Dialog 240 folderDeleteDialogCtl: CustomDialogController = new CustomDialogController({ 241 builder: DeleteDialog({ onConfirm: this.onDeleteConfirm.bind(this), deleteFileType: DeleteFileType.FolderData }), 242 alignment: DialogAlignment.Center, 243 autoCancel: false, 244 customStyle: true, 245 }) 246 // Folder Delete Dialog for portrait model 247 folderDeleteDialogCtlBottom: CustomDialogController = new CustomDialogController({ 248 builder: DeleteDialog({ onConfirm: this.onDeleteConfirm.bind(this), deleteFileType: DeleteFileType.FolderData }), 249 alignment: DialogAlignment.Bottom, 250 autoCancel: false, 251 customStyle: true, 252 }) 253 // Folder Delete Callback 254 onDeleteConfirm() { 255 let currentFolder = FolderUtil.getFolderData(this.AllFolderArray, this.folderItem.uuid) 256 let index = this.AllFolderArray.indexOf(currentFolder) 257 let currentNoteDataArray = NoteUtil.getNoteDataArray(AppStorage.Get('AllNoteArray'), this.folderItem.uuid) 258 let deleteNoteDataArray = NoteUtil.getNoteDataArray(AppStorage.Get('AllNoteArray'), 'sys_def_recentDeletes_uuid') 259 if (index > -1) { 260 this.AllFolderArray.splice(index, 1) 261 if (deleteNoteDataArray.length != 0) { 262 deleteNoteDataArray.forEach((noteItem: NoteData) => { 263 let folderData: FolderData = FolderUtil.getFolderData(this.AllFolderArray, noteItem.folder_uuid) 264 if (folderData == undefined) { 265 noteItem.folder_uuid = SysDefFolderUuid.UnClassified 266 // update note to db 267 let predicates_note = RdbStoreUtil.getRdbPredicates(TableName.NoteTable) 268 predicates_note.equalTo(NoteTableColumn.Uuid, noteItem.uuid) 269 RdbStoreUtil.update(noteItem.toNoteObject(), predicates_note, null) 270 } 271 }) 272 } 273 if (currentNoteDataArray.length != 0) { 274 currentNoteDataArray.forEach((noteItem: NoteData) => { 275 noteItem.is_deleted = Delete.Yes 276 noteItem.folder_uuid = SysDefFolderUuid.UnClassified 277 noteItem.deleted_time = new Date().getTime() 278 // update note to db 279 let predicates_note = RdbStoreUtil.getRdbPredicates(TableName.NoteTable) 280 predicates_note.equalTo(NoteTableColumn.Uuid, noteItem.uuid) 281 RdbStoreUtil.update(noteItem.toNoteObject(), predicates_note, null) 282 }) 283 } 284 // delete folder from db 285 let predicates_folder = RdbStoreUtil.getRdbPredicates(TableName.FolderTable) 286 predicates_folder.equalTo(FolderTableColumn.Uuid, this.folderItem.uuid) 287 RdbStoreUtil.delete(predicates_folder, null) 288 // update selectedFolderData and selectedNoteData 289 this.selectedFolderData = FolderUtil.getFolderData(this.AllFolderArray, SysDefFolderUuid.AllNotes) 290 this.selectedNoteData = NoteUtil.getFirstNoteData(this.AllNoteArray, SysDefFolderUuid.AllNotes) 291 if (!this.selectedNoteData) { 292 return 293 } 294 // 刷新web界面 295 if (this.portraitModel == false) { 296 try { 297 this.controllerShow.runJavaScript( 298 "RICH_EDITOR.setHtml('" + this.selectedNoteData.content_text + "')" 299 ) 300 LogUtil.info(this.TAG, `runJavaScript success.`); 301 } catch (error) { 302 LogUtil.error(this.TAG, `runJavaScript failed.code:${JSON.stringify(error.code)},message:${JSON.stringify(error.message)}`); 303 } 304 } 305 // save continue data 306 let continueNote: string = JSON.stringify(this.selectedNoteData.toNoteObject()) 307 AppStorage.SetOrCreate<string>('ContinueNote', continueNote) 308 LogUtil.info(this.TAG, "onDeleteConfirm, set continue note success") 309 } 310 this.isUpdate = true 311 } 312 // Folder Create Dialog 313 folderCreateDialogCtl: CustomDialogController = new CustomDialogController({ 314 builder: NewOrEditFolderDialog({ confirm: this.onCreateConfirm.bind(this), dialogType: 0 }), 315 alignment: DialogAlignment.Center, 316 autoCancel: false, 317 customStyle: true, 318 }) 319 // Folder Create Dialog for portrait model 320 folderCreateDialogCtlBottom: CustomDialogController = new CustomDialogController({ 321 builder: NewOrEditFolderDialog({ confirm: this.onCreateConfirm.bind(this), dialogType: 0 }), 322 alignment: DialogAlignment.Bottom, 323 autoCancel: false, 324 customStyle: true, 325 }) 326 // Folder Create Callback 327 onCreateConfirm(color: string, name: string) { 328 let folderData = new FolderData(0, name, new Date().getTime() + "", color, FolderType.CusDef, Delete.No, new Date().getTime(), new Date().getTime()) // 新的的笔记本都是自定义类型 type为1 329 this.AllFolderArray.push(folderData) 330 // insert folder to db 331 RdbStoreUtil.insert(TableName.FolderTable, folderData.toFolderObject(), null) 332 this.isUpdate = true 333 } 334 335 @Builder menuBuilder() { 336 Column({ space: 1 }) { 337 Text($r("app.string.editFolder")) 338 .width(124) 339 .height(48) 340 .padding({ top: 13, bottom: 13 }) 341 .fontSize(16) 342 .fontColor($r("app.color.folder_color_182431")) 343 .onClick(() => { 344 this.selectedColor = this.folderItem.color 345 if (this.portraitModel) { 346 this.folderEditDialogCtlBottom.open() 347 } else { 348 this.folderEditDialogCtl.open() 349 } 350 ContextMenu.close() 351 }) 352 Divider() 353 .color($r("app.color.divider_color_e4e4e4")) 354 .strokeWidth(1) 355 Text($r("app.string.deleteFolder")) 356 .width(124) 357 .height(48) 358 .padding({ top: 13, bottom: 14 }) 359 .fontSize(16) 360 .fontColor($r("app.color.folder_color_182431")) 361 .onClick(() => { 362 if (this.portraitModel) { 363 this.folderDeleteDialogCtlBottom.open() 364 } else { 365 this.folderDeleteDialogCtl.open() 366 } 367 ContextMenu.close() 368 }) 369 Divider() 370 .color($r("app.color.divider_color_e4e4e4")) 371 .strokeWidth(1) 372 Text($r("app.string.createFolder")) 373 .width(124) 374 .height(48) 375 .padding({ top: 13, bottom: 15 }) 376 .fontSize(16) 377 .fontColor($r("app.color.folder_color_182431")) 378 .onClick(() => { 379 this.selectedColor = "#e84026" // 新建的时候选中第一个颜色 380 if (this.portraitModel) { 381 this.folderCreateDialogCtlBottom.open() 382 } else { 383 this.folderCreateDialogCtl.open() 384 } 385 ContextMenu.close() 386 }) 387 } 388 .width(156) 389 .height(154) 390 .padding({ top: 4, bottom: 4, left: 16, right: 16 }) 391 .borderRadius(16) 392 .backgroundColor($r("app.color.press_folder_bg_color")) 393 } 394 395 build() { 396 Flex() { 397 if (this.folderItem?.folder_type == FolderType.CusDef) { 398 Flex({ alignItems: ItemAlign.Center, wrap: FlexWrap.NoWrap, justifyContent: FlexAlign.SpaceBetween }) { 399 Row() { 400 Image(FolderUtil.getFolderIcon(this.folderItem.uuid)) 401 .id(this.isUpdate + '') 402 .objectFit(ImageFit.Fill) 403 .width(24) 404 .height(24) 405 .fillColor(FolderUtil.getFolderIconColor(this.AllFolderArray, this.folderItem.uuid, this.selectedFolderData.uuid == this.folderItem.uuid)) 406 .margin({ right: 16 }) 407 Text(FolderUtil.getFolderText(this.folderItem)) 408 .id(this.isUpdate + '') 409 .fontWeight(FontWeight.Medium) 410 .fontSize(16) 411 .textAlign(TextAlign.Center) 412 .maxLines(1) 413 .textOverflow({ overflow: TextOverflow.Ellipsis }) 414 .flexShrink(1) 415 .fontColor(FolderUtil.getFolderTextColor(this.selectedFolderData.uuid == this.folderItem.uuid)) 416 Text(JSON.stringify(this.refreshFlag)) 417 .visibility(Visibility.None) // 用于强制刷新使用 418 }.width(118) 419 420 Text(FolderUtil.getNoteCount(AppStorage.Get('AllNoteArray'), this.folderItem.uuid).toString()) 421 .id(this.isUpdate + '') 422 .fontWeight(FontWeight.Regular) 423 .fontSize(14) 424 .textAlign(TextAlign.Center) 425 } 426 .width('100%') 427 .borderRadius(12) 428 .height(56) 429 .padding({ left: 12, right: 12 }) 430 .backgroundColor(this.isLongPress ? $r("app.color.folder_color_19182431") : this.selectedFolderData.uuid == this.folderItem.uuid 431 ? $r("app.color.folder_color_ffffff") : "#00FFFFFF") 432 .bindContextMenu(this.menuBuilder, ResponseType.LongPress) 433 .bindContextMenu(this.menuBuilder, ResponseType.RightClick) 434 .onClick(() => { 435 if (this.longpress) { 436 this.longpress = false 437 NoteUtil.unsetAllNotesChecked(this.CheckedNoteArray) 438 } else { 439 this.selectedFolderData = this.folderItem 440 this.selectedNoteData = NoteUtil.getFirstNoteData(AppStorage.Get('AllNoteArray'), this.folderItem.uuid) 441 if (!this.selectedNoteData) { 442 return 443 } 444 // 刷新web界面 445 if (this.portraitModel == false) { 446 try { 447 this.controllerShow.runJavaScript( 448 "RICH_EDITOR.setHtml('" + this.selectedNoteData.content_text + "')" 449 ); 450 LogUtil.info(this.TAG, `onClick runJavaScript setHtml success.`); 451 } catch (error) { 452 LogUtil.error(this.TAG, `onClick runJavaScript setHtml failed,code:${JSON.stringify(error.code)}, 453 message:${JSON.stringify(error.message)}.`); 454 } 455 } 456 // save continue data 457 let continueNote: string = JSON.stringify(this.selectedNoteData.toNoteObject()) 458 AppStorage.SetOrCreate<string>('ContinueNote', continueNote) 459 AppStorage.SetOrCreate('ContinueSection', 3) 460 LogUtil.info(this.TAG, "FolderItemComp, set continue note success") 461 } 462 NoteUtil.refreshAll() 463 }) 464 } else { 465 Flex({ alignItems: ItemAlign.Center, wrap: FlexWrap.NoWrap, justifyContent: FlexAlign.SpaceBetween }) { 466 Row() { 467 Image(FolderUtil.getFolderIcon(this.folderItem.uuid)) 468 .id(this.isUpdate + '') 469 .objectFit(ImageFit.Fill) 470 .width(24) 471 .height(24) 472 .fillColor(this.isUpdate ? FolderUtil.getFolderIconColor(this.AllFolderArray, this.folderItem.uuid, this.selectedFolderData.uuid == this.folderItem.uuid) : FolderUtil.getFolderIconColor(this.AllFolderArray, this.folderItem.uuid, this.selectedFolderData.uuid == this.folderItem.uuid)) 473 .margin({ right: 16 }) 474 Text(FolderUtil.getFolderText(this.folderItem)) 475 .id(this.isUpdate + '') 476 .fontWeight(FontWeight.Medium) 477 .fontSize(16) 478 .textAlign(TextAlign.Center) 479 .maxLines(1) 480 .textOverflow({ overflow: TextOverflow.Ellipsis }) 481 .flexShrink(1) 482 .fontColor(FolderUtil.getFolderTextColor(this.selectedFolderData.uuid == this.folderItem.uuid)) 483 Text(JSON.stringify(this.refreshFlag)) 484 .visibility(Visibility.None) // 用于强制刷新使用 485 }.width(118) 486 487 Text(FolderUtil.getNoteCount(AppStorage.Get('AllNoteArray'), this.folderItem.uuid).toString()) 488 .id(this.isUpdate + '') 489 .fontWeight(FontWeight.Regular) 490 .fontSize(14) 491 .textAlign(TextAlign.Center) 492 } 493 .width('100%') 494 .borderRadius(12) 495 .height(56) 496 .padding({ left: 12, right: 12 }) 497 .backgroundColor(this.isLongPress ? $r("app.color.folder_color_19182431") : this.selectedFolderData.uuid == this.folderItem.uuid 498 ? $r("app.color.folder_color_ffffff") : "#00FFFFFF") 499 .onClick(() => { 500 if (this.longpress) { 501 this.longpress = false 502 NoteUtil.unsetAllNotesChecked(this.CheckedNoteArray) 503 } else { 504 this.selectedFolderData = this.folderItem 505 this.selectedNoteData = NoteUtil.getFirstNoteData(AppStorage.Get('AllNoteArray'), this.folderItem.uuid) 506 if (!this.selectedNoteData) { 507 return 508 } 509 // 刷新web界面 510 if (this.portraitModel == false) { 511 try { 512 this.controllerShow.runJavaScript( 513 "RICH_EDITOR.setHtml('" + this.selectedNoteData.content_text + "')" 514 ); 515 LogUtil.info(this.TAG, `else runJavaScript setHtml success.`); 516 } catch (error) { 517 LogUtil.info(this.TAG, `else runJavaScript setHtml failed.code:${JSON.stringify(error.code)}, 518 message:${JSON.stringify(error.message)}`); 519 } 520 } 521 // save continue data 522 let continueNote: string = JSON.stringify(this.selectedNoteData.toNoteObject()) 523 AppStorage.SetOrCreate<string>('ContinueNote', continueNote) 524 AppStorage.SetOrCreate('ContinueSection', 3) 525 LogUtil.info(this.TAG, "FolderItemComp, set continue note success") 526 } 527 NoteUtil.refreshAll() 528 }) 529 } 530 } 531 .width('100%') 532 .height(56) 533 .parallelGesture( 534 GestureGroup(GestureMode.Exclusive, 535 LongPressGesture() 536 .onAction(() => { 537 this.isLongPress = true 538 this.refreshFlag = (this.refreshFlag == 0 ? 1 : 0) 539 }) 540 .onActionEnd(() => { 541 this.isLongPress = false 542 this.refreshFlag = (this.refreshFlag == 0 ? 1 : 0) 543 }) 544 ) 545 ) 546 } 547}