diff --git a/src/components/Field/Field.js b/src/components/Field/Field.js
index 027e08b2..0e987a16 100644
--- a/src/components/Field/Field.js
+++ b/src/components/Field/Field.js
@@ -1,4 +1,4 @@
-import React, { useState } from 'react';
+import React, { useState, useCallback, useMemo } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import './Field.css';
import Brush from '../Tools/Brush';
@@ -19,33 +19,47 @@ const Field = () => {
const field = useSelector((state) => state.auth.field);
const pixelSize = useSelector((state) => state.auth.pixelSize);
const brush = useSelector((state) => state.auth.brush);
+ const currentColor = useSelector((state) => state.auth.currentColor);
+ const historyColor = useSelector((state) => state.auth.historyColor);
- const changePixelColor = (index) => {
- dispatch({
- type: 'CHANGE_PIXEL_COLOR_AND_SAVE_TO_HISTORY',
- payload: { index },
- });
- };
+ const changePixelColor = useCallback(
+ (index) => {
+ if (!field || !field[index]) return;
+
+ const color = field[index].color;
+ if (color && !historyColor.includes(color)) {
+ dispatch({
+ type: 'ADD_COLOR_TO_HISTORY',
+ payload: { color },
+ });
+ }
+ dispatch({
+ type: 'CHANGE_PIXEL_COLOR_AND_SAVE_TO_HISTORY',
+ payload: { index, color: currentColor },
+ });
+ },
+ [dispatch, field, currentColor, historyColor]
+ );
- const clearField = () => {
+ const clearField = useCallback(() => {
dispatch({
type: 'CLEAR_FIELD',
});
- };
+ }, [dispatch]);
- const onKeyPressed = (e) => {
+ const onKeyPressed = useCallback((e) => {
if (e.code === 'Space' || e.type === 'mousedown') {
setContinueToDraw(true);
}
- };
+ }, []);
- const onKeyUp = (e) => {
+ const onKeyUp = useCallback((e) => {
if (e.code === 'Space' || e.type === 'mouseup') {
setContinueToDraw(false);
}
- };
+ }, []);
- const saveToImage = () => {
+ const saveToImage = useCallback(() => {
domtoimage
.toJpeg(document.getElementById('capture'), { quality: 0.95 })
.then((dataUrl) => {
@@ -54,11 +68,49 @@ const Field = () => {
link.href = dataUrl;
link.click();
});
- };
+ }, []);
- if (!field || !Array.isArray(field)) {
- return
Loading...
;
- }
+ const fieldMemo = useMemo(() => {
+ if (!field || !Array.isArray(field)) {
+ return Loading...
;
+ }
+
+ return (
+ setContinueToDraw(false)}
+ tabIndex="0"
+ >
+ {field.map((el, i) => (
+
changePixelColor(i)}
+ onMouseOver={
+ brush !== 'fill' && brush !== 'fillPart'
+ ? () => changePixelColor(continueToDraw ? i : undefined)
+ : null
+ }
+ >
+ {}
+
+ ))}
+
+ );
+ }, [field, fieldSize, pixelSize, gridMap, brush, changePixelColor, onKeyPressed, onKeyUp, continueToDraw]);
return (
@@ -103,41 +155,7 @@ const Field = () => {
{/* FIELD DRAW */}
-
-
setContinueToDraw(false)}
- tabIndex="0"
- >
- {field.map((el, i) => (
-
changePixelColor(i)}
- onMouseOver={
- brush !== 'fill' && brush !== 'fillPart'
- ? () => changePixelColor(continueToDraw ? i : undefined)
- : null
- }
- >
- {}
-
- ))}
-
-
+ {fieldMemo}
diff --git a/src/components/Field/FieldSize.js b/src/components/Field/FieldSize.js
index 5a991f8b..7235a3c4 100644
--- a/src/components/Field/FieldSize.js
+++ b/src/components/Field/FieldSize.js
@@ -1,56 +1,53 @@
import React from 'react';
-import { connect } from 'react-redux';
+import { useSelector, useDispatch } from 'react-redux';
-const FieldSize = ({ currentSize, changeFieldSize }) => (
-
-);
-
-const mapStateToProps = (state) => ({
- currentSize: state.fieldSize,
-});
-
-const mapDispatchToProps = (dispatch) => ({
- changeFieldSize: (size) =>
+ const changeFieldSize = (size) => {
dispatch({
type: 'CHANGE_FIELD_SIZE',
payload: { size },
- }),
-});
+ });
+ };
+
+ return (
+
+ );
+};
-export default connect(mapStateToProps, mapDispatchToProps)(FieldSize);
+export default FieldSize;
diff --git a/src/components/Tools/Brush.js b/src/components/Tools/Brush.js
index 2782a1c4..5921dbb2 100644
--- a/src/components/Tools/Brush.js
+++ b/src/components/Tools/Brush.js
@@ -1,11 +1,14 @@
import React from 'react';
-import { connect } from 'react-redux';
+import { useSelector, useDispatch } from 'react-redux';
import classnames from 'classnames';
import fill from '../icons/fill.png';
import random from '../icons/random.jpeg';
import colorpicker from '../icons/colorpicker.png';
-const Brush = ({ changeBrush, fieldRandomBrush, brush }) => {
+const Brush = () => {
+ const dispatch = useDispatch();
+ const brush = useSelector((state) => state.auth.brush);
+
const brushTypes = [
{ type: 'dot', label: '▣' },
{ type: 'horizontal', label: '↔' },
@@ -15,9 +18,23 @@ const Brush = ({ changeBrush, fieldRandomBrush, brush }) => {
{ type: 'fillPart', label: 'fillPart' },
{ type: 'mirrorH', label: '═' },
{ type: 'mirrorV', label: '||' },
- { type: 'color-picker', label:
}
+ { type: 'color-picker', label:
},
];
+ const changeBrush = (type) => {
+ dispatch({
+ type: 'CHANGE_BRUSH',
+ payload: { brush: type },
+ });
+ };
+
+ const fieldRandomBrush = () => {
+ dispatch({
+ type: 'FILL_RANDOM_BRUSH',
+ payload: {},
+ });
+ };
+
return (
{brushTypes.map(({ type, label }) => (
@@ -36,19 +53,4 @@ const Brush = ({ changeBrush, fieldRandomBrush, brush }) => {
);
};
-const mapStateToProps = (state) => ({
- brush: state.brush
-});
-
-const mapDispatchToProps = (dispatch) => ({
- changeBrush: (brush) => dispatch({
- type: 'CHANGE_BRUSH',
- payload: { brush }
- }),
- fieldRandomBrush: () => dispatch({
- type: 'FILL_RANDOM_BRUSH',
- payload: {}
- })
-});
-
-export default connect(mapStateToProps, mapDispatchToProps)(Brush);
+export default Brush;
diff --git a/src/components/Tools/ColorHistory.js b/src/components/Tools/ColorHistory.js
index 76379b39..4ae9d981 100644
--- a/src/components/Tools/ColorHistory.js
+++ b/src/components/Tools/ColorHistory.js
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { useCallback } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { v4 as uuidv4 } from 'uuid';
import history_del from '../icons/history_del.png';
@@ -6,19 +6,19 @@ import history_del from '../icons/history_del.png';
const ColorHistory = () => {
const dispatch = useDispatch();
const historyColor = useSelector((state) => state.auth.historyColor);
-console.log(historyColor)
- const changeColor = (color) => {
+
+ const changeColor = useCallback((color) => {
dispatch({
type: 'CHANGE_CURRENT_COLOR',
payload: { color },
});
- };
+ }, [dispatch]);
- const deleteColorHistory = () => {
+ const deleteColorHistory = useCallback(() => {
dispatch({
type: 'DELETE_COLOR_HISTORY',
});
- };
+ }, [dispatch]);
return (
@@ -43,4 +43,4 @@ console.log(historyColor)
);
};
-export default ColorHistory;
+export default React.memo(ColorHistory);
diff --git a/src/components/redux/reducers.js b/src/components/redux/reducers.js
index 57950ce8..bc5f207d 100644
--- a/src/components/redux/reducers.js
+++ b/src/components/redux/reducers.js
@@ -18,9 +18,16 @@ const drawField = (state = initialState, action) => {
case 'CHANGE_CURRENT_COLOR':
return {
...state,
- currentColor: action.payload.color
+ currentColor: action.payload.color,
};
- // ******** START DRAW FUNCTIONAL **********************
+ case 'ADD_COLOR_TO_HISTORY':
+ if (!state.historyColor.includes(action.payload.color)) {
+ return {
+ ...state,
+ historyColor: [...state.historyColor, action.payload.color]
+ };
+ }
+ return state;
case 'CHANGE_PIXEL_COLOR_AND_SAVE_TO_HISTORY':
let copyField;
const copyHistoryColor = [...state.historyColor, state.currentColor];
@@ -28,7 +35,7 @@ const drawField = (state = initialState, action) => {
if (action.payload.index) {
return {
...state,
- currentColor: state.field[action.payload.index].color
+ currentColor: state.field[action.payload.index].color,
};
}
}
@@ -40,11 +47,11 @@ const drawField = (state = initialState, action) => {
size,
state.fieldSize,
state.field[action.payload.index].color,
- state.currentColor
+ state.currentColor,
);
return {
...state,
- field: newField
+ field: newField,
};
}
@@ -226,37 +233,40 @@ const drawField = (state = initialState, action) => {
};
function fillParticip(arrJSON, current, size, max, oldColor, newColor) {
- console.log(current, size, oldColor);
const a = JSON.parse(arrJSON);
if (oldColor === newColor) return a;
let next = [];
- const stop = [];
+ const stop = new Set();
function ch(current) {
if (a[current] && a[current].color === oldColor) {
a[current].color = newColor;
- stop.push(current);
+ stop.add(current);
let up = current - size;
let down = current + size;
let left = current - 1;
let right = current + 1;
- if (right % size === 0) {
- stop.push(right);
+
+ if (current % size !== 0) {
+ next.push(left);
+ }
+ if ((current + 1) % size !== 0) {
+ next.push(right);
}
- if (left % size === size - 1) {
- stop.push(left);
+ if (up >= 0) {
+ next.push(up);
}
- next.push(
- ...[up, down, left, right].filter(
- (e) => e >= 0 && !stop.includes(e) && !next.includes(e) && e <= max
- )
- );
+ if (down < max) {
+ next.push(down);
+ }
+
+ next = next.filter((e) => e >= 0 && !stop.has(e));
} else {
- stop.push(current);
+ stop.add(current);
}
next = next.filter((el) => el !== current);
- return next.length > 0 ? ch(next[0], size, newColor, max) : a;
+ return next.length > 0 ? ch(next[0]) : a;
}
return ch(current);
diff --git a/src/styles.css b/src/styles.css
index 3353b2a9..26d9ddb2 100644
--- a/src/styles.css
+++ b/src/styles.css
@@ -110,7 +110,10 @@ input:checked + .slider:before {
.btn-pushed {
background: linear-gradient(to bottom, #fceadd 5%, rgba(226, 91, 255, .94) 100%)
}
+.btn-pushed:hover{
+ background: linear-gradient(to bottom, #fad5ba 5%, rgba(204, 30, 241, 0.94) 100%)
+}
.warn {
background: linear-gradient(to bottom, #fcdde3 5%, rgba(245, 130, 140, .65) 100%);
border: 1px solid #ef6565