diff --git a/src/components/dialogs/SaveDialog.tsx b/src/components/dialogs/SaveDialog.tsx index ac47f7a..59c6f08 100644 --- a/src/components/dialogs/SaveDialog.tsx +++ b/src/components/dialogs/SaveDialog.tsx @@ -14,6 +14,11 @@ interface Props extends IRootState { width: number, setMode: typeof setMode, sendSaveRequest: typeof sendSaveRequest, + save_error: string, + + save_loading: boolean, + save_finished: boolean, + save_overwriting: boolean, } interface State { @@ -44,7 +49,6 @@ export class SaveDialog extends React.Component { setAddress = ({ target: { value } }) => this.setState({ address: (value || '') }); - // cancelSaving = () => this.props.editor.changeMode(MODES.NONE); cancelSaving = () => this.props.setMode(MODES.NONE); sendSaveRequest = (e, force = false) => { @@ -70,12 +74,14 @@ export class SaveDialog extends React.Component { render() { const { title, is_public } = this.state; - const { save_error, save_finished, save_overwriting, width } = this.props; + const { save_error, save_finished, save_overwriting, width, save_loading } = this.props; const { host, protocol } = getUrlData(); return (
+
+
Название
diff --git a/src/redux/user/actions.ts b/src/redux/user/actions.ts index e820f27..1081666 100644 --- a/src/redux/user/actions.ts +++ b/src/redux/user/actions.ts @@ -31,6 +31,7 @@ export const clearCancel = () => ({ type: ACTIONS.CLEAR_CANCEL }); export const sendSaveRequest = payload => ({ type: ACTIONS.SEND_SAVE_REQUEST, ...payload }); export const resetSaveDialog = () => ({ type: ACTIONS.RESET_SAVE_DIALOG }); +export const setSaveLoading = save_loading => ({ type: ACTIONS.SET_SAVE_LOADING, save_loading }); export const setSaveSuccess = payload => ({ type: ACTIONS.SET_SAVE_SUCCESS, ...payload }); export const setSaveError = save_error => ({ type: ACTIONS.SET_SAVE_ERROR, save_error }); export const setSaveOverwrite = () => ({ type: ACTIONS.SET_SAVE_OVERWRITE }); diff --git a/src/redux/user/constants.ts b/src/redux/user/constants.ts index 7df35e5..e0003e4 100644 --- a/src/redux/user/constants.ts +++ b/src/redux/user/constants.ts @@ -30,6 +30,7 @@ export const ACTIONS: IActions = { CLEAR_CANCEL: 'CLEAR_CANCEL', SEND_SAVE_REQUEST: 'SEND_SAVE_REQUEST', + SET_SAVE_LOADING: 'SET_SAVE_LOADING', CANCEL_SAVE_REQUEST: 'CANCEL_SAVE_REQUEST', RESET_SAVE_DIALOG: 'RESET_SAVE_DIALOG', diff --git a/src/redux/user/reducer.ts b/src/redux/user/reducer.ts index 453c956..50b8a7d 100644 --- a/src/redux/user/reducer.ts +++ b/src/redux/user/reducer.ts @@ -39,6 +39,7 @@ interface IRootReducer { save_finished: boolean, save_overwriting: boolean, save_processing: boolean, + save_loading: boolean, dialog: IDialogs[keyof IDialogs], dialog_active: boolean, @@ -147,6 +148,10 @@ const setSaveError: ActionHandler = (state, ...state, save_error, save_finished: false, save_processing: false }); +const setSaveLoading: ActionHandler = (state, { save_loading }) => ({ + ...state, save_loading +}); + const setSaveOverwrite: ActionHandler = (state) => ({ ...state, save_overwriting: true, @@ -279,6 +284,7 @@ const HANDLERS = ({ [ACTIONS.SET_ADDRESS_ORIGIN]: setAddressOrigin, [ACTIONS.SET_SAVE_ERROR]: setSaveError, + [ACTIONS.SET_SAVE_LOADING]: setSaveLoading, [ACTIONS.SET_SAVE_OVERWRITE]: setSaveOverwrite, [ACTIONS.SET_SAVE_SUCCESS]: setSaveSuccess, [ACTIONS.SEND_SAVE_REQUEST]: sendSaveRequest, @@ -327,6 +333,7 @@ export const INITIAL_STATE: IRootReducer = { save_finished: false, save_overwriting: false, save_processing: false, + save_loading: false, dialog: DIALOGS.NONE, dialog_active: false, diff --git a/src/redux/user/sagas.ts b/src/redux/user/sagas.ts index c2ff2ee..8f38021 100644 --- a/src/redux/user/sagas.ts +++ b/src/redux/user/sagas.ts @@ -17,7 +17,7 @@ import { setSaveError, setSaveOverwrite, setSaveSuccess, setTitle, searchSetTab, - setUser, setDialog, setPublic, setAddressOrigin, setProvider, changeProvider, openMapDialog, + setUser, setDialog, setPublic, setAddressOrigin, setProvider, changeProvider, openMapDialog, setSaveLoading, } from '$redux/user/actions'; import { getUrlData, parseQuery, pushLoaderState, pushNetworkInitError, pushPath, replacePath } from '$utils/history'; import { editor } from '$modules/Editor'; @@ -285,6 +285,8 @@ function* sendSaveRequestSaga({ const { logo, distance } = yield select(getState); const { id, token } = yield select(getUser); + yield put(setSaveLoading(true)); + const { result, timeout, cancel } = yield race({ result: postMap({ id, token, route, stickers, title, force, address, logo, distance, provider, is_public @@ -293,6 +295,8 @@ function* sendSaveRequestSaga({ cancel: take(ACTIONS.RESET_SAVE_DIALOG), }); + yield put(setSaveLoading(false)); + if (cancel) return yield put(setMode(MODES.NONE)); if (result && result.mode === 'overwriting') return yield put(setSaveOverwrite()); if (result && result.mode === 'exists') return yield put(setSaveError(TIPS.SAVE_EXISTS)); diff --git a/src/sprites/icon.svg b/src/sprites/icon.svg index c1f9ef0..c1567be 100644 --- a/src/sprites/icon.svg +++ b/src/sprites/icon.svg @@ -369,6 +369,11 @@ + + + + + diff --git a/src/styles/save.less b/src/styles/save.less index 77e01e8..a21e0dd 100644 --- a/src/styles/save.less +++ b/src/styles/save.less @@ -13,6 +13,45 @@ box-sizing: border-box; } +@keyframes jump { + 0% { transform: translate3d(0, 0, 0) scale(0.5); } + 100% { transform: translate3d(0, -20px, 0) scale(1); } +} + +.save-loader { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: darken(fade(@blue_secondary, 80%), 20%); + z-index: 2; + display: flex; + align-items: center; + justify-content: center; + transition: opacity 250ms; + opacity: 0; + touch-action: none; + pointer-events: none; + + svg { + fill: white; + + &:nth-child(2) { animation-delay: 200ms; } + &:nth-child(3) { animation-delay: 400ms; } + } + + &.active { + opacity: 1; + touch-action: all; + pointer-events: all; + + svg { + animation: jump infinite alternate 600ms; + } + } +} + .save-description { padding: 5px 10px; }