web/satellite: move access grant web worker initialization to onlogin loading state

WHAT:
web worker is initialized during onlogin loading screen now

WHY:
removed unnecessary initializations and increased UX experience

Change-Id: I734f194f862c15b3fb08e436a161da32d8d4a8ac
This commit is contained in:
VitaliiShpital 2020-12-15 20:48:34 +02:00 committed by Stefan Benten
parent b1712cc93b
commit 50dd9fb11a
9 changed files with 147 additions and 54 deletions

View File

@ -17684,6 +17684,15 @@
"errno": "~0.1.7"
}
},
"worker-plugin": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/worker-plugin/-/worker-plugin-5.0.0.tgz",
"integrity": "sha512-AXMUstURCxDD6yGam2r4E34aJg6kW85IiaeX72hi+I1cxyaMUtrvVY6sbfpGKAj5e7f68Acl62BjQF5aOOx2IQ==",
"dev": true,
"requires": {
"loader-utils": "^1.1.0"
}
},
"worker-rpc": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/worker-rpc/-/worker-rpc-0.1.1.tgz",

View File

@ -58,7 +58,8 @@
"vue-template-compiler": "2.6.12",
"vue-tslint": "0.3.2",
"vue-tslint-loader": "3.5.6",
"webpack": "4.44.1"
"webpack": "4.44.1",
"worker-plugin": "5.0.0"
},
"postcss": {
"plugins": {

View File

@ -111,7 +111,29 @@ export default class CreatePassphraseStep extends Vue {
this.key = this.$route.params.key;
this.restrictedKey = this.$route.params.restrictedKey;
this.passphrase = bip39.generateMnemonic();
this.worker = await new Worker('/static/static/wasm/webWorker.js');
this.setWorker();
this.isLoading = false;
}
/**
* Changes state to generate passphrase.
*/
public onChooseGenerate(): void {
if (this.passphrase && this.isGenerateState) return;
this.passphrase = bip39.generateMnemonic();
this.isCreateState = false;
this.isGenerateState = true;
}
/**
* Sets local worker with worker instantiated in store.
* Also sets worker's onmessage and onerror logic.
*/
public setWorker(): void {
this.worker = this.$store.state.accessGrantsModule.accessGrantsWebWorker;
this.worker.onmessage = (event: MessageEvent) => {
const data = event.data;
if (data.error) {
@ -127,19 +149,6 @@ export default class CreatePassphraseStep extends Vue {
this.worker.onerror = (error: ErrorEvent) => {
this.$notify.error(error.message);
};
this.isLoading = false;
}
/**
* Changes state to generate passphrase.
*/
public onChooseGenerate(): void {
if (this.passphrase && this.isGenerateState) return;
this.passphrase = bip39.generateMnemonic();
this.isCreateState = false;
this.isGenerateState = true;
}
/**

View File

@ -65,22 +65,8 @@ export default class EnterPassphraseStep extends Vue {
this.key = this.$route.params.key;
this.restrictedKey = this.$route.params.restrictedKey;
this.worker = await new Worker('/static/static/wasm/webWorker.js');
this.worker.onmessage = (event: MessageEvent) => {
const data = event.data;
if (data.error) {
this.$notify.error(data.error);
return;
}
this.access = data.value;
this.$notify.success('Access Grant was generated successfully');
};
this.worker.onerror = (error: ErrorEvent) => {
this.$notify.error(error.message);
};
this.setWorker();
this.isLoading = false;
}
@ -131,6 +117,29 @@ export default class EnterPassphraseStep extends Vue {
}, 1000);
}
/**
* Sets local worker with worker instantiated in store.
* Also sets worker's onmessage and onerror logic.
*/
public setWorker(): void {
this.worker = this.$store.state.accessGrantsModule.accessGrantsWebWorker;
this.worker.onmessage = (event: MessageEvent) => {
const data = event.data;
if (data.error) {
this.$notify.error(data.error);
return;
}
this.access = data.value;
this.$notify.success('Access Grant was generated successfully');
};
this.worker.onerror = (error: ErrorEvent) => {
this.$notify.error(error.message);
};
}
/**
* Holds on back button click logic.
* Redirects to previous step.

View File

@ -53,9 +53,13 @@
width="100%"
height="48px"
:on-press="onContinueInBrowserClick"
:is-disabled="isLoading"
:is-disabled="isLoading || !isAccessGrantsWebWorkerReady"
/>
<p class="permissions__cli-link" @click.stop="onContinueInCLIClick">
<p
class="permissions__cli-link"
:class="{ disabled: !isAccessGrantsWebWorkerReady || isLoading }"
@click.stop="onContinueInCLIClick"
>
Continue in CLI
</p>
</div>
@ -108,22 +112,8 @@ export default class PermissionsStep extends Vue {
}
this.key = this.$route.params.key;
this.worker = await new Worker('/static/static/wasm/webWorker.js');
this.worker.onmessage = (event: MessageEvent) => {
const data = event.data;
if (data.error) {
this.$notify.error(data.error);
return;
}
this.restrictedKey = data.value;
this.$notify.success('Permissions were set successfully');
};
this.worker.onerror = (error: ErrorEvent) => {
this.$notify.error(error.message);
};
this.setWorker();
try {
await this.$store.dispatch(BUCKET_ACTIONS.FETCH_ALL_BUCKET_NAMES);
@ -142,11 +132,34 @@ export default class PermissionsStep extends Vue {
this.$router.push(RouteConfig.AccessGrants.with(RouteConfig.CreateAccessGrant.with(RouteConfig.NameStep)).path);
}
/**
* Sets local worker with worker instantiated in store.
* Also sets worker's onmessage and onerror logic.
*/
public setWorker(): void {
this.worker = this.$store.state.accessGrantsModule.accessGrantsWebWorker;
this.worker.onmessage = (event: MessageEvent) => {
const data = event.data;
if (data.error) {
this.$notify.error(data.error);
return;
}
this.restrictedKey = data.value;
this.$notify.success('Permissions were set successfully');
};
this.worker.onerror = (error: ErrorEvent) => {
this.$notify.error(error.message);
};
}
/**
* Holds on continue in CLI button click logic.
*/
public onContinueInCLIClick(): void {
if (this.isLoading) return;
if (this.isLoading || !this.isAccessGrantsWebWorkerReady) return;
this.isLoading = true;
@ -193,7 +206,7 @@ export default class PermissionsStep extends Vue {
* Holds on continue in browser button click logic.
*/
public onContinueInBrowserClick(): void {
if (this.isLoading) return;
if (this.isLoading || !this.isAccessGrantsWebWorkerReady) return;
this.isLoading = true;
@ -248,6 +261,13 @@ export default class PermissionsStep extends Vue {
}, 1000);
}
/**
* Indicates if access grants web worker ready to use.
*/
public get isAccessGrantsWebWorkerReady(): boolean {
return this.$store.state.accessGrantsModule.isAccessGrantsWebWorkerReady;
}
/**
* Indicates if current route is onboarding tour.
*/
@ -419,4 +439,9 @@ export default class PermissionsStep extends Vue {
.border-radius {
border-radius: 6px;
}
.disabled {
pointer-events: none;
color: rgba(0, 0, 0, 0.4);
}
</style>

View File

@ -19,6 +19,7 @@ export const ACCESS_GRANTS_ACTIONS = {
DELETE: 'deleteAccessGrants',
CLEAR: 'clearAccessGrants',
GET_GATEWAY_CREDENTIALS: 'getGatewayCredentials',
SET_ACCESS_GRANTS_WEB_WORKER: 'setAccessGrantsWebWorker',
SET_SEARCH_QUERY: 'setAccessGrantsSearchQuery',
SET_SORT_BY: 'setAccessGrantsSortingBy',
SET_SORT_DIRECTION: 'setAccessGrantsSortingDirection',
@ -31,6 +32,7 @@ export const ACCESS_GRANTS_ACTIONS = {
export const ACCESS_GRANTS_MUTATIONS = {
SET_PAGE: 'setAccessGrants',
SET_GATEWAY_CREDENTIALS: 'setGatewayCredentials',
SET_ACCESS_GRANTS_WEB_WORKER: 'setAccessGrantsWebWorker',
TOGGLE_SELECTION: 'toggleAccessGrantsSelection',
TOGGLE_BUCKET_SELECTION: 'toggleBucketSelection',
CLEAR_SELECTION: 'clearAccessGrantsSelection',
@ -54,6 +56,7 @@ const {
SET_PAGE_NUMBER,
SET_DURATION_PERMISSION,
SET_GATEWAY_CREDENTIALS,
SET_ACCESS_GRANTS_WEB_WORKER,
} = ACCESS_GRANTS_MUTATIONS;
export class AccessGrantsState {
@ -64,6 +67,8 @@ export class AccessGrantsState {
public permissionNotBefore: Date = new Date();
public permissionNotAfter: Date = new Date('2200-01-01');
public gatewayCredentials: GatewayCredentials = new GatewayCredentials();
public accessGrantsWebWorker: Worker | null = null;
public isAccessGrantsWebWorkerReady: boolean = false;
}
/**
@ -75,6 +80,22 @@ export function makeAccessGrantsModule(api: AccessGrantsApi): StoreModule<Access
return {
state: new AccessGrantsState(),
mutations: {
[SET_ACCESS_GRANTS_WEB_WORKER](state: AccessGrantsState): void {
state.accessGrantsWebWorker = new Worker('@/../static/wasm/accessGrant.worker.js', { type: 'module' });
state.accessGrantsWebWorker.onmessage = (event: MessageEvent) => {
const data = event.data;
if (data !== 'configured') {
console.error('Failed to configure access grants web worker');
return;
}
state.isAccessGrantsWebWorkerReady = true;
};
state.accessGrantsWebWorker.onerror = (error: ErrorEvent) => {
console.error(`Failed to configure access grants web worker. ${error.message}`);
};
},
[SET_PAGE](state: AccessGrantsState, page: AccessGrantsPage) {
state.page = page;
state.page.accessGrants = state.page.accessGrants.map(accessGrant => {
@ -155,6 +176,9 @@ export function makeAccessGrantsModule(api: AccessGrantsApi): StoreModule<Access
},
},
actions: {
setAccessGrantsWebWorker: function({commit}: any): void {
commit(SET_ACCESS_GRANTS_WEB_WORKER);
},
fetchAccessGrants: async function ({commit, rootGetters, state}, pageNumber: number): Promise<AccessGrantsPage> {
const projectId = rootGetters.selectedProject.id;
commit(SET_PAGE_NUMBER, pageNumber);

View File

@ -57,7 +57,6 @@ import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
import { PROJECTS_ACTIONS } from '@/store/modules/projects';
import { USER_ACTIONS } from '@/store/modules/users';
import { Project } from '@/types/projects';
import { User } from '@/types/users';
import { Size } from '@/utils/bytesSize';
import {
APP_STATE_ACTIONS,
@ -93,16 +92,26 @@ export default class DashboardArea extends Vue {
*/
public readonly projectDashboardPath: string = RouteConfig.ProjectDashboard.path;
/**
* Lifecycle hook before initial render.
* Sets access grants web worker.
*/
public beforeMount(): void {
try {
this.$store.dispatch(ACCESS_GRANTS_ACTIONS.SET_ACCESS_GRANTS_WEB_WORKER);
} catch (error) {
this.$notify.error(`Unable to set access grants wizard. ${error.message}`);
}
}
/**
* Lifecycle hook after initial render.
* Pre fetches user`s and project information.
*/
public async mounted(): Promise<void> {
let user: User;
// TODO: combine all project related requests in one
try {
user = await this.$store.dispatch(USER_ACTIONS.GET);
await this.$store.dispatch(USER_ACTIONS.GET);
} catch (error) {
if (!(error instanceof ErrorUnauthorized)) {
await this.$store.dispatch(APP_STATE_ACTIONS.CHANGE_STATE, AppState.ERROR);

View File

@ -15,7 +15,10 @@ const instantiateStreaming = WebAssembly.instantiateStreaming || async function
return await WebAssembly.instantiate(source, importObject);
};
const response = fetch('/static/static/wasm/access.wasm');
instantiateStreaming(response, go.importObject).then(result => go.run(result.instance)).catch(err => self.postMessage(new Error(err.message)));
instantiateStreaming(response, go.importObject).then(result => {
go.run(result.instance)
self.postMessage('configured');
}).catch(err => self.postMessage(new Error(err.message)));
self.onmessage = function (event) {
const data = event.data;

View File

@ -4,6 +4,7 @@
const path = require('path');
const CompressionWebpackPlugin = require('compression-webpack-plugin');
const StyleLintPlugin = require('stylelint-webpack-plugin');
const WorkerPlugin = require('worker-plugin');
const productionGzipExtensions = ['js', 'css', 'ttf'];
module.exports = {
@ -21,6 +22,9 @@ module.exports = {
new StyleLintPlugin({
files: ['**/*.{vue,sss,less,scss,sass}'],
emitWarning: true,
}),
new WorkerPlugin({
globalObject: 'self',
})
],
},