More Client Fixes (#9036)

* add automatic user syncing when user._v does not match with server

* fix google signup

* fixes to user sync

* check for next cron on activity

* add comment
This commit is contained in:
Matteo Pagliazzi
2017-09-14 18:55:17 +02:00
committed by GitHub
parent 2f913666cd
commit c6881c5e30
4 changed files with 59 additions and 26 deletions

View File

@@ -130,6 +130,7 @@ export default {
this.selectedItemToBuy = item;
});
// @TODO split up this file, it's too big
// Set up Error interceptors
axios.interceptors.response.use((response) => {
if (this.user) {
@@ -149,6 +150,39 @@ export default {
return Promise.reject(error);
});
axios.interceptors.response.use((response) => {
// Verify that the user was not updated from another browser/app/client
// If it was, sync
const url = response.config.url;
const method = response.config.method;
const isApiCall = url.indexOf('api/v3') !== -1;
const userV = response.data && response.data.userV;
if (this.isUserLoaded && isApiCall && userV) {
const oldUserV = this.user._v;
this.user._v = userV;
// Do not sync again if already syncing
const isUserSync = url.indexOf('/api/v3/user') === 0 && method === 'get';
const isTasksSync = url.indexOf('/api/v3/tasks/user') === 0 && method === 'get';
// exclude chat seen requests because with real time chat they would be too many
const isChatSeen = url.indexOf('/chat/seen') !== -1 && method === 'post';
// exclude POST /api/v3/cron because the user is synced automatically after cron runs
const isCron = url.indexOf('/api/v3/cron') === 0 && method === 'post';
// Something has changed on the user object that was not tracked here, sync the user
if (userV - oldUserV > 1 && !isCron && !isChatSeen && !isUserSync && !isTasksSync) {
Promise.all([
this.$store.dispatch('user:fetch', {forceLoad: true}),
this.$store.dispatch('tasks:fetchUserTasks', {forceLoad: true}),
]);
}
}
return response;
});
// Setup listener for title
this.$store.watch(state => state.title, (title) => {
document.title = title;

View File

@@ -86,6 +86,7 @@ div
<script>
import axios from 'axios';
import moment from 'moment';
import throttle from 'lodash/throttle';
import { shouldDo } from '../../common/script/cron';
import { mapState } from 'client/libs/store';
@@ -162,6 +163,7 @@ export default {
lastShownNotifications,
alreadyReadNotification,
isRunningYesterdailies: false,
nextCron: null,
};
},
computed: {
@@ -311,12 +313,27 @@ export default {
console.log('before first yesterDailies run, current time:', (new Date()).toString());
this.runYesterDailies();
// Do not remove the event listener as it's live for the entire app lifetime
document.addEventListener('mousemove', () => this.checkNextCron());
document.addEventListener('touchstart', () => this.checkNextCron());
document.addEventListener('mousedown', () => this.checkNextCron());
document.addEventListener('keydown', () => this.checkNextCron());
});
},
methods: {
playSound (sound) {
this.$root.$emit('playSound', sound);
},
checkNextCron: throttle(function checkNextCron () {
console.log('checking for next cron');
if (!this.isRunningYesterdailies && this.nextCron && Date.now() > this.nextCron) {
Promise.all([
this.$store.dispatch('user:fetch', {forceLoad: true}),
this.$store.dispatch('tasks:fetchUserTasks', {forceLoad: true}),
]).then(() => this.runYesterDailies());
}
}, 1000),
scheduleNextCron () {
console.log('scheduling next cron (scheduleNextCron fn), current time:', (new Date()).toString());
// Open yesterdailies modal the next time cron runs
@@ -336,28 +353,18 @@ export default {
console.log('next cron after edit', nextCron.toDate());
// Setup a listener that executes 10 seconds after the next cron time
const nextCronIn = Number(nextCron.format('x')) - Date.now() + 10 * 1000;
this.nextCron = Number(nextCron.format('x'));
this.isRunningYesterdailies = false;
console.log('next cron in', nextCronIn);
setTimeout(async () => {
console.log('next cron timer fired, current time:', new Date(), 'syncing...');
// Sync the user before showing the modal
await Promise.all([
this.$store.dispatch('user:fetch', {forceLoad: true}),
this.$store.dispatch('tasks:fetchUserTasks', {forceLoad: true}),
]);
console.log('next timer after syncing, running yesterDailies, current time:', (new Date()).toString());
this.runYesterDailies();
}, nextCronIn);
console.log('finished running yesterDailies');
},
async runYesterDailies () {
console.log('running yesterdailies at, current time:', new Date(), 'needsCron:', this.user.needsCron);
console.log('isRunningYesterdailies:', this.isRunningYesterdailies, (new Date()).toString());
// @TODO: Hopefully we don't need this even we load correctly
if (this.isRunningYesterdailies) return;
console.log('running yesterdailies at, current time:', new Date(), 'needsCron:', this.user.needsCron);
this.isRunningYesterdailies = true;
if (!this.user.needsCron) {
console.log('cron not needed, scheduling, current time:', (new Date()).toString());
this.handleUserNotifications(this.user.notifications);
@@ -366,7 +373,6 @@ export default {
}
let dailys = this.$store.state.tasks.data.dailys;
this.isRunningYesterdailies = true;
console.log('running yesterdailies (real part), current time:', (new Date()).toString());
let yesterDay = moment().subtract('1', 'day').startOf('day').add({
@@ -411,7 +417,6 @@ export default {
this.handleUserNotifications(this.user.notifications);
console.log('scheduling next cron after runYesterDailiesAction, current time:', (new Date()).toString());
this.isRunningYesterdailies = false;
this.scheduleNextCron();
},
/* eslint-enable no-console */

View File

@@ -19,7 +19,7 @@
button.social-button(@click='socialAuth("facebook")')
.svg-icon.social-icon(v-html="icons.facebookIcon")
span {{$t('signUpWithSocial', {social: 'Facebook'})}}
button.social-button(@click='socialAuth("facebook")')
button.social-button(@click='socialAuth("google")')
.svg-icon.social-icon(v-html="icons.googleIcon")
span {{$t('signUpWithSocial', {social: 'Google'})}}
.strike

View File

@@ -10,16 +10,10 @@ module.exports = function responseHandler (req, res, next) {
if (message) response.message = message;
// When userV=Number (user version) query parameter is passed and a user is logged in,
// sends back the current user._v in the response so that the client
// can verify if it's the most up to date data.
// Considered part of the private API for now and not officially supported
if (user) {
response.notifications = user.notifications.map(notification => notification.toJSON());
if (req.query.userV) {
response.userV = user._v;
}
}
res.status(status).json(response);
};