diff --git a/client/components/Reader/ServerStorage/ServerStorage.vue b/client/components/Reader/ServerStorage/ServerStorage.vue index 07025236..60f6175c 100644 --- a/client/components/Reader/ServerStorage/ServerStorage.vue +++ b/client/components/Reader/ServerStorage/ServerStorage.vue @@ -34,6 +34,7 @@ class ServerStorage extends Vue { } this.hashedStorageKey = utils.toBase58(cryptoUtils.sha256(this.serverStorageKey)); + this.oldProfiles = this.profiles; await this.loadProfiles(); } @@ -79,10 +80,19 @@ class ServerStorage extends Vue { if (prof.state == 'success') { const oldRev = this.profilesRev; prof = prof.items.profiles; + + if (prof.rev == 0) + prof.data = {}; + this.commit('reader/setProfiles', prof.data); this.commit('reader/setProfilesRev', prof.rev); this.oldProfiles = this.profiles; + + if (!this.profiles[this.currentProfile]) { + this.commit('reader/setCurrentProfile', ''); + } + this.notifySuccessIfNeeded(oldRev, prof.rev); } else { this.warning(`Неверный ответ сервера: ${prof.state}`); @@ -93,31 +103,39 @@ class ServerStorage extends Vue { if (!this.currentProfile || this.savingProfiles) return; - this.savingProfiles = true; - const diff = utils.getObjDiff(this.oldProfiles, this.profiles); - let result = {state: ''}; - let tries = 0; - while (result.state != 'success' && tries < maxSetTries) { - result = await this.storageSet({'profiles': {rev: this.profilesRev + 1, data: this.profiles}}); + if (utils.isEmptyObjDiff(diff)) + return; - if (result.state == 'reject') { - await this.loadProfiles(); - const newProfiles = utils.applyObjDiff(this.profiles, diff); - this.commit('reader/setProfiles', newProfiles); - this.commit('reader/setProfilesRev', result.items.profiles.rev); + this.savingProfiles = true; + try { + let result = {state: ''}; + let tries = 0; + while (result.state != 'success' && tries < maxSetTries) { + result = await this.storageSet({'profiles': {rev: this.profilesRev + 1, data: this.profiles}}); + + if (result.state == 'reject') { + await this.loadProfiles(); + const newProfiles = utils.applyObjDiff(this.profiles, diff); + this.commit('reader/setProfiles', newProfiles); + } + + tries++; } - tries++; + if (tries >= maxSetTries) { + this.commit('reader/setProfiles', this.oldProfiles); + if (!this.profiles[this.currentProfile]) { + this.commit('reader/setCurrentProfile', ''); + } + this.warning('Не удалось отправить данные на сервер'); + } else { + this.oldProfiles = this.profiles; + this.commit('reader/setProfilesRev', this.profilesRev + 1); + } + } finally { + this.savingProfiles = false; } - - this.commit('reader/setProfilesRev', this.profilesRev + 1); - - if (tries >= maxSetTries) { - throw new Error('Не удалось отправить данные на сервер'); - } - - this.savingProfiles = false; } generateNewServerStorageKey() { @@ -165,7 +183,7 @@ class ServerStorage extends Vue { const comp = utils.pako.deflate(JSON.stringify(item.data), {level: 1}); let encrypted = null; try { - encrypted = await cryptoUtils.aesEncrypt(comp, this.serverStorageKey); + encrypted = cryptoUtils.aesEncrypt(comp, this.serverStorageKey); } catch (e) { throw new Error('encrypt failed'); } @@ -200,7 +218,7 @@ class ServerStorage extends Vue { const a = utils.fromBase64(item.data.substr(1)); let decrypted = null; try { - decrypted = await cryptoUtils.aesDecrypt(a, this.serverStorageKey); + decrypted = cryptoUtils.aesDecrypt(a, this.serverStorageKey); } catch (e) { throw new Error('decrypt failed'); } diff --git a/client/components/Reader/SettingsPage/SettingsPage.vue b/client/components/Reader/SettingsPage/SettingsPage.vue index 383c1b61..d830e525 100644 --- a/client/components/Reader/SettingsPage/SettingsPage.vue +++ b/client/components/Reader/SettingsPage/SettingsPage.vue @@ -416,6 +416,7 @@ //----------------------------------------------------------------------------- import Vue from 'vue'; import Component from 'vue-class-component'; +//import _ from 'lodash'; import Window from '../../share/Window.vue'; import rstore from '../../../store/modules/reader'; @@ -462,8 +463,6 @@ class SettingsPage extends Vue { webFonts = []; fonts = []; - currentProfile = ''; - created() { this.commit = this.$store.commit; this.reader = this.$store.state.reader; @@ -496,6 +495,14 @@ class SettingsPage extends Vue { return Object.keys(this.profiles); } + get currentProfile() { + return this.$store.state.reader.currentProfile; + } + + set currentProfile(newValue) { + this.commit('reader/setCurrentProfile', newValue); + } + get partialStorageKey() { return this.serverStorageKey.substr(0, 7) + '***'; } @@ -541,9 +548,9 @@ class SettingsPage extends Vue { async setDefaults() { try { if (await this.$confirm('Подтвердите установку настроек по-умолчанию', '', { - confirmButtonText: 'OK', - cancelButtonText: 'Отмена', - type: 'warning' + confirmButtonText: 'OK', + cancelButtonText: 'Отмена', + type: 'warning' })) { this.form = Object.assign({}, rstore.settingDefaults); for (let prop in rstore.settingDefaults) { @@ -557,12 +564,20 @@ class SettingsPage extends Vue { async addProfile() { try { - const result = await this.$prompt('Введите произвольное имя для профиля устройства', '', { - confirmButtonText: 'OK', - cancelButtonText: 'Отмена' + const result = await this.$prompt('Введите произвольное название для профиля устройства', '', { + confirmButtonText: 'OK', + cancelButtonText: 'Отмена', + inputValidator: (str) => { if (str.length > 50) return 'Слишком длинное название'; else return true; }, }); if (result.value) { - + if (this.profiles[result.value]) { + this.$alert('Такой профиль уже существует', 'Ошибка'); + } else { + this.currentProfile = result.value; + await this.$nextTick(); + const newProfiles = Object.assign({}, this.profiles, {[result.value]: 1}); + this.commit('reader/setProfiles', newProfiles); + } } } catch (e) { // diff --git a/client/element.js b/client/element.js index b58fece0..579c2214 100644 --- a/client/element.js +++ b/client/element.js @@ -95,6 +95,9 @@ import './theme/loading.css'; import MessageBox from 'element-ui/lib/message-box'; import './theme/message-box.css'; +//import Message from 'element-ui/lib/message'; +//import './theme/message.css'; + const components = { ElMenu, ElMenuItem, ElButton, ElButtonGroup, ElCheckbox, ElTabs, ElTabPane, ElTooltip, ElCol, ElContainer, ElAside, ElMain, ElHeader, diff --git a/client/store/modules/reader.js b/client/store/modules/reader.js index 34acbd08..a83c2a51 100644 --- a/client/store/modules/reader.js +++ b/client/store/modules/reader.js @@ -178,7 +178,7 @@ for (const font of webFonts) const state = { toolBarActive: true, serverStorageKey: '', - profiles: [], + profiles: {}, profilesRev: 0, currentProfile: '', settings: Object.assign({}, settingDefaults),