diff --git a/client/src/common/components/countdown/Countdown.jsx b/client/src/common/components/countdown/Countdown.jsx
index 8f1f3a3e9..8fcb76316 100644
--- a/client/src/common/components/countdown/Countdown.jsx
+++ b/client/src/common/components/countdown/Countdown.jsx
@@ -1,9 +1,8 @@
-import { useEffect, useState } from 'react';
+import { memo, useEffect, useState } from 'react';
import { formatDisplay } from '../../dateConfig';
import styles from './Countdown.module.css';
-export default function Countdown(props) {
- const { time, small, hideZeroHours } = props;
+const Countdown = ({ time, small, hideZeroHours }) => {
const [clock, setClock] = useState(time);
let display = '-- : -- : --';
@@ -20,4 +19,6 @@ export default function Countdown(props) {
{display}
);
-}
+};
+
+export default memo(Countdown);
diff --git a/client/src/common/components/views/Paginator.module.css b/client/src/common/components/views/Paginator.module.css
index de283765e..e52e2dcfc 100644
--- a/client/src/common/components/views/Paginator.module.css
+++ b/client/src/common/components/views/Paginator.module.css
@@ -1,5 +1,3 @@
-@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;600;800&display=swap');
-
.entries {
display: flex;
flex-direction: column;
diff --git a/client/src/features/control/PlaybackButtons.jsx b/client/src/features/control/PlaybackButtons.jsx
new file mode 100644
index 000000000..a25a783da
--- /dev/null
+++ b/client/src/features/control/PlaybackButtons.jsx
@@ -0,0 +1,73 @@
+import { memo } from 'react';
+import style from './PlaybackControl.module.css';
+import StartIconBtn from '../../common/components/buttons/StartIconBtn';
+import PauseIconBtn from '../../common/components/buttons/PauseIconBtn';
+import PrevIconBtn from '../../common/components/buttons/PrevIconBtn';
+import NextIconBtn from '../../common/components/buttons/NextIconBtn';
+import RollIconBtn from '../../common/components/buttons/RollIconBtn';
+import UnloadIconBtn from '../../common/components/buttons/UnloadIconBtn';
+import ReloadIconButton from '../../common/components/buttons/ReloadIconBtn';
+
+const areEqual = (prevProps, nextProps) => {
+ return (
+ prevProps.playback === nextProps.playback &&
+ prevProps.selectedId === nextProps.selectedId
+ );
+};
+
+const Playback = ({ playback, selectedId, playbackControl }) => {
+ return (
+
+
playbackControl('start')}
+ disabled={!selectedId}
+ />
+ playbackControl('pause')}
+ disabled={!selectedId}
+ />
+ playbackControl('roll')}
+ />
+
+ );
+};
+
+const Transport = ({ selectedId, playbackControl }) => {
+ return (
+
+
playbackControl('previous')} />
+ playbackControl('next')} />
+ playbackControl('unload')}
+ disabled={!selectedId}
+ />
+ playbackControl('reload')}
+ disabled={!selectedId}
+ />
+
+ );
+};
+
+const PlaybackButtons = (props) => {
+ const { playback, selectedId } = props;
+ return (
+ <>
+
+
+ >
+ );
+};
+
+export default memo(PlaybackButtons, areEqual);
diff --git a/client/src/features/control/PlaybackControl.jsx b/client/src/features/control/PlaybackControl.jsx
index 36947fc76..3d74e69f8 100644
--- a/client/src/features/control/PlaybackControl.jsx
+++ b/client/src/features/control/PlaybackControl.jsx
@@ -4,13 +4,7 @@ import { stringFromMillis } from '../../common/dateConfig';
import { useEffect, useState } from 'react';
import { useSocket } from '../../app/context/socketContext';
import { Button } from '@chakra-ui/button';
-import StartIconBtn from '../../common/components/buttons/StartIconBtn';
-import PauseIconBtn from '../../common/components/buttons/PauseIconBtn';
-import PrevIconBtn from '../../common/components/buttons/PrevIconBtn';
-import NextIconBtn from '../../common/components/buttons/NextIconBtn';
-import RollIconBtn from '../../common/components/buttons/RollIconBtn';
-import UnloadIconBtn from '../../common/components/buttons/UnloadIconBtn';
-import ReloadIconButton from '../../common/components/buttons/ReloadIconBtn';
+import PlaybackButtons from './PlaybackButtons';
export default function PlaybackControl() {
const socket = useSocket();
@@ -146,35 +140,11 @@ export default function PlaybackControl() {
-
-
-
playbackControl('start')}
- disabled={!selectedId}
- />
- playbackControl('pause')}
- disabled={!selectedId}
- />
- playbackControl('roll')}
- />
-
-
-
playbackControl('previous')} />
- playbackControl('next')} />
- playbackControl('unload')}
- disabled={!selectedId}
- />
- playbackControl('reload')}
- disabled={!selectedId}
- />
-
+
);
}
diff --git a/client/src/features/editors/Editor.jsx b/client/src/features/editors/Editor.jsx
index b47a7636e..6b062a9ae 100644
--- a/client/src/features/editors/Editor.jsx
+++ b/client/src/features/editors/Editor.jsx
@@ -40,7 +40,7 @@ export default function Editor() {
diff --git a/client/src/features/editors/list/EventBlock.jsx b/client/src/features/editors/list/EventBlock.jsx
index dc16ad949..1914af8a8 100644
--- a/client/src/features/editors/list/EventBlock.jsx
+++ b/client/src/features/editors/list/EventBlock.jsx
@@ -1,5 +1,5 @@
import { FiChevronDown, FiChevronUp, FiMoreVertical } from 'react-icons/fi';
-import { useState } from 'react';
+import { memo, useEffect, useState } from 'react';
import EventTimes from '../../../common/components/eventTimes/EventTimes';
import { showErrorToast } from '../../../common/helpers/toastManager';
import style from './Block.module.css';
@@ -9,13 +9,30 @@ import ActionButtons from './ActionButtons';
import VisibleIconBtn from '../../../common/components/buttons/VisibleIconBtn';
import DeleteIconBtn from '../../../common/components/buttons/DeleteIconBtn';
-export default function EventBlock(props) {
+const areEqual = (prevProps, nextProps) => {
+ let shouldNotRerender =
+ prevProps.data.revision === nextProps.data.revision &&
+ prevProps.selected === nextProps.selected &&
+ prevProps.next === nextProps.next;
+ console.log('debug memo2', shouldNotRerender);
+ return (
+ prevProps.data.revision === nextProps.data.revision &&
+ prevProps.selected === nextProps.selected &&
+ prevProps.next === nextProps.next
+ );
+};
+
+const EventBlock = (props) => {
const { data, selected, next, delay, index, eventsHandler } = props;
const [more, setMore] = useState(false);
- // NOTE: cheating to add responsiveness
const [visible, setVisible] = useState(data.isPublic || false);
+ // Set visibility indicator
+ useEffect(() => {
+ setVisible(data.isPublic);
+ }, [data.isPublic]);
+
const updateValues = (field, value) => {
// validate field
if (field in data) {
@@ -56,7 +73,6 @@ export default function EventBlock(props) {
const handleVisibleToggle = () => {
let viz = !data.isPublic || !visible;
- setVisible(viz);
updateValues('isPublic', viz);
};
@@ -85,13 +101,6 @@ export default function EventBlock(props) {
submitHandler={handleTitleSubmit}
underlined
/>
-
+
) : (
@@ -129,4 +145,6 @@ export default function EventBlock(props) {
);
-}
+};
+
+export default memo(EventBlock, areEqual);
diff --git a/client/src/features/editors/list/EventList.jsx b/client/src/features/editors/list/EventList.jsx
index edfe79a44..dfe2c8ccd 100644
--- a/client/src/features/editors/list/EventList.jsx
+++ b/client/src/features/editors/list/EventList.jsx
@@ -1,6 +1,6 @@
import style from './List.module.css';
-import { useEffect, useState } from 'react';
+import { Fragment, useEffect, useState } from 'react';
import { useSocket } from '../../../app/context/socketContext';
import tinykeys from 'tinykeys';
import Empty from '../../../common/state/Empty';
@@ -111,7 +111,7 @@ export default function EventList(props) {
if (e.type === 'delay') cumulativeDelay += e.duration;
else if (e.type === 'block') cumulativeDelay = 0;
return (
-
+
)}
-
+
);
})}
diff --git a/client/src/features/menu/EventListMenu.jsx b/client/src/features/menu/EventListMenu.jsx
index 8baf11a93..29aed0d5c 100644
--- a/client/src/features/menu/EventListMenu.jsx
+++ b/client/src/features/menu/EventListMenu.jsx
@@ -1,3 +1,4 @@
+import { memo, useCallback } from 'react';
import { FiChevronDown } from 'react-icons/fi';
import {
Button,
@@ -9,9 +10,9 @@ import {
} from '@chakra-ui/react';
import AddIconBtn from '../../common/components/buttons/AddIconBtn';
import style from './EventListMenu.module.css';
+import MenuActionButtons from '../editors/list/MenuActionButtons';
-export default function EventListMenu(props) {
- const { eventsHandler } = props;
+const EventListMenu = ({ eventsHandler }) => {
const buttonProps = {
size: 'sm',
variant: 'outline',
@@ -27,9 +28,9 @@ export default function EventListMenu(props) {
backgroundColor: 'rgba(255,255,255,0.67)',
};
- const addHandler = () => {
+ const addHandler = useCallback(() => {
eventsHandler('add', { type: 'event', order: 0 });
- };
+ }, [eventsHandler]);
return (
@@ -58,6 +59,9 @@ export default function EventListMenu(props) {
+ {/*
*/}
);
-}
+};
+
+export default memo(EventListMenu);
diff --git a/server/classes/EventTimer.js b/server/classes/EventTimer.js
index 92ac96ab5..53153b225 100644
--- a/server/classes/EventTimer.js
+++ b/server/classes/EventTimer.js
@@ -1,5 +1,7 @@
const Timer = require('./Timer');
const socketIo = require('socket.io');
+// DEBUG
+const { instrument } = require("@socket.io/admin-ui");
/*
* EventTimer adds functions specific to APP
@@ -71,6 +73,11 @@ class EventTimer extends Timer {
},
});
+ // DEBUG
+ instrument(this.io, {
+ auth: false
+ });
+
// set recurrent emits
this._interval = setInterval(
() => this.broadcastTimer(),
diff --git a/server/controllers/eventsController.js b/server/controllers/eventsController.js
index 8d009a444..ac7b4196f 100644
--- a/server/controllers/eventsController.js
+++ b/server/controllers/eventsController.js
@@ -14,6 +14,7 @@ function incrementFrom(start, incr = 1) {
db.get('events')
.find({ id: e.id })
.assign({ order: e.order + incr })
+ .update('revision', (n) => n + 1)
.write();
});
}
@@ -163,6 +164,7 @@ exports.eventsPatch = async (req, res) => {
db.get('events')
.find({ id: req.body.id })
.assign({ ...req.body })
+ .update('revision', (n) => n + 1)
.write();
// update timer
diff --git a/server/data/eventsDefinition.js b/server/data/eventsDefinition.js
index 8f4acd1f5..2599f7330 100644
--- a/server/data/eventsDefinition.js
+++ b/server/data/eventsDefinition.js
@@ -7,6 +7,7 @@ const event = {
timeEnd: 0,
isPublic: false,
type: 'event',
+ revision: 0,
};
const delay = {