From 02e2caf8b7c2b8ebdaaa9ee393df5ff8be7d6441 Mon Sep 17 00:00:00 2001 From: evgeny Date: Mon, 21 Aug 2023 14:41:50 +0100 Subject: [PATCH] fix: add global state for slides data --- demo/src/components/EditableText.tsx | 2 +- demo/src/components/Paragraph.tsx | 7 +++++-- demo/src/components/SlidesStateContext.tsx | 24 ++++++++++++++++++++++ demo/src/components/Title.tsx | 7 +++++-- demo/src/hooks/useSlideElementContent.ts | 13 ++++++++++++ demo/src/main.tsx | 5 ++++- 6 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 demo/src/components/SlidesStateContext.tsx create mode 100644 demo/src/hooks/useSlideElementContent.ts diff --git a/demo/src/components/EditableText.tsx b/demo/src/components/EditableText.tsx index 0e7c3c49..26a4e0bf 100644 --- a/demo/src/components/EditableText.tsx +++ b/demo/src/components/EditableText.tsx @@ -35,7 +35,7 @@ export const EditableText: React.FC = ({ const enterPressed = key === 'Enter'; const deleteButtonPressed = key === 'Backspace' || key === 'Delete'; const replacing = window.getSelection()?.toString() !== ''; - const limitReached = elementRef.current?.innerText.length ?? 0 >= maxChars; + const limitReached = (elementRef.current?.innerText.length ?? 0) >= maxChars; if (enterPressed || (limitReached && !replacing && !deleteButtonPressed)) { event.stopPropagation(); event.preventDefault(); diff --git a/demo/src/components/Paragraph.tsx b/demo/src/components/Paragraph.tsx index 3f1d1e00..9dfa8dc9 100644 --- a/demo/src/components/Paragraph.tsx +++ b/demo/src/components/Paragraph.tsx @@ -7,6 +7,7 @@ import { StickyLabel } from './StickyLabel'; import { LockFilledSvg } from './svg/LockedFilled.tsx'; import { EditableText } from './EditableText.tsx'; import { buildLockId } from '../utils/locking.ts'; +import { useSlideElementContent } from '../hooks/useSlideElementContent.ts'; interface Props extends React.HTMLAttributes { id: string; @@ -23,11 +24,13 @@ export const Paragraph = ({ variant = 'regular', id, slide, className, children, const { outlineClasses, stickyLabelClasses } = getOutlineClasses(activeMember); const { locked, lockedByYou } = useLockStatus(slide, id, self?.connectionId); const memberName = getMemberFirstName(activeMember); - const channelName = `[?rewind=1]${spaceName}-${buildLockId(slide, id)}`; + const lockId = buildLockId(slide, id); + const channelName = `[?rewind=1]${spaceName}${lockId}`; + const [content, setContent] = useSlideElementContent(lockId, children); const { channel } = useChannel(channelName, (message) => { + if (message.connectionId === self?.connectionId) return; setContent(message.data); }); - const [content, setContent] = useState(children); const editIsNotAllowed = locked && !lockedByYou && !!activeMember; return ( diff --git a/demo/src/components/SlidesStateContext.tsx b/demo/src/components/SlidesStateContext.tsx new file mode 100644 index 00000000..1680223a --- /dev/null +++ b/demo/src/components/SlidesStateContext.tsx @@ -0,0 +1,24 @@ +import React, { useMemo, useState } from 'react'; + +interface SlidesStateContextProps { + slidesState: Record; + setContent(id: string, nextContent: string): void; +} +export const SlidesStateContext = React.createContext({ + slidesState: {}, + setContent: () => {}, +}); + +export const SlidesStateContextProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { + const [slidesState, setSlidesState] = useState>({}); + const value = useMemo( + () => ({ + slidesState, + setContent: (id: string, nextContent: string) => { + setSlidesState((prevState) => ({ ...prevState, [id]: nextContent })); + }, + }), + [slidesState, setSlidesState], + ); + return {children}; +}; diff --git a/demo/src/components/Title.tsx b/demo/src/components/Title.tsx index ad1b0522..83f7c5a2 100644 --- a/demo/src/components/Title.tsx +++ b/demo/src/components/Title.tsx @@ -8,6 +8,7 @@ import { LockFilledSvg } from './svg/LockedFilled.tsx'; import { StickyLabel } from './StickyLabel.tsx'; import { EditableText } from './EditableText.tsx'; import { buildLockId } from '../utils/locking.ts'; +import { useSlideElementContent } from '../hooks/useSlideElementContent.ts'; interface Props extends React.HTMLAttributes { id: string; @@ -24,11 +25,13 @@ export const Title = ({ variant = 'h1', className, id, slide, children, ...props const { outlineClasses, stickyLabelClasses } = getOutlineClasses(activeMember); const memberName = getMemberFirstName(activeMember); const { locked, lockedByYou } = useLockStatus(slide, id, self?.connectionId); - const channelName = `[?rewind=1]${spaceName}-${buildLockId(slide, id)}`; + const lockId = buildLockId(slide, id); + const channelName = `[?rewind=1]${spaceName}${lockId}`; + const [content, setContent] = useSlideElementContent(lockId, children); const { channel } = useChannel(channelName, (message) => { + if (message.connectionId === self?.connectionId) return; setContent(message.data); }); - const [content, setContent] = useState(children); const editIsNotAllowed = locked && !lockedByYou && !!activeMember; return ( diff --git a/demo/src/hooks/useSlideElementContent.ts b/demo/src/hooks/useSlideElementContent.ts new file mode 100644 index 00000000..725c515b --- /dev/null +++ b/demo/src/hooks/useSlideElementContent.ts @@ -0,0 +1,13 @@ +import { useCallback, useContext } from 'react'; +import { SlidesStateContext } from '../components/SlidesStateContext.tsx'; + +export const useSlideElementContent = (id: string, defaultContent: string) => { + const { slidesState, setContent } = useContext(SlidesStateContext); + const setNextContent = useCallback( + (nextContent: string) => { + setContent(id, nextContent); + }, + [id], + ); + return [slidesState[id] ?? defaultContent, setNextContent] as const; +}; diff --git a/demo/src/main.tsx b/demo/src/main.tsx index 64b92d02..2a03391d 100644 --- a/demo/src/main.tsx +++ b/demo/src/main.tsx @@ -5,6 +5,7 @@ import App from './App'; import './index.css'; import { ably, SpaceContextProvider } from './components'; +import { SlidesStateContext, SlidesStateContextProvider } from './components/SlidesStateContext.tsx'; const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement); @@ -12,7 +13,9 @@ root.render( - + + + ,