فهرست منبع

Перенес управление и хранение recentBooks из vuex в bookManager

Book Pauk 6 سال پیش
والد
کامیت
1ea6fc6926

+ 18 - 9
client/components/Reader/HistoryPage/HistoryPage.vue

@@ -99,26 +99,34 @@ import _ from 'lodash';
 
 
 import {formatDate} from '../../../share/utils';
 import {formatDate} from '../../../share/utils';
 import Window from '../../share/Window.vue';
 import Window from '../../share/Window.vue';
+import bookManager from '../share/bookManager';
 
 
 export default @Component({
 export default @Component({
     components: {
     components: {
         Window,
         Window,
     },
     },
+    watch: {
+        search: function() {
+            this.updateTableData();
+        }
+    },
 })
 })
 class HistoryPage extends Vue {
 class HistoryPage extends Vue {
     search = null;
     search = null;
+    tableData = null;
 
 
     created() {
     created() {
-        this.commit = this.$store.commit;
-        this.reader = this.$store.state.reader;
     }
     }
 
 
-    get tableData() {
-        const state = this.reader;
+    mounted() {
+        this.updateTableData();
+    }
+
+    updateTableData() {
         let result = [];
         let result = [];
 
 
-        for (let bookKey in state.openedBook) {
-            const book = state.openedBook[bookKey];
+        for (let bookKey in bookManager.recent) {
+            const book = bookManager.recent[bookKey];
             let d = new Date();
             let d = new Date();
             d.setTime(book.touchTime);
             d.setTime(book.touchTime);
             const t = formatDate(d).split(' ');
             const t = formatDate(d).split(' ');
@@ -151,7 +159,7 @@ class HistoryPage extends Vue {
         }
         }
 
 
         const search = this.search;
         const search = this.search;
-        return result.filter(item => {
+        this.tableData = result.filter(item => {
             return !search ||
             return !search ||
                 item.touchTime.includes(search) ||
                 item.touchTime.includes(search) ||
                 item.touchDate.includes(search) ||
                 item.touchDate.includes(search) ||
@@ -184,8 +192,9 @@ class HistoryPage extends Vue {
         window.open(path, '_blank');
         window.open(path, '_blank');
     }
     }
 
 
-    handleDel(key) {
-        this.commit('reader/delOpenedBook', {key});
+    async handleDel(key) {
+        await bookManager.delRecentBook({key});
+        this.updateTableData();
     }
     }
 
 
     loadBook(url) {
     loadBook(url) {

+ 27 - 28
client/components/Reader/Reader.vue

@@ -107,7 +107,7 @@ export default @Component({
                 if (textPage.bookPos != newValue) {
                 if (textPage.bookPos != newValue) {
                     textPage.bookPos = newValue;
                     textPage.bookPos = newValue;
                 }
                 }
-                this.debouncedCommitOpenedBook(newValue);
+                this.debouncedSetRecentBook(newValue);
             }
             }
         },
         },
         routeParamPos: function(newValue) {
         routeParamPos: function(newValue) {
@@ -116,7 +116,7 @@ export default @Component({
             }
             }
         },
         },
         routeParamUrl: function(newValue) {
         routeParamUrl: function(newValue) {
-            if (newValue !== '' && newValue !== this.lastOpenedBook.url) {
+            if (newValue !== '' && newValue !== this.mostRecentBook().url) {
                 this.loadBook({url: newValue, bookPos: this.routeParamPos});
                 this.loadBook({url: newValue, bookPos: this.routeParamPos});
             }
             }
         },
         },
@@ -155,9 +155,10 @@ class Reader extends Vue {
             this.updateRoute();
             this.updateRoute();
         }, 1000);
         }, 1000);
 
 
-        this.debouncedCommitOpenedBook = _.debounce((newValue) => {
-            if (this.lastOpenedBook && this.lastOpenedBook.bookPos != newValue) {
-                this.commit('reader/setOpenedBook', Object.assign({}, this.lastOpenedBook, {bookPos: newValue, bookPosSeen: this.bookPosSeen}));
+        this.debouncedSetRecentBook = _.debounce(async(newValue) => {
+            const recent = this.mostRecentBook();
+            if (recent && recent.bookPos != newValue) {
+                await bookManager.setRecentBook(Object.assign({}, recent, {bookPos: newValue, bookPosSeen: this.bookPosSeen}));
             }
             }
         }, 500);
         }, 500);
 
 
@@ -169,14 +170,11 @@ class Reader extends Vue {
     }
     }
 
 
     mounted() {
     mounted() {
-        /*while (this.lastOpenedBook) {
-            this.commit('reader/delOpenedBook', this.lastOpenedBook);
-        }*/
         if (this.$root.rootRoute == '/reader') {
         if (this.$root.rootRoute == '/reader') {
             if (this.routeParamUrl) {
             if (this.routeParamUrl) {
                 this.loadBook({url: this.routeParamUrl, bookPos: this.routeParamPos});
                 this.loadBook({url: this.routeParamUrl, bookPos: this.routeParamPos});
-            } else if (this.lastOpenedBook) {
-                this.loadBook({url: this.lastOpenedBook.url});
+            } else if (this.mostRecentBook()) {
+                this.loadBook({url: this.this.mostRecentBook().url});
             } else {
             } else {
                 this.loaderActive = true;
                 this.loaderActive = true;
             }
             }
@@ -197,10 +195,11 @@ class Reader extends Vue {
 
 
     updateRoute(isNewRoute) {
     updateRoute(isNewRoute) {
         const pos = (this.bookPos != undefined && this.allowUrlParamBookPos ? `__p=${this.bookPos}&` : '');
         const pos = (this.bookPos != undefined && this.allowUrlParamBookPos ? `__p=${this.bookPos}&` : '');
+        const url = (this.mostRecentBook() ? `url=${this.mostRecentBook().url}` : '');        
         if (isNewRoute)
         if (isNewRoute)
-            this.$router.push(`/reader?${pos}url=${this.lastOpenedBook.url}`);
+            this.$router.push(`/reader?${pos}${url}`);
         else
         else
-            this.$router.replace(`/reader?${pos}url=${this.lastOpenedBook.url}`);
+            this.$router.replace(`/reader?${pos}${url}`);
 
 
     }
     }
 
 
@@ -226,8 +225,8 @@ class Reader extends Vue {
         return this.reader.toolBarActive;
         return this.reader.toolBarActive;
     }
     }
 
 
-    get lastOpenedBook() {
-        const result = this.$store.getters['reader/lastOpenedBook'];
+    mostRecentBook() {
+        const result = bookManager.mostRecentBook();
         if (!result)
         if (!result)
             this.closeAllTextPages();
             this.closeAllTextPages();
         return result;
         return result;
@@ -281,13 +280,13 @@ class Reader extends Vue {
 
 
     setPositionToggle() {
     setPositionToggle() {
         this.setPositionActive = !this.setPositionActive;
         this.setPositionActive = !this.setPositionActive;
-        if (this.setPositionActive && this.activePage == 'TextPage' && this.lastOpenedBook) {
+        if (this.setPositionActive && this.activePage == 'TextPage' && this.mostRecentBook()) {
             this.closeAllTextPages();
             this.closeAllTextPages();
             this.setPositionActive = true;
             this.setPositionActive = true;
 
 
             this.$nextTick(() => {
             this.$nextTick(() => {
-                this.$refs.setPositionPage.sliderMax = this.lastOpenedBook.textLength - 1;
-                this.$refs.setPositionPage.sliderValue = this.lastOpenedBook.bookPos;
+                this.$refs.setPositionPage.sliderMax = this.mostRecentBook().textLength - 1;
+                this.$refs.setPositionPage.sliderValue = this.mostRecentBook().bookPos;
             });
             });
         } else {
         } else {
             this.setPositionActive = false;
             this.setPositionActive = false;
@@ -329,7 +328,7 @@ class Reader extends Vue {
     searchToggle() {
     searchToggle() {
         this.searchActive = !this.searchActive;
         this.searchActive = !this.searchActive;
         const page = this.$refs.page;
         const page = this.$refs.page;
-        if (this.searchActive && this.activePage == 'TextPage' && page.parsed && this.lastOpenedBook) {
+        if (this.searchActive && this.activePage == 'TextPage' && page.parsed && this.mostRecentBook()) {
             this.closeAllTextPages();
             this.closeAllTextPages();
             this.searchActive = true;
             this.searchActive = true;
 
 
@@ -383,8 +382,8 @@ class Reader extends Vue {
                 this.historyToggle();
                 this.historyToggle();
                 break;
                 break;
             case 'refresh':
             case 'refresh':
-                if (this.lastOpenedBook) {
-                    this.loadBook({url: this.lastOpenedBook.url, force: true});
+                if (this.mostRecentBook()) {
+                    this.loadBook({url: this.mostRecentBook().url, force: true});
                 }
                 }
                 break;
                 break;
             case 'settings':
             case 'settings':
@@ -413,7 +412,7 @@ class Reader extends Vue {
                 break;
                 break;
         }
         }
 
 
-        if (this.activePage == 'LoaderPage' || !this.lastOpenedBook) {
+        if (this.activePage == 'LoaderPage' || !this.mostRecentBook()) {
             switch (button) {
             switch (button) {
                 case 'undoAction':
                 case 'undoAction':
                 case 'redoAction':
                 case 'redoAction':
@@ -425,7 +424,7 @@ class Reader extends Vue {
                     break;
                     break;
                 case 'history':
                 case 'history':
                 case 'refresh':
                 case 'refresh':
-                    if (!this.lastOpenedBook)
+                    if (!this.mostRecentBook())
                         classResult = classDisabled;
                         classResult = classDisabled;
                     break;
                     break;
             }
             }
@@ -441,7 +440,7 @@ class Reader extends Vue {
             result = 'ProgressPage';
             result = 'ProgressPage';
         else if (this.loaderActive)
         else if (this.loaderActive)
             result = 'LoaderPage';
             result = 'LoaderPage';
-        else if (this.lastOpenedBook)
+        else if (this.mostRecentBook())
             result = 'TextPage';
             result = 'TextPage';
 
 
         if (!result) {
         if (!result) {
@@ -456,7 +455,7 @@ class Reader extends Vue {
         if (this.lastActivePage != result && result == 'TextPage') {
         if (this.lastActivePage != result && result == 'TextPage') {
             //акивируем страницу с текстом
             //акивируем страницу с текстом
             this.$nextTick(async() => {
             this.$nextTick(async() => {
-                const last = this.lastOpenedBook;
+                const last = this.mostRecentBook();
 
 
                 const isParsed = await bookManager.hasBookParsed(last);
                 const isParsed = await bookManager.hasBookParsed(last);
                 if (!isParsed) {
                 if (!isParsed) {
@@ -489,9 +488,9 @@ class Reader extends Vue {
                 progress.show();
                 progress.show();
                 progress.setState({state: 'parse'});
                 progress.setState({state: 'parse'});
 
 
-                // есть ли среди истории OpenedBook
+                // есть ли среди недавних
                 const key = bookManager.keyFromUrl(opts.url);
                 const key = bookManager.keyFromUrl(opts.url);
-                let wasOpened = this.reader.openedBook[key];
+                let wasOpened = bookManager.getRecentBook({key});
                 wasOpened = (wasOpened ? wasOpened : {});
                 wasOpened = (wasOpened ? wasOpened : {});
                 const bookPos = (opts.bookPos !== undefined ? opts.bookPos : wasOpened.bookPos);
                 const bookPos = (opts.bookPos !== undefined ? opts.bookPos : wasOpened.bookPos);
                 const bookPosSeen = (opts.bookPos !== undefined ? opts.bookPos : wasOpened.bookPosSeen);
                 const bookPosSeen = (opts.bookPos !== undefined ? opts.bookPos : wasOpened.bookPosSeen);
@@ -506,7 +505,7 @@ class Reader extends Vue {
 
 
                     // если есть в локальном кеше
                     // если есть в локальном кеше
                     if (bookParsed) {
                     if (bookParsed) {
-                        this.commit('reader/setOpenedBook', Object.assign({bookPos, bookPosSeen}, bookManager.metaOnly(bookParsed)));
+                        await bookManager.setRecentBook(Object.assign({bookPos, bookPosSeen}, bookManager.metaOnly(bookParsed)));
                         this.loaderActive = false;
                         this.loaderActive = false;
                         progress.hide(); this.progressActive = false;
                         progress.hide(); this.progressActive = false;
                         this.blinkCachedLoadMessage();
                         this.blinkCachedLoadMessage();
@@ -545,7 +544,7 @@ class Reader extends Vue {
                 });
                 });
 
 
                 // добавляем в историю
                 // добавляем в историю
-                this.commit('reader/setOpenedBook', Object.assign({bookPos, bookPosSeen}, bookManager.metaOnly(addedBook)));
+                await bookManager.setRecentBook(Object.assign({bookPos, bookPosSeen}, bookManager.metaOnly(addedBook)));
                 this.updateRoute(true);
                 this.updateRoute(true);
 
 
                 this.loaderActive = false;
                 this.loaderActive = false;

+ 83 - 2
client/components/Reader/share/bookManager.js

@@ -13,12 +13,17 @@ const bmDataStore = localForage.createInstance({
     name: 'bmDataStore'
     name: 'bmDataStore'
 });
 });
 
 
+const bmRecentStore = localForage.createInstance({
+    name: 'bmRecentStore'
+});
+
 class BookManager {
 class BookManager {
     async init() {
     async init() {
         this.books = {};
         this.books = {};
+        this.recent = {};
+        this.recentChanged = true;
 
 
-        const len = await bmMetaStore.length();
-
+        let len = await bmMetaStore.length();
         for (let i = 0; i < len; i++) {
         for (let i = 0; i < len; i++) {
             const key = await bmMetaStore.key(i);
             const key = await bmMetaStore.key(i);
             const keySplit = key.split('-');
             const keySplit = key.split('-');
@@ -30,6 +35,13 @@ class BookManager {
             }
             }
         }
         }
 
 
+        len = await bmRecentStore.length();
+        for (let i = 0; i < len; i++) {
+            const key = await bmRecentStore.key(i);
+            let r = await bmRecentStore.getItem(key);
+            this.recent[r.key] = r;
+        }
+
         await this.cleanBooks();
         await this.cleanBooks();
     }
     }
 
 
@@ -142,6 +154,75 @@ class BookManager {
         return utils.stringToHex(url);
         return utils.stringToHex(url);
     }
     }
 
 
+    async setRecentBook(value) {
+        if (!this.recent) 
+            await this.init();
+        const result = Object.assign({}, value, {touchTime: Date.now()});
+        this.recent[result.key] = result;
+
+        await bmRecentStore.setItem(result.key, result);
+        await this.cleanRecentBooks();
+
+        this.recentChanged = true;
+        return result;
+    }
+
+    async getRecentBook(value) {
+        if (!this.recent) 
+            await this.init();
+        return this.recent[value.key];
+    }
+
+    async delRecentBook(value) {
+        if (!this.recent) 
+            await this.init();
+
+        await bmRecentStore.removeItem(value.key);
+        delete this.recent[value.key];
+        this.recentChanged = true;
+    }
+
+    async cleanRecentBooks() {
+        if (!this.recent) 
+            await this.init();
+
+        if (Object.keys(this.recent).length > 3) {
+            let min = Date.now();
+            let found = null;
+            for (let key in this.recent) {
+                const book = this.recent[key];
+                if (book.touchTime < min) {
+                    min = book.touchTime;
+                    found = book;
+                }
+            }
+
+            if (found) {
+                await this.delRecentBook(found);
+                await this.cleanRecentBooks();
+            }
+        }
+    }
+
+    mostRecentBook() {
+        if (!this.recentChanged && this.mostRecentCached) {
+            return this.mostRecentCached;
+        }
+
+        let max = 0;
+        let result = null;
+        for (let key in this.recent) {
+            const book = this.recent[key];
+            if (book.touchTime > max) {
+                max = book.touchTime;
+                result = book;
+            }
+        }
+        this.mostRecentCached = result;
+        this.recentChanged = false;
+        return result;
+    }
+
 }
 }
 
 
 export default new BookManager();
 export default new BookManager();

+ 1 - 45
client/store/modules/reader.js

@@ -168,64 +168,20 @@ for (const font of webFonts)
 // initial state
 // initial state
 const state = {
 const state = {
     toolBarActive: true,
     toolBarActive: true,
-    openedBook: {},
     settings: Object.assign({}, settingDefaults),
     settings: Object.assign({}, settingDefaults),
 };
 };
 
 
 // getters
 // getters
-const getters = {
-    lastOpenedBook: (state) => {
-        let max = 0;
-        let result = null;
-        for (let bookKey in state.openedBook) {
-            const book = state.openedBook[bookKey];
-            if (book.touchTime > max) {
-                max = book.touchTime;
-                result = book;
-            }
-        }
-        return result;
-    },
-};
+const getters = {};
 
 
 // actions
 // actions
 const actions = {};
 const actions = {};
 
 
-function delBook(state, value) {
-    Vue.delete(state.openedBook, value.key);
-}
-
-function cleanBooks(state) {
-    if (Object.keys(state.openedBook).length > 100) {
-        let min = Date.now();
-        let found = null;
-        for (let bookKey in state.openedBook) {
-            const book = state.openedBook[bookKey];
-            if (book.touchTime < min) {
-                min = book.touchTime;
-                found = book;
-            }
-        }
-
-        if (found) {
-            delBook(state, found);
-            cleanBooks(state);
-        }
-    }
-}
-
 // mutations
 // mutations
 const mutations = {
 const mutations = {
     setToolBarActive(state, value) {
     setToolBarActive(state, value) {
         state.toolBarActive = value;
         state.toolBarActive = value;
     },
     },
-    setOpenedBook(state, value) {
-        Vue.set(state.openedBook, value.key, Object.assign({}, value, {touchTime: Date.now()}));
-        cleanBooks(state);
-    },
-    delOpenedBook(state, value) {
-        delBook(state, value);
-    },
     setSettings(state, value) {
     setSettings(state, value) {
         state.settings = Object.assign({}, state.settings, value);
         state.settings = Object.assign({}, state.settings, value);
     }
     }