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