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;
|
||||
});
|
||||
|
||||
// @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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user