Updated Liveblocks Config and Added Liveblocks test Pages (Non-Functional)

This commit is contained in:
Ahmad 2024-03-08 23:03:19 -05:00
parent a44563748d
commit b1ab232900
No known key found for this signature in database
GPG key ID: 8FD8A93530D182BF
6 changed files with 117 additions and 86 deletions

View file

@ -0,0 +1,27 @@
type Props = {
x: number;
y: number;
};
export function Cursor({ x, y }: Props) {
return (
<svg
style={{
position: 'absolute',
left: 0,
top: 0,
transform: `translateX(${x}px) translateY(${y}px)`,
}}
width='16'
height='16'
viewBox='0 0 16 16'
fill='none'
xmlns='http://www.w3.org/2000/svg'
>
<path
d='m13.67 6.03-11-4a.5.5 0 0 0-.64.64l4 11a.5.5 0 0 0 .935.015l1.92-4.8 4.8-1.92a.5.5 0 0 0 0-.935h-.015Z'
fill='var(--preview-background-inverse)'
/>
</svg>
);
}

View file

@ -0,0 +1,22 @@
'use client';
import { ReactNode } from 'react';
import { RoomProvider } from '@/liveblocks.config';
import { ClientSideSuspense } from '@liveblocks/react';
import { useAuth } from '@clerk/nextjs';
const Room = ({ children }: { children: ReactNode }) => {
const { orgId } = useAuth();
if (!orgId) return null;
return (
<RoomProvider id={orgId} initialPresence={{ cursor: null }}>
<ClientSideSuspense fallback={<div>Loading</div>}>
{() => children}
</ClientSideSuspense>
</RoomProvider>
);
}
export default Room;

View file

@ -0,0 +1,38 @@
import { useMyPresence, useOthers } from '@/liveblocks.config';
import { Cursor } from './cursor';
const TestPage = () => {
const [myPresence, updateMyPresence] = useMyPresence();
const others = useOthers();
function handlePointerMove(e: any) {
const cursor = { x: Math.floor(e.clientX), y: Math.floor(e.clientY) };
updateMyPresence({ cursor });
}
function handlePointerLeave() {
updateMyPresence({ cursor: null });
}
return (
<div
style={{ width: '100vw', height: '100vh' }}
onPointerMove={handlePointerMove}
onPointerLeave={handlePointerLeave}
>
Cursor: {JSON.stringify(myPresence.cursor)}
{others
.filter((other) => other.presence.cursor !== null)
.map(({ connectionId, presence }) => (
<Cursor
key={connectionId}
x={presence.cursor.x}
y={presence.cursor.y}
/>
))}
</div>
);
};
export default TestPage;

View file

