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