orchidmap-front/src/redux/user/sagas.js
2018-11-30 13:49:03 +07:00

324 lines
8.1 KiB
JavaScript

import { REHYDRATE } from 'redux-persist';
import { delay } from 'redux-saga';
import { takeLatest, select, call, put, takeEvery, race, take } from 'redux-saga/effects';
import { checkUserToken, getGuestToken, getStoredMap, postMap } from '$utils/api';
import {
hideRenderer,
setActiveSticker, setAddress,
setChanged,
setEditing,
setMode, setRenderer,
setSaveError,
setSaveOverwrite, setSaveSuccess, setTitle,
setUser
} from '$redux/user/actions';
import { getUrlData, pushPath } from '$utils/history';
import { editor } from '$modules/Editor';
import { ACTIONS } from '$redux/user/constants';
import { MODES } from '$constants/modes';
import { DEFAULT_USER } from '$constants/auth';
import { TIPS } from '$constants/tips';
import {
composeImages,
composePoly, downloadCanvas,
fetchImages,
getPolyPlacement,
getTilePlacement,
imageFetcher
} from '$utils/renderer';
import { LOGOS } from '$constants/logos';
import { DEFAULT_PROVIDER } from '$constants/providers';
const getUser = state => (state.user.user);
const getState = state => (state.user);
const hideLoader = () => {
document.getElementById('loader').style.opacity = 0;
document.getElementById('loader').style.pointerEvents = 'none';
return true;
};
function* generateGuestSaga() {
const user = yield call(getGuestToken);
yield put(setUser(user));
return user;
}
function* startEmptyEditorSaga() {
const { id, random_url, provider = DEFAULT_PROVIDER } = yield select(getUser);
pushPath(`/${random_url}/edit`);
editor.owner = id;
editor.setProvider(provider);
editor.startEditing();
yield put(setChanged(false));
yield put(setEditing(true));
return hideLoader();
}
function* startEditingSaga() {
yield editor.startEditing();
yield put(setEditing(true));
}
function* stopEditingSaga() {
const { changed, editing, mode } = yield select(getState);
if (!editing) return;
if (changed && mode !== MODES.CONFIRM_CANCEL) {
yield put(setMode(MODES.CONFIRM_CANCEL));
return;
}
yield editor.cancelEditing();
yield put(setMode(MODES.NONE));
yield put(setChanged(false));
yield put(setEditing(editor.hasEmptyHistory)); // don't close editor if no previous map
}
function* mapInitSaga() {
const { path, mode } = getUrlData();
if (path) {
const map = yield call(getStoredMap, { name: path });
if (map) {
yield editor.setData(map);
yield editor.fitDrawing();
yield put(setChanged(false));
if (mode && mode === 'edit') {
yield call(startEditingSaga);
// yield put(setEditing(true));
// editor.startEditing();
} else {
yield put(setEditing(false));
// yield call(stopEditingSaga);
editor.stopEditing();
}
return hideLoader();
}
}
return yield call(startEmptyEditorSaga);
}
function* authChechSaga() {
const { id, token } = yield select(getUser);
if (id && token) {
const user = yield call(checkUserToken, { id, token });
if (user) {
yield put(setUser(user));
return yield call(mapInitSaga);
}
}
yield call(generateGuestSaga);
return yield call(mapInitSaga);
}
function* setModeSaga({ mode }) {
return yield editor.changeMode(mode);
// console.log('change', mode);
}
function* userLogoutSaga() {
const { id } = yield select(getUser);
if (id === editor.owner) {
editor.owner = null;
}
yield put(setUser(DEFAULT_USER));
yield call(generateGuestSaga);
}
function* setActiveStickerSaga({ activeSticker }) {
yield editor.activeSticker = activeSticker;
return true;
}
function* setLogoSaga({ logo }) {
const { mode } = yield select(getState);
editor.logo = logo;
if (mode === MODES.LOGO) {
yield put(setMode(MODES.NONE));
}
}
function* routerCancelSaga() {
yield call(editor.router.cancelDrawing);
yield put(setMode(MODES.NONE));
return true;
}
function* routerSubmitSaga() {
yield call(editor.router.submitDrawing);
yield put(setMode(MODES.NONE));
return true;
}
function* clearSaga({ type }) {
switch (type) {
case ACTIONS.CLEAR_POLY:
yield editor.poly.clearAll();
yield editor.router.clearAll();
break;
case ACTIONS.CLEAR_STICKERS:
yield editor.stickers.clearAll();
break;
case ACTIONS.CLEAR_ALL:
yield editor.clearAll();
yield put(setChanged(false));
break;
default: break;
}
yield put(setActiveSticker(null));
yield put(setMode(MODES.NONE));
}
function* sendSaveRequestSaga({ title, address, force }) {
if (editor.isEmpty) return yield put(setSaveError(TIPS.SAVE_EMPTY));
const { route, stickers } = editor.dumpData();
const { logo, distance } = yield select(getState);
const { id, token } = yield select(getUser);
const { result, timeout, cancel } = yield race({
result: postMap({
id, token, route, stickers, title, force, address, logo, distance,
}),
timeout: delay(10000),
cancel: take(ACTIONS.RESET_SAVE_DIALOG),
});
if (cancel) return yield put(setMode(MODES.NONE));
if (result && result.mode === 'overwriting') return yield put(setSaveOverwrite());
if (timeout || !result || !result.success || !result.address) return yield put(setSaveError(TIPS.SAVE_TIMED_OUT));
return yield put(setSaveSuccess({ address: result.address, save_error: TIPS.SAVE_SUCCESS, title }));
}
function* setSaveSuccessSaga({ address, title }) {
const { id } = yield select(getUser);
pushPath(`/${address}/edit`);
yield put(setTitle(title));
yield put(setAddress(address));
// yield editor.setAddress(address);
yield editor.owner = id;
return yield editor.setInitialData();
}
function* getRenderData() {
const canvas = document.getElementById('renderer');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const ctx = canvas.getContext('2d');
const geometry = getTilePlacement();
const points = getPolyPlacement();
ctx.clearRect(0, 0, canvas.width, canvas.height);
const images = yield fetchImages(ctx, geometry);
yield composeImages({ geometry, images, ctx });
yield composePoly({ points, ctx });
return yield canvas.toDataURL('image/jpeg');
}
function* takeAShotSaga() {
const data = yield call(getRenderData);
yield put(setRenderer({
data, renderer_active: true, width: window.innerWidth, height: window.innerHeight
}));
return true;
}
function* getCropData({
x, y, width, height
}) {
const { logo, renderer: { data } } = yield select(getState);
const canvas = document.getElementById('renderer');
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
const image = yield imageFetcher(data);
ctx.drawImage(image, -x, -y);
if (logo && LOGOS[logo][1]) {
const logoImage = yield imageFetcher(LOGOS[logo][1]);
ctx.drawImage(logoImage, width - logoImage.width, height - logoImage.height);
}
return yield canvas.toDataURL('image/jpeg');
}
function* cropAShotSaga(params) {
const { title, address } = yield select(getState);
yield call(getCropData, params);
const canvas = document.getElementById('renderer');
downloadCanvas(canvas, (title || address));
return yield put(hideRenderer());
}
function setProviderSaga({ provider }) {
return editor.setProvider(provider);
// return put(setMode(MODES.NONE))
}
export function* userSaga() {
// ASYNCHRONOUS!!! :-)
yield takeLatest(REHYDRATE, authChechSaga);
yield takeEvery(ACTIONS.SET_MODE, setModeSaga);
yield takeEvery(ACTIONS.START_EDITING, startEditingSaga);
yield takeEvery(ACTIONS.STOP_EDITING, stopEditingSaga);
yield takeEvery(ACTIONS.USER_LOGOUT, userLogoutSaga);
yield takeEvery(ACTIONS.SET_ACTIVE_STICKER, setActiveStickerSaga);
yield takeEvery(ACTIONS.SET_LOGO, setLogoSaga);
yield takeEvery(ACTIONS.ROUTER_CANCEL, routerCancelSaga);
yield takeEvery(ACTIONS.ROUTER_SUBMIT, routerSubmitSaga);
yield takeEvery([
ACTIONS.CLEAR_POLY,
ACTIONS.CLEAR_STICKERS,
ACTIONS.CLEAR_ALL,
ACTIONS.CLEAR_CANCEL,
], clearSaga);
yield takeLatest(ACTIONS.SEND_SAVE_REQUEST, sendSaveRequestSaga);
yield takeLatest(ACTIONS.SET_SAVE_SUCCESS, setSaveSuccessSaga);
yield takeLatest(ACTIONS.TAKE_A_SHOT, takeAShotSaga);
yield takeLatest(ACTIONS.CROP_A_SHOT, cropAShotSaga);
yield takeEvery(ACTIONS.SET_PROVIDER, setProviderSaga);
}