• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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