Skip to content

Commit

Permalink
Tidy up and move /pages/draw directory to /pages/tldraw
Browse files Browse the repository at this point in the history
  • Loading branch information
fnwbr committed Mar 7, 2024
1 parent 540dc16 commit 510e7af
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 165 deletions.
2 changes: 0 additions & 2 deletions lib/Auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import MatrixAuthProvider from './auth/MatrixAuthProvider';
import PeerTubeAuthProvider from './auth/PeerTubeAuthProvider';
import MyPadsAuthProvider from './auth/MyPadsAuthProvider';
import SpacedeckAuthProvider from './auth/SpacedeckAuthProvider';
import TldrawAuthProvider from './auth/TldrawAuthProvider';

/*
Mapping of authentication provider types and which corresponding class should be used to actually perform
Expand All @@ -20,7 +19,6 @@ const AuthProviders = {
peerTube: PeerTubeAuthProvider,
etherpad: MyPadsAuthProvider,
spacedeck: SpacedeckAuthProvider,
tldraw: TldrawAuthProvider,
};

function useAuthProvider() {
Expand Down
35 changes: 20 additions & 15 deletions lib/Matrix.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,22 +50,27 @@ function useMatrixProvider(auth) {
const roomState = room.getLiveTimeline().getState(EventTimeline.FORWARDS);

const pushRules = matrixClient.getAccountData('m.push_rules')?.event?.content?.global?.override;
const rule = pushRules?.find(rule => rule.rule_id === roomId);
const metaEvent = roomState.getStateEvents('dev.medienhaus.meta', '')?.getContent();

// we check if we have an metaevent avaialble and if the template is 'sketch-link' and if the rule is not set to 'dont_notify' we will set a push rule to 'dont_notify' for this room
// for future purposes we should not check for item instead for the templates which needs to be muted
if (metaEvent && metaEvent.type === 'item') {
if (!rule || !rule?.actions.includes(PushRuleActionName.DontNotify)) {
matrixClient.addPushRule('global', PushRuleKind.Override, roomId, { 'conditions': [{ 'kind': 'event_match', 'key': 'room_id', 'pattern': roomId }], 'actions': [PushRuleActionName.DontNotify] });
const rule = pushRules?.find((rule) => rule.rule_id === roomId);
const metaEvent = roomState.getStateEvents('dev.medienhaus.meta', '')?.getContent();

// we check if we have an metaevent avaialble and if the template is 'sketch-link' and if the rule is not set to 'dont_notify' we will set a push rule to 'dont_notify' for this room
// for future purposes we should not check for item instead for the templates which needs to be muted
if (metaEvent && metaEvent.type === 'item') {
if (!rule || !rule?.actions.includes(PushRuleActionName.DontNotify)) {
matrixClient.addPushRule('global', PushRuleKind.Override, roomId, {
conditions: [{ kind: 'event_match', key: 'room_id', pattern: roomId }],
actions: [PushRuleActionName.DontNotify],
});
}
}
}

return {
roomId,
name: room.name,
meta: roomState.getStateEvents('dev.medienhaus.meta', '')?.getContent(),
children: roomState.getStateEvents('m.space.child').map((event) => !_.isEmpty(event.getContent()) && event.getStateKey())
return {
roomId,
name: room.name,
meta: roomState.getStateEvents('dev.medienhaus.meta', '')?.getContent(),
children: roomState
.getStateEvents('m.space.child')
.map((event) => !_.isEmpty(event.getContent()) && event.getStateKey())
.filter((child) => child),
notificationCount: room.getUnreadNotificationCount(),
avatar,
Expand Down Expand Up @@ -434,7 +439,7 @@ function useMatrixProvider(auth) {
.map((child) => spaces.get(child)) // Map over the 'children' array and fetch the corresponding objects from the 'spaces' map
.filter((child) => child !== undefined); // Filter out any undefined values to ensure 'applicationsChildren' only contains valid objects

for (const element of Object.keys(getConfig().publicRuntimeConfig.authProviders)) {
for (const element of ['tldraw', ...Object.keys(getConfig().publicRuntimeConfig.authProviders)]) {
if (element === 'matrix') continue; // we don't want to create a service folder for matrix

const existingServiceSpace = applicationsChildren.find((space) => space.name === element);
Expand Down
36 changes: 0 additions & 36 deletions lib/auth/TldrawAuthProvider.js

This file was deleted.

7 changes: 4 additions & 3 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,13 @@ module.exports = {
rewriteConfig.push(
{
source: SpacesConfig.authProviders.tldraw.path,
destination: '/draw',
destination: '/tldraw',
},
{
source: SpacesConfig.authProviders.tldraw.path + '/:roomId',
destination: '/draw/:roomId',
});
destination: '/tldraw/:roomId',
},
);
}

return rewriteConfig;
Expand Down
136 changes: 35 additions & 101 deletions pages/draw/[[...roomId]].js → pages/tldraw/[[...roomId]].js
Original file line number Diff line number Diff line change
@@ -1,75 +1,47 @@
import React, { memo, useMemo, useCallback, useEffect, useRef, useState } from 'react';
import React, { useCallback, useEffect, useRef } from 'react';
import { useRouter } from 'next/router';
import { useTranslation } from 'react-i18next';
import dynamic from 'next/dynamic';
import _ from 'lodash';
import { RiDeleteBinLine, RiUserAddLine } from '@remixicon/react';

import { useAuth } from '../../lib/Auth';
import LoadingSpinner from '../../components/UI/LoadingSpinner';
import LoadingSpinnerInline from '../../components/UI/LoadingSpinnerInline';
import { useMatrix } from '../../lib/Matrix';
import ErrorMessage from '../../components/UI/ErrorMessage';
import { ServiceSubmenu } from '../../components/UI/ServiceSubmenu';
import DefaultLayout from '../../components/layouts/default';
import { ServiceTable } from '../../components/UI/ServiceTable';
import ServiceLink from '../../components/UI/ServiceLink';
import { path as tldrawPath } from '../../lib/Tldraw';
import { TldrawMatrixProvider } from './tldrawMatrix';
import CreateNewTlDrawSketch from './actions/CreateNewTlDrawSketch';
import CopyToClipboard from '../../components/UI/CopyToClipboard';
import { InviteUserToMatrixRoom } from '../../components/UI/InviteUsersToMatrixRoom';
import TextButton from '../../components/UI/TextButton';
import Icon from '../../components/UI/Icon';

const Editor = dynamic(() => import('./editor'), { ssr: false });

const TlDrawListEntry = memo(({ name, href, roomId, ref, selected }) => {
return <ServiceLink key={roomId} name={name} href={href} selected={selected} ref={ref} />;
});

TlDrawListEntry.displayName = 'TlDrawListEntry';

export default function Draw() {
import { RiUserAddLine } from '@remixicon/react';

import { useAuth } from '@/lib/Auth';
import LoadingSpinner from '@/components/UI/LoadingSpinner';
import { useMatrix } from '@/lib/Matrix';
import { ServiceSubmenu } from '@/components/UI/ServiceSubmenu';
import DefaultLayout from '@/components/layouts/default';
import { ServiceTable } from '@/components/UI/ServiceTable';
import ServiceLink from '@/components/UI/ServiceLink';
import { path as tldrawPath } from '@/lib/Tldraw';
import { TldrawMatrixProvider } from '../draw/tldrawMatrix';
import CreateNewTldraw from './actions/CreateNewTldraw';
import CopyToClipboard from '@/components/UI/CopyToClipboard';
import { InviteUserToMatrixRoom } from '@/components/UI/InviteUsersToMatrixRoom';
import TextButton from '@/components/UI/TextButton';
import Icon from '@/components/UI/Icon';

const Editor = dynamic(() => import('../draw/editor'), { ssr: false });

export default function Tldraw() {
const auth = useAuth();
const matrix = useMatrix();
const matrixClient = auth.getAuthenticationProvider('matrix').getMatrixClient();

const { t } = useTranslation('tldraw');
const router = useRouter();
const roomId = _.get(router, 'query.roomId.0');

const [errorMessage, setErrorMessage] = useState(false);
const serviceSpaceId = matrix.serviceSpaces.tldraw;
const spacedeckChildren = matrix.spaces.get(serviceSpaceId)?.children?.filter((child) => child !== 'undefined'); // Filter out any undefined values to ensure 'spacedeckChildren' only contains valid objects
const [syncingServerSketches, setSyncingServerSketches] = useState(false);

const tldrawMatrix = TldrawMatrixProvider(roomId);

Check failure

Code scanning / ESLint

Require constructor names to begin with a capital letter Error

A function with a name starting with an uppercase letter should only be used as a constructor.
const [isInviteUsersOpen, setIsInviteUsersOpen] = useState(false);
const [isDeletingSketch, setIsDeletingSketch] = useState(false);

// Whenever the roomId changes (e.g. after a new sketch was created), automatically focus that element.
// Whenever the roomId changes (e.g. after a new item was created), automatically focus that element.
// This makes the sidebar scroll to the element if it is outside of the current viewport.
const selectedSketchRef = useRef(null);
const selectedDrawRef = useRef(null);
useEffect(() => {
console.error('roomId::', roomId);
setIsInviteUsersOpen(false);

// setTldrawMatrix(TldrawMatrixProvider(roomId));
selectedSketchRef.current?.focus();
selectedDrawRef.current?.focus();
}, [roomId]);

const listEntries = useMemo(() => {
return matrix.spaces.get(matrix.serviceSpaces.tldraw)?.children?.map((tldrawRoomId) => {
const name = _.get(matrix.rooms.get(tldrawRoomId), 'name');

// if the room name is undefined we don't want to display it
if (!name) return;

return <TlDrawListEntry key={tldrawRoomId} name={name} roomId={tldrawRoomId} selected={tldrawRoomId === roomId} />;
});
}, [matrix.rooms, matrix.serviceSpaces.tldraw, matrix.spaces, roomId]);

// based on the createWriteRoom in etherpad. there was a @TODO mentioned with 'function creates infinite loop in useEffect below' dont know if this applies here as well.
const createSketchRoom = useCallback(
async (name) => {
Expand Down Expand Up @@ -131,25 +103,6 @@ export default function Draw() {
[matrix, auth, serviceSpaceId, matrixClient],
);

/**
* copied from etherpad and modified to fit our needs
*/
const deleteSketch = async () => {
// Confirm if the user really wants to remove/delete this pad ...
let confirmDeletionMessage;

// ... and cancel the process if the user decided otherwise.
if (!confirm(confirmDeletionMessage)) return;

setIsDeletingSketch(true);

await auth.getAuthenticationProvider('matrix').removeSpaceChild(matrix.serviceSpaces.etherpad, roomId);
await matrix.leaveRoom(roomId);

router.push(tldrawPath);
setIsDeletingSketch(false);
};

