• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2022-2025 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 {
21  TableName,
22  NoteTableColumn,
23  SysDefFolderUuid,
24  Favorite,
25  Delete,
26  FolderType
27} from '@ohos/utils/src/main/ets/default/model/databaseModel/EnumData';
28import StyleConstants from '@ohos/utils/src/main/ets/default/constants/StyleConstants';
29import { EditContentDialog, 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 { promptAction } from '@kit.ArkUI';
33import util from '@ohos.util';
34import { LogUtil } from '@ohos/utils/src/main/ets/default/baseUtil/LogUtil';
35import OperationUtils from '@ohos/utils/src/main/ets/default/baseUtil/OperationUtils';
36import mediaquery from '@ohos.mediaquery';
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 common from '@ohos.app.ability.common';
42import { BusinessError } from '@ohos.base';
43import resourceManager from '@ohos.resourceManager';
44
45const TAG = 'NoteContentComp';
46
47let timeId: number = 0;
48let noteContext = AppStorage.Get<common.UIAbilityContext>('noteContext')!;
49
50// Note content component
51let inSetValue: string = AppStorage.Link('inSetValue');
52
53interface NoteContentType {
54  callbackhtml: (html: string) => void;
55  callbackImagePath: (imgName: string) => void;
56  callbackhtmlSave: (html: string) => void;
57  callbackScheduledSave: (html: string) => void;
58  callbackPasteImage: (html: string) => void;
59  callbackGetSize: (fontSize: number) => void;
60}
61
62@Component
63export struct NoteContentComp {
64  @Consume('SelectedNoteData') selectedNoteData: NoteData;
65  @StorageLink('AllNoteArray') AllNoteArray: NoteData[] = AppStorage.Link('AllNoteArray');
66  @Consume('SelectedFolderData') selectedFolderData: FolderData;
67  @Consume('RefreshFlag') refreshFlag: number;
68  @Consume('EditModel') editModel: boolean;
69  @Consume('SectionStatus') sectionStatus: number;
70  @Consume('LastSectionStatus') lastSectionStatus: number;
71  @Consume('Issave') issave: number;
72  @Consume('Search') search: boolean;
73  @StorageLink('dpi') dpi: number = 240;
74  controllerShow: webview.WebviewController = new webview.WebviewController();
75  private editContentFlag = false;
76  @State uri1: string = "";
77  private context = getContext(this);
78  @StorageLink('ScrollTopPercent') scrollTopPercent: number = 0.0;
79  @StorageLink('isUpdate') isUpdate: boolean = false;
80  @StorageLink('refreshCurrentNote') @Watch('isDataChange') refreshCurrentNote: boolean = false;
81  @Consume('AsideWidth') asideWidth: number;
82
83  isDataChange() {
84    if (!this.refreshCurrentNote) {
85      return;
86    }
87    try {
88      this.controllerShow.runJavaScript("RICH_EDITOR.setHtml('" + this.selectedNoteData.content_text + "')");
89      LogUtil.info(TAG, `runJavaScript setHtml success.`);
90    } catch (error) {
91      LogUtil.error(TAG, `runJavaScript setHtml failed.code:${JSON.stringify(error.code)},
92        message:${JSON.stringify(error.message)}`);
93    }
94    this.refreshCurrentNote = false;
95  }
96
97  storeScrollTop(scrollTop: number) {
98    if (scrollTop < 0) {
99      return;
100    }
101    AppStorage.SetOrCreate<number>('ScrollTopPercent', scrollTop / this.controllerShow.getPageHeight());
102  }
103
104  restoreScrollTop() {
105    try {
106      if (!AppStorage.Has('remoteScrollTopPercent')) {
107        return;
108      }
109      let scrollTopPercent = AppStorage.Get<number>('remoteScrollTopPercent')!;
110      if (scrollTopPercent < 0) {
111        return;
112      }
113      this.controllerShow.runJavaScript(
114        'document.documentElement.scrollTop = ' + this.controllerShow.getPageHeight() * scrollTopPercent
115      )
116    } catch (error) {
117      LogUtil.error(TAG, `restoreScrollTop failed.code:${JSON.stringify(error.code)},
118      message:${JSON.stringify(error.message)}`);
119    }
120  }
121
122  restoreFocus() {
123    if (!AppStorage.Has('isRemoteFocusOnSearch')) {
124      return;
125    }
126    let isRemoteFocusOnSearch = AppStorage.Get<boolean>('isRemoteFocusOnSearch');
127    if (isRemoteFocusOnSearch) {
128      focusControl.requestFocus('searchInput');
129    }
130    AppStorage.Delete('isRemoteFocusOnSearch');
131  }
132
133  noteContent: NoteContentType = {
134    callbackhtml: (html) => {
135      try {
136        LogUtil.info(TAG, 'note uuid is:' + this.selectedNoteData.uuid);
137        this.selectedNoteData.content_text = NoteUtil.contrastInitType(this.selectedNoteData.content_text);
138        if (this.selectedNoteData.content_text === html) {
139          return;
140        }
141        ;
142        this.selectedNoteData.content_text = html;
143        this.selectedNoteData.modified_time = new Date().getTime();
144        let predicatesNote = RdbStoreUtil.getRdbPredicates(TableName.NoteTable);
145        predicatesNote.equalTo(NoteTableColumn.Uuid, this.selectedNoteData.uuid);
146        RdbStoreUtil.update(this.selectedNoteData.toNoteObject(), predicatesNote, null);
147        LogUtil.info(TAG, 'update note success:' + this.selectedNoteData.uuid);
148        // save continue data
149        let continueNote: string = JSON.stringify(this.selectedNoteData.toNoteObject());
150        AppStorage.SetOrCreate<string>('ContinueNote', continueNote);
151        LogUtil.info(TAG, 'callbackhtml, set continue note success');
152        return 'AceString';
153      } catch (error) {
154        LogUtil.error(TAG, 'callbackhtml error: ' + JSON.stringify(error));
155        return 'AceString';
156      }
157    },
158    callbackImagePath: (imgName) => {
159      // updata note image
160      try {
161        LogUtil.info(TAG, 'note imgName is:' + imgName);
162        this.selectedNoteData.content_img = imgName;
163        LogUtil.info(TAG, 'set content_img success');
164      } catch (error) {
165        LogUtil.error(TAG, 'callbackImagePath error: ' + JSON.stringify(error));
166      }
167    },
168
169    callbackhtmlSave: (html) => {
170      try {
171        LogUtil.info(TAG, 'note uuid is:' + this.selectedNoteData.uuid);
172        this.selectedNoteData.content_text = html;
173        this.selectedNoteData.modified_time = new Date().getTime();
174        let predicatesNote = RdbStoreUtil.getRdbPredicates(TableName.NoteTable);
175        predicatesNote.equalTo(NoteTableColumn.Uuid, this.selectedNoteData.uuid);
176        RdbStoreUtil.update(this.selectedNoteData.toNoteObject(), predicatesNote, null);
177        LogUtil.info(TAG, 'update note success:' + this.selectedNoteData.uuid);
178        this.sectionStatus = this.lastSectionStatus;
179        this.sectionStatus = mediaquery.matchMediaSync('(width < 2000)').matches ? 2 : 3;
180        // save continue data
181        let continueNote: string = JSON.stringify(this.selectedNoteData.toNoteObject());
182        AppStorage.SetOrCreate<string>('ContinueNote', continueNote);
183        AppStorage.SetOrCreate<number>('ContinueSection', this.sectionStatus);
184        LogUtil.info(TAG, 'callbackhtmlSave, set continue note and section success');
185        return 'AceString';
186      } catch (error) {
187        LogUtil.error(TAG, 'callbackhtmlSave error: ' + JSON.stringify(error));
188        return 'AceString';
189      }
190    },
191
192    callbackScheduledSave: (html) => {
193      try {
194        LogUtil.info(TAG, 'callbackScheduledSave');
195        if (this.selectedNoteData.content_text == html) {
196          LogUtil.info(TAG, 'callbackScheduledSave the same value return');
197          return;
198        }
199        this.selectedNoteData.content_text = html;
200        this.selectedNoteData.modified_time = new Date().getTime();
201        let predicatesNote = RdbStoreUtil.getRdbPredicates(TableName.NoteTable);
202        predicatesNote.equalTo(NoteTableColumn.Uuid, this.selectedNoteData.uuid);
203        RdbStoreUtil.update(this.selectedNoteData.toNoteObject(), predicatesNote, null);
204        LogUtil.info(TAG, 'callbackScheduledSave, update note success:' + this.selectedNoteData.uuid);
205        // save continue data
206        let continueNote: string = JSON.stringify(this.selectedNoteData.toNoteObject());
207        AppStorage.SetOrCreate<string>('ContinueNote', continueNote);
208        LogUtil.info(TAG, 'callbackScheduledSave, set continue note success');
209      } catch (error) {
210        LogUtil.error(TAG, 'callbackScheduledSave error: ' + JSON.stringify(error));
211      }
212    },
213
214    callbackPasteImage: (html) => {
215      try {
216        if (html) {
217          LogUtil.info(TAG, 'paste info' + html);
218          let realHtml = "";
219          let base64regex: RegExp = new RegExp('/^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/');
220          if (html && html.indexOf('base64') > 0) {
221            LogUtil.info(TAG, ' getSrcFromHtml, src[1] : ' + html);
222            let imgData = html.split(',')[1];
223            let imgType = 'png';
224            if (html.indexOf('jpeg') > 0) {
225              imgType = 'jpg';
226            } else if (html.indexOf('gif') > 0) {
227              imgType = 'gif';
228            }
229            let filePath = "";
230            if (base64regex.test(imgData)) {
231              let base64 = new util.Base64();
232              let decodeArr = base64.decodeSync(imgData);
233              filePath = OperationUtils.saveImageData(decodeArr, imgType);
234            } else {
235              filePath = OperationUtils.saveImage(imgData, imgType);
236            }
237            realHtml = 'file://' + filePath;
238          }
239          LogUtil.info(TAG, 'paste info11-' + realHtml);
240          this.controllerShow.runJavaScript("javascript:RICH_EDITOR.insertImageHtml('" + realHtml + "')");
241          LogUtil.info(TAG, 'paste info11--' + realHtml);
242        } else {
243          LogUtil.info(TAG, 'paste info22225');
244        }
245      } catch (error) {
246        LogUtil.error(TAG, `callbackPasteImage failed.code:${JSON.stringify(error.code)},
247        message:${JSON.stringify(error.message)}`);
248      }
249    },
250    callbackGetSize: (fontSize) => {
251      if (fontSize === 16) {
252        this.selectedNoteData.slider_value = 0;
253      } else if (fontSize === 18) {
254        this.selectedNoteData.slider_value = 4;
255      } else if (fontSize === 24) {
256        this.selectedNoteData.slider_value = 8;
257      } else if (fontSize === 32) {
258        this.selectedNoteData.slider_value = 12;
259      } else if (fontSize === 48) {
260        this.selectedNoteData.slider_value = 16;
261      }
262    }
263  }
264
265  build() {
266    Stack({ alignContent: Alignment.Bottom }) {
267      Flex({
268        direction: FlexDirection.Column,
269        wrap: FlexWrap.NoWrap,
270        alignItems: ItemAlign.Start,
271        alignContent: FlexAlign.SpaceAround
272      }) {
273        Column() {
274          ToolBarComp({ controllerShow: this.controllerShow })
275        }
276        .margin({ left: 24, right: 24 })
277
278        Column() {
279          NoteContentOverViewComp({ controllerShow: this.controllerShow })
280          Text(this.refreshFlag.toString()).visibility(Visibility.None)
281          Text(this.AllNoteArray.length.toString()).visibility(Visibility.None) // 用于强制刷新使用
282
283          Web({ src: $rawfile('editor.html'), controller: this.controllerShow })
284            .javaScriptAccess(true)
285            .javaScriptProxy({
286              object: this.noteContent,
287              name: 'callBackToApp', // html-->  name.method
288              methodList: ['callbackhtml', 'callbackhtmlSave', 'callbackScheduledSave', 'callbackGetSize',
289                'callbackPasteImage', 'callbackImagePath'],
290              controller: this.controllerShow
291            })
292            .enabled(this.sectionStatus !== 1 ? false : true)
293            .onPageEnd((e) => {
294              try {
295                if (this.dpi <= 240) {
296                  this.controllerShow.runJavaScript('changeSizeToRk()');
297                } else if (this.dpi <= 320 && this.dpi > 240) {
298                  this.controllerShow.runJavaScript('changeSizeToPhone()');
299                } else {
300                  this.controllerShow.runJavaScript('changeSizeToTablet()');
301                }
302                if (AppStorage.Get('breakPoint') !== 'sm') {
303                  this.controllerShow.runJavaScript('hiddenButton()');
304                }
305                LogUtil.info(TAG, 'finish loadurl');
306                if (this.selectedNoteData) {
307                  let self = this;
308                  this.controllerShow.runJavaScript(
309                    "RICH_EDITOR.setHtml('" + this.selectedNoteData.content_text + "')",
310                    () => {
311                      // wait for the image in the note to load
312                      setTimeout(() => {
313                        self.restoreScrollTop();
314                        self.restoreFocus();
315                      }, 100)
316                    }
317                  );
318                }
319                // 初次加载为为小屏预览模式
320                if (this.sectionStatus != 1) {
321                  this.controllerShow.runJavaScript('RICH_EDITOR.setInputEnabled(false)');
322                }
323              } catch (error) {
324                LogUtil.info(TAG,
325                  `runJavaScript onPageEnd error. code:${JSON.stringify(error.code)},message:${error.message}`);
326              }
327            })
328            .imageAccess(true)
329            .onlineImageAccess(true)
330            .fileAccess(true)
331            .domStorageAccess(true)
332            .zoomAccess(false)
333            .height('88%')
334            .width('100%')
335            .onScroll((event) => {
336              this.storeScrollTop(event.yOffset);
337            })
338        }
339        .margin({ left: 24, right: 24 })
340        //        .width(StyleConstants.PERCENTAGE_100)
341        .enabled(this.selectedNoteData && this.selectedNoteData.is_deleted == Delete.Yes ? false : true)
342        .onClick(() => {
343          try {
344            this.issave = 0;
345            LogUtil.info(TAG, 'editModel : ' + this.editModel + ', sectionStatus : ' + this.sectionStatus);
346            let isContinue = AppStorage.Get<boolean>('IsContinue');
347            LogUtil.info(TAG, 'isContinue : ' + isContinue);
348            // 点击第三屏进入全屏编辑模式
349            if (this.sectionStatus != 1 || isContinue) {
350              this.asideWidth = 0;
351              this.lastSectionStatus = this.sectionStatus;
352              this.sectionStatus = 1;
353              this.controllerShow.runJavaScript('RICH_EDITOR.setInputEnabled(true)');
354              // 添加定时器:3s自动保存
355              if (timeId) {
356                clearInterval(timeId);
357              }
358              timeId = setInterval(() => {
359                this.controllerShow.runJavaScript('scheduledSaveContent()');
360              }, 3000)
361              LogUtil.info(TAG, 'setInterval timeId : ' + timeId);
362              // save continue data
363              AppStorage.SetOrCreate<number>('ContinueSection', this.sectionStatus);
364              LogUtil.info(TAG, 'set continue section success');
365              this.editModel = !this.editModel;
366              AppStorage.SetOrCreate<boolean>('IsContinue', false);
367            }
368          } catch (error) {
369            LogUtil.error(TAG, `Column failed.code:${JSON.stringify(error.code)},
370            message:${JSON.stringify(error.message)}`);
371          }
372        })
373      }
374      .id(this.isUpdate + '')
375      .height(StyleConstants.PERCENTAGE_100)
376      .visibility(FolderUtil.getNoteCount(AppStorage.Get('AllNoteArray'), this.selectedFolderData.uuid) == 0 ?
377      Visibility.Hidden : Visibility.Visible)
378
379      Column() {
380      }
381      .height('100%')
382      .width('100%')
383      .backgroundColor('#18181A')
384      .opacity(0.1)
385      .visibility(this.search ? Visibility.Visible : Visibility.Hidden)
386    }
387    .height(StyleConstants.PERCENTAGE_100)
388    .width(StyleConstants.PERCENTAGE_100)
389  }
390
391  aboutToAppear(): void {
392    LogUtil.info(TAG, 'aboutToAppear')
393  }
394
395  aboutToDisappear(): void {
396    clearInterval(timeId)
397    LogUtil.info(TAG, 'aboutToDisappear')
398  }
399}
400
401@Component
402export struct NoteContentOverViewComp {
403  @Consume('SelectedNoteData') selectedNoteData: NoteData;
404  @StorageLink('AllFolderArray') @Watch('getArray') AllFolderArray: FolderData[] = [];
405  @StorageLink('CheckedNoteArray') CheckedNoteArray: NoteData[] = [];
406  @StorageLink('AllNoteArray') AllNoteArray: NoteData[] = AppStorage.Link('AllNoteArray');
407  @Consume('SelectedFolderData') selectedFolderData: FolderData;
408  @Consume('EditModel') editModel: boolean;
409  @Consume('SectionStatus') sectionStatus: number;
410  @Consume('RefreshFlag') refreshFlag: number;
411  @StorageLink('isUpdate') isUpdate: boolean = false;
412  NoteDataMoveArray: FolderData[] = [];
413  controllerShow: webview.WebviewController = new webview.WebviewController();
414  editTitleDialogCtl: CustomDialogController | null = new CustomDialogController({
415    builder: EditContentDialog({
416      confirm: (newTitle: string) => {
417        this.confirm(newTitle);
418      }
419    }),
420    alignment: DialogAlignment.Center,
421    autoCancel: false,
422    customStyle: true,
423  })
424
425  getArray() {
426    this.NoteDataMoveArray = this.AllFolderArray.slice(2, this.AllFolderArray.length);
427    if (this.AllFolderArray[1] === undefined || this.AllFolderArray[1] === null) {
428      LogUtil.info(TAG, 'this AllFolderArray[1] undefined');
429      return;
430    }
431    this.NoteDataMoveArray.push(this.AllFolderArray[1]);
432  }
433
434  aboutToAppear() {
435    this.NoteDataMoveArray = this.AllFolderArray.slice(2, this.AllFolderArray.length);
436    if (this.AllFolderArray[1] === undefined || this.AllFolderArray[1] === null) {
437      LogUtil.info(TAG, 'this AllFolderArray[1] undefined');
438      return;
439    }
440    this.NoteDataMoveArray.push(this.AllFolderArray[1]);
441  }
442
443  aboutToDisappear() {
444    this.editTitleDialogCtl = null;
445  }
446
447  confirm(newTitle: string) {
448    try {
449      this.selectedNoteData.title = newTitle;
450      this.selectedNoteData.modified_time = new Date().getTime();
451      let predicatesNote = RdbStoreUtil.getRdbPredicates(TableName.NoteTable);
452      predicatesNote.equalTo(NoteTableColumn.Uuid, this.selectedNoteData.uuid);
453      RdbStoreUtil.update(this.selectedNoteData.toNoteObject(), predicatesNote, null);
454      NoteUtil.refreshAll();
455    } catch (error) {
456      LogUtil.error(TAG, 'confirm error: ' + JSON.stringify(error));
457    }
458  }
459
460  @Builder
461  MenuBuilder() {
462    Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
463      List() {
464        if (this.NoteDataMoveArray !== undefined && this.NoteDataMoveArray !== null &&
465          this.NoteDataMoveArray.length > 0) {
466          ForEach(this.NoteDataMoveArray, (item: FolderData) => {
467            ListItem() {
468              NoteDataMoveItemCompTablet({ folderItem: item, uuid: this.selectedNoteData.folder_uuid })
469            }
470            .onClick(() => {
471              try {
472                this.selectedNoteData.folder_uuid = item.uuid;
473                let predicatesNote = RdbStoreUtil.getRdbPredicates(TableName.NoteTable);
474                predicatesNote.equalTo(NoteTableColumn.Uuid, this.selectedNoteData.uuid);
475                RdbStoreUtil.update(this.selectedNoteData.toNoteObject(), predicatesNote, null);
476                if (this.sectionStatus != 1) {
477                  this.selectedNoteData = NoteUtil.getFirstNoteData(this.AllNoteArray, this.selectedFolderData.uuid)!;
478                  this.controllerShow.runJavaScript(
479                    "RICH_EDITOR.setHtml('" + this.selectedNoteData.content_text + "')"
480                  )
481                  this.refreshFlag = (this.refreshFlag == 0 ? 1 : 0);
482                } else {
483                  this.selectedFolderData = FolderUtil.getFolderData(AppStorage.Get('AllFolderArray')!, item.uuid);
484                }
485                // save continue data
486                let continueNote: string = JSON.stringify(this.selectedNoteData.toNoteObject());
487                AppStorage.SetOrCreate<string>('ContinueNote', continueNote);
488                LogUtil.info(TAG, 'NoteContentOverViewComp, MenuBuilder, set continue note success');
489                NoteUtil.refreshAll();
490              } catch (error) {
491                LogUtil.error(TAG, 'ListItem click error: ' + JSON.stringify(error));
492              }
493            })
494          }, (noteItem: NoteData) => noteItem.uuid)
495        }
496      }.listDirection(Axis.Vertical)
497      .edgeEffect(EdgeEffect.Spring)
498      .height(this.AllFolderArray.length > 12 ? 504 : (this.AllFolderArray.length - 3) * 56)
499    }
500    .width(148)
501    .backgroundColor($r('app.color.color_fffffB'))
502    .padding({ left: 24, right: 24 })
503  }
504
505  build() {
506    if (this.selectedNoteData) {
507      Flex({
508        direction: FlexDirection.Column,
509        wrap: FlexWrap.NoWrap,
510        justifyContent: FlexAlign.SpaceBetween,
511        alignItems: ItemAlign.Center
512      }) {
513        Row() {
514          Text(this.selectedNoteData.title)
515            .id(this.isUpdate + '')
516            .fontSize(30)
517            .margin({ left: 0, right: 24 })
518            .onClick(() => {
519              clearInterval(timeId);
520              this.editTitleDialogCtl!.open();
521              // save continue data
522              AppStorage.SetOrCreate<number>('ContinueSection', this.sectionStatus);
523              LogUtil.info(TAG, 'NoteContentComp, set continue section success');
524            })
525        }.height(40)
526        .width(StyleConstants.PERCENTAGE_100)
527
528        Row() {
529          Text(DateUtil.formateDateForNoteContent(new Date(this.selectedNoteData.modified_time)))
530            .id(this.isUpdate + '')
531            .fontSize(12)
532            .padding({ top: 4, bottom: 4 })
533            .fontColor($r('app.color.modified_time_font_color'))
534            .margin({ left: 0 })
535          Row() {
536            Text(FolderUtil.getFolderText(FolderUtil.getFolderData(AppStorage.Get('AllFolderArray'),
537              this.selectedNoteData.folder_uuid)) ==
538            folderTextMap.sys_def_myFavorites_uuid ? folderTextMap.sys_def_unClassified_uuid :
539            FolderUtil.getFolderText(FolderUtil.getFolderData(AppStorage.Get('AllFolderArray'),
540              this.selectedNoteData.folder_uuid)))
541              .id(this.isUpdate + '')
542              .fontSize(12)
543              .fontColor($r('app.color.list_modified_time_font_color'))
544              .padding({ top: 1 })
545            Image($r('app.media.triangle'))
546              .width(6)
547              .height(12)
548              .margin({ left: 4 })
549          }
550          .id(this.isUpdate + '')
551          .padding({
552            left: 8,
553            right: 8,
554            top: 4,
555            bottom: 4
556          })
557          .margin({ left: 8 })
558          .borderRadius(16)
559          .backgroundColor(NoteUtil.getNoteBgColor(AppStorage.Get('AllFolderArray')!, this.selectedNoteData.folder_uuid,
560            SysDefFolderUuid.AllNotes, false))
561          .bindMenu(this.MenuBuilder)
562        }.alignItems(VerticalAlign.Top).height(40).width(StyleConstants.PERCENTAGE_100)
563      }
564      .opacity(this.selectedNoteData.is_deleted == Delete.Yes ? 0.4 : 1)
565      .width(StyleConstants.PERCENTAGE_100)
566      .height(80)
567    }
568  }
569}
570
571@Component
572export struct ToolBarComp {
573  @Consume('SelectedNoteData') selectedNoteData: NoteData;
574  @Consume('RefreshFlag') refreshFlag: number;
575  @Consume('SectionStatus') sectionStatus: number;
576  @Consume('LastSectionStatus') lastSectionStatus: number;
577  @Consume('SelectedFolderData') selectedFolderData: FolderData;
578  @Consume('ChooseNote') chooseNote: boolean;
579  @Consume('PortraitModel') portraitModel: boolean;
580  @StorageLink('AllNoteArray') AllNoteArray: NoteData[] = AppStorage.Link('AllNoteArray');
581  @Consume('EditModel') editModel: boolean;
582  @Consume('Issave') issave: number;
583  controllerShow: webview.WebviewController = new webview.WebviewController();
584  private context = getContext(this);
585  noteDataDeleteDialogCtl: CustomDialogController | null = new CustomDialogController({
586    builder: DeleteDialog({
587      onConfirm: () => {
588        this.onDeleteConfirm();
589      }
590    }),
591    alignment: DialogAlignment.Center,
592    autoCancel: false,
593    customStyle: true,
594  });
595  @Consume('AsideWidth') asideWidth: number;
596
597  aboutToDisappear() {
598    this.noteDataDeleteDialogCtl = null;
599    this.editContentDialogCtl = null;
600  }
601
602  onDeleteConfirm() {
603    try {
604      if (this.selectedFolderData.uuid != SysDefFolderUuid.RecentDeletes) {
605        this.selectedNoteData.is_deleted = Delete.Yes;
606        this.selectedNoteData.deleted_time = new Date().getTime();
607        // update note to db
608        let predicatesNote = RdbStoreUtil.getRdbPredicates(TableName.NoteTable);
609        predicatesNote.equalTo(NoteTableColumn.Uuid, this.selectedNoteData.uuid);
610        RdbStoreUtil.update(this.selectedNoteData.toNoteObject(), predicatesNote, null);
611      } else {
612        NoteUtil.removeNoteData(this.AllNoteArray, this.selectedNoteData.uuid);
613        // delete note from db
614        let predicatesNote = RdbStoreUtil.getRdbPredicates(TableName.NoteTable);
615        predicatesNote.equalTo(NoteTableColumn.Uuid, this.selectedNoteData.uuid);
616        RdbStoreUtil.delete(predicatesNote, null);
617      }
618      this.refreshFlag = (this.refreshFlag == 0 ? 1 : 0);
619      this.selectedNoteData = NoteUtil.getFirstNoteData(AppStorage.Get('AllNoteArray')!, this.selectedFolderData.uuid)!;
620      try {
621        this.controllerShow.runJavaScript("RICH_EDITOR.setHtml('" + this.selectedNoteData.content_text! + "')");
622      } catch (error) {
623        LogUtil.info(TAG, `setHtml error. code:${JSON.stringify(error.code)},message:${error.message}`);
624      }
625      this.chooseNote = false;
626      // save continue data
627      let continueNote: string = JSON.stringify(this.selectedNoteData.toNoteObject());
628      AppStorage.SetOrCreate<string>('ContinueNote', continueNote);
629      LogUtil.info(TAG, 'NoteContentOverViewComp, set continue note success');
630      AppStorage.SetOrCreate('isUpdate', true);
631    } catch (error) {
632      LogUtil.error(TAG, 'onDeleteConfirm error: ' + JSON.stringify(error));
633    }
634  }
635
636  editContentDialogCtl: CustomDialogController | null = new CustomDialogController({
637    builder: EditContentDialog({
638      confirm: (newTitle: string) => {
639        this.confirm(newTitle);
640      }
641    }),
642    alignment: DialogAlignment.Bottom,
643    autoCancel: true,
644    customStyle: true,
645  })
646
647  confirm(excuteJs: string) {
648    this.controllerShow.runJavaScript(excuteJs);
649  }
650
651  build() {
652    Flex({
653      direction: FlexDirection.Row,
654      wrap: FlexWrap.NoWrap,
655      justifyContent: FlexAlign.SpaceBetween,
656      alignItems: ItemAlign.Center
657    }) {
658      Image(this.sectionStatus == 1 ? $r('app.media.narrow') : $r('app.media.zoom'))
659        .height(24)
660        .width(24)
661        .onClick(() => {
662          try {
663            if (this.sectionStatus != 1) {
664              this.lastSectionStatus = this.sectionStatus;
665              this.sectionStatus = 1;
666              this.asideWidth = 0;
667              this.controllerShow.runJavaScript('RICH_EDITOR.setInputEnabled(true)');
668            } else {
669              if (this.lastSectionStatus != undefined) {
670                this.asideWidth = 200;
671                // 切换为小屏预览模式
672                this.controllerShow.runJavaScript('RICH_EDITOR.setInputEnabled(false)');
673                this.sectionStatus = this.lastSectionStatus;
674                // 退出全屏时存库
675                LogUtil.info(TAG, 'close note' + this.selectedNoteData.uuid);
676                this.controllerShow.runJavaScript('saveHtmlContent()');
677                //退出键盘
678                inputMethod.getController().stopInputSession();
679                // 清除定时器
680                if (timeId != undefined) {
681                  LogUtil.info(TAG, 'zoom, clearInterval timeId : ' + timeId);
682                  clearInterval(timeId);
683                }
684              } else {
685                this.sectionStatus = 3;
686              }
687            }
688            this.editModel = !this.editModel;
689            // save continue data
690            AppStorage.SetOrCreate<number>('ContinueSection', this.sectionStatus);
691            LogUtil.info(TAG, 'ToolBarComp, set continue section success');
692            NoteUtil.refreshAll();
693          } catch (error) {
694            LogUtil.error(TAG,
695              `Image ${this.sectionStatus == 1 ? 'narrow' : 'zoom'} click failed.code:${JSON.stringify(error.code)},
696            message:${JSON.stringify(error.message)}`);
697          }
698        })
699        .visibility(!this.selectedNoteData ? Visibility.None :
700          this.selectedNoteData.is_deleted == Delete.Yes ? Visibility.None : Visibility.Visible)
701
702      if (this.selectedNoteData) {
703        if (this.selectedNoteData.is_deleted == Delete.Yes) {
704          Row({ space: StyleConstants.SPACE_24 }) {
705            Image($r('app.media.delete'))
706              .height(24)
707              .width(24)
708              .onClick(() => {
709                this.noteDataDeleteDialogCtl!.open();
710              })
711            Image($r('app.media.recover'))
712              .height(24)
713              .width(24)
714              .onClick(() => {
715                try {
716                  this.selectedNoteData.is_deleted = Delete.No;
717                  this.selectedNoteData.deleted_time = 0;
718                  let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
719                  let resource: resourceManager.Resource = {
720                    bundleName: 'com.ohos.note',
721                    moduleName: 'default',
722                    id: $r('app.string.restore').id
723                  };
724                  context.resourceManager.getStringValue(resource, (error: BusinessError, value: string) => {
725                    if (error != null) {
726                      LogUtil.error(TAG, 'error is ' + error);
727                    } else {
728                      promptAction.showToast({ message: value, duration: 2000 });
729                    }
730                  });
731                  this.refreshFlag = (this.refreshFlag == 0 ? 1 : 0);
732                  this.chooseNote = false;
733                  // update note to db
734                  let predicatesNote = RdbStoreUtil.getRdbPredicates(TableName.NoteTable);
735                  predicatesNote.equalTo(NoteTableColumn.Uuid, this.selectedNoteData.uuid);
736                  RdbStoreUtil.update(this.selectedNoteData.toNoteObject(), predicatesNote, null);
737
738                  this.selectedNoteData =
739                    NoteUtil.getFirstNoteData(AppStorage.Get('AllNoteArray')!, this.selectedFolderData.uuid)!;
740                  this.controllerShow.runJavaScript(
741                    "RICH_EDITOR.setHtml('" + this.selectedNoteData!.content_text + "')"
742                  )
743                  // save continue data
744                  let continueNote: string = JSON.stringify(this.selectedNoteData.toNoteObject());
745                  AppStorage.SetOrCreate<string>('ContinueNote', continueNote);
746                  LogUtil.info(TAG, 'recover, set continue note success');
747                  NoteUtil.refreshAll();
748                } catch (error) {
749                  LogUtil.error(TAG,
750                    `recover failed.code:${JSON.stringify(error.code)}, message:${JSON.stringify(error.message)}`);
751                }
752              })
753          }.width(72)
754        } else if (this.editModel == true) {
755          Row({ space: StyleConstants.SPACE_6 }) {
756            Button({ type: ButtonType.Normal, stateEffect: true }) {
757              Image($r('app.media.circle_tick1'))
758                .height(24)
759                .width(24)
760                .onClick(() => {
761                  try {
762                    // 清单
763                    this.controllerShow.runJavaScript('javascript:RICH_EDITOR.setTodo()');
764                    // 退出键盘
765                    inputMethod.getController().stopInputSession();
766                  } catch (error) {
767                    LogUtil.error(TAG, `Image circle_tick1 click failed.code:${JSON.stringify(error.code)},
768                    message:${JSON.stringify(error.message)}`);
769                  }
770                })
771            }.width(42)
772            .height(42)
773            .borderRadius(8)
774            .backgroundColor($r('app.color.color_fffffB'))
775
776            Button({ type: ButtonType.Normal, stateEffect: true }) {
777              Image($r('app.media.styles'))
778                .height(24)
779                .width(24)
780                .onClick(() => {
781                  // 退出键盘
782                  inputMethod.getController().stopInputSession();
783                  this.editContentDialogCtl!.open();
784                })
785            }.width(42)
786            .height(42)
787            .borderRadius(8)
788            .backgroundColor($r('app.color.color_fffffB'))
789
790            Button({ type: ButtonType.Normal, stateEffect: true }) {
791              Image($r('app.media.picture_white'))
792                .height(24)
793                .width(24)
794                .onClick(async () => {
795                  let permissionList: Permissions[] = [
796                    'ohos.permission.READ_MEDIA',
797                    'ohos.permission.WRITE_MEDIA',
798                  ];
799                  let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
800                  let AtManager = abilityAccessCtrl.createAtManager();
801                  await AtManager.requestPermissionsFromUser(context, permissionList).then((data) => {
802                    LogUtil.info(TAG, 'data permissions : ' + data.permissions);
803                    LogUtil.info(TAG, 'data result: ' + data.authResults);
804                    let sum = 0;
805                    for (let i = 0; i < data.authResults.length; i++) {
806                      sum += data.authResults[i];
807                    }
808                    LogUtil.info(TAG, 'request permissions sum: ' + sum);
809                  }).catch((err: BusinessError) => {
810                    LogUtil.warn(TAG, 'failed to requestPermissionsFromUser : ' + err.code);
811                  })
812                  // 退出键盘
813                  inputMethod.getController().stopInputSession();
814                  LogUtil.info(TAG, 'startAbility start');
815                  await noteContext.startAbilityForResult({
816                    parameters: { uri: 'singleselect' },
817                    bundleName: 'com.ohos.photos',
818                    abilityName: 'com.ohos.photos.MainAbility',
819                  })
820                    .then((v: common.AbilityResult) => {
821                      try {
822                        let want = v['want'];
823                        if (want != null && want != undefined) {
824                          let param = want['parameters'];
825                          let imageUri = "";
826                          if (param != null && param != undefined) {
827                            let uri = param['select-item-list'];
828                            imageUri = uri as string;
829                          }
830                          // 拷贝
831                          if (imageUri != null && imageUri != "") {
832                            OperationUtils.copy(imageUri).then((uriPath) => {
833                              let path = 'file://' + uriPath;
834                              LogUtil.info(TAG, 'image uri is:' + path);
835                              this.controllerShow.runJavaScript(
836                                "javascript:RICH_EDITOR.insertImage('" + path + "')"
837                              );
838                              this.issave = 1;
839                              // 保存笔记信息到数据库
840                              this.controllerShow.runJavaScript('getHtmlContent()');
841                            })
842                          }
843                        }
844                        NoteUtil.refreshAll();
845                      } catch (error) {
846                        LogUtil.error(TAG, `startAbilityForResult failed.code:${JSON.stringify(error.code)},
847                        message:${JSON.stringify(error.message)}`);
848                      }
849                    });
850                })
851            }.width(42)
852            .height(42)
853            .borderRadius(8)
854            .backgroundColor($r('app.color.color_fffffB'))
855
856            Button({ type: ButtonType.Normal, stateEffect: true }) {
857              Image($r('app.media.undo'))
858                .height(24)
859                .width(24)
860                .onClick(() => {
861                  try {
862                    // 退出键盘
863                    inputMethod.getController().stopInputSession();
864                    this.controllerShow.runJavaScript('RICH_EDITOR.undo()');
865                  } catch (error) {
866                    LogUtil.error(TAG, `Image undo click failed.code:${JSON.stringify(error.code)},
867                    message:${JSON.stringify(error.message)}`);
868                  }
869                })
870            }.width(42)
871            .height(42)
872            .borderRadius(8)
873            .backgroundColor($r('app.color.color_fffffB'))
874
875            Button({ type: ButtonType.Normal, stateEffect: true }) {
876              Image($r('app.media.todo'))
877                .height(24)
878                .width(24)
879                .onClick(() => {
880                  try {
881                    // 退出键盘
882                    inputMethod.getController().stopInputSession();
883                    this.controllerShow.runJavaScript('RICH_EDITOR.redo()');
884                  } catch (error) {
885                    LogUtil.error(TAG, `Image todo click failed.code:${JSON.stringify(error.code)},
886                    message:${JSON.stringify(error.message)}`);
887                  }
888                })
889            }.width(42)
890            .height(42)
891            .borderRadius(8)
892            .backgroundColor($r('app.color.color_fffffB'))
893
894
895            Button({ type: ButtonType.Normal, stateEffect: true }) {
896              Image($r('app.media.tick_thin'))
897                .height(24)
898                .width(24)
899                .fillColor(this.issave == 0 ? Color.Black : Color.Grey)
900                .onClick(() => {
901                  try {
902                    // 保存笔记信息到数据库
903                    this.controllerShow.runJavaScript('getHtmlContent()');
904                    this.controllerShow.runJavaScript('javascript:RICH_EDITOR.getBlur()');
905                    if (this.selectedNoteData.title == '标题' && this.selectedNoteData.content_text == "") {
906                      LogUtil.info(TAG, 'note is empty,save note failed');
907                    }
908                    this.issave = 1;
909                  } catch (error) {
910                    LogUtil.error(TAG, `Image tick_thin click failed.code:${JSON.stringify(error.code)},
911                    message:${JSON.stringify(error.message)}`);
912                  }
913                })
914            }.width(42)
915            .height(42)
916            .borderRadius(8)
917            .backgroundColor($r('app.color.color_fffffB'))
918          }.width(274)
919        } else {
920          Row({ space: StyleConstants.SPACE_24 }) {
921            Image(this.selectedNoteData.is_favorite == Favorite.Yes ? $r('app.media.favorite') :
922            $r('app.media.favorite_cancel'))
923              .height(24)
924              .width(24)
925              .onClick(() => {
926                try {
927                  this.selectedNoteData.is_favorite =
928                    (this.selectedNoteData.is_favorite == Favorite.Yes ? Favorite.No : Favorite.Yes);
929                  this.refreshFlag = (this.refreshFlag == 0 ? 1 : 0);
930                  // update note to db
931                  let predicatesNote = RdbStoreUtil.getRdbPredicates(TableName.NoteTable);
932                  predicatesNote.equalTo(NoteTableColumn.Uuid, this.selectedNoteData.uuid);
933                  RdbStoreUtil.update(this.selectedNoteData.toNoteObject(), predicatesNote, null);
934                  if (this.selectedFolderData.uuid === SysDefFolderUuid.MyFavorites) {
935                    this.selectedNoteData =
936                      NoteUtil.getFirstNoteData(AppStorage.Get('AllNoteArray')!, SysDefFolderUuid.MyFavorites)!;
937                    try {
938                      this.controllerShow.runJavaScript(
939                        "RICH_EDITOR.setHtml('" + this.selectedNoteData.content_text + "')"
940                      );
941                      LogUtil.info(TAG, `setHtml success`);
942                    } catch (error) {
943                      LogUtil.error(TAG, `setHtml failed.code:${JSON.stringify(error.code)},
944                        message:${JSON.stringify(error.message)}`);
945                    }
946                    // save continue data
947                    let continueNote: string = JSON.stringify(this.selectedNoteData.toNoteObject());
948                    AppStorage.SetOrCreate<string>('ContinueNote', continueNote);
949                    LogUtil.info(TAG, 'ToolBarComp, set continue note success');
950                  }
951                  NoteUtil.refreshAll();
952                } catch (error) {
953                  LogUtil.error(TAG, 'favorite error: ' + JSON.stringify(error));
954                }
955              })
956            Image($r('app.media.delete'))
957              .height(24)
958              .width(24)
959              .onClick(() => {
960                this.noteDataDeleteDialogCtl!.open();
961              })
962          }.width(72)
963        }
964      }
965    }
966    .width(StyleConstants.PERCENTAGE_100)
967    .height(80)
968  }
969}
970
971@Component
972struct NoteDataMoveItemCompTablet {
973  @StorageLink('CheckedNoteArray') CheckedNoteArray: NoteData[] = [];
974  @StorageLink('AllFolderArray') AllFolderArray: FolderData[] = [];
975  @StorageLink('isUpdate') isUpdate: boolean = false;
976  folderItem: FolderData =
977    new FolderData(0, '', new Date().getTime() + '', '', FolderType.CusDef, Delete.No, new Date().getTime(),
978      new Date().getTime());
979  uuid: string = '';
980
981  build() {
982    Flex({ alignItems: ItemAlign.Center, wrap: FlexWrap.NoWrap, justifyContent: FlexAlign.Center }) {
983      Flex({ alignItems: ItemAlign.Center, wrap: FlexWrap.NoWrap }) {
984        Image(FolderUtil.getFolderIcon(this.folderItem.uuid))
985          .id(this.isUpdate + '')
986          .objectFit(ImageFit.Fill)
987          .width(24)
988          .height(24)
989          .flexShrink(0)
990          .fillColor(FolderUtil.getFolderIconColor(this.AllFolderArray, this.folderItem.uuid,
991            this.folderItem.uuid == this.uuid))
992      }
993      .width(24)
994
995      Column() {
996        Flex({ alignItems: ItemAlign.Center, wrap: FlexWrap.NoWrap, justifyContent: FlexAlign.SpaceBetween }) {
997          Text(FolderUtil.getFolderText(this.folderItem))
998            .id(this.isUpdate + '')
999            .padding({ top: 3 })
1000            .fontSize(16)
1001            .fontColor(FolderUtil.getFolderIconColor(this.AllFolderArray,
1002              this.folderItem.uuid == this.uuid ? this.folderItem.uuid : '', this.folderItem.uuid == this.uuid))
1003            .textAlign(TextAlign.Center)
1004            .maxLines(1)
1005            .textOverflow({ overflow: TextOverflow.Ellipsis })
1006            .flexShrink(1)
1007        }
1008        .width('100%')
1009        .height(55)
1010
1011        if (this.folderItem.uuid != SysDefFolderUuid.UnClassified) {
1012          Divider()
1013            .color($r('app.color.divider_color_e4e4e4'))
1014            .strokeWidth(1)
1015        }
1016      }
1017      .padding({ left: 16 })
1018    }
1019    .id(this.isUpdate + '')
1020    .width('100%')
1021    .height(56)
1022    .visibility(FolderUtil.isFolderMoveIn(this.folderItem) ? Visibility.Visible : Visibility.None)
1023  }
1024}
1025