diff --git a/src/components/dialogs/ShotPrefetchDialog.jsx b/src/components/dialogs/ShotPrefetchDialog.jsx new file mode 100644 index 0000000..fed53ba --- /dev/null +++ b/src/components/dialogs/ShotPrefetchDialog.jsx @@ -0,0 +1,21 @@ +import React from 'react'; + +type Props = { + renderer: { + info: String, + progress: Number, + } +} + +export const ShotPrefetchDialog = ({ renderer: { info, progress }}: Props) => ( +
+
+
{info}
+
+
+
+
+
+
+
+); diff --git a/src/components/panels/EditorDialog.jsx b/src/components/panels/EditorDialog.jsx index e236e43..9cc48fa 100644 --- a/src/components/panels/EditorDialog.jsx +++ b/src/components/panels/EditorDialog.jsx @@ -27,6 +27,7 @@ import { setProvider, } from '$redux/user/actions'; import { ProviderDialog } from '$components/dialogs/ProviderDialog'; +import { ShotPrefetchDialog } from '$components/dialogs/ShotPrefetchDialog'; type Props = { mode: String, @@ -42,6 +43,7 @@ const DIALOG_CONTENTS = { [MODES.SAVE]: SaveDialog, [MODES.CONFIRM_CANCEL]: CancelDialog, [MODES.PROVIDER]: ProviderDialog, + [MODES.SHOT_PREFETCH]: ShotPrefetchDialog, }; export const Component = (props: Props) => { diff --git a/src/constants/modes.js b/src/constants/modes.js index 1be7253..585ac2c 100644 --- a/src/constants/modes.js +++ b/src/constants/modes.js @@ -11,4 +11,6 @@ export const MODES = ({ SAVE: 'SAVE', CONFIRM_CANCEL: 'CONFIRM_CANCEL', PROVIDER: 'PROVIDER', + + SHOT_PREFETCH: 'SHOT_PREFETCH', }: { [key: String]: String }); diff --git a/src/modules/Editor.js b/src/modules/Editor.js index bd250a3..d3c47bd 100644 --- a/src/modules/Editor.js +++ b/src/modules/Editor.js @@ -5,7 +5,6 @@ import { Stickers } from '$modules/Stickers'; import { Router } from '$modules/Router'; import { DEFAULT_LOGO, LOGOS } from '$constants/logos'; -import { parseStickerAngle, parseStickerStyle } from '$utils/import'; import { getUrlData } from '$utils/history'; import { store } from '$redux/store'; import { diff --git a/src/redux/user/reducer.js b/src/redux/user/reducer.js index 8767696..3297678 100644 --- a/src/redux/user/reducer.js +++ b/src/redux/user/reducer.js @@ -128,7 +128,8 @@ export const INITIAL_STATE = { ready: false, user: { ...DEFAULT_USER }, editing: false, - mode: MODES.NONE, + // mode: MODES.NONE, + mode: MODES.SHOT_PREFETCH, logo: DEFAULT_LOGO, routerPoints: 0, distance: 0, @@ -152,6 +153,8 @@ export const INITIAL_STATE = { width: 0, height: 0, renderer_active: false, + info: '', + progress: 0, } }; diff --git a/src/redux/user/sagas.js b/src/redux/user/sagas.js index fbaf7a6..4faeefa 100644 --- a/src/redux/user/sagas.js +++ b/src/redux/user/sagas.js @@ -28,6 +28,7 @@ import { } from '$utils/renderer'; import { LOGOS } from '$constants/logos'; import { DEFAULT_PROVIDER } from '$constants/providers'; +import { store } from '$redux/store'; const getUser = state => (state.user.user); const getState = state => (state.user); @@ -284,31 +285,39 @@ function* getRenderData() { const geometry = getTilePlacement(); const points = getPolyPlacement(); const stickers = getStickersPlacement(); - ctx.clearRect(0, 0, canvas.width, canvas.height); + yield put(setRenderer({ info: 'Загрузка тайлов', progress: 0.1 })); + const images = yield fetchImages(ctx, geometry); + yield put(setRenderer({ info: 'Отрисовка', progress: 0.5 })); + yield composeImages({ geometry, images, ctx }); yield composePoly({ points, ctx }); yield composeStickers({ stickers, ctx }); + yield put(setRenderer({ info: 'Готово', progress: 1 })); + return yield canvas.toDataURL('image/jpeg'); } function* takeAShotSaga() { - const { data, cancel } = yield race({ - data: call(getRenderData), - cancel: take(ACTIONS.HIDE_RENDERER), + const worker = call(getRenderData); + + 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({ data, renderer_active: true, width: window.innerWidth, height: window.innerHeight })); - - return true; } function* getCropData({ diff --git a/src/styles/main.less b/src/styles/main.less index 2278fc9..ca08231 100644 --- a/src/styles/main.less +++ b/src/styles/main.less @@ -10,6 +10,7 @@ @import 'save.less'; @import 'renderer.less'; @import 'dialogs.less'; +@import 'progress.less'; body { font-family: 'Rubik', sans-serif; diff --git a/src/styles/panel.less b/src/styles/panel.less index f19bc83..a1fcf06 100644 --- a/src/styles/panel.less +++ b/src/styles/panel.less @@ -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 { @@ -242,6 +254,9 @@ } } +.helper-prefetch { + flex-direction: column; +} .helper__text { width: 100%; @@ -460,3 +475,13 @@ background: #444444; margin: 0 8px 0 5px; } + +.dialog-prefetch-stage { + font-size: 1em; + text-transform: uppercase; + opacity: 0.7; +} + +.dialog-prefetch-progress { + padding: 10px 0 5px; +} diff --git a/src/styles/progress.less b/src/styles/progress.less new file mode 100644 index 0000000..9e0314d --- /dev/null +++ b/src/styles/progress.less @@ -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; + } +}