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 ohosDataRdb from '@ohos.data.rdb' 18import fileio from '@ohos.fileio' 19import { LogUtil } from './LogUtil' 20import FolderUtil from './FolderUtil' 21import NoteUtil from './NoteUtil' 22import SysDefData from '../model/databaseModel/SysDefData' 23import FolderData from '../model/databaseModel/FolderData' 24import NoteData from '../model/databaseModel/NoteData' 25import { TableSql, TableName, FolderTableColumn, NoteTableColumn, SysDefFolderUuid 26} from '../model/databaseModel/EnumData' 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 ohosDataRdb.getRdbStore(context, SysDefData.dbInfo.db_name, SysDefData.dbInfo.db_verison) 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 ohosDataRdb.getRdbStore(context, SysDefData.dbInfo.db_name, SysDefData.dbInfo.db_verison) 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 ohosDataRdb.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 LogUtil.info(TAG, "folderDataArray[query] : " + folderDataArray.length) 194 // query note 195 let columns_note = [] 196 let predicates_note = new ohosDataRdb.RdbPredicates(TableName.NoteTable) 197 let resultSet_note = await globalThis.rdbStore.query(predicates_note, columns_note) 198 while (resultSet_note.goToNextRow()) { 199 let id = resultSet_note.getLong(resultSet_note.getColumnIndex(NoteTableColumn.Id)) 200 let title = resultSet_note.getString(resultSet_note.getColumnIndex(NoteTableColumn.Title)) 201 let uuid = resultSet_note.getString(resultSet_note.getColumnIndex(NoteTableColumn.Uuid)) 202 let folder_uuid = resultSet_note.getString(resultSet_note.getColumnIndex(NoteTableColumn.FolderUuid)) 203 // 暂时规避备忘录二次打开白屏问题,后续数据库解决 204 let content_text = ''; 205 let content_img = ''; 206 try { 207 content_text = resultSet_note.getString(resultSet_note.getColumnIndex(NoteTableColumn.ContentText)) 208 content_img = resultSet_note.getString(resultSet_note.getColumnIndex(NoteTableColumn.ContentImg)) 209 } catch (err) { 210 LogUtil.error(TAG, "initAppStorage, content_img = error : " + err) 211 } 212 let noteType = resultSet_note.getLong(resultSet_note.getColumnIndex(NoteTableColumn.NoteType)) 213 let is_top = resultSet_note.getLong(resultSet_note.getColumnIndex(NoteTableColumn.IsTop)) 214 let is_favorite = resultSet_note.getLong(resultSet_note.getColumnIndex(NoteTableColumn.IsFavorite)) 215 let is_deleted = resultSet_note.getLong(resultSet_note.getColumnIndex(NoteTableColumn.IsDeleted)) 216 let created_time = resultSet_note.getLong(resultSet_note.getColumnIndex(NoteTableColumn.CreatedTime)) 217 let modified_time = resultSet_note.getLong(resultSet_note.getColumnIndex(NoteTableColumn.ModifiedTime)) 218 let deleted_time = resultSet_note.getLong(resultSet_note.getColumnIndex(NoteTableColumn.DeletedTime)) 219 let slider_value = resultSet_note.getLong(resultSet_note.getColumnIndex(NoteTableColumn.SliderValue)) 220 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) 221 noteDataArray.push(noteData) 222 } 223 LogUtil.info(TAG, "noteDataArray[query] : " + noteDataArray.length) 224 225 AppStorage.SetOrCreate('AllFolderArray', folderDataArray) 226 AppStorage.SetOrCreate('AllNoteArray', noteDataArray) 227 LogUtil.info(TAG, "AppStorage[query] set AllFolderArray and AllNoteArray success") 228 229 // save continue data 230 let isContinue = AppStorage.Get<boolean>('IsContinue'); 231 LogUtil.info(TAG, "initAppStorage, isContinue is " + isContinue) 232 if (isContinue) { 233 let continueNote: string = AppStorage.Get('ContinueNote') 234 let continueSection = AppStorage.Get('ContinueSection') 235 236 let noteObj = JSON.parse(continueNote) 237 let noteData = new NoteData(noteObj.uuid, noteObj.title, noteObj.uuid, noteObj.folder_uuid, 238 noteObj.content_text, noteObj.content_img, noteObj.note_type, noteObj.is_top, noteObj.is_favorite, 239 noteObj.is_deleted, noteObj.created_time, noteObj.modified_time, noteObj.deleted_time, noteObj.slider_value) 240 241 // save img to FileDir 242 LogUtil.info(TAG, "initAppStorage, save img to FileDir") 243 let imgNameArray = this.getImgNameFromHtml(noteData) 244 imgNameArray.forEach((imgName: string) => { 245 this.writeToFileDir(imgName) 246 }) 247 248 // if not exit this note 249 let exist = false 250 let folderUuid = "" 251 for (let note of noteDataArray) { 252 if (noteData.created_time == note.created_time) { 253 exist = true 254 folderUuid = note.folder_uuid 255 break 256 } 257 } 258 LogUtil.info(TAG, "initAppStorage, exist : " + exist) 259 if (!exist) { 260 // 迁移过来的笔记在本地不存在,则保存在未分类文件夹 261 noteData.folder_uuid = SysDefFolderUuid.UnClassified 262 noteDataArray.push(noteData) 263 AppStorage.SetOrCreate('AllNoteArray', noteDataArray) 264 this.insert(TableName.NoteTable, noteData.toNoteObject(), null) 265 AppStorage.SetOrCreate('Folder', FolderUtil.getFolderData(folderDataArray, SysDefFolderUuid.UnClassified)) 266 } else { 267 // 迁移过来的笔记在本地存在,则进行修改 268 for (let i = 0; i < noteDataArray.length; i++) { 269 if (noteData.created_time == noteDataArray[i].created_time) { 270 noteDataArray[i] = noteData 271 LogUtil.info(TAG, "initAppStorage, update noteData in noteDataArray success") 272 break 273 } 274 } 275 let predicates_note = this.getRdbPredicates(TableName.NoteTable) 276 predicates_note.equalTo(NoteTableColumn.CreatedTime, noteData.created_time) 277 this.update(noteData.toNoteObject(), predicates_note, null) 278 AppStorage.SetOrCreate('Folder', FolderUtil.getFolderData(folderDataArray, folderUuid)) 279 } 280 AppStorage.SetOrCreate('Note', noteData) 281 AppStorage.SetOrCreate<string>('ContinueNote', JSON.stringify(noteData.toNoteObject())) 282 AppStorage.SetOrCreate('Section', continueSection) 283 AppStorage.SetOrCreate<NoteData>('NewNote', noteData) 284 } else { 285 LogUtil.info(TAG, "initAppStorage, IsContinue false") 286 AppStorage.SetOrCreate('Folder', AppStorage.Get('AllFolderArray')[0]) 287 let note = NoteUtil.getFirstNoteData(AppStorage.Get('AllNoteArray'), SysDefFolderUuid.AllNotes) 288 AppStorage.SetOrCreate('Note', note) 289 if (note) { 290 AppStorage.SetOrCreate<string>('ContinueNote', JSON.stringify(note.toNoteObject())) 291 } 292 AppStorage.SetOrCreate('Section', 3) 293 } 294 AppStorage.SetOrCreate('DBQueryFinished', 1) 295 LogUtil.info(TAG, "initAppStorage, set DBQueryFinished 1") 296 }) 297 .catch((err) => { 298 LogUtil.error(TAG, "initAppStorage, error : " + err) 299 }) 300 }, 301 302 getImgNameFromHtml(noteData: NoteData): any{ 303 let newModuleName = "file://" + globalThis.noteContext.filesDir 304 let imgNameArray = [] 305 if (noteData.content_text == undefined || noteData.content_text == null || noteData.content_text == "") { 306 LogUtil.info(TAG, "noteData.content_text is null or undefined") 307 return imgNameArray 308 } 309 let base64regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/ 310 let html = "" 311 if (base64regex.test(noteData.content_text)) { 312 html = atob(noteData.content_text) 313 } else { 314 html = noteData.content_text 315 } 316 if (html == undefined || html == null || html == "") { 317 return imgNameArray 318 } 319 let imgReg = /<img[^>]+>/g 320 let srcReg = /src=[\'\"]?([^\'\"]*)[\'\"]?/i 321 let imgArray = html.match(imgReg) 322 if (imgArray != null) { 323 let hasFirstImg: boolean = false 324 for (let i = 0; i < imgArray.length; i++) { 325 let src = imgArray[i].match(srcReg) 326 if (src != null && src.length > 1) { 327 LogUtil.info(TAG, "getImgNameFromHtml, src[1] : " + src[1]) 328 let lastIndex = src[1].lastIndexOf('/') 329 if (lastIndex != -1) { 330 let oldModuleName = src[1].substring(0, lastIndex) 331 let imgName = src[1].substring(lastIndex + 1) 332 noteData.content_text = noteData.content_text.replace(oldModuleName, newModuleName) 333 if (!hasFirstImg) { 334 noteData.content_img = newModuleName + "/" + imgName 335 hasFirstImg = true 336 } 337 imgNameArray.push(imgName) 338 } 339 } 340 } 341 } 342 return imgNameArray 343 }, 344 345 writeToFileDir(fileName: string) { 346 LogUtil.info(TAG, "writeToFileDir fileName : " + fileName) 347 348 let desPath = globalThis.noteContext.filesDir + "/" + fileName 349 LogUtil.info(TAG, "desPath : " + desPath) 350 try { 351 fileio.accessSync(desPath) 352 LogUtil.info(TAG, "desPath has existed, return") 353 return 354 } catch (err) { 355 LogUtil.warn(TAG, "desPath has not existed, need to write") 356 } 357 let srcPath 358 let size 359 try{ 360 srcPath = globalThis.noteContext.distributedFilesDir + "/" + fileName 361 LogUtil.info(TAG, "srcPath : " + srcPath) 362 size = fileio.statSync(srcPath).size 363 LogUtil.info(TAG, "srcPath size : " + size) 364 if (size > FileMaxSize) { 365 LogUtil.warn(TAG, "srcPath size more then FileMaxSize, return") 366 return 367 } 368 } 369 catch (err) { 370 LogUtil.warn(TAG, "desPath has not existed, need to write two") 371 return 372 } 373 374 375 let srcFd 376 try { 377 srcFd = fileio.openSync(srcPath, 0o0) 378 LogUtil.info(TAG, "open srcPath success : " + srcFd) 379 } catch (err) { 380 LogUtil.warn(TAG, "open srcPath failed : " + err) 381 return 382 } 383 384 let desFd 385 try { 386 desFd = fileio.openSync(desPath, 0o2 | 0o100, 0o400 | 0o200 | 0o040 | 0o020) 387 LogUtil.info(TAG, "open desPath success : " + srcFd) 388 } catch (err) { 389 LogUtil.warn(TAG, "open desPath failed : " + err) 390 return 391 } 392 393 let buf = new ArrayBuffer(size) 394 try { 395 let readNum = fileio.readSync(srcFd, buf) 396 LogUtil.info(TAG, "readNum : " + readNum) 397 let writeNum = fileio.writeSync(desFd, buf) 398 LogUtil.info(TAG, "writeNum : " + writeNum) 399 } catch (err) { 400 LogUtil.warn(TAG, "read or write error : " + err) 401 } 402 }, 403 404 /** 405 * insert 406 * @param tableName 407 * @param valueBucket 408 * @param callback 409 */ 410 insert(tableName, valueBucket, callback) { 411 globalThis.rdbStore.insert(tableName, valueBucket).then((rowId) => { 412 LogUtil.info(TAG, "insert success, rowId is " + rowId) 413 if (callback != null) { 414 callback(rowId) 415 } 416 }).catch((err) => { 417 LogUtil.warn(TAG, "insert error : " + err) 418 }) 419 }, 420 421 /** 422 * delete 423 * @param predicates 424 * @param callback 425 */ 426 delete(predicates, callback) { 427 globalThis.rdbStore.delete(predicates).then((affectedRowCount) => { 428 LogUtil.info(TAG, "delete success, affectedRowCount is " + affectedRowCount) 429 if (callback != null) { 430 callback(affectedRowCount) 431 } 432 }).catch((err) => { 433 LogUtil.warn(TAG, "delete error : " + err) 434 }) 435 }, 436 437 /** 438 * update 439 * @param valueBucket 440 * @param predicates 441 * @param callback 442 */ 443 update(valueBucket, predicates, callback) { 444 if (!globalThis.rdbStore) { 445 return; 446 } 447 globalThis.rdbStore.update(valueBucket, predicates).then((affectedRowCount) => { 448 LogUtil.info(TAG, "update success, affectedRowCount is " + affectedRowCount) 449 if (callback != null) { 450 callback(affectedRowCount) 451 } 452 }).catch((err) => { 453 LogUtil.warn(TAG, "update error : " + err) 454 }) 455 }, 456 457 /** 458 * query 459 * @param columns 460 * @param predicates 461 * @param callback 462 */ 463 query(columns, predicates, callback) { 464 globalThis.rdbStore.query(predicates, columns).then((resultSet) => { 465 LogUtil.info(TAG, "query success, row count : " + resultSet.rowCount) 466 if (callback != null) { 467 callback(resultSet) 468 } 469 }).catch((err) => { 470 LogUtil.warn(TAG, "query error : " + err) 471 }) 472 }, 473 474 /** 475 * get RdbPredicates by table name 476 * @param tableName 477 */ 478 getRdbPredicates(tableName) { 479 return new ohosDataRdb.RdbPredicates(tableName) 480 }, 481 482 updataNoteImage(noteData: NoteData): string { 483 let content_img = "" 484 let imgNameArray = this.getImgNameFromHtml(noteData) 485 if (imgNameArray.length == 0) { 486 return content_img 487 } 488 if (imgNameArray[0] == 'shuxue.png' || imgNameArray[0] == 'cake.png') { 489 content_img = "/res/" + imgNameArray[0] 490 } else { 491 content_img = noteData.content_img 492 } 493 LogUtil.info(TAG, "updataNoteImage, content_img : " + content_img) 494 return content_img 495 } 496}