mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-18 15:17:25 +01:00
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:
@@ -130,6 +130,7 @@ export default {
|
|||||||
this.selectedItemToBuy = item;
|
this.selectedItemToBuy = item;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// @TODO split up this file, it's too big
|
||||||
// Set up Error interceptors
|
// Set up Error interceptors
|
||||||
axios.interceptors.response.use((response) => {
|
axios.interceptors.response.use((response) => {
|
||||||
if (this.user) {
|
if (this.user) {
|
||||||
@@ -149,6 +150,39 @@ export default {
|
|||||||
return Promise.reject(error);
|
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
|
// Setup listener for title
|
||||||
this.$store.watch(state => state.title, (title) => {
|
this.$store.watch(state => state.title, (title) => {
|
||||||
document.title = title;
|
document.title = title;
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ div
|
|||||||
<script>
|
<script>
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
import throttle from 'lodash/throttle';
|
||||||
|
|
||||||
import { shouldDo } from '../../common/script/cron';
|
import { shouldDo } from '../../common/script/cron';
|
||||||
import { mapState } from 'client/libs/store';
|
import { mapState } from 'client/libs/store';
|
||||||
@@ -162,6 +163,7 @@ export default {
|
|||||||
lastShownNotifications,
|
lastShownNotifications,
|
||||||
alreadyReadNotification,
|
alreadyReadNotification,
|
||||||
isRunningYesterdailies: false,
|
isRunningYesterdailies: false,
|
||||||
|
nextCron: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -311,12 +313,27 @@ export default {
|
|||||||
|
|
||||||
console.log('before first yesterDailies run, current time:', (new Date()).toString());
|
console.log('before first yesterDailies run, current time:', (new Date()).toString());
|
||||||
this.runYesterDailies();
|
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: {
|
methods: {
|
||||||
playSound (sound) {
|
playSound (sound) {
|
||||||
this.$root.$emit('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 () {
|
scheduleNextCron () {
|
||||||
console.log('scheduling next cron (scheduleNextCron fn), current time:', (new Date()).toString());
|
console.log('scheduling next cron (scheduleNextCron fn), current time:', (new Date()).toString());
|
||||||
// Open yesterdailies modal the next time cron runs
|
// Open yesterdailies modal the next time cron runs
|
||||||
@@ -336,28 +353,18 @@ export default {
|
|||||||
console.log('next cron after edit', nextCron.toDate());
|
console.log('next cron after edit', nextCron.toDate());
|
||||||
|
|
||||||
// Setup a listener that executes 10 seconds after the next cron time
|
// 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);
|
console.log('finished running yesterDailies');
|
||||||
|
|
||||||
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);
|
|
||||||
},
|
},
|
||||||
async runYesterDailies () {
|
async runYesterDailies () {
|
||||||
console.log('running yesterdailies at, current time:', new Date(), 'needsCron:', this.user.needsCron);
|
|
||||||
console.log('isRunningYesterdailies:', this.isRunningYesterdailies, (new Date()).toString());
|
console.log('isRunningYesterdailies:', this.isRunningYesterdailies, (new Date()).toString());
|
||||||
// @TODO: Hopefully we don't need this even we load correctly
|
// @TODO: Hopefully we don't need this even we load correctly
|
||||||
if (this.isRunningYesterdailies) return;
|
if (this.isRunningYesterdailies) return;
|
||||||
|
console.log('running yesterdailies at, current time:', new Date(), 'needsCron:', this.user.needsCron);
|
||||||
|
this.isRunningYesterdailies = true;
|
||||||
|
|
||||||
if (!this.user.needsCron) {
|
if (!this.user.needsCron) {
|
||||||
console.log('cron not needed, scheduling, current time:', (new Date()).toString());
|
console.log('cron not needed, scheduling, current time:', (new Date()).toString());
|
||||||
this.handleUserNotifications(this.user.notifications);
|
this.handleUserNotifications(this.user.notifications);
|
||||||
@@ -366,7 +373,6 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let dailys = this.$store.state.tasks.data.dailys;
|
let dailys = this.$store.state.tasks.data.dailys;
|
||||||
this.isRunningYesterdailies = true;
|
|
||||||
console.log('running yesterdailies (real part), current time:', (new Date()).toString());
|
console.log('running yesterdailies (real part), current time:', (new Date()).toString());
|
||||||
|
|
||||||
let yesterDay = moment().subtract('1', 'day').startOf('day').add({
|
let yesterDay = moment().subtract('1', 'day').startOf('day').add({
|
||||||
@@ -411,7 +417,6 @@ export default {
|
|||||||
|
|
||||||
this.handleUserNotifications(this.user.notifications);
|
this.handleUserNotifications(this.user.notifications);
|
||||||
console.log('scheduling next cron after runYesterDailiesAction, current time:', (new Date()).toString());
|
console.log('scheduling next cron after runYesterDailiesAction, current time:', (new Date()).toString());
|
||||||
this.isRunningYesterdailies = false;
|
|
||||||
this.scheduleNextCron();
|
this.scheduleNextCron();
|
||||||
},
|
},
|
||||||
/* eslint-enable no-console */
|
/* eslint-enable no-console */
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
button.social-button(@click='socialAuth("facebook")')
|
button.social-button(@click='socialAuth("facebook")')
|
||||||
.svg-icon.social-icon(v-html="icons.facebookIcon")
|
.svg-icon.social-icon(v-html="icons.facebookIcon")
|
||||||
span {{$t('signUpWithSocial', {social: 'Facebook'})}}
|
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")
|
.svg-icon.social-icon(v-html="icons.googleIcon")
|
||||||
span {{$t('signUpWithSocial', {social: 'Google'})}}
|
span {{$t('signUpWithSocial', {social: 'Google'})}}
|
||||||
.strike
|
.strike
|
||||||
|
|||||||
@@ -10,16 +10,10 @@ module.exports = function responseHandler (req, res, next) {
|
|||||||
|
|
||||||
if (message) response.message = message;
|
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) {
|
if (user) {
|
||||||
response.notifications = user.notifications.map(notification => notification.toJSON());
|
response.notifications = user.notifications.map(notification => notification.toJSON());
|
||||||
if (req.query.userV) {
|
|
||||||
response.userV = user._v;
|
response.userV = user._v;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
res.status(status).json(response);
|
res.status(status).json(response);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user