Fixed workspace ID dependency
This commit is contained in:
parent
9596339684
commit
8263e14bcc
@ -14,6 +14,8 @@ import Modal from './Modal';
|
||||
import Notification from './Notification';
|
||||
import SplashScreen from './SplashScreen';
|
||||
import syncSvc from '../services/syncSvc';
|
||||
import networkSvc from '../services/networkSvc';
|
||||
import sponsorSvc from '../services/sponsorSvc';
|
||||
import timeSvc from '../services/timeSvc';
|
||||
import store from '../store';
|
||||
|
||||
@ -77,6 +79,8 @@ export default {
|
||||
created() {
|
||||
syncSvc.init()
|
||||
.then(() => {
|
||||
networkSvc.init();
|
||||
sponsorSvc.init();
|
||||
this.ready = true;
|
||||
});
|
||||
},
|
||||
|
@ -4,7 +4,6 @@ import store from '../store';
|
||||
import welcomeFile from '../data/welcomeFile.md';
|
||||
|
||||
const dbVersion = 1;
|
||||
const dbVersionKey = `${utils.workspaceId}/localDbVersion`;
|
||||
const dbStoreName = 'objects';
|
||||
const exportBackup = utils.queryParams.exportBackup;
|
||||
if (exportBackup) {
|
||||
@ -15,11 +14,18 @@ const deleteMarkerMaxAge = 1000;
|
||||
const checkSponsorshipAfter = (5 * 60 * 1000) + (30 * 1000); // tokenExpirationMargin + 30 sec
|
||||
|
||||
class Connection {
|
||||
constructor(dbName) {
|
||||
constructor() {
|
||||
this.getTxCbs = [];
|
||||
|
||||
// Make the DB name
|
||||
const workspaceId = store.getters['workspace/currentWorkspace'].id;
|
||||
this.dbName = 'stackedit-db';
|
||||
if (workspaceId !== 'main') {
|
||||
this.dbName += `-${workspaceId}`;
|
||||
}
|
||||
|
||||
// Init connection
|
||||
const request = indexedDB.open(dbName, dbVersion);
|
||||
const request = indexedDB.open(this.dbName, dbVersion);
|
||||
|
||||
request.onerror = () => {
|
||||
throw new Error("Can't connect to IndexedDB.");
|
||||
@ -27,7 +33,6 @@ class Connection {
|
||||
|
||||
request.onsuccess = (event) => {
|
||||
this.db = event.target.result;
|
||||
localStorage[dbVersionKey] = this.db.version; // Safari does not support onversionchange
|
||||
this.db.onversionchange = () => window.location.reload();
|
||||
|
||||
this.getTxCbs.forEach(({ onTx, onError }) => this.createTx(onTx, onError));
|
||||
@ -67,11 +72,6 @@ class Connection {
|
||||
return this.getTxCbs.push({ onTx, onError });
|
||||
}
|
||||
|
||||
// If DB version has changed (Safari support)
|
||||
if (parseInt(localStorage[dbVersionKey], 10) !== this.db.version) {
|
||||
return window.location.reload();
|
||||
}
|
||||
|
||||
// Open transaction in read/write will prevent conflict with other tabs
|
||||
const tx = this.db.transaction(this.db.objectStoreNames, 'readwrite');
|
||||
tx.onerror = onError;
|
||||
@ -102,7 +102,7 @@ const localDbSvc = {
|
||||
*/
|
||||
init() {
|
||||
// Create the connection
|
||||
this.connection = new Connection(store.getters['data/dbName']);
|
||||
this.connection = new Connection();
|
||||
|
||||
// Load the DB
|
||||
return localDbSvc.sync()
|
||||
@ -131,7 +131,7 @@ const localDbSvc = {
|
||||
|
||||
// If app was last opened 7 days ago and synchronization is off
|
||||
if (!store.getters['data/loginToken'] &&
|
||||
(utils.lastOpened + utils.cleanTrashAfter < Date.now())
|
||||
(store.getters['workspace/lastFocus'] + utils.cleanTrashAfter < Date.now())
|
||||
) {
|
||||
// Clean files
|
||||
store.getters['file/items']
|
||||
@ -447,7 +447,6 @@ const localDbSvc = {
|
||||
request.onsuccess = resolve;
|
||||
})
|
||||
.then(() => {
|
||||
localStorage.removeItem(dbVersionKey);
|
||||
window.location.reload();
|
||||
}, () => store.dispatch('notification/error', 'Could not delete local database.'));
|
||||
},
|
||||
|
@ -5,8 +5,88 @@ const scriptLoadingPromises = Object.create(null);
|
||||
const oauth2AuthorizationTimeout = 120 * 1000; // 2 minutes
|
||||
const networkTimeout = 30 * 1000; // 30 sec
|
||||
let isConnectionDown = false;
|
||||
const userInactiveAfter = 2 * 60 * 1000; // 2 minutes
|
||||
|
||||
|
||||
export default {
|
||||
init() {
|
||||
// Keep track of the last user activity
|
||||
this.lastActivity = 0;
|
||||
const setLastActivity = () => {
|
||||
this.lastActivity = Date.now();
|
||||
};
|
||||
window.document.addEventListener('mousedown', setLastActivity);
|
||||
window.document.addEventListener('keydown', setLastActivity);
|
||||
window.document.addEventListener('touchstart', setLastActivity);
|
||||
|
||||
// Keep track of the last window focus
|
||||
this.lastFocus = 0;
|
||||
const setLastFocus = () => {
|
||||
this.lastFocus = Date.now();
|
||||
localStorage.setItem(store.getters['workspace/lastFocusKey'], this.lastFocus);
|
||||
setLastActivity();
|
||||
};
|
||||
if (document.hasFocus()) {
|
||||
setLastFocus();
|
||||
}
|
||||
window.addEventListener('focus', setLastFocus);
|
||||
|
||||
// Check browser is online periodically
|
||||
const checkOffline = () => {
|
||||
const isBrowserOffline = window.navigator.onLine === false;
|
||||
if (!isBrowserOffline &&
|
||||
store.state.lastOfflineCheck + networkTimeout + 5000 < Date.now() &&
|
||||
this.isUserActive()
|
||||
) {
|
||||
store.commit('updateLastOfflineCheck');
|
||||
new Promise((resolve, reject) => {
|
||||
const script = document.createElement('script');
|
||||
let timeout;
|
||||
let clean = (cb) => {
|
||||
clearTimeout(timeout);
|
||||
document.head.removeChild(script);
|
||||
clean = () => {}; // Prevent from cleaning several times
|
||||
cb();
|
||||
};
|
||||
script.onload = () => clean(resolve);
|
||||
script.onerror = () => clean(reject);
|
||||
script.src = `https://apis.google.com/js/api.js?${Date.now()}`;
|
||||
try {
|
||||
document.head.appendChild(script); // This can fail with bad network
|
||||
timeout = setTimeout(() => clean(reject), networkTimeout);
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
isConnectionDown = false;
|
||||
}, () => {
|
||||
isConnectionDown = true;
|
||||
});
|
||||
}
|
||||
const offline = isBrowserOffline || isConnectionDown;
|
||||
if (store.state.offline !== offline) {
|
||||
store.commit('setOffline', offline);
|
||||
if (offline) {
|
||||
store.dispatch('notification/error', 'You are offline.');
|
||||
} else {
|
||||
store.dispatch('notification/info', 'You are back online!');
|
||||
}
|
||||
}
|
||||
};
|
||||
utils.setInterval(checkOffline, 1000);
|
||||
window.addEventListener('online', () => {
|
||||
isConnectionDown = false;
|
||||
checkOffline();
|
||||
});
|
||||
window.addEventListener('offline', checkOffline);
|
||||
},
|
||||
isWindowFocused() {
|
||||
return parseInt(localStorage.getItem(this.lastFocusKey), 10) === this.lastFocus;
|
||||
},
|
||||
isUserActive() {
|
||||
return this.lastActivity > Date.now() - userInactiveAfter && this.isWindowFocused();
|
||||
},
|
||||
loadScript(url) {
|
||||
if (!scriptLoadingPromises[url]) {
|
||||
scriptLoadingPromises[url] = new Promise((resolve, reject) => {
|
||||
@ -217,53 +297,3 @@ export default {
|
||||
return attempt();
|
||||
},
|
||||
};
|
||||
|
||||
function checkOffline() {
|
||||
const isBrowserOffline = window.navigator.onLine === false;
|
||||
if (!isBrowserOffline &&
|
||||
store.state.lastOfflineCheck + networkTimeout + 5000 < Date.now() &&
|
||||
utils.isUserActive()
|
||||
) {
|
||||
store.commit('updateLastOfflineCheck');
|
||||
new Promise((resolve, reject) => {
|
||||
const script = document.createElement('script');
|
||||
let timeout;
|
||||
let clean = (cb) => {
|
||||
clearTimeout(timeout);
|
||||
document.head.removeChild(script);
|
||||
clean = () => {}; // Prevent from cleaning several times
|
||||
cb();
|
||||
};
|
||||
script.onload = () => clean(resolve);
|
||||
script.onerror = () => clean(reject);
|
||||
script.src = `https://apis.google.com/js/api.js?${Date.now()}`;
|
||||
try {
|
||||
document.head.appendChild(script); // This can fail with bad network
|
||||
timeout = setTimeout(() => clean(reject), networkTimeout);
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
isConnectionDown = false;
|
||||
}, () => {
|
||||
isConnectionDown = true;
|
||||
});
|
||||
}
|
||||
const offline = isBrowserOffline || isConnectionDown;
|
||||
if (store.state.offline !== offline) {
|
||||
store.commit('setOffline', offline);
|
||||
if (offline) {
|
||||
store.dispatch('notification/error', 'You are offline.');
|
||||
} else {
|
||||
store.dispatch('notification/info', 'You are back online!');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
utils.setInterval(checkOffline, 1000);
|
||||
window.addEventListener('online', () => {
|
||||
isConnectionDown = false;
|
||||
checkOffline();
|
||||
});
|
||||
window.addEventListener('offline', checkOffline);
|
||||
|
@ -1,6 +1,7 @@
|
||||
import localDbSvc from './localDbSvc';
|
||||
import store from '../store';
|
||||
import utils from './utils';
|
||||
import networkSvc from './networkSvc';
|
||||
import exportSvc from './exportSvc';
|
||||
import providerRegistry from './providers/providerRegistry';
|
||||
|
||||
@ -114,7 +115,7 @@ function requestPublish() {
|
||||
let intervalId;
|
||||
const attempt = () => {
|
||||
// Only start publishing when these conditions are met
|
||||
if (utils.isUserActive()) {
|
||||
if (networkSvc.isUserActive()) {
|
||||
clearInterval(intervalId);
|
||||
if (!hasCurrentFilePublishLocations()) {
|
||||
// Cancel sync
|
||||
|
@ -23,7 +23,7 @@ const isGoogleSponsor = () => {
|
||||
|
||||
const checkPayment = () => {
|
||||
const currentDate = Date.now();
|
||||
if (!isGoogleSponsor() && utils.isUserActive() && !store.state.offline &&
|
||||
if (!isGoogleSponsor() && networkSvc.isUserActive() && !store.state.offline &&
|
||||
lastCheck + checkPaymentEvery < currentDate
|
||||
) {
|
||||
lastCheck = currentDate;
|
||||
@ -39,9 +39,10 @@ const checkPayment = () => {
|
||||
}
|
||||
};
|
||||
|
||||
utils.setInterval(checkPayment, 2000);
|
||||
|
||||
export default {
|
||||
init: () => {
|
||||
utils.setInterval(checkPayment, 2000);
|
||||
},
|
||||
getToken() {
|
||||
if (isGoogleSponsor() || store.state.offline) {
|
||||
return Promise.resolve();
|
||||
|
@ -2,6 +2,7 @@ import localDbSvc from './localDbSvc';
|
||||
import store from '../store';
|
||||
import utils from './utils';
|
||||
import diffUtils from './diffUtils';
|
||||
import networkSvc from './networkSvc';
|
||||
import providerRegistry from './providers/providerRegistry';
|
||||
import googleDriveAppDataProvider from './providers/googleDriveAppDataProvider';
|
||||
|
||||
@ -14,9 +15,9 @@ let workspaceProvider;
|
||||
/**
|
||||
* Use a lock in the local storage to prevent multiple windows concurrency.
|
||||
*/
|
||||
const lastSyncActivityKey = `${utils.workspaceId}/lastSyncActivity`;
|
||||
let lastSyncActivity;
|
||||
const getLastStoredSyncActivity = () => parseInt(localStorage[lastSyncActivityKey], 10) || 0;
|
||||
const getLastStoredSyncActivity = () =>
|
||||
parseInt(localStorage.getItem(store.getters['workspace/lastSyncActivityKey']), 10) || 0;
|
||||
|
||||
/**
|
||||
* Return true if workspace sync is possible.
|
||||
@ -51,7 +52,7 @@ function isSyncWindow() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if auto sync can start, ie that lastSyncActivity is old enough.
|
||||
* Return true if auto sync can start, ie if lastSyncActivity is old enough.
|
||||
*/
|
||||
function isAutoSyncReady() {
|
||||
const storedLastSyncActivity = getLastStoredSyncActivity();
|
||||
@ -64,7 +65,7 @@ function isAutoSyncReady() {
|
||||
function setLastSyncActivity() {
|
||||
const currentDate = Date.now();
|
||||
lastSyncActivity = currentDate;
|
||||
localStorage[lastSyncActivityKey] = currentDate;
|
||||
localStorage.setItem(store.getters['workspace/lastSyncActivityKey'], currentDate);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -626,7 +627,7 @@ function requestSync() {
|
||||
let intervalId;
|
||||
const attempt = () => {
|
||||
// Only start syncing when these conditions are met
|
||||
if (utils.isUserActive() && isSyncWindow()) {
|
||||
if (networkSvc.isUserActive() && isSyncWindow()) {
|
||||
clearInterval(intervalId);
|
||||
if (!isSyncPossible()) {
|
||||
// Cancel sync
|
||||
@ -704,7 +705,7 @@ export default {
|
||||
// Sync periodically
|
||||
utils.setInterval(() => {
|
||||
if (isSyncPossible() &&
|
||||
utils.isUserActive() &&
|
||||
networkSvc.isUserActive() &&
|
||||
isSyncWindow() &&
|
||||
isAutoSyncReady()
|
||||
) {
|
||||
|
@ -2,7 +2,6 @@ import yaml from 'js-yaml';
|
||||
import '../libs/clunderscore';
|
||||
import defaultProperties from '../data/defaultFileProperties.yml';
|
||||
|
||||
const workspaceId = 'main';
|
||||
const origin = `${location.protocol}//${location.host}`;
|
||||
|
||||
// For uid()
|
||||
@ -12,30 +11,6 @@ const alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||
const radix = alphabet.length;
|
||||
const array = new Uint32Array(uidLength);
|
||||
|
||||
// For isUserActive
|
||||
const inactiveAfter = 2 * 60 * 1000; // 2 minutes
|
||||
let lastActivity;
|
||||
const setLastActivity = () => {
|
||||
lastActivity = Date.now();
|
||||
};
|
||||
window.document.addEventListener('mousedown', setLastActivity);
|
||||
window.document.addEventListener('keydown', setLastActivity);
|
||||
window.document.addEventListener('touchstart', setLastActivity);
|
||||
|
||||
// For isWindowFocused
|
||||
let lastFocus;
|
||||
const lastFocusKey = `${workspaceId}/lastWindowFocus`;
|
||||
const lastOpened = parseInt(localStorage[lastFocusKey], 10) || 0;
|
||||
const setLastFocus = () => {
|
||||
lastFocus = Date.now();
|
||||
localStorage[lastFocusKey] = lastFocus;
|
||||
setLastActivity();
|
||||
};
|
||||
if (document.hasFocus()) {
|
||||
setLastFocus();
|
||||
}
|
||||
window.addEventListener('focus', setLastFocus);
|
||||
|
||||
// For parseQueryParams()
|
||||
const parseQueryParams = (params) => {
|
||||
const result = {};
|
||||
@ -50,11 +25,9 @@ const parseQueryParams = (params) => {
|
||||
const urlParser = window.document.createElement('a');
|
||||
|
||||
export default {
|
||||
workspaceId,
|
||||
origin,
|
||||
queryParams: parseQueryParams(location.hash.slice(1)),
|
||||
oauth2RedirectUri: `${origin}/oauth2/callback`,
|
||||
lastOpened,
|
||||
cleanTrashAfter: 7 * 24 * 60 * 60 * 1000, // 7 days
|
||||
types: [
|
||||
'contentState',
|
||||
@ -147,12 +120,6 @@ export default {
|
||||
setInterval(func, interval) {
|
||||
return setInterval(() => func(), this.randomize(interval));
|
||||
},
|
||||
isWindowFocused() {
|
||||
return parseInt(localStorage[lastFocusKey], 10) === lastFocus;
|
||||
},
|
||||
isUserActive() {
|
||||
return lastActivity > Date.now() - inactiveAfter && this.isWindowFocused();
|
||||
},
|
||||
parseQueryParams,
|
||||
addQueryParams(url = '', params = {}) {
|
||||
const keys = Object.keys(params).filter(key => params[key] != null);
|
||||
|
@ -131,17 +131,6 @@ export default {
|
||||
});
|
||||
return result;
|
||||
},
|
||||
dbName: (state, getters) => {
|
||||
let dbName;
|
||||
Object.keys(getters.workspaces).some((id) => {
|
||||
dbName = 'stackedit-db';
|
||||
if (id !== 'main') {
|
||||
dbName += `-${id}`;
|
||||
}
|
||||
return dbName;
|
||||
});
|
||||
return dbName;
|
||||
},
|
||||
settings: getter('settings'),
|
||||
computedSettings: (state, getters) => {
|
||||
const customSettings = yaml.safeLoad(getters.settings);
|
||||
|
@ -23,6 +23,15 @@ export default {
|
||||
const workspaces = rootGetters['data/workspaces'];
|
||||
return workspaces[state.currentWorkspaceId] || workspaces.main;
|
||||
},
|
||||
lastSyncActivityKey: (state, getters) => {
|
||||
const workspaceId = getters.currentWorkspace.id;
|
||||
return `${workspaceId}/lastSyncActivity`;
|
||||
},
|
||||
lastFocusKey: (state, getters) => {
|
||||
const workspaceId = getters.currentWorkspace.id;
|
||||
return `${workspaceId}/lastWindowFocus`;
|
||||
},
|
||||
lastFocus: (state, getters) => parseInt(localStorage.getItem(getters.lastFocusKey), 10) || 0,
|
||||
},
|
||||
actions: {
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user