bookManager.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import localForage from 'localforage';
  2. import * as utils from '../../../share/utils';
  3. import BookParser from './BookParser';
  4. const maxDataSize = 100*1024*1024;//chars, not bytes
  5. class BookManager {
  6. async init() {
  7. this.books = {};
  8. const len = await localForage.length();
  9. for (let i = 0; i < len; i++) {
  10. const key = await localForage.key(i);
  11. const keySplit = key.split('-');
  12. if (keySplit.length == 2 && keySplit[0] == 'bmMeta') {
  13. let meta = await localForage.getItem(key);
  14. this.books[meta.key] = meta;
  15. }
  16. }
  17. await this.cleanBooks();
  18. }
  19. async cleanBooks() {
  20. while (1) {// eslint-disable-line no-constant-condition
  21. let size = 0;
  22. let min = Date.now();
  23. let toDel = null;
  24. for (let key in this.books) {
  25. let book = this.books[key];
  26. size += book.data.length;
  27. if (book.addTime < min) {
  28. toDel = book;
  29. min = book.addTime;
  30. }
  31. }
  32. if (size > maxDataSize && toDel) {
  33. await this.delBook(toDel);
  34. } else {
  35. break;
  36. }
  37. }
  38. }
  39. async addBook(newBook, callback) {
  40. if (!this.books)
  41. await this.init();
  42. let meta = {url: newBook.url, path: newBook.path};
  43. meta.key = this.keyFromUrl(meta.url);
  44. meta.addTime = Date.now();
  45. const result = await this.parseBook(meta, newBook.data, callback);
  46. await localForage.setItem(`bmMeta-${meta.key}`, this.metaOnly(result));
  47. await localForage.setItem(`bmData-${meta.key}`, result.data);
  48. return result;
  49. }
  50. async getBook(meta, callback) {
  51. if (!this.books)
  52. await this.init();
  53. let result = undefined;
  54. if (!meta.key)
  55. meta.key = this.keyFromUrl(meta.url);
  56. result = this.books[meta.key];
  57. if (result && !result.data) {
  58. result.data = await localForage.getItem(`bmData-${meta.key}`);
  59. }
  60. if (result && !result.parsed) {
  61. result = await this.parseBook(result, result.data, callback);
  62. }
  63. return result;
  64. }
  65. async delBook(meta) {
  66. if (!this.books)
  67. await this.init();
  68. await localForage.removeItem(`bmMeta-${meta.key}`);
  69. await localForage.removeItem(`bmData-${meta.key}`);
  70. delete this.books[meta.key];
  71. }
  72. async parseBook(meta, data, callback) {
  73. if (!this.books)
  74. await this.init();
  75. const parsed = new BookParser();
  76. const parsedMeta = await parsed.parse(data, callback);
  77. const result = Object.assign({}, meta, parsedMeta, {data, parsed});
  78. this.books[meta.key] = result;
  79. return result;
  80. }
  81. metaOnly(book) {
  82. let result = Object.assign({}, book);
  83. delete result.data;
  84. delete result.parsed;
  85. return result;
  86. }
  87. keyFromUrl(url) {
  88. return utils.stringToHex(url);
  89. }
  90. }
  91. export default new BookManager();