bookManager.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  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.length ? book.length : 0);
  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. this.books[meta.key] = result;
  47. await localForage.setItem(`bmMeta-${meta.key}`, this.metaOnly(result));
  48. await localForage.setItem(`bmData-${meta.key}`, result.data);
  49. return result;
  50. }
  51. hasBookParsed(meta) {
  52. if (!this.books)
  53. return false;
  54. if (!meta.url)
  55. return false;
  56. if (!meta.key)
  57. meta.key = this.keyFromUrl(meta.url);
  58. let book = this.books[meta.key];
  59. return (book && book.parsed);
  60. }
  61. async getBook(meta, callback) {
  62. if (!this.books)
  63. await this.init();
  64. let result = undefined;
  65. if (!meta.key)
  66. meta.key = this.keyFromUrl(meta.url);
  67. result = this.books[meta.key];
  68. if (result && !result.data) {
  69. result.data = await localForage.getItem(`bmData-${meta.key}`);
  70. this.books[meta.key] = result;
  71. }
  72. if (result && !result.parsed) {
  73. result = await this.parseBook(result, result.data, callback);
  74. this.books[meta.key] = result;
  75. }
  76. return result;
  77. }
  78. async delBook(meta) {
  79. if (!this.books)
  80. await this.init();
  81. await localForage.removeItem(`bmMeta-${meta.key}`);
  82. await localForage.removeItem(`bmData-${meta.key}`);
  83. delete this.books[meta.key];
  84. }
  85. async parseBook(meta, data, callback) {
  86. if (!this.books)
  87. await this.init();
  88. const parsed = new BookParser();
  89. const parsedMeta = await parsed.parse(data, callback);
  90. const result = Object.assign({}, meta, parsedMeta, {length: data.length, data, parsed});
  91. return result;
  92. }
  93. metaOnly(book) {
  94. let result = Object.assign({}, book);
  95. delete result.data;
  96. delete result.parsed;
  97. return result;
  98. }
  99. keyFromUrl(url) {
  100. return utils.stringToHex(url);
  101. }
  102. }
  103. export default new BookManager();