浏览代码

Добавлена синхронизация файлов обоев

Book Pauk 3 年之前
父节点
当前提交
c7a17b0a76

+ 17 - 3
client/api/reader.js

@@ -174,11 +174,10 @@ class Reader {
         return await axios.get(url, options);
         return await axios.get(url, options);
     }
     }
 
 
-    async uploadFile(file, maxUploadFileSize, callback) {
-        if (!maxUploadFileSize)
-            maxUploadFileSize = 10*1024*1024;
+    async uploadFile(file, maxUploadFileSize = 10*1024*1024, callback) {
         if (file.size > maxUploadFileSize)
         if (file.size > maxUploadFileSize)
             throw new Error(`Размер файла превышает ${maxUploadFileSize} байт`);
             throw new Error(`Размер файла превышает ${maxUploadFileSize} байт`);
+
         let formData = new FormData();
         let formData = new FormData();
         formData.append('file', file, file.name);
         formData.append('file', file, file.name);
 
 
@@ -225,6 +224,21 @@ class Reader {
 
 
         return response;
         return response;
     }
     }
+
+    async uploadFileBuf(buf) {
+        const response = await wsc.message(await wsc.send({action: 'upload-file-buf', buf}));
+
+        if (response.error)
+            throw new Error(response.error);
+
+        return response;
+    }
+
+    async getUploadedFileBuf(url) {
+        url = url.replace('disk://', '/upload/');
+        return (await axios.get(url)).data;
+    }
+
 }
 }
 
 
 export default new Reader();
 export default new Reader();

+ 29 - 4
client/components/Reader/Reader.vue

@@ -450,22 +450,47 @@ class Reader {
 
 
     //wallpaper css
     //wallpaper css
     async loadWallpapers() {
     async loadWallpapers() {
-        const wallpaperDataLength = await wallpaperStorage.getLength();
-        if (wallpaperDataLength !== this.wallpaperDataLength) {//оптимизация
-            this.wallpaperDataLength = wallpaperDataLength;
+        if (!_.isEqual(this.userWallpapers, this.prevUserWallpapers)) {//оптимизация
+            this.prevUserWallpapers = _.cloneDeep(this.userWallpapers);
 
 
             let newCss = '';
             let newCss = '';
+            let updated = false;
+            const wallpaperExists = new Set();
             for (const wp of this.userWallpapers) {
             for (const wp of this.userWallpapers) {
-                const data = await wallpaperStorage.getData(wp.cssClass);
+                wallpaperExists.add(wp.cssClass);
 
 
+                let data = await wallpaperStorage.getData(wp.cssClass);
                 if (!data) {
                 if (!data) {
                     //здесь будем восстанавливать данные с сервера
                     //здесь будем восстанавливать данные с сервера
+                    const url = `disk://${wp.cssClass.replace('user-paper', '')}`;
+                    try {
+                        data = await readerApi.getUploadedFileBuf(url);
+                        await wallpaperStorage.setData(wp.cssClass, data);
+                        updated = true;
+                    } catch (e) {
+                        console.error(e);
+                    }
                 }
                 }
 
 
                 if (data) {
                 if (data) {
                     newCss += `.${wp.cssClass} {background: url(${data}) center; background-size: 100% 100%;}`;                
                     newCss += `.${wp.cssClass} {background: url(${data}) center; background-size: 100% 100%;}`;                
                 }
                 }
             }
             }
+
+            //почистим wallpaperStorage
+            for (const key of await wallpaperStorage.getKeys()) {
+                if (!wallpaperExists.has(key)) {
+                    await wallpaperStorage.removeData(key);
+                }
+            }
+
+            //обновим settings, если загружали обои из /upload/
+            if (updated) {
+                const newSettings = _.cloneDeep(this.settings);
+                newSettings.needUpdateSettingsView = (newSettings.needUpdateSettingsView < 10 ? newSettings.needUpdateSettingsView + 1 : 0);
+                this.commit('reader/setSettings', newSettings);
+            }
+
             dynamicCss.replace('wallpapers', newCss);
             dynamicCss.replace('wallpapers', newCss);
         }
         }
     }
     }

+ 11 - 1
client/components/Reader/SettingsPage/SettingsPage.vue

@@ -124,6 +124,7 @@ import NumInput from '../../share/NumInput.vue';
 import UserHotKeys from './UserHotKeys/UserHotKeys.vue';
 import UserHotKeys from './UserHotKeys/UserHotKeys.vue';
 import wallpaperStorage from '../share/wallpaperStorage';
 import wallpaperStorage from '../share/wallpaperStorage';
 
 
+import readerApi from '../../../api/reader';
 import rstore from '../../../store/modules/reader';
 import rstore from '../../../store/modules/reader';
 import defPalette from './defPalette';
 import defPalette from './defPalette';
 
 
@@ -636,8 +637,17 @@ class SettingsPage {
 
 
                     if (index < 0)
                     if (index < 0)
                         newUserWallpapers.push({label, cssClass});
                         newUserWallpapers.push({label, cssClass});
-                    if (!wallpaperStorage.keyExists(cssClass))
+                    if (!wallpaperStorage.keyExists(cssClass)) {
                         await wallpaperStorage.setData(cssClass, data);
                         await wallpaperStorage.setData(cssClass, data);
+                        //отправим data на сервер в файл `/upload/${key}`
+                        try {
+                            //const res = 
+                            await readerApi.uploadFileBuf(data);
+                            //console.log(res);
+                        } catch (e) {
+                            console.error(e);
+                        }
+                    }
 
 
                     this.userWallpapers = newUserWallpapers;
                     this.userWallpapers = newUserWallpapers;
                     this.wallpaper = cssClass;
                     this.wallpaper = cssClass;

+ 4 - 0
client/components/Reader/share/wallpaperStorage.js

@@ -32,6 +32,10 @@ class WallpaperStorage {
         this.cachedKeys = await wpStore.keys();
         this.cachedKeys = await wpStore.keys();
     }
     }
 
 
+    async getKeys() {
+        return await wpStore.keys();
+    }
+
     keyExists(key) {//не асинхронная
     keyExists(key) {//не асинхронная
         return this.cachedKeys.includes(key);
         return this.cachedKeys.includes(key);
     }
     }

+ 2 - 0
client/store/modules/reader.js

@@ -191,6 +191,8 @@ const settingDefaults = {
 
 
     recentShowSameBook: false,
     recentShowSameBook: false,
     recentSortMethod: '',
     recentSortMethod: '',
+
+    needUpdateSettingsView: 0,
 };
 };
 
 
 for (const font of fonts)
 for (const font of fonts)

