Skip to content

Commit

Permalink
chore: renaming based on review feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
ttypic committed Aug 24, 2023
1 parent fedc1ef commit 70e4e61
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 99 deletions.
6 changes: 3 additions & 3 deletions demo/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useContext, useEffect } from 'react';
import { Header, SlideMenu, SpacesContext, CurrentSlide, AblySvg, slides } from './components';
import { getRandomName, getRandomColor } from './utils';
import { useMembers } from './hooks';
import { MiniatureContextProvider } from './components/MiniatureContext.tsx';
import { PreviewContextProvider } from './components/PreviewContext.tsx';

const App = () => {
const space = useContext(SpacesContext);
Expand Down Expand Up @@ -33,9 +33,9 @@ const App = () => {
id="feature-display"
className="absolute gap-12 bg-[#F7F6F9] w-full h-[calc(100%-80px)] -z-10 overflow-y-hidden overflow-x-hidden flex justify-between min-w-[375px] xs:flex-col md:flex-row"
>
<MiniatureContextProvider miniature={true}>
<PreviewContextProvider miniature={true}>
<SlideMenu slides={slides} />
</MiniatureContextProvider>
</PreviewContextProvider>
<CurrentSlide slides={slides} />
</section>
</main>
Expand Down
13 changes: 0 additions & 13 deletions demo/src/components/MiniatureContext.tsx

This file was deleted.

60 changes: 19 additions & 41 deletions demo/src/components/Paragraph.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import React, { useRef } from 'react';
import cn from 'classnames';
import { useChannel } from '@ably-labs/react-hooks';
import { useClearOnFailedLock, useClickOutside, useElementSelect, useLockStatus, useMembers } from '../hooks';
import { findActiveMember, getMemberFirstName, getOutlineClasses, getSpaceNameFromUrl } from '../utils';
import { getMemberFirstName, getOutlineClasses } from '../utils';
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';
import { useMiniature } from './MiniatureContext.tsx';
import { useTextComponentLock } from '../hooks/useTextComponentLock.ts';

interface Props extends React.HTMLAttributes<HTMLParagraphElement> {
id: string;
Expand All @@ -27,63 +23,45 @@ export const Paragraph = ({
maxlength = 300,
...props
}: Props) => {
const ref = useRef<HTMLDivElement | null>(null);
const spaceName = getSpaceNameFromUrl();
const { members, self } = useMembers();
const { handleSelect } = useElementSelect(id);
const activeMember = findActiveMember(id, slide, members);
const { outlineClasses, stickyLabelClasses } = getOutlineClasses(activeMember);
const { locked, lockedByYou } = useLockStatus(slide, id, self?.connectionId);
const containerRef = useRef<HTMLDivElement | null>(null);
const { content, activeMember, locked, lockedByYou, editIsNotAllowed, handleSelect, handleContentUpdate } =
useTextComponentLock({
id,
slide,
defaultText: children,
containerRef,
});
const memberName = getMemberFirstName(activeMember);
const lockId = buildLockId(slide, id);
const channelName = `[?rewind=1]${spaceName}${lockId}`;
const [content, setContent] = useSlideElementContent(lockId, children);
const miniature = useMiniature();

const { channel } = useChannel(channelName, (message) => {
if (message.connectionId === self?.connectionId || miniature) return;
setContent(message.data);
});

const optimisticallyLocked = !!activeMember;
const optimisticallyLockedByYou = optimisticallyLocked && activeMember?.connectionId === self?.connectionId;
const editIsNotAllowed = !optimisticallyLockedByYou && optimisticallyLocked;
const lockConflict = optimisticallyLockedByYou && locked && !lockedByYou && !miniature;

useClickOutside(ref, self, optimisticallyLockedByYou && !miniature);
useClearOnFailedLock(lockConflict, self);
const { outlineClasses, stickyLabelClasses } = getOutlineClasses(activeMember);

return (
<div
ref={ref}
ref={containerRef}
{...props}
className="relative"
onClick={optimisticallyLocked ? undefined : handleSelect}
onClick={locked ? undefined : handleSelect}
>
<StickyLabel
visible={optimisticallyLocked}
visible={locked}
className={`${stickyLabelClasses} flex flex-row items-center`}
>
{optimisticallyLockedByYou ? 'You' : memberName}
{lockedByYou ? 'You' : memberName}
{editIsNotAllowed && <LockFilledSvg className="text-white" />}
</StickyLabel>
<EditableText
as="p"
id={id}
disabled={!optimisticallyLockedByYou}
disabled={!lockedByYou}
value={content}
onChange={(nextValue) => {
setContent(nextValue);
channel.publish('update', nextValue);
}}
onChange={handleContentUpdate}
maxlength={maxlength}
className={cn(
'text-ably-avatar-stack-demo-slide-text break-all',
{
'xs:w-auto text-xs xs:text-base md:text-lg xs:my-4 md:my-0': variant === 'regular',
'text-[13px] p-0 leading-6': variant === 'aside',
[`outline-2 outline ${outlineClasses}`]: optimisticallyLocked,
'cursor-pointer': !optimisticallyLocked,
[`outline-2 outline ${outlineClasses}`]: locked,
'cursor-pointer': !locked,
'cursor-not-allowed': editIsNotAllowed,
'bg-slate-200': editIsNotAllowed,
},
Expand Down
13 changes: 13 additions & 0 deletions demo/src/components/PreviewContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React, { useContext } from 'react';

interface PreviewContextProviderProps {
miniature: boolean;
children: React.ReactNode;
}
const PreviewContext = React.createContext<boolean>(false);

export const PreviewContextProvider: React.FC<PreviewContextProviderProps> = ({ miniature, children }) => (
<PreviewContext.Provider value={miniature}>{children}</PreviewContext.Provider>
);

export const usePreview = () => useContext<boolean>(PreviewContext);
58 changes: 18 additions & 40 deletions demo/src/components/Title.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
import React, { useRef } from 'react';
import cn from 'classnames';
import { useChannel } from '@ably-labs/react-hooks';

import { useClearOnFailedLock, useClickOutside, useElementSelect, useLockStatus, useMembers } from '../hooks';
import { findActiveMember, getMemberFirstName, getOutlineClasses, getSpaceNameFromUrl } from '../utils';
import { getMemberFirstName, getOutlineClasses } from '../utils';
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';
import { useMiniature } from './MiniatureContext.tsx';
import { useTextComponentLock } from '../hooks/useTextComponentLock.ts';

interface Props extends React.HTMLAttributes<HTMLHeadingElement> {
id: string;
Expand All @@ -20,65 +16,47 @@ interface Props extends React.HTMLAttributes<HTMLHeadingElement> {
}

export const Title = ({ variant = 'h1', className, id, slide, children, maxlength = 70, ...props }: Props) => {
const ref = useRef<HTMLDivElement | null>(null);
const spaceName = getSpaceNameFromUrl();
const { members, self } = useMembers();
const { handleSelect } = useElementSelect(id);
const activeMember = findActiveMember(id, slide, members);
const { outlineClasses, stickyLabelClasses } = getOutlineClasses(activeMember);
const { locked, lockedByYou } = useLockStatus(slide, id, self?.connectionId);
const containerRef = useRef<HTMLDivElement | null>(null);
const { content, activeMember, locked, lockedByYou, editIsNotAllowed, handleSelect, handleContentUpdate } =
useTextComponentLock({
id,
slide,
defaultText: children,
containerRef,
});
const memberName = getMemberFirstName(activeMember);
const lockId = buildLockId(slide, id);
const channelName = `[?rewind=1]${spaceName}${lockId}`;
const [content, setContent] = useSlideElementContent(lockId, children);
const miniature = useMiniature();

const { channel } = useChannel(channelName, (message) => {
if (message.connectionId === self?.connectionId || miniature) return;
setContent(message.data);
});

const optimisticallyLocked = !!activeMember;
const optimisticallyLockedByYou = optimisticallyLocked && activeMember?.connectionId === self?.connectionId;
const editIsNotAllowed = !optimisticallyLockedByYou && optimisticallyLocked;
const lockConflict = optimisticallyLockedByYou && locked && !lockedByYou && !miniature;

useClickOutside(ref, self, optimisticallyLockedByYou && !miniature);
useClearOnFailedLock(lockConflict, self);
const { outlineClasses, stickyLabelClasses } = getOutlineClasses(activeMember);

return (
<div
ref={ref}
ref={containerRef}
{...props}
className="relative"
onClick={optimisticallyLocked ? undefined : handleSelect}
onClick={locked ? undefined : handleSelect}
>
<StickyLabel
visible={!!activeMember}
className={`${stickyLabelClasses} flex flex-row items-center`}
>
{optimisticallyLockedByYou ? 'You' : memberName}
{lockedByYou ? 'You' : memberName}
{editIsNotAllowed && <LockFilledSvg className="text-white" />}
</StickyLabel>
<EditableText
id={id}
as={variant}
disabled={!optimisticallyLockedByYou}
disabled={!lockedByYou}
maxlength={maxlength}
value={content}
onChange={(nextValue) => {
setContent(nextValue);
channel.publish('update', nextValue);
}}
onChange={handleContentUpdate}
className={cn(
'relative break-all',
{
'font-semibold text-ably-avatar-stack-demo-slide-text my-2 xs:text-3xl md:text-4xl': variant === 'h1',
'font-semibold text-ably-avatar-stack-demo-slide-text md:text-2xl': variant === 'h2',
'font-medium uppercase text-ably-avatar-stack-demo-slide-title-highlight xs:text-xs xs:my-4 md:my-0 md:text-md':
variant === 'h3',
[`outline-2 outline ${outlineClasses}`]: optimisticallyLocked,
'cursor-pointer': !optimisticallyLocked,
[`outline-2 outline ${outlineClasses}`]: locked,
'cursor-pointer': !locked,
'cursor-not-allowed': editIsNotAllowed,
'bg-slate-200': editIsNotAllowed,
},
Expand Down
4 changes: 2 additions & 2 deletions demo/src/hooks/useSlideElementContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { SlidesStateContext } from '../components/SlidesStateContext.tsx';

export const useSlideElementContent = (id: string, defaultContent: string) => {
const { slidesState, setContent } = useContext(SlidesStateContext);
const setNextContent = useCallback(
const updateContent = useCallback(
(nextContent: string) => {
setContent(id, nextContent);
},
[id],
);
return [slidesState[id] ?? defaultContent, setNextContent] as const;
return [slidesState[id] ?? defaultContent, updateContent] as const;
};
55 changes: 55 additions & 0 deletions demo/src/hooks/useTextComponentLock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { MutableRefObject, useCallback } from 'react';
import { useChannel } from '@ably-labs/react-hooks';
import { findActiveMember, getSpaceNameFromUrl } from '../utils';
import { buildLockId } from '../utils/locking.ts';
import { usePreview } from '../components/PreviewContext.tsx';
import { useMembers } from './useMembers.ts';
import { useClearOnFailedLock, useClickOutside, useElementSelect } from './useElementSelect.ts';
import { useLockStatus } from './useLock.ts';
import { useSlideElementContent } from './useSlideElementContent.ts';

interface UseTextComponentLockArgs {
id: string;
slide: string;
defaultText: string;
containerRef: MutableRefObject<HTMLElement | null>;
}
export const useTextComponentLock = ({ id, slide, defaultText, containerRef }: UseTextComponentLockArgs) => {
const spaceName = getSpaceNameFromUrl();
const { members, self } = useMembers();
const activeMember = findActiveMember(id, slide, members);
const { locked, lockedByYou } = useLockStatus(slide, id, self?.connectionId);
const lockId = buildLockId(slide, id);
const channelName = `[?rewind=1]${spaceName}${lockId}`;
const [content, updateContent] = useSlideElementContent(lockId, defaultText);
const preview = usePreview();

const { handleSelect } = useElementSelect(id);
const handleContentUpdate = useCallback((content: string) => {
updateContent(content);
channel.publish('update', content);
}, []);

const { channel } = useChannel(channelName, (message) => {
if (message.connectionId === self?.connectionId) return;
updateContent(message.data);
});

const optimisticallyLocked = !!activeMember;
const optimisticallyLockedByYou = optimisticallyLocked && activeMember?.connectionId === self?.connectionId;
const editIsNotAllowed = !optimisticallyLockedByYou && optimisticallyLocked;
const lockConflict = optimisticallyLockedByYou && locked && !lockedByYou && !preview;

useClickOutside(containerRef, self, optimisticallyLockedByYou && !preview);
useClearOnFailedLock(lockConflict, self);

return {
content,
activeMember,
locked: optimisticallyLocked,
lockedByYou: optimisticallyLockedByYou,
editIsNotAllowed,
handleSelect,
handleContentUpdate,
};
};

0 comments on commit 70e4e61

Please sign in to comment.