mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-18 07:07:35 +01:00
Client Fixes (#9064)
* fix loading of payments scripts * improve loading times
This commit is contained in:
@@ -75,6 +75,7 @@ import * as Analytics from 'client/libs/analytics';
|
|||||||
import BuyModal from './components/shops/buyModal.vue';
|
import BuyModal from './components/shops/buyModal.vue';
|
||||||
import SelectMembersModal from 'client/components/selectMembersModal.vue';
|
import SelectMembersModal from 'client/components/selectMembersModal.vue';
|
||||||
import notifications from 'client/mixins/notifications';
|
import notifications from 'client/mixins/notifications';
|
||||||
|
import { setup as setupPayments } from 'client/libs/payments';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [notifications],
|
mixins: [notifications],
|
||||||
@@ -205,6 +206,12 @@ export default {
|
|||||||
'preferences.timezoneOffset': this.browserTimezoneOffset,
|
'preferences.timezoneOffset': this.browserTimezoneOffset,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
// Load external scripts after the app has been rendered
|
||||||
|
setupPayments();
|
||||||
|
Analytics.load();
|
||||||
|
});
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
console.error('Impossible to fetch user. Clean up localStorage and refresh.', err); // eslint-disable-line no-console
|
console.error('Impossible to fetch user. Clean up localStorage and refresh.', err); // eslint-disable-line no-console
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { mapState } from 'client/libs/store';
|
import { mapState } from 'client/libs/store';
|
||||||
|
|
||||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||||
|
|
||||||
const AMAZON_PAYMENTS = process.env.AMAZON_PAYMENTS; // eslint-disable-line
|
const AMAZON_PAYMENTS = process.env.AMAZON_PAYMENTS; // eslint-disable-line
|
||||||
@@ -32,7 +31,7 @@ export default {
|
|||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
OffAmazonPayments: {},
|
OffAmazonPayments: {},
|
||||||
isAmazonReady: false,
|
isAmazonSetup: false,
|
||||||
amazonButtonEnabled: false,
|
amazonButtonEnabled: false,
|
||||||
amazonPaymentsbillingAgreementId: '',
|
amazonPaymentsbillingAgreementId: '',
|
||||||
amazonPaymentspaymentSelected: false,
|
amazonPaymentspaymentSelected: false,
|
||||||
@@ -41,16 +40,22 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState({user: 'user.data'}),
|
...mapState({user: 'user.data'}),
|
||||||
|
...mapState(['isAmazonReady']),
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
window.onAmazonLoginReady = () => {
|
if (this.isAmazonReady) return this.setupAmazon();
|
||||||
window.amazon.Login.setClientId(AMAZON_PAYMENTS.CLIENT_ID);
|
|
||||||
this.OffAmazonPayments = window.OffAmazonPayments;
|
this.$store.watch(state => state.isAmazonReady, (isAmazonReady) => {
|
||||||
this.isAmazonReady = true;
|
if (isAmazonReady) return this.setupAmazon();
|
||||||
this.showButton();
|
});
|
||||||
};
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
setupAmazon () {
|
||||||
|
if (this.isAmazonSetup) return false;
|
||||||
|
this.isAmazonSetup = true;
|
||||||
|
this.OffAmazonPayments = window.OffAmazonPayments;
|
||||||
|
this.showButton();
|
||||||
|
},
|
||||||
showButton () {
|
showButton () {
|
||||||
// @TODO: prevent modal close form clicking outside
|
// @TODO: prevent modal close form clicking outside
|
||||||
let amazonButton = this.OffAmazonPayments.Button( // eslint-disable-line
|
let amazonButton = this.OffAmazonPayments.Button( // eslint-disable-line
|
||||||
|
|||||||
@@ -19,8 +19,5 @@
|
|||||||
|
|
||||||
<!-- Translations -->
|
<!-- Translations -->
|
||||||
<script type='text/javascript' src='/api/v3/i18n/browser-script'></script>
|
<script type='text/javascript' src='/api/v3/i18n/browser-script'></script>
|
||||||
|
|
||||||
<script async type='text/javascript' src='https://static-na.payments-amazon.com/OffAmazonPayments/us/sandbox/js/Widgets.js'></script>
|
|
||||||
<script async type='text/javascript' src="https://checkout.stripe.com/v2/checkout.js"></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ import includes from 'lodash/includes';
|
|||||||
import getStore from 'client/store';
|
import getStore from 'client/store';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
|
||||||
|
const IS_PRODUCTION = process.env.NODE_ENV === 'production'; // eslint-disable-line no-process-env
|
||||||
|
const AMPLITUDE_KEY = process.env.AMPLITUDE_KEY; // eslint-disable-line no-process-env
|
||||||
|
const GA_ID = process.env.GA_ID; // eslint-disable-line no-process-env
|
||||||
|
|
||||||
let REQUIRED_FIELDS = ['hitType', 'eventCategory', 'eventAction'];
|
let REQUIRED_FIELDS = ['hitType', 'eventCategory', 'eventAction'];
|
||||||
let ALLOWED_HIT_TYPES = [
|
let ALLOWED_HIT_TYPES = [
|
||||||
'pageview',
|
'pageview',
|
||||||
@@ -93,12 +97,7 @@ export function updateUser (properties) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function setup () {
|
export function setup () {
|
||||||
const IS_PRODUCTION = process.env.NODE_ENV === 'production'; // eslint-disable-line no-process-env
|
|
||||||
const AMPLITUDE_KEY = process.env.AMPLITUDE_KEY; // eslint-disable-line no-process-env
|
|
||||||
const GA_ID = process.env.GA_ID; // eslint-disable-line no-process-env
|
|
||||||
|
|
||||||
// Setup queues until the real scripts are loaded
|
// Setup queues until the real scripts are loaded
|
||||||
|
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
@@ -119,25 +118,24 @@ export function setup () {
|
|||||||
}, window['ga'].l = 1 * new Date();
|
}, window['ga'].l = 1 * new Date();
|
||||||
ga('create', GA_ID);
|
ga('create', GA_ID);
|
||||||
/* eslint-enable */
|
/* eslint-enable */
|
||||||
|
}
|
||||||
|
|
||||||
|
export function load () {
|
||||||
// Load real scripts
|
// Load real scripts
|
||||||
|
|
||||||
if (!IS_PRODUCTION) return;
|
if (!IS_PRODUCTION) return;
|
||||||
|
|
||||||
Vue.nextTick(() => {
|
// Amplitude
|
||||||
// Amplitude
|
const amplitudeScript = document.createElement('script');
|
||||||
const amplitudeScript = document.createElement('script');
|
let firstScript = document.getElementsByTagName('script')[0];
|
||||||
let firstScript = document.getElementsByTagName('script')[0];
|
amplitudeScript.type = 'text/javascript';
|
||||||
amplitudeScript.type = 'text/javascript';
|
amplitudeScript.async = true;
|
||||||
amplitudeScript.async = true;
|
amplitudeScript.src = 'https://d24n15hnbwhuhn.cloudfront.net/libs/amplitude-2.2.0-min.gz.js';
|
||||||
amplitudeScript.src = 'https://d24n15hnbwhuhn.cloudfront.net/libs/amplitude-2.2.0-min.gz.js';
|
firstScript.parentNode.insertBefore(amplitudeScript, firstScript);
|
||||||
firstScript.parentNode.insertBefore(amplitudeScript, firstScript);
|
|
||||||
|
|
||||||
// Google Analytics
|
// Google Analytics
|
||||||
const gaScript = document.createElement('script');
|
const gaScript = document.createElement('script');
|
||||||
firstScript = document.getElementsByTagName('script')[0];
|
firstScript = document.getElementsByTagName('script')[0];
|
||||||
gaScript.async = 1;
|
gaScript.async = 1;
|
||||||
gaScript.src = '//www.google-analytics.com/analytics.js';
|
gaScript.src = '//www.google-analytics.com/analytics.js';
|
||||||
firstScript.parentNode.insertBefore(gaScript, firstScript);
|
firstScript.parentNode.insertBefore(gaScript, firstScript);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
32
website/client/libs/payments.js
Normal file
32
website/client/libs/payments.js
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import getStore from 'client/store';
|
||||||
|
|
||||||
|
const AMAZON_PAYMENTS = process.env.AMAZON_PAYMENTS; // eslint-disable-line
|
||||||
|
const NODE_ENV = process.env.NODE_ENV; // eslint-disable-line
|
||||||
|
|
||||||
|
export function setup () {
|
||||||
|
const store = getStore();
|
||||||
|
|
||||||
|
// Set Amazon Payments as ready in the store,
|
||||||
|
// Added here to make sure the listener is registered before the script can be executed
|
||||||
|
window.onAmazonLoginReady = () => {
|
||||||
|
store.state.isAmazonReady = true;
|
||||||
|
window.amazon.Login.setClientId(AMAZON_PAYMENTS.CLIENT_ID);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Load the scripts
|
||||||
|
|
||||||
|
// Amazon Payments
|
||||||
|
const amazonScript = document.createElement('script');
|
||||||
|
let firstScript = document.getElementsByTagName('script')[0];
|
||||||
|
amazonScript.type = 'text/javascript';
|
||||||
|
amazonScript.async = true;
|
||||||
|
amazonScript.src = `https://static-na.payments-amazon.com/OffAmazonPayments/us/${(NODE_ENV === 'production' ? '' : 'sandbox/')}js/Widgets.js`;
|
||||||
|
firstScript.parentNode.insertBefore(amazonScript, firstScript);
|
||||||
|
|
||||||
|
// Stripe
|
||||||
|
const stripeScript = document.createElement('script');
|
||||||
|
firstScript = document.getElementsByTagName('script')[0];
|
||||||
|
stripeScript.async = true;
|
||||||
|
stripeScript.src = '//checkout.stripe.com/v2/checkout.js';
|
||||||
|
firstScript.parentNode.insertBefore(stripeScript, firstScript);
|
||||||
|
}
|
||||||
@@ -4,7 +4,9 @@ require('babel-polyfill');
|
|||||||
|
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import AppComponent from './app';
|
import AppComponent from './app';
|
||||||
import { setup as setupAnalytics } from 'client/libs/analytics';
|
import {
|
||||||
|
setup as setupAnalytics,
|
||||||
|
} from 'client/libs/analytics';
|
||||||
import router from './router';
|
import router from './router';
|
||||||
import getStore from './store';
|
import getStore from './store';
|
||||||
import StoreModule from './libs/store';
|
import StoreModule from './libs/store';
|
||||||
@@ -27,11 +29,12 @@ Vue.config.productionTip = IS_PRODUCTION;
|
|||||||
Vue.use(i18n, {i18nData: window && window['habitica-i18n']});
|
Vue.use(i18n, {i18nData: window && window['habitica-i18n']});
|
||||||
Vue.use(StoreModule);
|
Vue.use(StoreModule);
|
||||||
|
|
||||||
setupAnalytics();
|
setupAnalytics(); // just create queues for analytics, no scripts loaded at this time
|
||||||
|
const store = getStore();
|
||||||
|
|
||||||
export default new Vue({
|
export default new Vue({
|
||||||
el: '#app',
|
el: '#app',
|
||||||
router,
|
router,
|
||||||
store: getStore(),
|
store,
|
||||||
render: h => h(AppComponent),
|
render: h => h(AppComponent),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ export default function () {
|
|||||||
title: 'Habitica',
|
title: 'Habitica',
|
||||||
isUserLoggedIn,
|
isUserLoggedIn,
|
||||||
isUserLoaded: false, // Means the user and the user's tasks are ready
|
isUserLoaded: false, // Means the user and the user's tasks are ready
|
||||||
|
isAmazonReady: false, // Whether the Amazon Payments lib can be used
|
||||||
user: asyncResourceFactory(),
|
user: asyncResourceFactory(),
|
||||||
credentials: AUTH_SETTINGS ? {
|
credentials: AUTH_SETTINGS ? {
|
||||||
API_ID: AUTH_SETTINGS.auth.apiId,
|
API_ID: AUTH_SETTINGS.auth.apiId,
|
||||||
@@ -95,9 +96,9 @@ export default function () {
|
|||||||
cloning: false,
|
cloning: false,
|
||||||
tasksToClone: {},
|
tasksToClone: {},
|
||||||
},
|
},
|
||||||
editingGroup: {}, // TODO move to local state
|
editingGroup: {}, // @TODO move to local state
|
||||||
// content data, frozen to prevent Vue from modifying it since it's static and never changes
|
// content data, frozen to prevent Vue from modifying it since it's static and never changes
|
||||||
// TODO apply freezing to the entire codebase (the server) and not only to the client side?
|
// @TODO apply freezing to the entire codebase (the server) and not only to the client side?
|
||||||
// NOTE this takes about 10-15ms on a fast computer
|
// NOTE this takes about 10-15ms on a fast computer
|
||||||
content: deepFreeze(content),
|
content: deepFreeze(content),
|
||||||
constants: deepFreeze({...commonConstants, DAY_MAPPING}),
|
constants: deepFreeze({...commonConstants, DAY_MAPPING}),
|
||||||
|
|||||||
Reference in New Issue
Block a user