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 DateUtil from '@ohos/utils/src/main/ets/default/baseUtil/DateUtil' 17import RdbStoreUtil from '@ohos/utils/src/main/ets/default/baseUtil/RdbStoreUtil' 18import FolderData from '@ohos/utils/src/main/ets/default/model/databaseModel/FolderData' 19import NoteData from '@ohos/utils/src/main/ets/default/model/databaseModel/NoteData' 20import util from '@ohos.util' 21import { 22 TableName, 23 NoteTableColumn, 24 SysDefFolderUuid, 25 Favorite, 26 Delete, 27 FolderType 28} from '@ohos/utils/src/main/ets/default/model/databaseModel/EnumData'; 29import StyleConstants from '@ohos/utils/src/main/ets/default/constants/StyleConstants' 30import { EditContentDialogPortrait, DeleteDialog, EditTitleDialog } from './CusDialogComp' 31import FolderUtil from '@ohos/utils/src/main/ets/default/baseUtil/FolderUtil' 32import NoteUtil from '@ohos/utils/src/main/ets/default/baseUtil/NoteUtil' 33import { promptAction } from '@kit.ArkUI'; 34import { LogUtil } from '@ohos/utils/src/main/ets/default/baseUtil/LogUtil' 35import OperationUtils from '@ohos/utils/src/main/ets/default/baseUtil/OperationUtils' 36import router from '@system.router' 37import inputMethod from '@ohos.inputMethod'; 38import { folderTextMap } from '@ohos/utils/src/main/ets/default/model/NoteBaseData' 39import abilityAccessCtrl,{ Permissions } from '@ohos.abilityAccessCtrl'; 40import webview from '@ohos.web.webview'; 41import { BusinessError } from '@ohos.base'; 42import resourceManager from '@ohos.resourceManager'; 43import common from '@ohos.app.ability.common'; 44import window from '@ohos.window'; 45import { wantAgent, WantAgent } from '@kit.AbilityKit'; 46import { backgroundTaskManager } from '@kit.BackgroundTasksKit'; 47 48let time_id: number = 0; 49let noteContext = AppStorage.Get<common.UIAbilityContext>('noteContext')!; 50 51const TAG = 'NoteContentCompPortrait'; 52 53interface NoteContentType { 54 callbackhtml: (html: string) => void; 55 callbackImagePath: (imgName: string) => void; 56 callbackScheduledSave: (html: string) => void; 57 callbackPasteImage: (html: string) => void; 58 callbackGetSize: (fontSize: number) => void; 59 addToDo: () => void; 60 chooseStyle: () => void; 61 openAlbum: () => Promise<void>; 62 getBreakPoint: () => void; 63} 64 65async function routePage() { 66 try { 67 await router.back() 68 } catch (err) { 69 LogUtil.info(TAG, 'fail callback'); 70 } 71} 72 73// Note content component 74@Component 75export struct NoteContentCompPortrait { 76 @Provide('SelectedNoteData') selectedNoteData: NoteData = AppStorage.Get('NewNote')!; 77 @Provide('SelectedFolderData') selectedFolderData: FolderData = AppStorage.Get('NewFolder')!; 78 @StorageLink('AllNoteArray') AllNoteArray: NoteData[] = AppStorage.Link('AllNoteArray') 79 @Provide('EditModel') editModel: boolean = false 80 @StorageLink('dpi') dpi: number = 240 81 controllerShow: webview.WebviewController = new webview.WebviewController(); 82 private editContentFlag = false 83 private isClickBack: boolean = false 84 @StorageLink('ScrollTopPercent') scrollTopPercent: number = 0.0 85 editContentDialogCtl: CustomDialogController | null = new CustomDialogController({ 86 builder: EditContentDialogPortrait({ confirm: (newTitle: string) => { 87 this.confirm(newTitle); 88 } }), 89 alignment: DialogAlignment.Bottom, 90 autoCancel: true, 91 customStyle: true, 92 }) 93 @StorageLink('topHeight') topHeight: number = 0; // 窗口规避区域高 94 @StorageLink('topWidth') topWidth: number = 0; // 窗口规避区域宽 95 96 confirm(excuteJs: string) { 97 this.controllerShow.runJavaScript(excuteJs) 98 } 99 100 storeScrollTop(scrollTop: number) { 101 if (scrollTop < 0) { 102 return 103 } 104 AppStorage.SetOrCreate<number>('ScrollTopPercent', scrollTop / this.controllerShow.getPageHeight()) 105 } 106 107 restoreScrollTop() { 108 try { 109 if (!AppStorage.Has('remoteScrollTopPercent')) { 110 return 111 } 112 let scrollTopPercent = AppStorage.Get<number>('remoteScrollTopPercent')!; 113 if (scrollTopPercent < 0) { 114 return 115 } 116 this.controllerShow.runJavaScript( 117 'document.documentElement.scrollTop = ' + this.controllerShow.getPageHeight() * scrollTopPercent 118 ) 119 } catch (error) { 120 LogUtil.info(TAG, 'restoreScrollTop error') 121 } 122 123 } 124 125 restoreFocus() { 126 if (!AppStorage.Has('isRemoteFocusOnSearch')) { 127 return 128 } 129 let isRemoteFocusOnSearch = AppStorage.Get<boolean>('isRemoteFocusOnSearch') 130 if (isRemoteFocusOnSearch) { 131 focusControl.requestFocus('searchInput') 132 } 133 AppStorage.Delete('isRemoteFocusOnSearch') 134 } 135 136 noteContent: NoteContentType = { 137 callbackhtml: (html) => { 138 LogUtil.info(TAG, 'note uuid is:' + this.selectedNoteData?.uuid) 139 this.selectedNoteData.content_text = NoteUtil.contrastInitType(this.selectedNoteData.content_text); 140 if (this.selectedNoteData.content_text === html ) { 141 return; 142 }; 143 this.selectedNoteData.content_text = html 144 this.selectedNoteData.modified_time = new Date().getTime() 145 let predicatesNote = RdbStoreUtil.getRdbPredicates(TableName.NoteTable); 146 predicatesNote.equalTo(NoteTableColumn.Uuid, this.selectedNoteData?.uuid); 147 RdbStoreUtil.update(this.selectedNoteData?.toNoteObject(), predicatesNote, null); 148 LogUtil.info(TAG, 'update note success:' + this.selectedNoteData?.uuid) 149 // save continue data 150 let continueNote: string = JSON.stringify(this.selectedNoteData?.toNoteObject()) 151 AppStorage.SetOrCreate<string>('ContinueNote', continueNote) 152 LogUtil.info(TAG, 'callbackhtml, set continue note success'); 153 }, 154 callbackImagePath: (imgName) => { 155 // updata note image 156 LogUtil.info(TAG, 'note imgName is:' + imgName) 157 this.selectedNoteData.content_img = imgName 158 }, 159 160 callbackScheduledSave: (html) => { 161 LogUtil.info(TAG, 'callbackScheduledSave') 162 if (this.selectedNoteData?.content_text == html) { 163 LogUtil.info(TAG, 'callbackScheduledSave the same value return') 164 return; 165 } 166 this.selectedNoteData.content_text = html 167 this.selectedNoteData.modified_time = new Date().getTime() 168 let predicatesNote = RdbStoreUtil.getRdbPredicates(TableName.NoteTable); 169 predicatesNote.equalTo(NoteTableColumn.Uuid, this.selectedNoteData?.uuid); 170 RdbStoreUtil.update(this.selectedNoteData?.toNoteObject(), predicatesNote, null); 171 LogUtil.info(TAG, 'callbackScheduledSave, update note success:' + this.selectedNoteData?.uuid) 172 // save continue data 173 let continueNote: string = JSON.stringify(this.selectedNoteData?.toNoteObject()) 174 AppStorage.SetOrCreate<string>('ContinueNote', continueNote) 175 LogUtil.info(TAG, 'callbackScheduledSave, set continue note success') 176 }, 177 callbackPasteImage: (html) => { 178 if (html) { 179 LogUtil.info(TAG, 'paste info' + html) 180 let realHtml = ''; 181 let base64regex: RegExp = new RegExp('/^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/'); 182 if (html && html.indexOf('base64') > 0) { 183 LogUtil.info(TAG, ' getSrcFromHtml, src[1] : ' + html); 184 let imgData = html.split(',')[1]; 185 let imgType = 'png' 186 if (html.indexOf('jpeg') > 0) { 187 imgType = 'jpg' 188 } else if (html.indexOf('gif') > 0) { 189 imgType = 'gif' 190 } 191 let filePath = ''; 192 if (base64regex.test(imgData)) { 193 let base64 = new util.Base64() 194 let decodeArr = base64.decodeSync(imgData) 195 filePath = OperationUtils.saveImageData(decodeArr, imgType) 196 } else { 197 filePath = OperationUtils.saveImage(imgData, imgType) 198 } 199 realHtml = 'file://' + filePath; 200 } 201 LogUtil.info(TAG, 'paste info11' + realHtml) 202 this.controllerShow.runJavaScript("javascript:RICH_EDITOR.insertImageHtml('" + realHtml + "')") 203 } else { 204 LogUtil.info(TAG, 'paste info22224') 205 } 206 }, 207 callbackGetSize: (fontSize) => { 208 if (fontSize === 16) { 209 this.selectedNoteData.slider_value = 0 210 } else if (fontSize === 18) { 211 this.selectedNoteData.slider_value = 4 212 } else if (fontSize === 24) { 213 this.selectedNoteData.slider_value = 8 214 } else if (fontSize === 32) { 215 this.selectedNoteData.slider_value = 12 216 } else if (fontSize === 48) { 217 this.selectedNoteData.slider_value = 16 218 } 219 }, 220 addToDo: () => { 221 // 清单 222 this.controllerShow.runJavaScript('javascript:RICH_EDITOR.setTodo()'); 223 }, 224 chooseStyle: () => { 225 this.editContentDialogCtl!.open(); 226 }, 227 openAlbum: async () => { 228 let context: common.UIAbilityContext = AppStorage.Get('context')!; 229 // 申请长时任务 230 let wantAgentInfo: wantAgent.WantAgentInfo = { 231 wants: [ 232 { 233 bundleName: 'com.ohos.note', 234 abilityName: 'com.ohos.note.MainAbility' 235 } 236 ], 237 actionType: wantAgent.OperationType.START_ABILITY, 238 requestCode: 0, 239 wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG] 240 }; 241 try { 242 wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj: WantAgent) => { 243 backgroundTaskManager.startBackgroundRunning(context, 244 backgroundTaskManager.BackgroundMode.DATA_TRANSFER, wantAgentObj).then(() => { 245 LogUtil.info(TAG, `Operation startBackgroundRunning succeeded`); 246 }).catch((error: BusinessError) => { 247 LogUtil.error(TAG, `Operation startBackgroundRunning failed. code is ${JSON.stringify(error.code)}, 248 message is ${JSON.stringify(error.message)}`); 249 }); 250 }); 251 } catch (error) { 252 LogUtil.error(TAG, `Operation getWantAgent failed. code is ${(error as BusinessError).code}, 253 message is ${(error as BusinessError).message}`); 254 } 255 let permissionList: Permissions[] = [ 256 'ohos.permission.READ_IMAGEVIDEO', 257 'ohos.permission.WRITE_IMAGEVIDEO' 258 ] 259 let AtManager = abilityAccessCtrl.createAtManager(); 260 await AtManager.requestPermissionsFromUser(context, permissionList).then((data) => { 261 LogUtil.info(TAG, 'data permissions : ' + data.permissions) 262 LogUtil.info(TAG, 'data result: ' + data.authResults) 263 let sum = 0 264 for (let i = 0; i < data.authResults.length; i++) { 265 sum += data.authResults[i] 266 } 267 LogUtil.info(TAG, 'request permissions sum: ' + sum) 268 }).catch((err: BusinessError) => { 269 LogUtil.warn(TAG, 'failed to requestPermissionsFromUser : ' + err.code); 270 }) 271 LogUtil.info(TAG, 'startAbility start') 272 await noteContext.startAbilityForResult({ 273 parameters: { uri: 'singleselect', filterMediaType: 'FILTER_MEDIA_TYPE_IMAGE' }, 274 bundleName: 'com.ohos.photos', 275 abilityName: 'com.ohos.photos.MainAbility', 276 }).then((v: common.AbilityResult) => { 277 let want = v['want']; 278 if (want != null && want != undefined) { 279 let param = want['parameters']; 280 let imageUri = ''; 281 if (param != null && param != undefined) { 282 let uri = param['select-item-list'] as Record<string, string>; 283 imageUri = uri[0]; 284 } 285 LogUtil.info(TAG, 'image url' + imageUri); 286 // 拷贝 287 if (imageUri != null && imageUri != '') { 288 OperationUtils.copy(imageUri).then((uriPath) => { 289 let path = 'file://' + uriPath; 290 LogUtil.info(TAG, 'image uri is:' + path) 291 this.controllerShow.runJavaScript('javascript:RICH_EDITOR.getFocus()'); 292 this.controllerShow.runJavaScript("javascript:RICH_EDITOR.insertImage('" + path + "')") 293 }) 294 } 295 } 296 // 取消长时任务 297 try { 298 backgroundTaskManager.stopBackgroundRunning(context).then(() => { 299 LogUtil.info(TAG, `Operation stopBackgroundRunning succeeded`); 300 }).catch((error: BusinessError) => { 301 LogUtil.error(TAG, `Operation stopBackgroundRunning failed. code is ${JSON.stringify(error.code)}, 302 message is ${JSON.stringify(error.message)}`); 303 }); 304 } catch (error) { 305 LogUtil.error(TAG, `Operation stopBackgroundRunning failed. code is ${JSON.stringify(error.code)}, 306 message is ${JSON.stringify(error.message)}`); 307 } 308 }); 309 }, 310 getBreakPoint: () => { 311 return AppStorage.Get('breakPoint'); 312 } 313 } 314 315 build() { 316 Column() { 317 Flex({ direction: FlexDirection.Column, wrap: FlexWrap.NoWrap, 318 alignItems: ItemAlign.Start, alignContent: FlexAlign.SpaceAround }) { 319 Column() { 320 // 窗口顶部规避区域 321 Row() 322 .width(px2vp(this.topWidth)) 323 .height(px2vp(this.topHeight)) 324 ToolBarComp({ controllerShow: this.controllerShow }) 325 NoteContentOverViewComp() 326 .enabled(this.selectedNoteData && this.selectedNoteData?.is_deleted == Delete.Yes ? false : true) 327 } 328 329 Column() { 330 Web({ src: $rawfile('editor.html'), controller: this.controllerShow }) 331 .overviewModeAccess(false) 332 .javaScriptAccess(true) 333 .javaScriptProxy({ 334 object: this.noteContent, 335 name: 'callBackToApp', // html--> name.method 336 methodList: ['callbackhtml', 'callbackScheduledSave', 'callbackPasteImage', 'callbackImagePath', 337 'addToDo', 'chooseStyle', 'openAlbum', 'callbackGetSize', 'getBreakPoint'], 338 controller: this.controllerShow 339 }) 340 .onPageEnd((e) => { 341 try { 342 if (this.dpi <= 240) { 343 this.controllerShow.runJavaScript('changeSizeToRk()'); 344 } else if (this.dpi <= 320 && this.dpi > 240) { 345 this.controllerShow.runJavaScript('changeSizeToPhone()'); 346 } else { 347 this.controllerShow.runJavaScript('changeSizeToTablet()'); 348 } 349 LogUtil.info(TAG, 'finish loadurl'); 350 let self = this 351 this.controllerShow.runJavaScript( 352 "RICH_EDITOR.setHtml('" + this.selectedNoteData?.content_text + "')", 353 () => { 354 // wait for the image in the note to load 355 setTimeout(() => { 356 self.restoreScrollTop() 357 self.restoreFocus() 358 }, 100) 359 } 360 ) 361 } catch (error) { 362 LogUtil.info(TAG, 'onPageEnd error') 363 } 364 365 }) 366 .imageAccess(true) 367 .onlineImageAccess(true) 368 .fileAccess(true) 369 .domStorageAccess(true) 370 .zoomAccess(false) 371 .height('100%') 372 .width('100%') 373 .onScroll((event) => { 374 this.storeScrollTop(event.yOffset) 375 }) 376 .onClick(() => { 377 if (time_id) { 378 clearInterval(time_id) 379 } 380 // 添加定时器:3s自动保存 381 time_id = setInterval(() => { 382 try { 383 if (!this.isClickBack) { 384 this.controllerShow.runJavaScript('scheduledSaveContent()'); 385 } 386 } catch (error) { 387 LogUtil.info(TAG, 'setInterval error') 388 } 389 }, 3000) 390 LogUtil.info(TAG, 'setInterval time_id : ' + time_id) 391 this.editModel = true 392 }) 393 } 394 .height('100%') 395 .enabled(this.selectedNoteData && this.selectedNoteData?.is_deleted == Delete.Yes ? false : true) 396 .flexShrink(1) 397 .margin({ top: 16 }) 398 .width(StyleConstants.PERCENTAGE_100) 399 } 400 .flexShrink(1) 401 .padding({ left: 24, right: 24 }) 402 DeleteNoteComp() 403 } 404 .expandSafeArea([SafeAreaType.KEYBOARD, SafeAreaType.SYSTEM]) 405 .height(StyleConstants.PERCENTAGE_100) 406 .width(StyleConstants.PERCENTAGE_100) 407 } 408 409 aboutToAppear(): void { 410 this.isClickBack = false 411 LogUtil.info(TAG, 'aboutToAppear'); 412 window.getLastWindow(getContext(this)).then(currentWindow => { 413 currentWindow.setWindowLayoutFullScreen(true); 414 }) 415 } 416 417 aboutToDisappear(): void { 418 this.isClickBack = true 419 clearInterval(time_id) 420 NoteUtil.refreshAll() 421 LogUtil.info(TAG, 'aboutToDisappear'); 422 this.editContentDialogCtl = null 423 } 424} 425 426@Component 427export struct NoteContentOverViewComp { 428 @Consume('SelectedNoteData') selectedNoteData: NoteData 429 @StorageLink('AllFolderArray') AllFolderArray: FolderData[] = [] 430 @StorageLink('CheckedNoteArray') CheckedNoteArray: NoteData[] = [] 431 @StorageLink('isUpdate') isUpdate: boolean = false 432 NoteDataMoveArray: FolderData[] = []; 433 editTitleDialogCtl: CustomDialogController | null = new CustomDialogController({ 434 builder: EditTitleDialog({ confirm: (newTitle: string) => { 435 this.confirm(newTitle); 436 } }), 437 alignment: DialogAlignment.Center, 438 autoCancel: false, 439 customStyle: true, 440 }) 441 442 aboutToAppear() { 443 this.NoteDataMoveArray = this.AllFolderArray.slice(2, this.AllFolderArray.length); 444 if (this.AllFolderArray[1] === undefined || this.AllFolderArray[1] === null) { 445 LogUtil.info(TAG, 'this AllFolderArray[1] undefined'); 446 return 447 } 448 this.NoteDataMoveArray.push(this.AllFolderArray[1]); 449 } 450 451 aboutToDisappear() { 452 this.editTitleDialogCtl = null 453 } 454 455 confirm(newTitle: string) { 456 this.selectedNoteData.title = newTitle 457 this.selectedNoteData.modified_time = new Date().getTime() 458 let predicatesNote = RdbStoreUtil.getRdbPredicates(TableName.NoteTable); 459 predicatesNote.equalTo(NoteTableColumn.Uuid, this.selectedNoteData?.uuid); 460 RdbStoreUtil.update(this.selectedNoteData?.toNoteObject(), predicatesNote, null); 461 // save continue data 462 let continueNote: string = JSON.stringify(this.selectedNoteData?.toNoteObject()) 463 AppStorage.SetOrCreate<string>('ContinueNote', continueNote) 464 LogUtil.info(TAG, 'NoteContentOverViewComp, MenuBuilder, set continue note success') 465 NoteUtil.refreshAll() 466 } 467 468 @Builder 469 MenuBuilder() { 470 Column() { 471 Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 472 List() { 473 if (this.NoteDataMoveArray !== undefined && this.NoteDataMoveArray !== null && 474 this.NoteDataMoveArray.length > 0) { 475 ForEach(this.NoteDataMoveArray, (item: FolderData) => { 476 ListItem() { 477 NoteDataMoveItemCompMenu({ folderItem: item, uuid: this.selectedNoteData?.folder_uuid }) 478 } 479 .onClick(() => { 480 this.selectedNoteData.folder_uuid = item.uuid 481 let predicatesNote = RdbStoreUtil.getRdbPredicates(TableName.NoteTable); 482 predicatesNote.equalTo(NoteTableColumn.Uuid, this.selectedNoteData?.uuid); 483 RdbStoreUtil.update(this.selectedNoteData?.toNoteObject(), predicatesNote, null); 484 // save continue data 485 let continueNote: string = JSON.stringify(this.selectedNoteData?.toNoteObject()) 486 AppStorage.SetOrCreate<string>('ContinueNote', continueNote) 487 LogUtil.info(TAG, 'MenuBuilder, set continue note success') 488 NoteUtil.refreshAll() 489 }) 490 }, (noteItem: NoteData) => noteItem?.uuid) 491 } 492 } 493 .margin({ top: 4, bottom: 4 }) 494 .listDirection(Axis.Vertical) 495 .edgeEffect(EdgeEffect.Spring) 496 .height(this.AllFolderArray.length > 12 ? 504 : (this.AllFolderArray.length - 3) * 56) 497 } 498 .backgroundColor($r('app.color.folder_color_ffffff')) 499 .width(148) 500 .padding({ left: 24, right: 24 }) 501 } 502 } 503 504 build() { 505 if (this.selectedNoteData) { 506 Flex({ direction: FlexDirection.Column, wrap: FlexWrap.NoWrap, 507 justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { 508 Row() { 509 Text(this.selectedNoteData?.title) 510 .id(this.isUpdate + '') 511 .fontSize(30).fontWeight(FontWeight.Medium) 512 .onClick(() => { 513 clearInterval(time_id) 514 this.editTitleDialogCtl!.open(); 515 }) 516 }.height(40) 517 .width(StyleConstants.PERCENTAGE_100) 518 519 Row() { 520 Text(DateUtil.formateDateForNoteContent(new Date(this.selectedNoteData?.modified_time))) 521 .id(this.isUpdate + '') 522 .fontSize(12) 523 .padding({ top: 4, bottom: 4 }) 524 .fontColor($r('app.color.modified_time_font_color')) 525 Row() { 526 Text(FolderUtil.getFolderText(FolderUtil.getFolderData(AppStorage.Get('AllFolderArray'), this.selectedNoteData?.folder_uuid)) == 527 folderTextMap.sys_def_myFavorites_uuid ? folderTextMap.sys_def_unClassified_uuid : 528 FolderUtil.getFolderText(FolderUtil.getFolderData(AppStorage.Get('AllFolderArray'), this.selectedNoteData?.folder_uuid))) 529 .id(this.isUpdate + '') 530 .fontColor($r('app.color.folder_color_99182431')) 531 .fontSize(12) 532 Image($r('app.media.triangle')) 533 .width(6) 534 .height(12) 535 .margin({ left: 4 }) 536 } 537 .id(this.isUpdate + '') 538 .padding({ left: 8, right: 8, top: 4, bottom: 4 }) 539 .margin({ left: 8 }) 540 .borderRadius(16) 541 .backgroundColor(NoteUtil.getNoteBgColor(AppStorage.Get('AllFolderArray')!, this.selectedNoteData?.folder_uuid, SysDefFolderUuid.AllNotes, false)) 542 .bindMenu(this.MenuBuilder) 543 }.alignItems(VerticalAlign.Top).height(40).width(StyleConstants.PERCENTAGE_100) 544 } 545 .opacity(this.selectedNoteData?.is_deleted == Delete.Yes ? 0.4 : 1) 546 .width(StyleConstants.PERCENTAGE_100) 547 .height(82) 548 } 549 } 550} 551 552@Component 553export struct ToolBarComp { 554 @Consume('SelectedNoteData') selectedNoteData: NoteData 555 @Consume('SelectedFolderData') selectedFolderData: FolderData 556 @Consume('EditModel') editModel: boolean 557 @StorageLink('AllNoteArray') AllNoteArray: NoteData[] = AppStorage.Link('AllNoteArray') 558 controllerShow: webview.WebviewController = new webview.WebviewController(); 559 560 onDeleteConfirm() { 561 if (this.selectedFolderData.uuid != SysDefFolderUuid.RecentDeletes) { 562 this.selectedNoteData.is_deleted = Delete.Yes 563 this.selectedNoteData.deleted_time = new Date().getTime() 564 // update note to db 565 let predicatesNote = RdbStoreUtil.getRdbPredicates(TableName.NoteTable); 566 predicatesNote.equalTo(NoteTableColumn.Uuid, this.selectedNoteData?.uuid); 567 RdbStoreUtil.update(this.selectedNoteData?.toNoteObject(), predicatesNote, null); 568 routePage() 569 } else { 570 NoteUtil.removeNoteData(this.AllNoteArray, this.selectedNoteData?.uuid) 571 // delete note from db 572 let predicatesNote = RdbStoreUtil.getRdbPredicates(TableName.NoteTable); 573 predicatesNote.equalTo(NoteTableColumn.Uuid, this.selectedNoteData?.uuid); 574 RdbStoreUtil.delete(predicatesNote, null); 575 routePage() 576 } 577 AppStorage.SetOrCreate('isUpdate', true) 578 } 579 580 noteDataDeleteDialogCtl: CustomDialogController | null = new CustomDialogController({ 581 builder: DeleteDialog({ onConfirm: () => { 582 this.onDeleteConfirm(); 583 }, multiSelect: true }), 584 alignment: DialogAlignment.Bottom, 585 autoCancel: false, 586 customStyle: true, 587 }) 588 589 aboutToDisappear() { 590 this.noteDataDeleteDialogCtl = null 591 } 592 593 build() { 594 Flex({ direction: FlexDirection.Row, wrap: FlexWrap.NoWrap, 595 justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) { 596 597 Image($r('app.media.back')) 598 .height(24) 599 .width(24) 600 .responseRegion({ width: 54, height: 54 }) 601 .onClick(() => { 602 try { 603 this.controllerShow.runJavaScript('getHtmlContent()'); 604 // 清除定时器 605 if (time_id != undefined) { 606 LogUtil.info(TAG, 'back, clearInterval time_id : ' + time_id); 607 clearInterval(time_id) 608 } 609 setTimeout(() => { 610 LogUtil.info(TAG, 'wait save cotext'); 611 router.back() 612 }, 50) 613 NoteUtil.refreshAll() 614 } catch (error) { 615 LogUtil.info(TAG, 'back error') 616 } 617 }) 618 619 if (this.editModel == false) { 620 Row({ space: StyleConstants.SPACE_24 }) { 621 Image(this.selectedNoteData?.is_favorite == Favorite.Yes ? $r('app.media.favorite') : $r('app.media.favorite_cancel')) 622 .height(24).width(24) 623 .onClick(() => { 624 try { 625 this.selectedNoteData.is_favorite = (this.selectedNoteData?.is_favorite == Favorite.Yes ? 626 Favorite.No : Favorite.Yes) 627 // update note to db 628 let predicatesNote = RdbStoreUtil.getRdbPredicates(TableName.NoteTable); 629 predicatesNote.equalTo(NoteTableColumn.Uuid, this.selectedNoteData?.uuid); 630 RdbStoreUtil.update(this.selectedNoteData?.toNoteObject(), predicatesNote, null); 631 if (this.selectedFolderData?.uuid === SysDefFolderUuid.MyFavorites) { 632 this.selectedNoteData = NoteUtil.getFirstNoteData(AppStorage.Get('AllNoteArray')!, SysDefFolderUuid.MyFavorites)!; 633 if (!this.selectedNoteData) { 634 routePage() 635 } 636 this.controllerShow.runJavaScript( 637 "RICH_EDITOR.setHtml('" + this.selectedNoteData.content_text + "')" 638 ) 639 // save continue data 640 let continueNote: string = JSON.stringify(this.selectedNoteData.toNoteObject()) 641 AppStorage.SetOrCreate<string>('ContinueNote', continueNote) 642 LogUtil.info(TAG, 'ToolBarComp, set continue note success'); 643 } 644 NoteUtil.refreshAll() 645 } catch (error) { 646 LogUtil.info(TAG, 'favorite error') 647 } 648 }) 649 Image($r('app.media.delete')).height(24).width(24) 650 .onClick(() => { 651 this.noteDataDeleteDialogCtl!.open(); 652 }) 653 }.width(72) 654 .visibility(this.selectedNoteData?.is_deleted == Delete.Yes ? Visibility.None : Visibility.Visible) 655 } else { 656 Row({ space: StyleConstants.SPACE_6 }) { 657 Button({ type: ButtonType.Normal, stateEffect: true }) { 658 Image($r('app.media.undo')).height(24).width(24) 659 .onClick(() => { 660 try { 661 // 退出键盘 662 inputMethod.getController().stopInputSession(); 663 this.controllerShow.runJavaScript('javascript:RICH_EDITOR.undo()'); 664 } catch (error) { 665 LogUtil.info(TAG, 'undo error') 666 } 667 }) 668 }.width(42) 669 .height(42) 670 .borderRadius(8) 671 .backgroundColor($r('app.color.color_fffffB')) 672 673 Button({ type: ButtonType.Normal, stateEffect: true }) { 674 Image($r('app.media.todo')).height(24).width(24) 675 .onClick(() => { 676 try { 677 // 退出键盘 678 inputMethod.getController().stopInputSession(); 679 this.controllerShow.runJavaScript('javascript:RICH_EDITOR.redo()'); 680 } catch (error) { 681 LogUtil.info(TAG, 'todo error') 682 } 683 }) 684 }.width(42) 685 .height(42) 686 .borderRadius(8) 687 .backgroundColor($r('app.color.color_fffffB')) 688 689 Button({ type: ButtonType.Normal, stateEffect: true }) { 690 Image($r('app.media.tick_thin')).height(24).width(24) 691 .onClick(() => { 692 try { 693 // 保存笔记信息到数据库 694 this.controllerShow.runJavaScript('getHtmlContent()'); 695 this.editModel = false 696 this.controllerShow.runJavaScript('javascript:RICH_EDITOR.getBlur()'); 697 } catch (error) { 698 LogUtil.info(TAG, 'tick_thin error') 699 } 700 }) 701 }.width(42) 702 .height(42) 703 .borderRadius(8) 704 .backgroundColor($r('app.color.color_fffffB')) 705 } 706 .width(130) 707 .visibility(this.selectedNoteData?.is_deleted == Delete.Yes ? Visibility.None : Visibility.Visible) 708 } 709 } 710 .width(StyleConstants.PERCENTAGE_100) 711 .height(40) 712 } 713} 714 715@Component 716export struct DeleteNoteComp { 717 @StorageLink('CheckedNoteArray') CheckedNoteArray: NoteData[] = [] 718 @StorageLink('AllNoteArray') AllNoteArray: NoteData[] = AppStorage.Link('AllNoteArray') 719 @Consume('SelectedFolderData') selectedFolderData: FolderData 720 @Consume('RefreshFlag') refreshFlag: number 721 @Consume('SelectedNoteData') selectedNoteData: NoteData; 722 noteDataDeleteDialogCtlBottom: CustomDialogController | null = new CustomDialogController({ 723 builder: DeleteDialog({ onConfirm: () => { 724 this.onDeleteConfirm(); 725 }, multiSelect: true }), 726 alignment: DialogAlignment.Bottom, 727 autoCancel: false, 728 customStyle: true, 729 }) 730 731 aboutToDisappear() { 732 this.noteDataDeleteDialogCtlBottom = null 733 } 734 735 onDeleteConfirm() { 736 if (this.selectedFolderData.uuid != SysDefFolderUuid.RecentDeletes) { 737 this.selectedNoteData.is_deleted = Delete.Yes 738 this.selectedNoteData.deleted_time = new Date().getTime() 739 // update note to db 740 let predicatesNote = RdbStoreUtil.getRdbPredicates(TableName.NoteTable); 741 predicatesNote.equalTo(NoteTableColumn.Uuid, this.selectedNoteData?.uuid); 742 RdbStoreUtil.update(this.selectedNoteData?.toNoteObject(), predicatesNote, null); 743 routePage() 744 } else { 745 NoteUtil.removeNoteData(this.AllNoteArray, this.selectedNoteData?.uuid) 746 // delete note from db 747 let predicatesNote = RdbStoreUtil.getRdbPredicates(TableName.NoteTable); 748 predicatesNote.equalTo(NoteTableColumn.Uuid, this.selectedNoteData?.uuid); 749 RdbStoreUtil.delete(predicatesNote, null); 750 NoteUtil.refreshAll() 751 routePage() 752 } 753 AppStorage.SetOrCreate('isUpdate', false) 754 } 755 756 build() { 757 Flex({ direction: FlexDirection.Row, wrap: FlexWrap.Wrap, justifyContent: FlexAlign.SpaceBetween }) { 758 Column() { 759 Image($r('app.media.delete')) 760 .width(24) 761 .height(24) 762 .responseRegion({ x: -15.0, y: -15.0, width: 54, height: 54 }) 763 .onClick(() => { 764 this.noteDataDeleteDialogCtlBottom!.open(); 765 }) 766 Text($r('app.string.delete')) 767 .fontSize(10) 768 .fontColor($r('app.color.delete_font_color')) 769 .padding({ top: 5 }) 770 } 771 .height('100%') 772 .width(180) 773 .justifyContent(FlexAlign.Center) 774 .alignItems(HorizontalAlign.Center) 775 .offset({ y: -50 }) 776 777 Column() { 778 Image($r('app.media.recover')) 779 .width(24) 780 .height(24) 781 .responseRegion({ x: -15.0, y: -15.0, width: 54, height: 54 }) 782 .onClick(() => { 783 this.selectedNoteData.is_deleted = Delete.No 784 this.selectedNoteData.deleted_time = 0 785 let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; 786 let resource: resourceManager.Resource = { 787 bundleName: 'com.ohos.note', 788 moduleName: 'default', 789 id: $r('app.string.restore').id 790 }; 791 context.resourceManager.getStringValue(resource, (error: BusinessError, value: string) => { 792 if (error != null) { 793 LogUtil.error(TAG, 'error is' + error); 794 } else { 795 promptAction.showToast({ message: value, duration: 2000 }); 796 } 797 }); 798 this.refreshFlag = (this.refreshFlag == 0 ? 1 : 0) 799 // update note to db 800 let predicatesNote = RdbStoreUtil.getRdbPredicates(TableName.NoteTable); 801 predicatesNote.equalTo(NoteTableColumn.Uuid, this.selectedNoteData?.uuid); 802 RdbStoreUtil.update(this.selectedNoteData?.toNoteObject(), predicatesNote, null); 803 NoteUtil.refreshAll() 804 }) 805 Text($r('app.string.recover')) 806 .fontSize(10) 807 .fontColor($r('app.color.recover_font_color')) 808 .padding({ top: 5 }) 809 } 810 .height('100%') 811 .width(180) 812 .justifyContent(FlexAlign.Center) 813 .alignItems(HorizontalAlign.Center) 814 .offset({ y: -50 }) 815 } 816 .width(360) 817 .height(56) 818 .visibility(this.selectedNoteData?.is_deleted == Delete.Yes ? 819 Visibility.Visible : Visibility.None) 820 } 821} 822 823@Component 824struct NoteDataMoveItemCompMenu { 825 @StorageLink('CheckedNoteArray') CheckedNoteArray: NoteData[] = [] 826 @StorageLink('AllFolderArray') AllFolderArray: FolderData[] = [] 827 @StorageLink('isUpdate') isUpdate: boolean = false 828 folderItem: FolderData = new FolderData(0, '', new Date().getTime() + '', '', FolderType.CusDef, Delete.No, new Date().getTime(), new Date().getTime()); 829 uuid: string = ''; 830 831 build() { 832 Flex({ alignItems: ItemAlign.Center, wrap: FlexWrap.NoWrap, justifyContent: FlexAlign.Center }) { 833 Flex({ alignItems: ItemAlign.Center, wrap: FlexWrap.NoWrap }) { 834 Image(FolderUtil.getFolderIcon(this.folderItem.uuid)) 835 .id(this.isUpdate + '') 836 .objectFit(ImageFit.Fill) 837 .width(24) 838 .height(24) 839 .flexShrink(0) 840 .fillColor(FolderUtil.getFolderIconColor(this.AllFolderArray, this.folderItem.uuid, 841 this.folderItem.uuid == this.uuid)) 842 } 843 .width(24) 844 845 Column() { 846 Flex({ alignItems: ItemAlign.Center, wrap: FlexWrap.NoWrap, justifyContent: FlexAlign.SpaceBetween }) { 847 Text(FolderUtil.getFolderText(this.folderItem)) 848 .id(this.isUpdate + '') 849 .fontSize(16) 850 .fontColor(FolderUtil.getFolderIconColor(this.AllFolderArray, this.folderItem.uuid == this.uuid ? this.folderItem.uuid : '', this.folderItem.uuid == this.uuid)) 851 .textAlign(TextAlign.Center) 852 .maxLines(1) 853 .textOverflow({ overflow: TextOverflow.Ellipsis }) 854 .flexShrink(1) 855 } 856 .width('100%') 857 .height(55) 858 859 if (this.folderItem.uuid != SysDefFolderUuid.UnClassified) { 860 Divider() 861 .color($r('app.color.divider_color_e4e4e4')) 862 .strokeWidth(1) 863 } 864 865 } 866 .padding({ left: 16 }) 867 } 868 .id(this.isUpdate + '') 869 .width('100%') 870 .height(56) 871 .visibility(FolderUtil.isFolderMoveIn(this.folderItem) ? Visibility.Visible : Visibility.None) 872 } 873} 874