@ -1,51 +1,22 @@
import { createClient } from '@liveblocks/client'; import { createClient } from "@liveblocks/client";
import { createRoomContext } from '@liveblocks/react'; import { createRoomContext, createLiveblocksContext } from "@liveblocks/react";
const client = createClient({ const client = createClient({
// publicApiKey: process.env.LIVEBLOCKS_PUBLIC_DEV_API_KEY!, publicApiKey: process.env.NEXT_PUBLIC_LIVEBLOCKS_PUBLIC_KEY!,
authEndpoint: '/api/liveblocks-auth', throttle: 16,
// throttle: 100,
}); });
// Presence represents the properties that exist on every user in the Room
// and that will automatically be kept in sync. Accessible through the
// `user.presence` property. Must be JSON-serializable.
type Presence = { type Presence = {
// cursor: { x: number, y: number } | null, cursor: { x: number; y: number } | null;
// ...
}; };
// Optionally, Storage represents the shared document that persists in the type Storage = {};
// Room, even after all users leave. Fields under Storage typically are
// LiveList, LiveMap, LiveObject instances, for which updates are
// automatically persisted and synced to all connected clients.
type Storage = {
// author: LiveObject<{ firstName: string, lastName: string }>,
// ...
};
// Optionally, UserMeta represents static/readonly metadata on each user, as type UserMeta = {};
// provided by your own custom auth back end (if used). Useful for data that
// will not change during a session, like a user's name or avatar.
type UserMeta = {
id?: string; // Accessible through `user.id`
// info?: Json, // Accessible through `user.info`
};
// Optionally, the type of custom events broadcast and listened to in this type RoomEvent = {};
// room. Use a union for multiple events. Must be JSON-serializable.
type RoomEvent = {
// type: "NOTIFICATION",
// ...
};
// Optionally, when using Comments, ThreadMetadata represents metadata on export type ThreadMetadata = {};
// each thread. Can only contain booleans, strings, and numbers.
export type ThreadMetadata = {
// resolved: boolean;
// quote: string;
// time: number;
};
export const { export const {
suspense: { suspense: {
@ -56,15 +27,13 @@ export const {
useSelf, useSelf,
useOthers, useOthers,
useOthersMapped, useOthersMapped,
useOthersListener,
useOthersConnectionIds, useOthersConnectionIds,
useOther, useOther,
useBroadcastEvent, useBroadcastEvent,
useEventListener, useEventListener,
useErrorListener, useErrorListener,
useStorage, useStorage,
useObject,
useMap,
useList,
useBatch, useBatch,
useHistory, useHistory,
useUndo, useUndo,
@ -75,7 +44,6 @@ export const {
useStatus, useStatus,
useLostConnectionListener, useLostConnectionListener,
useThreads, useThreads,
useUser,
useCreateThread, useCreateThread,
useEditThreadMetadata, useEditThreadMetadata,
useCreateComment, useCreateComment,
@ -83,45 +51,21 @@ export const {
useDeleteComment, useDeleteComment,
useAddReaction, useAddReaction,
useRemoveReaction, useRemoveReaction,
}, useThreadSubscription,
} = createRoomContext<Presence, Storage, UserMeta, RoomEvent, ThreadMetadata>( useMarkThreadAsRead,
client, useRoomNotificationSettings,
{ useUpdateRoomNotificationSettings,
async resolveUsers({ userIds }) {
// Used only for Comments. Return a list of user information retrieved
// from `userIds`. This info is used in comments, mentions etc.
// const usersData = await __fetchUsersFromDB__(userIds);
//
// return usersData.map((userData) => ({
// name: userData.name,
// avatar: userData.avatar.src,
// }));
return [];
},
async resolveMentionSuggestions({ text, roomId }) {
// Used only for Comments. Return a list of userIds that match `text`.
// These userIds are used to create a mention list when typing in the
// composer.
//
// For example when you type "@jo", `text` will be `"jo"`, and
// you should to return an array with John and Joanna's userIds:
// ["john@example.com", "joanna@example.com"]
// const userIds = await __fetchAllUserIdsFromDB__(roomId);
//
// Return all userIds if no `text`
// if (!text) {
// return userIds;
// }
//
// Otherwise, filter userIds for the search `text` and return
// return userIds.filter((userId) =>
// userId.toLowerCase().includes(text.toLowerCase())
// );
return [];
},
} }
); } = createRoomContext<Presence, Storage, UserMeta, RoomEvent, ThreadMetadata>(client);
export const {
suspense: {
LiveblocksProvider,
useMarkInboxNotificationAsRead,
useMarkAllInboxNotificationsAsRead,
useInboxNotifications,
useUnreadInboxNotificationsCount,
useUser,
useRoomInfo,
}
} = createLiveblocksContext<UserMeta, ThreadMetadata>(client);

2
package-lock.json generated
View file

@ -11,7 +11,7 @@
"dependencies": { "dependencies": {
"@clerk/nextjs": "^4.29.9", "@clerk/nextjs": "^4.29.9",
"@hello-pangea/dnd": "^16.5.0", "@hello-pangea/dnd": "^16.5.0",
"@liveblocks/client": "^1.9.8", "@liveblocks/client": "^1.10.2",
"@liveblocks/node": "^1.10.2", "@liveblocks/node": "^1.10.2",
"@liveblocks/react": "^1.10.2", "@liveblocks/react": "^1.10.2",
"@microsoft/eslint-formatter-sarif": "^3.0.0", "@microsoft/eslint-formatter-sarif": "^3.0.0",

View file

@ -14,7 +14,7 @@
"dependencies": { "dependencies": {
"@clerk/nextjs": "^4.29.9", "@clerk/nextjs": "^4.29.9",
"@hello-pangea/dnd": "^16.5.0", "@hello-pangea/dnd": "^16.5.0",
"@liveblocks/client": "^1.9.8", "@liveblocks/client": "^1.10.2",
"@liveblocks/node": "^1.10.2", "@liveblocks/node": "^1.10.2",
"@liveblocks/react": "^1.10.2", "@liveblocks/react": "^1.10.2",
"@microsoft/eslint-formatter-sarif": "^3.0.0", "@microsoft/eslint-formatter-sarif": "^3.0.0",