+ 15 - 0
server/controllers/WebSocketController.js

@@ -25,6 +25,10 @@ class WebSocketController {
             ws.on('message', (message) => {
             ws.on('message', (message) => {
                 this.onMessage(ws, message.toString());
                 this.onMessage(ws, message.toString());
             });
             });
+
+            ws.on('error', (err) => {
+                log(LM_ERR, err);
+            });
         });
         });
 
 
         setTimeout(() => { this.periodicClean(); }, cleanPeriod);
         setTimeout(() => { this.periodicClean(); }, cleanPeriod);
@@ -70,6 +74,8 @@ class WebSocketController {
                     await this.readerRestoreCachedFile(req, ws); break;
                     await this.readerRestoreCachedFile(req, ws); break;
                 case 'reader-storage':
                 case 'reader-storage':
                     await this.readerStorageDo(req, ws); break;
                     await this.readerStorageDo(req, ws); break;
+                case 'upload-file-buf':
+                    await this.uploadFileBuf(req, ws); break;
 
 
                 default:
                 default:
                     throw new Error(`Action not found: ${req.action}`);
                     throw new Error(`Action not found: ${req.action}`);
@@ -168,6 +174,15 @@ class WebSocketController {
 
 
         this.send(await this.readerStorage.doAction(req.body), req, ws);
         this.send(await this.readerStorage.doAction(req.body), req, ws);
     }
     }
+
+    async uploadFileBuf(req, ws) {
+        if (!req.buf)
+            throw new Error(`key 'buf' is empty`);
+        
+        this.send({url: await this.readerWorker.saveFileBuf(req.buf)}, req, ws);
+    }
+
+
 }
 }
 
 
 module.exports = WebSocketController;
 module.exports = WebSocketController;

+ 13 - 0
server/core/Reader/ReaderWorker.js

@@ -219,6 +219,19 @@ class ReaderWorker {
         return `disk://${hash}`;
         return `disk://${hash}`;
     }
     }
 
 
+    async saveFileBuf(buf) {
+        const hash = await utils.getBufHash(buf, 'sha256', 'hex');
+        const outFilename = `${this.config.uploadDir}/${hash}`;
+
+        if (!await fs.pathExists(outFilename)) {
+            await fs.writeFile(outFilename, buf);
+        } else {
+            await utils.touchFile(outFilename);
+        }
+
+        return `disk://${hash}`;
+    }
+
     async restoreRemoteFile(filename) {
     async restoreRemoteFile(filename) {
         const basename = path.basename(filename);
         const basename = path.basename(filename);
         const targetName = `${this.config.tempPublicDir}/${basename}`;
         const targetName = `${this.config.tempPublicDir}/${basename}`;

+ 7 - 0
server/core/utils.js

@@ -34,6 +34,12 @@ function getFileHash(filename, hashName, enc) {
     });
     });
 }
 }
 
 
+function getBufHash(buf, hashName, enc) {
+    const hash = crypto.createHash(hashName);
+    hash.update(buf);
+    return hash.digest(enc);
+}
+
 function sleep(ms) {
 function sleep(ms) {
     return new Promise(resolve => setTimeout(resolve, ms));
     return new Promise(resolve => setTimeout(resolve, ms));
 }
 }
@@ -129,6 +135,7 @@ module.exports = {
     fromBase36,
     fromBase36,
     bufferRemoveZeroes,
     bufferRemoveZeroes,
     getFileHash,
     getFileHash,
+    getBufHash,
     sleep,
     sleep,
     toUnixTime,
     toUnixTime,
     randomHexString,
     randomHexString,