From 272458b4129c50d352f5d2dccce0086de95df4f9 Mon Sep 17 00:00:00 2001
From: cv <34649812+cpvalente@users.noreply.github.com>
Date: Thu, 20 May 2021 12:38:48 +0200
Subject: [PATCH 1/5] cleanup buttons
---
.../common/components/buttons/CollapseBtn.jsx | 24 ++++++++++---------
.../common/components/buttons/CurrentBtn.jsx | 4 ++--
.../common/components/buttons/ExpandBtn.jsx | 24 ++++++++++---------
.../common/components/buttons/LockIconBtn.jsx | 21 ++++++++++++++++
4 files changed, 49 insertions(+), 24 deletions(-)
create mode 100644 client/src/common/components/buttons/LockIconBtn.jsx
diff --git a/client/src/common/components/buttons/CollapseBtn.jsx b/client/src/common/components/buttons/CollapseBtn.jsx
index 490af34bb..77891b087 100644
--- a/client/src/common/components/buttons/CollapseBtn.jsx
+++ b/client/src/common/components/buttons/CollapseBtn.jsx
@@ -1,18 +1,20 @@
-import { Button } from '@chakra-ui/button';
+import { IconButton } from '@chakra-ui/button';
+import { Tooltip } from '@chakra-ui/tooltip';
import { FiChevronsUp } from 'react-icons/fi';
export default function CollapseBtn(props) {
const { clickhandler } = props;
return (
- }
- colorScheme='white'
- variant='outline'
- onClick={clickhandler}
- _focus={{ boxShadow: 'none' }}
- >
- Collapse All
-
+
+ }
+ colorScheme='white'
+ variant='outline'
+ background='#fff1'
+ onClick={clickhandler}
+ _focus={{ boxShadow: 'none' }}
+ />
+
);
}
diff --git a/client/src/common/components/buttons/CurrentBtn.jsx b/client/src/common/components/buttons/CurrentBtn.jsx
index 2bea19028..a15c62aa0 100644
--- a/client/src/common/components/buttons/CurrentBtn.jsx
+++ b/client/src/common/components/buttons/CurrentBtn.jsx
@@ -2,13 +2,13 @@ import { Button } from '@chakra-ui/button';
import { FiTarget } from 'react-icons/fi';
export default function CurrentBtn(props) {
- const { clickhandler } = props;
+ const { clickhandler, active } = props;
return (
}
colorScheme='whiteAlpha'
- variant='outline'
+ variant={active ? 'solid' : 'outline'}
onClick={clickhandler}
_focus={{ boxShadow: 'none' }}
>
diff --git a/client/src/common/components/buttons/ExpandBtn.jsx b/client/src/common/components/buttons/ExpandBtn.jsx
index b0dddf8e7..a692e163b 100644
--- a/client/src/common/components/buttons/ExpandBtn.jsx
+++ b/client/src/common/components/buttons/ExpandBtn.jsx
@@ -1,18 +1,20 @@
-import { Button } from '@chakra-ui/button';
+import { IconButton } from '@chakra-ui/button';
+import { Tooltip } from '@chakra-ui/tooltip';
import { FiChevronsDown } from 'react-icons/fi';
export default function ExpandBtn(props) {
const { clickhandler } = props;
return (
- }
- colorScheme='white'
- variant='outline'
- onClick={clickhandler}
- _focus={{ boxShadow: 'none' }}
- >
- Expand All
-
+
+ }
+ colorScheme='white'
+ variant='outline'
+ background='#fff1'
+ onClick={clickhandler}
+ _focus={{ boxShadow: 'none' }}
+ />
+
);
}
diff --git a/client/src/common/components/buttons/LockIconBtn.jsx b/client/src/common/components/buttons/LockIconBtn.jsx
new file mode 100644
index 000000000..d52030fd1
--- /dev/null
+++ b/client/src/common/components/buttons/LockIconBtn.jsx
@@ -0,0 +1,21 @@
+import { IconButton } from '@chakra-ui/button';
+import { Tooltip } from '@chakra-ui/tooltip';
+import { FiTarget } from 'react-icons/fi';
+
+export default function LockIconBtn(props) {
+ const { clickhandler, active, ref } = props;
+ return (
+
+ }
+ colorScheme='pink'
+ color={'pink.300'}
+ variant={active ? 'solid' : 'outline'}
+ onClick={clickhandler}
+ _focus={{ boxShadow: 'none' }}
+ />
+
+ );
+}
From f1538def9947a84b9e33ceb15a20ba5757972dcc Mon Sep 17 00:00:00 2001
From: cv <34649812+cpvalente@users.noreply.github.com>
Date: Thu, 20 May 2021 12:40:33 +0200
Subject: [PATCH 2/5] list follows cursor
- add settings atom with cursor mode
- in locked mode eventlist scrolls to cursor
- cleanup unused menu items
---
client/src/app/context/settingsAtom.js | 34 +++++++++
.../src/features/editors/list/EventList.jsx | 26 ++++++-
client/src/features/menu/EventListMenu.jsx | 73 ++++++-------------
3 files changed, 80 insertions(+), 53 deletions(-)
create mode 100644 client/src/app/context/settingsAtom.js
diff --git a/client/src/app/context/settingsAtom.js b/client/src/app/context/settingsAtom.js
new file mode 100644
index 000000000..c49055d5b
--- /dev/null
+++ b/client/src/app/context/settingsAtom.js
@@ -0,0 +1,34 @@
+const { atom } = require('jotai');
+
+const PATH = 'option-gen';
+const initialValue = {
+ cursor: 'locked',
+};
+
+export const settingsAtom = atom(
+ (get) => {
+ const storedOptions = localStorage.getItem(PATH);
+ if (storedOptions == null) return initialValue;
+
+ return JSON.parse(storedOptions);
+ },
+ (get, set, newValues) => {
+ set(settingsAtom, newValues);
+ localStorage.setItem(PATH, JSON.stringify(newValues));
+ }
+);
+
+// get a single option, if it exists
+export const SelectSetting = (setting) => {
+ return atom((get) => get(settingsAtom)[setting]);
+};
+
+// change a single item in object
+export const HandleOptions = atom(null, (get, set, payload) => {
+ const updatedVal = {
+ ...get(settingsAtom),
+ ...payload,
+ };
+ set(settingsAtom, updatedVal);
+ localStorage.setItem(PATH, JSON.stringify(updatedVal));
+});
diff --git a/client/src/features/editors/list/EventList.jsx b/client/src/features/editors/list/EventList.jsx
index 51c582c90..8b43078fa 100644
--- a/client/src/features/editors/list/EventList.jsx
+++ b/client/src/features/editors/list/EventList.jsx
@@ -1,18 +1,23 @@
import style from './List.module.css';
-import { Fragment, useEffect, useState } from 'react';
+import { createRef, Fragment, useEffect, useMemo, useState } from 'react';
import { useSocket } from 'app/context/socketContext';
import tinykeys from 'tinykeys';
import Empty from 'common/state/Empty';
import EventListItem from './EventListItem';
import { AnimatePresence, motion } from 'framer-motion';
import { DragDropContext, Droppable } from 'react-beautiful-dnd';
+import { useAtom } from 'jotai';
+import { SelectSetting } from 'app/context/settingsAtom';
export default function EventList(props) {
const { events, eventsHandler } = props;
const socket = useSocket();
const [selected, setSelected] = useState(null);
const [next, setNext] = useState(null);
- const [cursor, setCursor] = useState(null);
+ const [cursor, setCursor] = useState(0);
+ const [cursorSettings] = useAtom(useMemo(() => SelectSetting('cursor'), []));
+
+ const cursorRef = createRef();
// Handle keyboard shortcuts
useEffect(() => {
@@ -70,6 +75,21 @@ export default function EventList(props) {
};
}, [socket]);
+ // attach scroll to cursor
+ useEffect(() => {
+ if (cursor == null || cursorRef.current == null) return;
+
+ cursorRef.current.scrollIntoView({
+ behavior: 'smooth',
+ block: 'nearest',
+ inline: 'start',
+ });
+ }, [cursor, cursorRef]);
+
+ useEffect(() => {
+ if (cursorSettings !== 'locked') return;
+ }, [selected]);
+
if (events.length < 1) {
return ;
}
@@ -114,6 +134,7 @@ export default function EventList(props) {
{cursor === -1 && (
{cursor === index && (
{
- const buttonProps = {
- size: 'sm',
- variant: 'outline',
- colorScheme: 'whiteAlpha',
- backgroundColor: '#ffffff05',
- _hover: { bg: 'blue.800' },
- _expanded: { bg: 'blue.400' },
- _focus: { boxShadow: 'none' },
- };
-
- const menuStyle = {
- color: 'initial',
- backgroundColor: 'rgba(255,255,255,0.67)',
- };
+ const [cursorSettings] = useAtom(useMemo(() => SelectSetting('cursor'), []));
+ const [, SetOption] = useAtom(HandleOptions);
const actionHandler = (action) => {
switch (action) {
@@ -41,6 +23,13 @@ const EventListMenu = ({ eventsHandler }) => {
case 'block':
eventsHandler('add', { type: action, order: 0 });
break;
+ case 'togglelock':
+ let newSet = 'locked';
+ if (cursorSettings === 'locked') {
+ newSet = 'unlocked';
+ }
+ SetOption({ cursor: newSet });
+ break;
default:
break;
}
@@ -48,36 +37,18 @@ const EventListMenu = ({ eventsHandler }) => {
return (
-
-
-
eventsHandler('collapseall')}
/>
eventsHandler('expandall')} />
+
+ actionHandler('togglelock')}
+ active={cursorSettings === 'locked'}
+ />
+
);
From 6f97e0caaaac8266d61747536b669d2953b3895d Mon Sep 17 00:00:00 2001
From: cv <34649812+cpvalente@users.noreply.github.com>
Date: Thu, 20 May 2021 12:53:24 +0200
Subject: [PATCH 3/5] style: cursor
---
.../src/features/editors/list/EventList.jsx | 50 +++----------------
.../src/features/editors/list/List.module.css | 18 ++++---
2 files changed, 17 insertions(+), 51 deletions(-)
diff --git a/client/src/features/editors/list/EventList.jsx b/client/src/features/editors/list/EventList.jsx
index 8b43078fa..11a9ad78a 100644
--- a/client/src/features/editors/list/EventList.jsx
+++ b/client/src/features/editors/list/EventList.jsx
@@ -1,10 +1,9 @@
import style from './List.module.css';
-import { createRef, Fragment, useEffect, useMemo, useState } from 'react';
+import { createRef, useEffect, useMemo, useState } from 'react';
import { useSocket } from 'app/context/socketContext';
import tinykeys from 'tinykeys';
import Empty from 'common/state/Empty';
import EventListItem from './EventListItem';
-import { AnimatePresence, motion } from 'framer-motion';
import { DragDropContext, Droppable } from 'react-beautiful-dnd';
import { useAtom } from 'jotai';
import { SelectSetting } from 'app/context/settingsAtom';
@@ -94,22 +93,6 @@ export default function EventList(props) {
return ;
}
- // motion
- const cursorVariants = {
- hidden: {
- scale: 0,
- },
- visible: {
- scale: 1,
- transition: {
- duration: 0.3,
- },
- },
- exit: {
- scale: 0,
- },
- };
-
// DND
const handleOnDragEnd = (result) => {
// drop outside of area
@@ -131,18 +114,6 @@ export default function EventList(props) {
return (
-
- {cursor === -1 && (
-
- )}
-
{(provided) => (
@@ -157,7 +128,10 @@ export default function EventList(props) {
cumulativeDelay += e.duration;
} else if (e.type === 'block') cumulativeDelay = 0;
return (
-
+
-
- {cursor === index && (
-
- )}
-
-
+
);
})}
{provided.placeholder}
diff --git a/client/src/features/editors/list/List.module.css b/client/src/features/editors/list/List.module.css
index e676a162c..339f84d3d 100644
--- a/client/src/features/editors/list/List.module.css
+++ b/client/src/features/editors/list/List.module.css
@@ -21,11 +21,15 @@
}
.cursor {
- width: 90%;
- min-height: 2px;
- background-color: #ff7597;
- border-radius: 2px;
- margin: 0 auto;
- /* transition: 1s;
- transition-property: all; */
+ width: 100%;
+ background: linear-gradient(
+ 180deg,
+ #ff7597 0%,
+ #0000 10%,
+ #0000 90%,
+ #ff7597 100%
+ );
+ border-radius: 20px;
+ transition: 0.3s;
+ transition-property: all;
}
From cc7b8278b8768a61a32e95d62bad9c0bb899f322 Mon Sep 17 00:00:00 2001
From: cv <34649812+cpvalente@users.noreply.github.com>
Date: Thu, 20 May 2021 13:13:30 +0200
Subject: [PATCH 4/5] cursor follows playback
---
client/src/features/editors/list/EventList.jsx | 18 ++++++++++++------
server/classes/EventTimer.js | 11 +++++++++++
2 files changed, 23 insertions(+), 6 deletions(-)
diff --git a/client/src/features/editors/list/EventList.jsx b/client/src/features/editors/list/EventList.jsx
index 11a9ad78a..3d2e874df 100644
--- a/client/src/features/editors/list/EventList.jsx
+++ b/client/src/features/editors/list/EventList.jsx
@@ -56,12 +56,13 @@ export default function EventList(props) {
if (socket == null) return;
// ask for playstate
- socket.emit('get-selected-id');
+ socket.emit('get-selected');
socket.emit('get-next-id');
// Handle playstate
- socket.on('selected-id', (data) => {
+ socket.on('selected', (data) => {
setSelected(data);
+ console.log('debug cursor setted', data);
});
socket.on('next-id', (data) => {
setNext(data);
@@ -69,7 +70,7 @@ export default function EventList(props) {
// Clear listener
return () => {
- socket.off('selected-id');
+ socket.off('selected');
socket.off('next-id');
};
}, [socket]);
@@ -86,8 +87,11 @@ export default function EventList(props) {
}, [cursor, cursorRef]);
useEffect(() => {
- if (cursorSettings !== 'locked') return;
- }, [selected]);
+ if (cursorSettings !== 'locked' || selected == null) return;
+ if (selected.index == null) return;
+
+ setCursor(selected.index);
+ }, [selected, cursorSettings]);
if (events.length < 1) {
return ;
@@ -112,6 +116,8 @@ export default function EventList(props) {
console.log('EventList: events in event list', events);
let cumulativeDelay = 0;
+ console.log('debug selected', selected);
+
return (
@@ -136,7 +142,7 @@ export default function EventList(props) {
type={e.type}
index={index}
data={e}
- selected={selected === e.id}
+ selected={selected?.id === e.id}
next={next === e.id}
eventsHandler={eventsHandler}
delay={cumulativeDelay}
diff --git a/server/classes/EventTimer.js b/server/classes/EventTimer.js
index 960b21af5..6059a7a18 100644
--- a/server/classes/EventTimer.js
+++ b/server/classes/EventTimer.js
@@ -90,6 +90,10 @@ class EventTimer extends Timer {
broadcastState() {
this.io.emit('timer', this.getObject());
this.io.emit('playstate', this.state);
+ this.io.emit('selected', {
+ id: this.selectedEventId,
+ index: this.selectedEventIndex,
+ });
this.io.emit('selected-id', this.selectedEventId);
this.io.emit('next-id', this.nextEventId);
this.io.emit('publicselected-id', this.selectedPublicEventId);
@@ -259,6 +263,13 @@ class EventTimer extends Timer {
/*******************************************/
// selection data
+ socket.on('get-selected', () => {
+ socket.emit('selected', {
+ id: this.selectedEventId,
+ index: this.selectedEventIndex,
+ });
+ });
+
socket.on('get-selected-id', () => {
socket.emit('selected-id', this.selectedEventId);
});
From 6ae075569676112a2e97e1216088c1af2c2ae6ed Mon Sep 17 00:00:00 2001
From: cv <34649812+cpvalente@users.noreply.github.com>
Date: Thu, 20 May 2021 13:42:53 +0200
Subject: [PATCH 5/5] cleanup
- style tweaks
- container follows cursor
---
.../src/features/editors/list/EventList.jsx | 20 +++++++++++--------
.../src/features/editors/list/List.module.css | 13 ++++++------
2 files changed, 18 insertions(+), 15 deletions(-)
diff --git a/client/src/features/editors/list/EventList.jsx b/client/src/features/editors/list/EventList.jsx
index 3d2e874df..dc6c0b913 100644
--- a/client/src/features/editors/list/EventList.jsx
+++ b/client/src/features/editors/list/EventList.jsx
@@ -75,9 +75,18 @@ export default function EventList(props) {
};
}, [socket]);
+ // attach cursor to selected
+ useEffect(() => {
+ if (cursorSettings !== 'locked' || selected == null) return;
+ if (selected.index == null) return;
+
+ setCursor(selected.index);
+ }, [selected, cursorSettings]);
+
// attach scroll to cursor
useEffect(() => {
if (cursor == null || cursorRef.current == null) return;
+ console.log('debug cursor scrolling');
cursorRef.current.scrollIntoView({
behavior: 'smooth',
@@ -86,13 +95,6 @@ export default function EventList(props) {
});
}, [cursor, cursorRef]);
- useEffect(() => {
- if (cursorSettings !== 'locked' || selected == null) return;
- if (selected.index == null) return;
-
- setCursor(selected.index);
- }, [selected, cursorSettings]);
-
if (events.length < 1) {
return ;
}
@@ -129,14 +131,16 @@ export default function EventList(props) {
ref={provided.innerRef}
>
{events.map((e, index) => {
+ let isCursor = cursor === index;
if (index === 0) cumulativeDelay = 0;
if (e.type === 'delay' && e.duration != null) {
cumulativeDelay += e.duration;
} else if (e.type === 'block') cumulativeDelay = 0;
return (