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 onCreateConfirm(color: string, name: string) { 139 let folderData = new FolderData(0, name, new Date().getTime() + "", color, FolderType.CusDef, Delete.No, new Date().getTime(), new Date().getTime()) // 新的的笔记本都是自定义类型 type为1 140 this.AllFolderArray.push(folderData) 141 // insert folder to db 142 RdbStoreUtil.insert(TableName.FolderTable, folderData.toFolderObject(), null) 143 AppStorage.SetOrCreate('isUpdate', true) 144 } 145 146 build() { 147 Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceBetween }) { 148 Row() { 149 Text($r("app.string.note")) 150 .fontSize(20) 151 .fontWeight(FontWeight.Bold) 152 }.width(102) 153 154 Row() { 155 Text($r("app.string.create")) 156 .fontSize(14) 157 .fontColor($r("app.color.text_color_f86d05")) 158 .onClick(() => { 159 this.selectedColor = "#e84026" // 新建的时候选中第一个颜色 160 if (this.portraitModel) { 161 this.folderCreateDialogCtlBottom.open() 162 } else { 163 this.folderCreateDialogCtl.open() 164 } 165 }).padding({ right: 0 }) 166 }.width(50) 167 }.width("100%") 168 .margin({ top: 8 }) 169 .padding({ left: 24 }) 170 .height(56) 171 } 172} 173 174@Component 175struct FolderItemComp { 176 @State folderItem: FolderData = new FolderData(0, "", new Date().getTime() + "", "", FolderType.CusDef, Delete.No, new Date().getTime(), new Date().getTime()) 177 @StorageLink('AllNoteArray') AllNoteArray: NoteData[] = [] 178 @StorageLink('AllFolderArray') AllFolderArray: FolderData[] = [] 179 @StorageLink('CheckedNoteArray') CheckedNoteArray: NoteData[] = [] 180 @Consume('SelectedFolderData') selectedFolderData: FolderData 181 @Consume('SelectedNoteData') selectedNoteData: NoteData 182 @Consume('RefreshFlag') refreshFlag: number 183 @Consume('Longpress') longpress: boolean 184 @Consume('SelectedColor') selectedColor: string 185 @Consume('PortraitModel') portraitModel: boolean 186 controllerShow: WebviewController 187 @State isLongPress: boolean = false 188 TAG = "FolderListComp" 189 @StorageLink('isUpdate') isUpdate: boolean = false 190 // Folder Edit Dialog 191 folderEditDialogCtl: CustomDialogController = new CustomDialogController({ 192 builder: NewOrEditFolderDialog({ 193 editFolderUuid: this.folderItem.uuid, 194 confirm: this.onEditConfirm.bind(this), 195 dialogType: 1 196 }), 197 alignment: DialogAlignment.Center, 198 autoCancel: false, 199 customStyle: true, 200 }) 201 // Folder Edit Dialog for portrait model 202 folderEditDialogCtlBottom: CustomDialogController = new CustomDialogController({ 203 builder: NewOrEditFolderDialog({ 204 editFolderUuid: this.folderItem.uuid, 205 confirm: this.onEditConfirm.bind(this), 206 dialogType: 1 207 }), 208 alignment: DialogAlignment.Bottom, 209 autoCancel: false, 210 customStyle: true, 211 }) 212 // Folder Edit Callback 213 onEditConfirm(color: string, name: string) { 214 this.folderItem.color = color 215 this.folderItem.name = name 216 this.folderItem.folder_type = FolderType.CusDef 217 // update folder to db 218 let predicates_folder = RdbStoreUtil.getRdbPredicates(TableName.FolderTable) 219 predicates_folder.equalTo(FolderTableColumn.Uuid, this.folderItem.uuid) 220 RdbStoreUtil.update(this.folderItem.toFolderObject(), predicates_folder, null) 221 this.isUpdate = true 222 } 223 // Folder Delete Dialog 224 folderDeleteDialogCtl: CustomDialogController = new CustomDialogController({ 225 builder: DeleteDialog({ onConfirm: this.onDeleteConfirm.bind(this), deleteFileType: DeleteFileType.FolderData }), 226 alignment: DialogAlignment.Center, 227 autoCancel: false, 228 customStyle: true, 229 }) 230 // Folder Delete Dialog for portrait model 231 folderDeleteDialogCtlBottom: CustomDialogController = new CustomDialogController({ 232 builder: DeleteDialog({ onConfirm: this.onDeleteConfirm.bind(this), deleteFileType: DeleteFileType.FolderData }), 233 alignment: DialogAlignment.Bottom, 234 autoCancel: false, 235 customStyle: true, 236 }) 237 // Folder Delete Callback 238 onDeleteConfirm() { 239 let currentFolder = FolderUtil.getFolderData(this.AllFolderArray, this.folderItem.uuid) 240 let index = this.AllFolderArray.indexOf(currentFolder) 241 let currentNoteDataArray = NoteUtil.getNoteDataArray(AppStorage.Get('AllNoteArray'), this.folderItem.uuid) 242 let deleteNoteDataArray = NoteUtil.getNoteDataArray(AppStorage.Get('AllNoteArray'), 'sys_def_recentDeletes_uuid') 243 if (index > -1) { 244 this.AllFolderArray.splice(index, 1) 245 if (deleteNoteDataArray.length != 0) { 246 deleteNoteDataArray.forEach((noteItem: NoteData) => { 247 let folderData: FolderData = FolderUtil.getFolderData(this.AllFolderArray, noteItem.folder_uuid) 248 if (folderData == undefined) { 249 noteItem.folder_uuid = SysDefFolderUuid.UnClassified 250 // update note to db 251 let predicates_note = RdbStoreUtil.getRdbPredicates(TableName.NoteTable) 252 predicates_note.equalTo(NoteTableColumn.Uuid, noteItem.uuid) 253 RdbStoreUtil.update(noteItem.toNoteObject(), predicates_note, null) 254 } 255 }) 256 } 257 if (currentNoteDataArray.length != 0) { 258 currentNoteDataArray.forEach((noteItem: NoteData) => { 259 noteItem.is_deleted = Delete.Yes 260 noteItem.folder_uuid = SysDefFolderUuid.UnClassified 261 noteItem.deleted_time = new Date().getTime() 262 // update note to db 263 let predicates_note = RdbStoreUtil.getRdbPredicates(TableName.NoteTable) 264 predicates_note.equalTo(NoteTableColumn.Uuid, noteItem.uuid) 265 RdbStoreUtil.update(noteItem.toNoteObject(), predicates_note, null) 266 }) 267 } 268 // delete folder from db 269 let predicates_folder = RdbStoreUtil.getRdbPredicates(TableName.FolderTable) 270 predicates_folder.equalTo(FolderTableColumn.Uuid, this.folderItem.uuid) 271 RdbStoreUtil.delete(predicates_folder, null) 272 // update selectedFolderData and selectedNoteData 273 this.selectedFolderData = FolderUtil.getFolderData(this.AllFolderArray, SysDefFolderUuid.AllNotes) 274 this.selectedNoteData = NoteUtil.getFirstNoteData(this.AllNoteArray, SysDefFolderUuid.AllNotes) 275 if (!this.selectedNoteData) { 276 return 277 } 278 // 刷新web界面 279 if (this.portraitModel == false) { 280 this.controllerShow.runJavaScript( 281 "RICH_EDITOR.setHtml('" + this.selectedNoteData.content_text + "')" 282 ) 283 } 284 // save continue data 285 let continueNote: string = JSON.stringify(this.selectedNoteData.toNoteObject()) 286 AppStorage.SetOrCreate<string>('ContinueNote', continueNote) 287 LogUtil.info(this.TAG, "onDeleteConfirm, set continue note success") 288 } 289 this.isUpdate = true 290 } 291 // Folder Create Dialog 292 folderCreateDialogCtl: CustomDialogController = new CustomDialogController({ 293 builder: NewOrEditFolderDialog({ confirm: this.onCreateConfirm.bind(this), dialogType: 0 }), 294 alignment: DialogAlignment.Center, 295 autoCancel: false, 296 customStyle: true, 297 }) 298 // Folder Create Dialog for portrait model 299 folderCreateDialogCtlBottom: CustomDialogController = new CustomDialogController({ 300 builder: NewOrEditFolderDialog({ confirm: this.onCreateConfirm.bind(this), dialogType: 0 }), 301 alignment: DialogAlignment.Bottom, 302 autoCancel: false, 303 customStyle: true, 304 }) 305 // Folder Create Callback 306 onCreateConfirm(color: string, name: string) { 307 let folderData = new FolderData(0, name, new Date().getTime() + "", color, FolderType.CusDef, Delete.No, new Date().getTime(), new Date().getTime()) // 新的的笔记本都是自定义类型 type为1 308 this.AllFolderArray.push(folderData) 309 // insert folder to db 310 RdbStoreUtil.insert(TableName.FolderTable, folderData.toFolderObject(), null) 311 this.isUpdate = true 312 } 313 314 @Builder menuBuilder() { 315 Column({ space: 1 }) { 316 Text($r("app.string.editFolder")) 317 .width(124) 318 .height(48) 319 .padding({ top: 13, bottom: 13 }) 320 .fontSize(16) 321 .fontColor($r("app.color.folder_color_182431")) 322 .onClick(() => { 323 this.selectedColor = this.folderItem.color 324 if (this.portraitModel) { 325 this.folderEditDialogCtlBottom.open() 326 } else { 327 this.folderEditDialogCtl.open() 328 } 329 ContextMenu.close() 330 }) 331 Divider() 332 .color($r("app.color.divider_color_e4e4e4")) 333 .strokeWidth(1) 334 Text($r("app.string.deleteFolder")) 335 .width(124) 336 .height(48) 337 .padding({ top: 13, bottom: 14 }) 338 .fontSize(16) 339 .fontColor($r("app.color.folder_color_182431")) 340 .onClick(() => { 341 if (this.portraitModel) { 342 this.folderDeleteDialogCtlBottom.open() 343 } else { 344 this.folderDeleteDialogCtl.open() 345 } 346 ContextMenu.close() 347 }) 348 Divider() 349 .color($r("app.color.divider_color_e4e4e4")) 350 .strokeWidth(1) 351 Text($r("app.string.createFolder")) 352 .width(124) 353 .height(48) 354 .padding({ top: 13, bottom: 15 }) 355 .fontSize(16) 356 .fontColor($r("app.color.folder_color_182431")) 357 .onClick(() => { 358 this.selectedColor = "#e84026" // 新建的时候选中第一个颜色 359 if (this.portraitModel) { 360 this.folderCreateDialogCtlBottom.open() 361 } else { 362 this.folderCreateDialogCtl.open() 363 } 364 ContextMenu.close() 365 }) 366 } 367 .width(156) 368 .height(154) 369 .padding({ top: 4, bottom: 4, left: 16, right: 16 }) 370 .borderRadius(16) 371 .backgroundColor($r("app.color.press_folder_bg_color")) 372 } 373 374 build() { 375 Flex() { 376 if (this.folderItem?.folder_type == FolderType.CusDef) { 377 Flex({ alignItems: ItemAlign.Center, wrap: FlexWrap.NoWrap, justifyContent: FlexAlign.SpaceBetween }) { 378 Row() { 379 Image(FolderUtil.getFolderIcon(this.folderItem.uuid)) 380 .id(this.isUpdate + '') 381 .objectFit(ImageFit.Fill) 382 .width(24) 383 .height(24) 384 .fillColor(FolderUtil.getFolderIconColor(this.AllFolderArray, this.folderItem.uuid, this.selectedFolderData.uuid == this.folderItem.uuid)) 385 .margin({ right: 16 }) 386 Text(FolderUtil.getFolderText(this.folderItem)) 387 .id(this.isUpdate + '') 388 .fontWeight(FontWeight.Medium) 389 .fontSize(16) 390 .textAlign(TextAlign.Center) 391 .maxLines(1) 392 .textOverflow({ overflow: TextOverflow.Ellipsis }) 393 .flexShrink(1) 394 .fontColor(FolderUtil.getFolderTextColor(this.selectedFolderData.uuid == this.folderItem.uuid)) 395 Text(JSON.stringify(this.refreshFlag)) 396 .visibility(Visibility.None) // 用于强制刷新使用 397 }.width(118) 398 399 Text(FolderUtil.getNoteCount(AppStorage.Get('AllNoteArray'), this.folderItem.uuid).toString()) 400 .id(this.isUpdate + '') 401 .fontWeight(FontWeight.Regular) 402 .fontSize(14) 403 .textAlign(TextAlign.Center) 404 } 405 .width('100%') 406 .borderRadius(12) 407 .height(56) 408 .padding({ left: 12, right: 12 }) 409 .backgroundColor(this.isLongPress ? $r("app.color.folder_color_19182431") : this.selectedFolderData.uuid == this.folderItem.uuid 410 ? $r("app.color.folder_color_ffffff") : "#00FFFFFF") 411 .bindContextMenu(this.menuBuilder, ResponseType.LongPress) 412 .bindContextMenu(this.menuBuilder, ResponseType.RightClick) 413 .onClick(() => { 414 if (this.longpress) { 415 this.longpress = false 416 NoteUtil.unsetAllNotesChecked(this.CheckedNoteArray) 417 } else { 418 this.selectedFolderData = this.folderItem 419 this.selectedNoteData = NoteUtil.getFirstNoteData(AppStorage.Get('AllNoteArray'), this.folderItem.uuid) 420 if (!this.selectedNoteData) { 421 return 422 } 423 // 刷新web界面 424 if (this.portraitModel == false) { 425 this.controllerShow.runJavaScript( 426 "RICH_EDITOR.setHtml('" + this.selectedNoteData.content_text + "')" 427 ) 428 } 429 // save continue data 430 let continueNote: string = JSON.stringify(this.selectedNoteData.toNoteObject()) 431 AppStorage.SetOrCreate<string>('ContinueNote', continueNote) 432 AppStorage.SetOrCreate('ContinueSection', 3) 433 LogUtil.info(this.TAG, "FolderItemComp, set continue note success") 434 } 435 NoteUtil.refreshAll() 436 }) 437 } else { 438 Flex({ alignItems: ItemAlign.Center, wrap: FlexWrap.NoWrap, justifyContent: FlexAlign.SpaceBetween }) { 439 Row() { 440 Image(FolderUtil.getFolderIcon(this.folderItem.uuid)) 441 .id(this.isUpdate + '') 442 .objectFit(ImageFit.Fill) 443 .width(24) 444 .height(24) 445 .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)) 446 .margin({ right: 16 }) 447 Text(FolderUtil.getFolderText(this.folderItem)) 448 .id(this.isUpdate + '') 449 .fontWeight(FontWeight.Medium) 450 .fontSize(16) 451 .textAlign(TextAlign.Center) 452 .maxLines(1) 453 .textOverflow({ overflow: TextOverflow.Ellipsis }) 454 .flexShrink(1) 455 .fontColor(FolderUtil.getFolderTextColor(this.selectedFolderData.uuid == this.folderItem.uuid)) 456 Text(JSON.stringify(this.refreshFlag)) 457 .visibility(Visibility.None) // 用于强制刷新使用 458 }.width(118) 459 460 Text(FolderUtil.getNoteCount(AppStorage.Get('AllNoteArray'), this.folderItem.uuid).toString()) 461 .id(this.isUpdate + '') 462 .fontWeight(FontWeight.Regular) 463 .fontSize(14) 464 .textAlign(TextAlign.Center) 465 } 466 .width('100%') 467 .borderRadius(12) 468 .height(56) 469 .padding({ left: 12, right: 12 }) 470 .backgroundColor(this.isLongPress ? $r("app.color.folder_color_19182431") : this.selectedFolderData.uuid == this.folderItem.uuid 471 ? $r("app.color.folder_color_ffffff") : "#00FFFFFF") 472 .onClick(() => { 473 if (this.longpress) { 474 this.longpress = false 475 NoteUtil.unsetAllNotesChecked(this.CheckedNoteArray) 476 } else { 477 this.selectedFolderData = this.folderItem 478 this.selectedNoteData = NoteUtil.getFirstNoteData(AppStorage.Get('AllNoteArray'), this.folderItem.uuid) 479 if (!this.selectedNoteData) { 480 return 481 } 482 // 刷新web界面 483 if (this.portraitModel == false) { 484 this.controllerShow.runJavaScript( 485 "RICH_EDITOR.setHtml('" + this.selectedNoteData.content_text + "')" 486 ) 487 } 488 // save continue data 489 let continueNote: string = JSON.stringify(this.selectedNoteData.toNoteObject()) 490 AppStorage.SetOrCreate<string>('ContinueNote', continueNote) 491 AppStorage.SetOrCreate('ContinueSection', 3) 492 LogUtil.info(this.TAG, "FolderItemComp, set continue note success") 493 } 494 NoteUtil.refreshAll() 495 }) 496 } 497 } 498 .width('100%') 499 .height(56) 500 .parallelGesture( 501 GestureGroup(GestureMode.Exclusive, 502 LongPressGesture() 503 .onAction(() => { 504 this.isLongPress = true 505 this.refreshFlag = (this.refreshFlag == 0 ? 1 : 0) 506 }) 507 .onActionEnd(() => { 508 this.isLongPress = false 509 this.refreshFlag = (this.refreshFlag == 0 ? 1 : 0) 510 }) 511 ) 512 ) 513 } 514}