Работа над ServerStorage - профили
This commit is contained in:
@@ -13,7 +13,14 @@ import readerApi from '../../../api/reader';
|
|||||||
import * as utils from '../../../share/utils';
|
import * as utils from '../../../share/utils';
|
||||||
import * as cryptoUtils from '../../../share/cryptoUtils';
|
import * as cryptoUtils from '../../../share/cryptoUtils';
|
||||||
|
|
||||||
|
const maxSetTries = 5;
|
||||||
|
|
||||||
export default @Component({
|
export default @Component({
|
||||||
|
watch: {
|
||||||
|
profiles: function() {
|
||||||
|
this.saveProfiles();
|
||||||
|
},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
class ServerStorage extends Vue {
|
class ServerStorage extends Vue {
|
||||||
created() {
|
created() {
|
||||||
@@ -27,9 +34,7 @@ class ServerStorage extends Vue {
|
|||||||
}
|
}
|
||||||
this.hashedStorageKey = utils.toBase58(await cryptoUtils.sha256(this.serverStorageKey));
|
this.hashedStorageKey = utils.toBase58(await cryptoUtils.sha256(this.serverStorageKey));
|
||||||
|
|
||||||
//console.log(await this.storageSet({'id1': {rev: 1, data: {test: 123}}}));
|
await this.loadProfiles();
|
||||||
//console.log(await this.storageGet({'id1': {}}));
|
|
||||||
//console.log(await this.storageCheck({'id1': {rev: 1, data: {test: 123}}}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get settings() {
|
get settings() {
|
||||||
@@ -40,6 +45,73 @@ class ServerStorage extends Vue {
|
|||||||
return this.$store.state.reader.serverStorageKey;
|
return this.$store.state.reader.serverStorageKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get profiles() {
|
||||||
|
return this.$store.state.reader.profiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
get profilesRev() {
|
||||||
|
return this.$store.state.reader.profilesRev;
|
||||||
|
}
|
||||||
|
|
||||||
|
notifySuccessIfNeeded(rev1, rev2) {
|
||||||
|
if (rev1 != rev2)
|
||||||
|
this.$notify.success({message: 'Данные синхронизированы с сервером'});
|
||||||
|
}
|
||||||
|
|
||||||
|
warning(message) {
|
||||||
|
this.$notify.warning({message});
|
||||||
|
}
|
||||||
|
|
||||||
|
error(message) {
|
||||||
|
this.$notify.error({message});
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadProfiles() {
|
||||||
|
let prof = await this.storageGet({'profiles': {}});
|
||||||
|
|
||||||
|
if (prof.state == 'success') {
|
||||||
|
const oldRev = this.profilesRev;
|
||||||
|
prof = prof.items.profiles;
|
||||||
|
this.commit('reader/setProfiles', prof.data);
|
||||||
|
this.commit('reader/setProfilesRev', prof.rev);
|
||||||
|
|
||||||
|
this.oldProfiles = this.profiles;
|
||||||
|
this.notifySuccessIfNeeded(oldRev, prof.rev);
|
||||||
|
} else {
|
||||||
|
this.warning(`Неверный ответ сервера: ${prof.state}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async saveProfiles() {
|
||||||
|
if (!this.savingProfiles) {
|
||||||
|
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 (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);
|
||||||
|
}
|
||||||
|
|
||||||
|
tries++;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.commit('reader/setProfilesRev', this.profilesRev + 1);
|
||||||
|
|
||||||
|
if (tries >= maxSetTries) {
|
||||||
|
throw new Error('Не удалось отправить данные на сервер');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.savingProfiles = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
generateNewServerStorageKey() {
|
generateNewServerStorageKey() {
|
||||||
const key = utils.toBase58(utils.randomArray(32));
|
const key = utils.toBase58(utils.randomArray(32));
|
||||||
this.commit('reader/setServerStorageKey', key);
|
this.commit('reader/setServerStorageKey', key);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import _ from 'lodash';
|
||||||
import baseX from 'base-x';
|
import baseX from 'base-x';
|
||||||
import PAKO from 'pako';
|
import PAKO from 'pako';
|
||||||
import {Buffer} from 'safe-buffer';
|
import {Buffer} from 'safe-buffer';
|
||||||
@@ -92,3 +93,67 @@ export function toBase64(data) {
|
|||||||
export function fromBase64(data) {
|
export function fromBase64(data) {
|
||||||
return bs64.decode(data);
|
return bs64.decode(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getObjDiff(oldObj, newObj) {
|
||||||
|
const result = {__isDiff: true, change: {}, add: {}, del: []};
|
||||||
|
|
||||||
|
for (const key of Object.keys(oldObj)) {
|
||||||
|
if (newObj.hasOwnProperty(key)) {
|
||||||
|
if (!_.isEqual(oldObj[key], newObj[key])) {
|
||||||
|
if (_.isObject(oldObj[key]) && _.isObject(newObj[key])) {
|
||||||
|
result.change[key] = getObjDiff(oldObj[key], newObj[key]);
|
||||||
|
} else {
|
||||||
|
result.change[key] = _.cloneDeep(newObj[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.del.push(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const key of Object.keys(newObj)) {
|
||||||
|
if (!oldObj.hasOwnProperty(key)) {
|
||||||
|
result.add[key] = _.cloneDeep(newObj[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isEmptyObjDiff(diff) {
|
||||||
|
return (!_.isObject(diff) || !diff.__isDiff ||
|
||||||
|
(!Object.keys(diff.change).length &&
|
||||||
|
!Object.keys(diff.add).length &&
|
||||||
|
!diff.del.length
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function applyObjDiff(obj, diff, isAddChanged) {
|
||||||
|
const result = _.cloneDeep(obj);
|
||||||
|
if (!diff.__isDiff)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
const change = diff.change;
|
||||||
|
for (const key of Object.keys(change)) {
|
||||||
|
if (result.hasOwnProperty(key)) {
|
||||||
|
if (_.isObject(change[key])) {
|
||||||
|
result[key] = applyObjDiff(result[key], change[key], isAddChanged);
|
||||||
|
} else {
|
||||||
|
result[key] = _.cloneDeep(change[key]);
|
||||||
|
}
|
||||||
|
} else if (isAddChanged) {
|
||||||
|
result[key] = _.cloneDeep(change[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const key of Object.keys(diff.add)) {
|
||||||
|
result[key] = _.cloneDeep(diff.add[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const key of diff.del) {
|
||||||
|
delete result[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
@@ -123,50 +123,50 @@ const webFonts = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const settingDefaults = {
|
const settingDefaults = {
|
||||||
textColor: '#000000',
|
textColor: '#000000',
|
||||||
backgroundColor: '#EBE2C9',
|
backgroundColor: '#EBE2C9',
|
||||||
wallpaper: '',
|
wallpaper: '',
|
||||||
fontStyle: '',// 'italic'
|
fontStyle: '',// 'italic'
|
||||||
fontWeight: '',// 'bold'
|
fontWeight: '',// 'bold'
|
||||||
fontSize: 20,// px
|
fontSize: 20,// px
|
||||||
fontName: 'ReaderDefault',
|
fontName: 'ReaderDefault',
|
||||||
webFontName: '',
|
webFontName: '',
|
||||||
fontVertShift: 0,
|
fontVertShift: 0,
|
||||||
textVertShift: -20,
|
textVertShift: -20,
|
||||||
|
|
||||||
lineInterval: 3,// px, межстрочный интервал
|
lineInterval: 3,// px, межстрочный интервал
|
||||||
textAlignJustify: true,// выравнивание по ширине
|
textAlignJustify: true,// выравнивание по ширине
|
||||||
p: 25,// px, отступ параграфа
|
p: 25,// px, отступ параграфа
|
||||||
indentLR: 15,// px, отступ всего текста слева и справа
|
indentLR: 15,// px, отступ всего текста слева и справа
|
||||||
indentTB: 0,// px, отступ всего текста сверху и снизу
|
indentTB: 0,// px, отступ всего текста сверху и снизу
|
||||||
wordWrap: true,//перенос по слогам
|
wordWrap: true,//перенос по слогам
|
||||||
keepLastToFirst: true,// перенос последней строки в первую при листании
|
keepLastToFirst: true,// перенос последней строки в первую при листании
|
||||||
|
|
||||||
showStatusBar: true,
|
showStatusBar: true,
|
||||||
statusBarTop: false,// top, bottom
|
statusBarTop: false,// top, bottom
|
||||||
statusBarHeight: 19,// px
|
statusBarHeight: 19,// px
|
||||||
statusBarColorAlpha: 0.4,
|
statusBarColorAlpha: 0.4,
|
||||||
|
|
||||||
scrollingDelay: 3000,// замедление, ms
|
scrollingDelay: 3000,// замедление, ms
|
||||||
scrollingType: 'ease-in-out', //linear, ease, ease-in, ease-out, ease-in-out
|
scrollingType: 'ease-in-out', //linear, ease, ease-in, ease-out, ease-in-out
|
||||||
|
|
||||||
pageChangeAnimation: 'blink',// '' - нет, downShift, rightShift, thaw - протаивание, blink - мерцание
|
pageChangeAnimation: 'blink',// '' - нет, downShift, rightShift, thaw - протаивание, blink - мерцание
|
||||||
pageChangeAnimationSpeed: 80, //0-100%
|
pageChangeAnimationSpeed: 80, //0-100%
|
||||||
|
|
||||||
allowUrlParamBookPos: false,
|
allowUrlParamBookPos: false,
|
||||||
lazyParseEnabled: false,
|
lazyParseEnabled: false,
|
||||||
copyFullText: false,
|
copyFullText: false,
|
||||||
showClickMapPage: true,
|
showClickMapPage: true,
|
||||||
clickControl: true,
|
clickControl: true,
|
||||||
cutEmptyParagraphs: false,
|
cutEmptyParagraphs: false,
|
||||||
addEmptyParagraphs: 0,
|
addEmptyParagraphs: 0,
|
||||||
blinkCachedLoad: true,
|
blinkCachedLoad: true,
|
||||||
showImages: true,
|
showImages: true,
|
||||||
showInlineImagesInCenter: true,
|
showInlineImagesInCenter: true,
|
||||||
imageHeightLines: 100,
|
imageHeightLines: 100,
|
||||||
imageFitWidth: true,
|
imageFitWidth: true,
|
||||||
|
|
||||||
fontShifts: {},
|
fontShifts: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const font of fonts)
|
for (const font of fonts)
|
||||||
@@ -178,6 +178,9 @@ for (const font of webFonts)
|
|||||||
const state = {
|
const state = {
|
||||||
toolBarActive: true,
|
toolBarActive: true,
|
||||||
serverStorageKey: '',
|
serverStorageKey: '',
|
||||||
|
profiles: [],
|
||||||
|
profilesRev: 0,
|
||||||
|
currentProfile: '',
|
||||||
settings: Object.assign({}, settingDefaults),
|
settings: Object.assign({}, settingDefaults),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -195,6 +198,15 @@ const mutations = {
|
|||||||
setServerStorageKey(state, value) {
|
setServerStorageKey(state, value) {
|
||||||
state.serverStorageKey = value;
|
state.serverStorageKey = value;
|
||||||
},
|
},
|
||||||
|
setProfiles(state, value) {
|
||||||
|
state.profiles = value;
|
||||||
|
},
|
||||||
|
setProfilesRev(state, value) {
|
||||||
|
state.profilesRev = value;
|
||||||
|
},
|
||||||
|
setCurrentProfile(state, value) {
|
||||||
|
state.currentProfile = value;
|
||||||
|
},
|
||||||
setSettings(state, value) {
|
setSettings(state, value) {
|
||||||
state.settings = Object.assign({}, state.settings, value);
|
state.settings = Object.assign({}, state.settings, value);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user