return (
<>
<DefaultLayout.Sidebar>
Expand All @@ -159,14 +112,13 @@ export default function Draw() {
disabled={!serviceSpaceId}
items={[
{
value: 'createtldrawsketch',
actionComponentToRender: <CreateNewTlDrawSketch createTlDrawRoom={createSketchRoom} />,
label: t('Create new sketch'),
value: 'createNew',
actionComponentToRender: <CreateNewTldraw createTlDrawRoom={createSketchRoom} />,
label: t('Create new draw'),
},
]}
/>
{errorMessage && <ErrorMessage>{errorMessage}</ErrorMessage>}
{!serviceSpaceId || syncingServerSketches ? (
{!serviceSpaceId ? (
<LoadingSpinner />
) : (
<>
Expand All @@ -182,7 +134,7 @@ export default function Draw() {
name={room.name}
href={`${tldrawPath}/${tldrawSketchRoomId}`}
selected={roomId === tldrawSketchRoomId}
ref={tldrawSketchRoomId === roomId ? selectedSketchRef : null}
ref={tldrawSketchRoomId === roomId ? selectedDrawRef : null}
/>
);
})}
Expand All @@ -207,33 +159,15 @@ export default function Draw() {
}
/>
<CopyToClipboard title={t('Copy sketch link to clipboard')} content={tldrawPath + '/' + roomId} />
<TextButton title={t('Remove sketch from my library')} onClick={deleteSketch}>
{isDeletingSketch ? (
<LoadingSpinnerInline />
) : (
<Icon>
<RiDeleteBinLine />
</Icon>
)}
</TextButton>
</DefaultLayout.IframeHeaderButtonWrapper>
</DefaultLayout.IframeHeader>
{isInviteUsersOpen ? (
<InviteUserToMatrixRoom
roomId={roomId}
roomName={matrix.rooms.get(roomId).name}
onSuccess={() => setIsInviteUsersOpen(false)}
{tldrawMatrix && tldrawMatrix.store && (
<Editor
store={tldrawMatrix.store}
updateStoreElement={tldrawMatrix.updateStoreElementInMatrix}
addStoreElement={tldrawMatrix.addStoreElementToMatrix}
deleteStoreElement={tldrawMatrix.deleteStoreElementInMatrix}
/>
) : (
tldrawMatrix &&
tldrawMatrix.store && (
<Editor
store={tldrawMatrix.store}
updateStoreElement={tldrawMatrix.updateStoreElementInMatrix}
addStoreElement={tldrawMatrix.addStoreElementToMatrix}
deleteStoreElement={tldrawMatrix.deleteStoreElementInMatrix}
/>
)
)}
</DefaultLayout.IframeWrapper>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useRouter } from 'next/router';
import getConfig from 'next/config';

import Form from '../../../components/UI/Form';
import LoadingSpinnerInline from '../../../components/UI/LoadingSpinnerInline';
import { path as tldrawPath } from '../../../lib/Tldraw';
import Form from '@/components/UI/Form';
import LoadingSpinnerInline from '@/components/UI/LoadingSpinnerInline';
import { path as tldrawPath } from '@/lib/Tldraw';
import { Input } from '@/components/UI/shadcn/Input';
import { Button } from '@/components/UI/shadcn/Button';

export default function CreateNewTlDrawSketch({ callbackDone, createTlDrawRoom }) {
export default function CreateNewTldraw({ callbackDone, createTlDrawRoom }) {
const router = useRouter();
const { t } = useTranslation('tldraw');

Expand All @@ -27,9 +28,16 @@ export default function CreateNewTlDrawSketch({ callbackDone, createTlDrawRoom }
};

return (
<Form onSubmit={(e) => { e.preventDefault(); createTlDrawSketch(sketchName); }}>
<input type="text" placeholder={t('Name')} value={sketchName} onChange={(e) => setSketchName(e.target.value)} />
<button type="submit" disabled={!sketchName}>{ isLoading ? <LoadingSpinnerInline inverted /> : t('Create sketch') }</button>
<Form
onSubmit={(e) => {
e.preventDefault();
createTlDrawSketch(sketchName);
}}
>
<Input type="text" placeholder={t('Name')} value={sketchName} onChange={(e) => setSketchName(e.target.value)} />
<Button type="submit" disabled={!sketchName}>
{isLoading ? <LoadingSpinnerInline inverted /> : t('Create draw')}
</Button>
</Form>
);
}

0 comments on commit 510e7af

Please sign in to comment.