renderer: showing progress on slow runs

This commit is contained in:
muerwre 2018-12-10 12:22:38 +07:00
parent 25ae7f8282
commit 66f79db43d
9 changed files with 87 additions and 9 deletions

View file

@ -0,0 +1,21 @@
import React from 'react';
type Props = {
renderer: {
info: String,
progress: Number,
}
}
export const ShotPrefetchDialog = ({ renderer: { info, progress }}: Props) => (
<div className="control-dialog control-dialog-small">
<div className="helper helper-prefetch">
<div className="dialog-prefetch-stage">{info}</div>
<div className="dialog-prefetch-progress">
<div className="progress">
<div className="bar" style={{ width: `${progress * 100}%` }} />
</div>
</div>
</div>
</div>
);

View file

@ -27,6 +27,7 @@ import {
setProvider, setProvider,
} from '$redux/user/actions'; } from '$redux/user/actions';
import { ProviderDialog } from '$components/dialogs/ProviderDialog'; import { ProviderDialog } from '$components/dialogs/ProviderDialog';
import { ShotPrefetchDialog } from '$components/dialogs/ShotPrefetchDialog';
type Props = { type Props = {
mode: String, mode: String,
@ -42,6 +43,7 @@ const DIALOG_CONTENTS = {
[MODES.SAVE]: SaveDialog, [MODES.SAVE]: SaveDialog,
[MODES.CONFIRM_CANCEL]: CancelDialog, [MODES.CONFIRM_CANCEL]: CancelDialog,
[MODES.PROVIDER]: ProviderDialog, [MODES.PROVIDER]: ProviderDialog,
[MODES.SHOT_PREFETCH]: ShotPrefetchDialog,
}; };
export const Component = (props: Props) => { export const Component = (props: Props) => {

View file

@ -11,4 +11,6 @@ export const MODES = ({
SAVE: 'SAVE', SAVE: 'SAVE',
CONFIRM_CANCEL: 'CONFIRM_CANCEL', CONFIRM_CANCEL: 'CONFIRM_CANCEL',
PROVIDER: 'PROVIDER', PROVIDER: 'PROVIDER',
SHOT_PREFETCH: 'SHOT_PREFETCH',
}: { [key: String]: String }); }: { [key: String]: String });

View file

@ -5,7 +5,6 @@ import { Stickers } from '$modules/Stickers';
import { Router } from '$modules/Router'; import { Router } from '$modules/Router';
import { DEFAULT_LOGO, LOGOS } from '$constants/logos'; import { DEFAULT_LOGO, LOGOS } from '$constants/logos';
import { parseStickerAngle, parseStickerStyle } from '$utils/import';
import { getUrlData } from '$utils/history'; import { getUrlData } from '$utils/history';
import { store } from '$redux/store'; import { store } from '$redux/store';
import { import {

View file

@ -128,7 +128,8 @@ export const INITIAL_STATE = {
ready: false, ready: false,
user: { ...DEFAULT_USER }, user: { ...DEFAULT_USER },
editing: false, editing: false,
mode: MODES.NONE, // mode: MODES.NONE,
mode: MODES.SHOT_PREFETCH,
logo: DEFAULT_LOGO, logo: DEFAULT_LOGO,
routerPoints: 0, routerPoints: 0,
distance: 0, distance: 0,
@ -152,6 +153,8 @@ export const INITIAL_STATE = {
width: 0, width: 0,
height: 0, height: 0,
renderer_active: false, renderer_active: false,
info: '',
progress: 0,
} }
}; };

View file

@ -28,6 +28,7 @@ import {
} from '$utils/renderer'; } from '$utils/renderer';
import { LOGOS } from '$constants/logos'; import { LOGOS } from '$constants/logos';
import { DEFAULT_PROVIDER } from '$constants/providers'; import { DEFAULT_PROVIDER } from '$constants/providers';
import { store } from '$redux/store';
const getUser = state => (state.user.user); const getUser = state => (state.user.user);
const getState = state => (state.user); const getState = state => (state.user);
@ -284,31 +285,39 @@ function* getRenderData() {
const geometry = getTilePlacement(); const geometry = getTilePlacement();
const points = getPolyPlacement(); const points = getPolyPlacement();
const stickers = getStickersPlacement(); const stickers = getStickersPlacement();
ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.clearRect(0, 0, canvas.width, canvas.height);
yield put(setRenderer({ info: 'Загрузка тайлов', progress: 0.1 }));
const images = yield fetchImages(ctx, geometry); const images = yield fetchImages(ctx, geometry);
yield put(setRenderer({ info: 'Отрисовка', progress: 0.5 }));
yield composeImages({ geometry, images, ctx }); yield composeImages({ geometry, images, ctx });
yield composePoly({ points, ctx }); yield composePoly({ points, ctx });
yield composeStickers({ stickers, ctx }); yield composeStickers({ stickers, ctx });
yield put(setRenderer({ info: 'Готово', progress: 1 }));
return yield canvas.toDataURL('image/jpeg'); return yield canvas.toDataURL('image/jpeg');
} }
function* takeAShotSaga() { function* takeAShotSaga() {
const { data, cancel } = yield race({ const worker = call(getRenderData);
data: call(getRenderData),
cancel: take(ACTIONS.HIDE_RENDERER), const { result, timeout } = yield race({
result: worker,
timeout: delay(500),
}); });
if (cancel || !data) return; // if (cancel) return;
if (timeout) yield put(setMode(MODES.SHOT_PREFETCH));
const data = yield (result || worker);
yield put(setMode(MODES.NONE));
yield put(setRenderer({ yield put(setRenderer({
data, renderer_active: true, width: window.innerWidth, height: window.innerHeight data, renderer_active: true, width: window.innerWidth, height: window.innerHeight
})); }));
return true;
} }
function* getCropData({ function* getCropData({

View file

@ -10,6 +10,7 @@
@import 'save.less'; @import 'save.less';
@import 'renderer.less'; @import 'renderer.less';
@import 'dialogs.less'; @import 'dialogs.less';
@import 'progress.less';
body { body {
font-family: 'Rubik', sans-serif; font-family: 'Rubik', sans-serif;

View file

@ -214,6 +214,18 @@
} }
} }
&.control-dialog-small {
min-width: 312px;
@media (max-width: @mobile_breakpoint) {
min-width: 100%;
max-width: 100%;
width: 100% !important;
left: 0;
padding: 0 10px;
}
}
} }
.control-dialog-provider { .control-dialog-provider {
@ -242,6 +254,9 @@
} }
} }
.helper-prefetch {
flex-direction: column;
}
.helper__text { .helper__text {
width: 100%; width: 100%;
@ -460,3 +475,13 @@
background: #444444; background: #444444;
margin: 0 8px 0 5px; margin: 0 8px 0 5px;
} }
.dialog-prefetch-stage {
font-size: 1em;
text-transform: uppercase;
opacity: 0.7;
}
.dialog-prefetch-progress {
padding: 10px 0 5px;
}

16
src/styles/progress.less Normal file
View file

@ -0,0 +1,16 @@
.progress {
width: 100%;
position: relative;
height: 5px;
background: #111111;
border-radius: @panel_radius;
box-sizing: border-box;
.bar {
width: 30%;
background: linear-gradient(270deg, @blue_primary, @blue_secondary);
height: 100%;
border-radius: @panel_radius;
transition: width 500ms;
}
}