store / reducers fixes, move websocketClient to reducers

This commit is contained in:
HF 2020-01-08 15:58:21 +01:00
parent 337fbf2462
commit e7a16fa3b9
12 changed files with 148 additions and 41 deletions

View File

@ -1,8 +1,5 @@
/* @flow */
import swal from 'sweetalert2';
import 'sweetalert2/src/sweetalert2.scss';
import type {
Action,
ThunkAction,
@ -11,13 +8,27 @@ import type {
import type { Cell } from '../core/Cell';
import type { ColorIndex } from '../core/Palette';
import ProtocolClient from '../socket/ProtocolClient';
import { loadImage } from '../ui/loadImage';
import {
getColorIndexOfPixel,
} from '../core/utils';
export function sweetAlert(
title: string,
text: string,
icon: string,
confirmButtonText: string,
): Action {
return {
type: 'ALERT',
title,
text,
icon,
confirmButtonText,
};
}
export function toggleChatBox(): Action {
return {
type: 'TOGGLE_CHAT_BOX',
@ -255,12 +266,12 @@ export function requestPlacePixel(
}
dispatch(pixelFailure());
swal.fire({
title: (errorTitle || `Error ${response.status}`),
text: errors[0].msg,
icon: 'error',
confirmButtonText: 'OK',
});
dispatch(sweetAlert(
(errorTitle || `Error ${response.status}`),
errors[0].msg,
'error',
'OK',
));
} finally {
dispatch(setPlaceAllowed(true));
}
@ -418,7 +429,6 @@ export function fetchChunk(canvasId, center: Cell): PromiseAction {
return async (dispatch) => {
dispatch(requestBigChunk(center));
try {
ProtocolClient.registerChunk([cx, cy]);
const url = `/chunks/${canvasId}/${cx}/${cy}.bmp`;
const response = await fetch(url);
if (response.ok) {
@ -475,7 +485,6 @@ export function receiveMe(
minecraftname,
canvases,
} = me;
ProtocolClient.setName(name);
return {
type: 'RECEIVE_ME',
name: (name) || null,
@ -504,7 +513,6 @@ export function receiveStats(
export function setName(
name: string,
): Action {
ProtocolClient.setName(name);
return {
type: 'SET_NAME',
name,
@ -557,9 +565,7 @@ export function fetchMe(): PromiseAction {
if (response.ok) {
const me = await response.json();
await dispatch(receiveMe(me));
const state = getState();
ProtocolClient.setCanvas(state.canvas.canvasId);
dispatch(receiveMe(me));
}
};
}
@ -660,18 +666,14 @@ export function onViewFinishChange(): Action {
}
export function urlChange(): PromiseAction {
return async (dispatch, getState) => {
await dispatch(reloadUrl());
const state = getState();
ProtocolClient.setCanvas(state.canvas.canvasId);
return (dispatch, getState) => {
dispatch(reloadUrl());
};
}
export function switchCanvas(canvasId: number): PromiseAction {
return async (dispatch, getState) => {
await dispatch(selectCanvas(canvasId));
const state = getState();
ProtocolClient.setCanvas(state.canvas.canvasId);
dispatch(onViewFinishChange());
};
}

View File

@ -8,6 +8,12 @@ import type { State } from '../reducers';
export type Action =
{ type: 'LOGGED_OUT' }
// my actions
| { type: 'ALERT',
title: string,
text: string,
icon: string,
confirmButtonText: string,
}
| { type: 'TOGGLE_GRID' }
| { type: 'TOGGLE_PIXEL_NOTIFY' }
| { type: 'TOGGLE_AUTO_ZOOM_IN' }
@ -38,13 +44,27 @@ export type Action =
| { type: 'RECEIVE_IMAGE_TILE', center: Cell, tile: Image }
| { type: 'RECEIVE_BIG_CHUNK_FAILURE', center: Cell, error: Error }
| { type: 'RECEIVE_COOLDOWN', waitSeconds: number }
| { type: 'RECEIVE_PIXEL_UPDATE', i: number, j: number, offset: number, color: ColorIndex }
| { type: 'RECEIVE_PIXEL_UPDATE',
i: number,
j: number,
offset: number,
color: ColorIndex,
}
| { type: 'RECEIVE_ONLINE', online: number }
| { type: 'RECEIVE_CHAT_MESSAGE', name: string, text: string }
| { type: 'RECEIVE_CHAT_HISTORY', data: Array }
| { type: 'RECEIVE_ME', name: string, waitSeconds: number, messages: Array,
mailreg: boolean, totalPixels: number, dailyTotalPixels: number,
ranking: number, dailyRanking: number, minecraftname: string, canvases: Object}
| { type: 'RECEIVE_ME',
name: string,
waitSeconds: number,
messages: Array,
mailreg: boolean,
totalPixels: number,
dailyTotalPixels: number,
ranking: number,
dailyRanking: number,
minecraftname: string,
canvases: Object
}
| { type: 'RECEIVE_STATS', totalRanking: Object, totalDailyRanking: Object }
| { type: 'SET_NAME', name: string }
| { type: 'SET_MINECRAFT_NAME', minecraftname: string }

View File

@ -7,7 +7,6 @@
import React from 'react';
import type { State } from '../reducers';
import store from '../ui/store';
import { requestPlacePixel } from '../actions';
@ -18,7 +17,7 @@ function onCaptcha(token: string) {
const { canvasId, coordinates, color } = window.pixel;
store.dispatch(requestPlacePixel(canvasId, coordinates, color, token));
grecaptcha.reset();
window.grecaptcha.reset();
}
// https://stackoverflow.com/questions/41717304/recaptcha-google-data-callback-with-angularjs
window.onCaptcha = onCaptcha;

View File

@ -11,7 +11,7 @@
import { playAd } from '../ui/ads';
export default (store) => (next) => (action) => {
export default () => (next) => (action) => {
switch (action.type) {
case 'PLACE_PIXEL': {
// wait 1 second

View File

@ -22,7 +22,7 @@
import track from './track';
export default (store) => (next) => (action) => {
export default () => (next) => (action) => {
track(action);
return next(action);
};

View File

@ -20,6 +20,6 @@
* DEALINGS IN THE SOFTWARE
*/
export default (store) => (next) => (action) => (Array.isArray(action)
export default () => (next) => (action) => (Array.isArray(action)
? action.map(next)
: next(action));

View File

@ -3,11 +3,13 @@
import { applyMiddleware, createStore, compose } from 'redux';
import thunk from 'redux-thunk';
import { createLogger } from 'redux-logger';
import { persistStore, autoRehydrate } from 'redux-persist';
import { persistStore } from 'redux-persist';
import ads from './ads';
import audio from './audio';
import analytics from './analytics';
import swal from './sweetAlert';
import protocolClientHook from './protocolClientHook';
// import ads from './ads';
// import analytics from './analytics';
import array from './array';
import promise from './promise';
import notifications from './notifications';
@ -18,7 +20,7 @@ import reducers from '../reducers';
const isDebuggingInChrome = __DEV__ && !!window.navigator.userAgent;
const logger = createLogger({
predicate: (getState, action) => isDebuggingInChrome,
predicate: () => isDebuggingInChrome,
collapsed: true,
duration: true,
});
@ -31,11 +33,13 @@ const store = createStore(
thunk,
promise,
array,
ads,
swal,
audio,
notifications,
title,
analytics,
protocolClientHook,
// ads,
// analytics,
logger,
),
),

View File

@ -5,7 +5,7 @@
*/
export default (store) => (next) => (action) => {
export default () => (next) => (action) => {
try {
switch (action.type) {
case 'PLACE_PIXEL': {

View File

@ -25,6 +25,6 @@ function warn(error) {
throw error; // To let the caller handle the rejection
}
export default (store) => (next) => (action) => (typeof action.then === 'function'
export default () => (next) => (action) => (typeof action.then === 'function'
? Promise.resolve(action).then(next, warn)
: next(action));

View File

@ -0,0 +1,51 @@
/*
* Hooks for websocket client to store changes
*
* @flow
*/
import ProtocolClient from '../socket/ProtocolClient';
export default (store) => (next) => (action) => {
switch (action.type) {
case 'RECEIVE_BIG_CHUNK': {
const [, cx, cy] = action.center;
ProtocolClient.registerChunk([cx, cy]);
break;
}
case 'RECEIVE_ME': {
const { name } = action;
ProtocolClient.setName(name);
break;
}
case 'SET_NAME': {
const { name } = action;
ProtocolClient.setName(name);
break;
}
default:
// nothing
}
const ret = next(action);
// executed after reducers
switch (action.type) {
case 'RELOAD_URL':
case 'SELECT_CANVAS':
case 'RECEIVE_ME': {
const state = store.getState();
const { canvasId } = state.canvas;
ProtocolClient.setCanvas(canvasId);
break;
}
default:
// nothing
}
return ret;
};

31
src/store/sweetAlert.js Normal file
View File

@ -0,0 +1,31 @@
/*
* @flow
*/
import swal from 'sweetalert2';
import 'sweetalert2/src/sweetalert2.scss';
export default () => (next) => (action) => {
switch (action.type) {
case 'ALERT': {
const {
title,
text,
icon,
confirmButtonText,
} = action;
swal.fire({
title,
text,
icon,
confirmButtonText,
});
break;
}
default:
// nothing
}
return next(action);
};

View File

@ -26,12 +26,12 @@ import type { Action } from '../actions/types';
export default function track(action: Action): void {
if (typeof ga === 'undefined') return;
if (typeof window.ga === 'undefined') return;
switch (action.type) {
case 'PLACE_PIXEL': {
const [x, y] = action.coordinates;
ga('send', {
window.ga('send', {
hitType: 'event',
eventCategory: 'Place',
eventAction: action.color,