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 { atob } from 'js-base64' 17import fileio from '@ohos.fileio' 18import { LogUtil } from './LogUtil' 19import FolderUtil from './FolderUtil' 20import NoteUtil from './NoteUtil' 21import SysDefData from '../model/databaseModel/SysDefData' 22import FolderData from '../model/databaseModel/FolderData' 23import NoteData from '../model/databaseModel/NoteData' 24import { TableSql, TableName, FolderTableColumn, NoteTableColumn, SysDefFolderUuid 25} from '../model/databaseModel/EnumData' 26import relationalStore from '@ohos.data.relationalStore' 27 28const TAG = "RdbStoreUtil" 29 30const FileMaxSize: number = 20 * 1024 * 1024 31 32/** 33 * db instance 34 */ 35 36export default { 37 /** 38 * create db and table 39 */ 40 createRdbStore(context) { 41 relationalStore.getRdbStore(context, SysDefData.dbInfo.db_name) 42 .then(async (store) => { 43 LogUtil.info(TAG, "createRdbStore, store is " + store) 44 globalThis.rdbStore = store 45 // create table 46 await globalThis.rdbStore.executeSql(TableSql.FolderTableSQL, null) 47 await globalThis.rdbStore.executeSql(TableSql.NoteTableSQL, null) 48 await globalThis.rdbStore.executeSql(TableSql.AttachmentTableSQL, null) 49 await globalThis.rdbStore.executeSql(TableSql.FormTableSQL, null) 50 LogUtil.info(TAG, "create table success") 51 // insert system defined folder 52 await globalThis.rdbStore.insert(TableName.FolderTable, SysDefData.sys_def_allNotes) 53 await globalThis.rdbStore.insert(TableName.FolderTable, SysDefData.sys_def_unClassified) 54 await globalThis.rdbStore.insert(TableName.FolderTable, SysDefData.sys_def_myFavorites) 55 await globalThis.rdbStore.insert(TableName.FolderTable, SysDefData.sys_def_recentDeletes) 56 await globalThis.rdbStore.insert(TableName.FolderTable, SysDefData.sys_def_personal) 57 await globalThis.rdbStore.insert(TableName.FolderTable, SysDefData.sys_def_life) 58 await globalThis.rdbStore.insert(TableName.FolderTable, SysDefData.sys_def_work) 59 LogUtil.info(TAG, "insert system defined folder success") 60 // insert system defined note and attachment 61 await globalThis.rdbStore.insert(TableName.NoteTable, SysDefData.sys_def_note1) 62 await globalThis.rdbStore.insert(TableName.NoteTable, SysDefData.sys_def_note2) 63 await globalThis.rdbStore.insert(TableName.NoteTable, SysDefData.sys_def_note3) 64 await globalThis.rdbStore.insert(TableName.NoteTable, SysDefData.sys_def_note4) 65 LogUtil.info(TAG, "insert system defined note and attachment success") 66 67 // add sys-def folder and note to AppStorage 68 let folderDataArray = [] 69 let sysDefFolderArray = [SysDefData.sys_def_allNotes, SysDefData.sys_def_unClassified, 70 SysDefData.sys_def_myFavorites, SysDefData.sys_def_recentDeletes, 71 SysDefData.sys_def_personal, SysDefData.sys_def_life, SysDefData.sys_def_work] 72 sysDefFolderArray.forEach((sysDefFolder) => { 73 let folderData = new FolderData(sysDefFolder.id, sysDefFolder.name, sysDefFolder.uuid, sysDefFolder.color, 74 sysDefFolder.folder_type, sysDefFolder.is_deleted, sysDefFolder.created_time, 75 sysDefFolder.modified_time) 76 folderDataArray.push(folderData) 77 }) 78 LogUtil.info(TAG, "folderDataArray[sysdef] : " + folderDataArray.length) 79 80 let noteDataArray = [] 81 let sysDefNoteArray = [SysDefData.sys_def_note1, SysDefData.sys_def_note2, 82 SysDefData.sys_def_note3, SysDefData.sys_def_note4] 83 sysDefNoteArray.forEach((sysDefNote) => { 84 let noteData = new NoteData(sysDefNote.id, sysDefNote.title, sysDefNote.uuid, sysDefNote.folder_uuid, sysDefNote.content_text, 85 sysDefNote.content_img, sysDefNote.note_type, sysDefNote.is_top, sysDefNote.is_favorite, 86 sysDefNote.is_deleted, sysDefNote.created_time, sysDefNote.modified_time, sysDefNote.deleted_time, sysDefNote.slider_value) 87 noteDataArray.push(noteData) 88 }) 89 LogUtil.info(TAG, "noteDataArray[sysdef] : " + noteDataArray.length) 90 91 AppStorage.SetOrCreate('AllFolderArray', folderDataArray) 92 AppStorage.SetOrCreate('AllNoteArray', noteDataArray) 93 LogUtil.info(TAG, "AppStorage[sysdef] set AllFolderArray and AllNoteArray success") 94 95 // save continue data 96 let isContinue = AppStorage.Get<boolean>('IsContinue'); 97 LogUtil.info(TAG, "createRdbStore, isContinue is " + isContinue) 98 if (isContinue) { 99 let continueNote: string = AppStorage.Get('ContinueNote') 100 let continueSection = AppStorage.Get('ContinueSection') 101 let noteObj = JSON.parse(continueNote) 102 let noteData = new NoteData(noteObj.uuid, noteObj.title, noteObj.uuid, noteObj.folder_uuid, 103 noteObj.content_text, noteObj.content_img, noteObj.note_type, noteObj.is_top, noteObj.is_favorite, 104 noteObj.is_deleted, noteObj.created_time, noteObj.modified_time, noteObj.deleted_time, noteObj.slider_value) 105 106 // save img to FileDir 107 LogUtil.info(TAG, "createRdbStore, save img to FileDir") 108 let imgNameArray = this.getImgNameFromHtml(noteData) 109 imgNameArray.forEach((imgName: string) => { 110 this.writeToFileDir(imgName) 111 }) 112 113 // if not exit this note 114 let exist = false 115 let folderUuid = "" 116 for (let note of noteDataArray) { 117 if (noteData.created_time == note.created_time) { 118 exist = true 119 folderUuid = note.folder_uuid 120 break 121 } 122 } 123 LogUtil.info(TAG, "createRdbStore, exist : " + exist) 124 if (!exist) { 125 // 迁移过来的笔记在本地不存在,则保存在未分类文件夹 126 noteData.folder_uuid = SysDefFolderUuid.UnClassified 127 noteDataArray.push(noteData) 128 AppStorage.SetOrCreate('AllNoteArray', noteDataArray) 129 this.insert(TableName.NoteTable, noteData.toNoteObject(), null) 130 AppStorage.SetOrCreate('Folder', FolderUtil.getFolderData(folderDataArray, SysDefFolderUuid.UnClassified)) 131 } else { 132 // 迁移过来的笔记在本地存在,则进行修改 133 for (let i = 0; i < noteDataArray.length; i++) { 134 if (noteData.created_time == noteDataArray[i].created_time) { 135 noteDataArray[i] = noteData 136 LogUtil.info(TAG, "createRdbStore, update noteData in noteDataArray success") 137 break 138 } 139 } 140 let predicates_note = this.getRdbPredicates(TableName.NoteTable) 141 predicates_note.equalTo(NoteTableColumn.CreatedTime, noteData.created_time) 142 this.update(noteData.toNoteObject(), predicates_note, null) 143 AppStorage.SetOrCreate('Folder', FolderUtil.getFolderData(folderDataArray, folderUuid)) 144 } 145 AppStorage.SetOrCreate('Note', noteData) 146 AppStorage.SetOrCreate<string>('ContinueNote', JSON.stringify(noteData.toNoteObject())) 147 AppStorage.SetOrCreate('Section', continueSection) 148 AppStorage.SetOrCreate<NoteData>('NewNote', noteData) 149 } else { 150 LogUtil.info(TAG, "createRdbStore, IsContinue false") 151 AppStorage.SetOrCreate('Folder', AppStorage.Get('AllFolderArray')[0]) 152 let note = NoteUtil.getFirstNoteData(AppStorage.Get('AllNoteArray'), SysDefFolderUuid.AllNotes) 153 AppStorage.SetOrCreate('Note', note) 154 if (note) { 155 AppStorage.SetOrCreate<string>('ContinueNote', JSON.stringify(note.toNoteObject())) 156 } 157 AppStorage.SetOrCreate('Section', 3) 158 } 159 AppStorage.SetOrCreate('DBQueryFinished', 1) 160 LogUtil.info(TAG, "createRdbStore, set DBQueryFinished 1") 161 }) 162 .catch((err) => { 163 LogUtil.warn(TAG, "createRdbStore, error : " + err) 164 }) 165 }, 166 167 /** 168 * query folders and notes from the database, then save them to the AppStorage. 169 */ 170 initAppStorage(context) { 171 let folderDataArray = [] 172 let noteDataArray = [] 173 relationalStore.getRdbStore(context, SysDefData.dbInfo.db_name) 174 .then(async (store) => { 175 LogUtil.info(TAG, "initAppStorage, store is " + store) 176 globalThis.rdbStore = store 177 // query folder 178 let columns_folder = [] 179 let predicates_folder = new relationalStore.RdbPredicates(TableName.FolderTable) 180 let resultSet_folder = await globalThis.rdbStore.query(predicates_folder, columns_folder) 181 while (resultSet_folder.goToNextRow()) { 182 let id = resultSet_folder.getLong(resultSet_folder.getColumnIndex(FolderTableColumn.Id)) 183 let name = resultSet_folder.getString(resultSet_folder.getColumnIndex(FolderTableColumn.Name)) 184 let uuid = resultSet_folder.getString(resultSet_folder.getColumnIndex(FolderTableColumn.Uuid)) 185 let color = resultSet_folder.getString(resultSet_folder.getColumnIndex(FolderTableColumn.Color)) 186 let folder_type = resultSet_folder.getLong(resultSet_folder.getColumnIndex(FolderTableColumn.FolderType)) 187 let is_deleted = resultSet_folder.getLong(resultSet_folder.getColumnIndex(FolderTableColumn.IsDeleted)) 188 let created_time = resultSet_folder.getLong(resultSet_folder.getColumnIndex(FolderTableColumn.CreatedTime)) 189 let modified_time = resultSet_folder.getLong(resultSet_folder.getColumnIndex(FolderTableColumn.ModifiedTime)) 190 let folderData = new FolderData(id, name, uuid, color, folder_type, is_deleted, created_time, modified_time) 191 folderDataArray.push(folderData) 192 } 193 resultSet_folder.close(); 194 LogUtil.info(TAG, "folderDataArray[query] : " + folderDataArray.length) 195 // query note 196 let columns_note = [] 197 let predicates_note = new relationalStore.RdbPredicates(TableName.NoteTable) 198 let resultSet_note = await globalThis.rdbStore.query(predicates_note, columns_note) 199 while (resultSet_note.goToNextRow()) { 200 let id = resultSet_note.getLong(resultSet_note.getColumnIndex(NoteTableColumn.Id)) 201 let title = resultSet_note.getString(resultSet_note.getColumnIndex(NoteTableColumn.Title)) 202 let uuid = resultSet_note.getString(resultSet_note.getColumnIndex(NoteTableColumn.Uuid)) 203 let folder_uuid = resultSet_note.getString(resultSet_note.getColumnIndex(NoteTableColumn.FolderUuid)) 204 // 暂时规避备忘录二次打开白屏问题,后续数据库解决 205 let content_text = ''; 206 let content_img = ''; 207 try { 208 content_text = resultSet_note.getString(resultSet_note.getColumnIndex(NoteTableColumn.ContentText)) 209 content_img = resultSet_note.getString(resultSet_note.getColumnIndex(NoteTableColumn.ContentImg)) 210 } catch (err) { 211 LogUtil.error(TAG, "initAppStorage, content_img = error : " + err) 212 } 213 let noteType = resultSet_note.getLong(resultSet_note.getColumnIndex(NoteTableColumn.NoteType)) 214 let is_top = resultSet_note.getLong(resultSet_note.getColumnIndex(NoteTableColumn.IsTop)) 215 let is_favorite = resultSet_note.getLong(resultSet_note.getColumnIndex(NoteTableColumn.IsFavorite)) 216 let is_deleted = resultSet_note.getLong(resultSet_note.getColumnIndex(NoteTableColumn.IsDeleted)) 217 let created_time = resultSet_note.getLong(resultSet_note.getColumnIndex(NoteTableColumn.CreatedTime)) 218 let modified_time = resultSet_note.getLong(resultSet_note.getColumnIndex(NoteTableColumn.ModifiedTime)) 219 let deleted_time = resultSet_note.getLong(resultSet_note.getColumnIndex(NoteTableColumn.DeletedTime)) 220 let slider_value = resultSet_note.getLong(resultSet_note.getColumnIndex(NoteTableColumn.SliderValue)) 221 let noteData = new NoteData(id, title, uuid, folder_uuid, content_text, content_img, noteType, is_top, is_favorite, is_deleted, created_time, modified_time, deleted_time, slider_value) 222 noteDataArray.push(noteData) 223 } 224 resultSet_note.close(); 225 LogUtil.info(TAG, "noteDataArray[query] : " + noteDataArray.length) 226 227 AppStorage.SetOrCreate('AllFolderArray', folderDataArray) 228 AppStorage.SetOrCreate('AllNoteArray', noteDataArray) 229 LogUtil.info(TAG, "AppStorage[query] set AllFolderArray and AllNoteArray success") 230 231 // save continue data 232 let isContinue = AppStorage.Get<boolean>('IsContinue'); 233 LogUtil.info(TAG, "initAppStorage, isContinue is " + isContinue) 234 if (isContinue) { 235 let continueNote: string = AppStorage.Get('ContinueNote') 236 let continueSection = AppStorage.Get('ContinueSection') 237 238 let noteObj = JSON.parse(continueNote) 239 let noteData = new NoteData(noteObj.uuid, noteObj.title, noteObj.uuid, noteObj.folder_uuid, 240 noteObj.content_text, noteObj.content_img, noteObj.note_type, noteObj.is_top, noteObj.is_favorite, 241 noteObj.is_deleted, noteObj.created_time, noteObj.modified_time, noteObj.deleted_time, noteObj.slider_value) 242 243 // save img to FileDir 244 LogUtil.info(TAG, "initAppStorage, save img to FileDir") 245 let imgNameArray = this.getImgNameFromHtml(noteData) 246 imgNameArray.forEach((imgName: string) => { 247 this.writeToFileDir(imgName) 248 }) 249 250 // if not exit this note 251 let exist = false 252 let folderUuid = "" 253 for (let note of noteDataArray) { 254 if (noteData.created_time == note.created_time) { 255 exist = true 256 folderUuid = note.folder_uuid 257 break 258 } 259 } 260 LogUtil.info(TAG, "initAppStorage, exist : " + exist) 261 if (!exist) { 262 // 迁移过来的笔记在本地不存在,则保存在未分类文件夹 263 noteData.folder_uuid = SysDefFolderUuid.UnClassified 264 noteDataArray.push(noteData) 265 AppStorage.SetOrCreate('AllNoteArray', noteDataArray) 266 this.insert(TableName.NoteTable, noteData.toNoteObject(), null) 267 AppStorage.SetOrCreate('Folder', FolderUtil.getFolderData(folderDataArray, SysDefFolderUuid.UnClassified)) 268 } else { 269 // 迁移过来的笔记在本地存在,则进行修改 270 for (let i = 0; i < noteDataArray.length; i++) { 271 if (noteData.created_time == noteDataArray[i].created_time) { 272 noteDataArray[i] = noteData 273 LogUtil.info(TAG, "initAppStorage, update noteData in noteDataArray success") 274 break 275 } 276 } 277 let predicates_note = this.getRdbPredicates(TableName.NoteTable) 278 predicates_note.equalTo(NoteTableColumn.CreatedTime, noteData.created_time) 279 this.update(noteData.toNoteObject(), predicates_note, null) 280 AppStorage.SetOrCreate('Folder', FolderUtil.getFolderData(folderDataArray, folderUuid)) 281 } 282 AppStorage.SetOrCreate('Note', noteData) 283 AppStorage.SetOrCreate<string>('ContinueNote', JSON.stringify(noteData.toNoteObject())) 284 AppStorage.SetOrCreate('Section', continueSection) 285 AppStorage.SetOrCreate<NoteData>('NewNote', noteData) 286 } else { 287 LogUtil.info(TAG, "initAppStorage, IsContinue false") 288 AppStorage.SetOrCreate('Folder', AppStorage.Get('AllFolderArray')[0]) 289 let note = NoteUtil.getFirstNoteData(AppStorage.Get('AllNoteArray'), SysDefFolderUuid.AllNotes) 290 AppStorage.SetOrCreate('Note', note) 291 if (note) { 292 AppStorage.SetOrCreate<string>('ContinueNote', JSON.stringify(note.toNoteObject())) 293 } 294 AppStorage.SetOrCreate('Section', 3) 295 } 296 AppStorage.SetOrCreate('DBQueryFinished', 1) 297 LogUtil.info(TAG, "initAppStorage, set DBQueryFinished 1") 298 }) 299 .catch((err) => { 300 LogUtil.error(TAG, "initAppStorage, error : " + err) 301 }) 302 }, 303 304 getImgNameFromHtml(noteData: NoteData): any{ 305 let newModuleName = "file://" + globalThis.noteContext.filesDir 306 let imgNameArray = [] 307 if (noteData.content_text == undefined || noteData.content_text == null || noteData.content_text == "") { 308 LogUtil.info(TAG, "noteData.content_text is null or undefined") 309 return imgNameArray 310 } 311 let base64regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/ 312 let html = "" 313 if (base64regex.test(noteData.content_text)) { 314 html = atob(noteData.content_text) 315 } else { 316 html = noteData.content_text 317 } 318 if (html == undefined || html == null || html == "") { 319 return imgNameArray 320 } 321 let imgReg = /<img[^>]+>/g 322 let srcReg = /src=[\'\"]?([^\'\"]*)[\'\"]?/i 323 let imgArray = html.match(imgReg) 324 if (imgArray != null) { 325 let hasFirstImg: boolean = false 326 for (let i = 0; i < imgArray.length; i++) { 327 let src = imgArray[i].match(srcReg) 328 if (src != null && src.length > 1) { 329 LogUtil.info(TAG, "getImgNameFromHtml, src[1] : " + src[1]) 330 let lastIndex = src[1].lastIndexOf('/') 331 if (lastIndex != -1) { 332 let oldModuleName = src[1].substring(0, lastIndex) 333 let imgName = src[1].substring(lastIndex + 1) 334 noteData.content_text = noteData.content_text.replace(oldModuleName, newModuleName) 335 if (!hasFirstImg) { 336 noteData.content_img = newModuleName + "/" + imgName 337 hasFirstImg = true 338 } 339 imgNameArray.push(imgName) 340 } 341 } 342 } 343 } 344 return imgNameArray 345 }, 346 347 writeToFileDir(fileName: string) { 348 LogUtil.info(TAG, "writeToFileDir fileName : " + fileName) 349 350 let desPath = globalThis.noteContext.filesDir + "/" + fileName 351 LogUtil.info(TAG, "desPath : " + desPath) 352 try { 353 fileio.accessSync(desPath) 354 LogUtil.info(TAG, "desPath has existed, return") 355 return 356 } catch (err) { 357 LogUtil.warn(TAG, "desPath has not existed, need to write") 358 } 359 let srcPath 360 let size 361 try{ 362 srcPath = globalThis.noteContext.distributedFilesDir + "/" + fileName 363 LogUtil.info(TAG, "srcPath : " + srcPath) 364 size = fileio.statSync(srcPath).size 365 LogUtil.info(TAG, "srcPath size : " + size) 366 if (size > FileMaxSize) { 367 LogUtil.warn(TAG, "srcPath size more then FileMaxSize, return") 368 return 369 } 370 } 371 catch (err) { 372 LogUtil.warn(TAG, "desPath has not existed, need to write two") 373 return 374 } 375 376 377 let srcFd 378 try { 379 srcFd = fileio.openSync(srcPath, 0o0) 380 LogUtil.info(TAG, "open srcPath success : " + srcFd) 381 } catch (err) { 382 LogUtil.warn(TAG, "open srcPath failed : " + err) 383 return 384 } 385 386 let desFd 387 try { 388 desFd = fileio.openSync(desPath, 0o2 | 0o100, 0o400 | 0o200 | 0o040 | 0o020) 389 LogUtil.info(TAG, "open desPath success : " + srcFd) 390 } catch (err) { 391 LogUtil.warn(TAG, "open desPath failed : " + err) 392 return 393 } 394 395 let buf = new ArrayBuffer(size) 396 try { 397 let readNum = fileio.readSync(srcFd, buf) 398 LogUtil.info(TAG, "readNum : " + readNum) 399 let writeNum = fileio.writeSync(desFd, buf) 400 LogUtil.info(TAG, "writeNum : " + writeNum) 401 } catch (err) { 402 LogUtil.warn(TAG, "read or write error : " + err) 403 } 404 }, 405 406 /** 407 * insert 408 * @param tableName 409 * @param valueBucket 410 * @param callback 411 */ 412 insert(tableName, valueBucket, callback) { 413 globalThis.rdbStore.insert(tableName, valueBucket).then((rowId) => { 414 LogUtil.info(TAG, "insert success, rowId is " + rowId) 415 if (callback != null) { 416 callback(rowId) 417 } 418 }).catch((err) => { 419 LogUtil.warn(TAG, "insert error : " + err) 420 }) 421 }, 422 423 /** 424 * delete 425 * @param predicates 426 * @param callback 427 */ 428 delete(predicates, callback) { 429 globalThis.rdbStore.delete(predicates).then((affectedRowCount) => { 430 LogUtil.info(TAG, "delete success, affectedRowCount is " + affectedRowCount) 431 if (callback != null) { 432 callback(affectedRowCount) 433 } 434 }).catch((err) => { 435 LogUtil.warn(TAG, "delete error : " + err) 436 }) 437 }, 438 439 /** 440 * update 441 * @param valueBucket 442 * @param predicates 443 * @param callback 444 */ 445 update(valueBucket, predicates, callback) { 446 if (!globalThis.rdbStore) { 447 return; 448 } 449 globalThis.rdbStore.update(valueBucket, predicates).then((affectedRowCount) => { 450 LogUtil.info(TAG, "update success, affectedRowCount is " + affectedRowCount) 451 if (callback != null) { 452 callback(affectedRowCount) 453 } 454 }).catch((err) => { 455 LogUtil.warn(TAG, "update error : " + err) 456 }) 457 }, 458 459 /** 460 * query 461 * @param columns 462 * @param predicates 463 * @param callback 464 */ 465 query(columns, predicates, callback) { 466 globalThis.rdbStore.query(predicates, columns).then((resultSet) => { 467 LogUtil.info(TAG, "query success, row count : " + resultSet.rowCount) 468 if (callback != null) { 469 callback(resultSet) 470 } 471 }).catch((err) => { 472 LogUtil.warn(TAG, "query error : " + err) 473 }) 474 }, 475 476 /** 477 * get RdbPredicates by table name 478 * @param tableName 479 */ 480 getRdbPredicates(tableName) { 481 return new relationalStore.RdbPredicates(tableName) 482 }, 483 484 updataNoteImage(noteData: NoteData): string { 485 let content_img = "" 486 let imgNameArray = this.getImgNameFromHtml(noteData) 487 if (imgNameArray.length == 0) { 488 return content_img 489 } 490 if (imgNameArray[0] == 'shuxue.png' || imgNameArray[0] == 'cake.png') { 491 content_img = "/res/" + imgNameArray[0] 492 } else { 493 content_img = noteData.content_img 494 } 495 LogUtil.info(TAG, "updataNoteImage, content_img : " + content_img) 496 return content_img 497 } 498}