Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify and fix presence in ai-collab example app #3

Closed
wants to merge 10 commits into from

Conversation

alexvy86
Copy link

This seems to fix the issues with presence we're having. A few callouts:

  • Simplified from a LatestMapValueManager to a LatestValueManager, since we just have 1 value to keep track of per participant (the photoUrl).
  • Removed used of uuids in favor of sessionId provided by the presence package.
  • Moved a couple of things around to appease React's linting rules.
  • Needed to configure NextJS to not use React strict mode so components aren't rendered twice. Otherwise, when loading a container it is loaded twice and it shows up as 2 presence participants.

@@ -51,7 +49,7 @@ export async function createAndInitializeContainer(): Promise<
export default function TasksListPage(): JSX.Element {
const [selectedTaskGroup, setSelectedTaskGroup] = useState<SharedTreeTaskGroup>();
const [treeView, setTreeView] = useState<TreeView<typeof SharedTreeAppState>>();
const [userPresenceGroup, setUserPresenceGroup] = useState<UserPresence>();
const [presence, setPresence] = useState<IPresence>();
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using IPresence "at the top" so we can leverage the events for updated data and for participants disconnecting, as well as the current participant's sessionId.

]);

// Detect when the page is closed
useEffect(() => {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apparently unnecessary; when a tab closes, the attendeeDisconnected event fires correctly in other tabs with no extra code required.

@@ -0,0 +1,17 @@
/*!
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seeing error: /home/tong/workspace/FluidFramework/node_modules/.pnpm/next@14.2.8_@babel+core@7.25.7_react-dom@18.3.1_react@18.3.1/node_modules/next/dist/server/config.js:787
throw new Error(Configuring Next.js via '${(0, _path.basename)(nonJsPath)}' is not supported. Please replace the file with 'next.config.js' or 'next.config.mjs'.);

including next.config.ts in tsconfig.json...see how it goes

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename to .cjs works. Thx!


import type { NextConfig } from "next/types";

// We deliberately configure NextJS to not use React Strict Mode, so we don't get double-rendering of React components

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you link to where this contract is documented?


export interface User {
photo: string;
}

const statesSchema = {
onlineUsers: LatestMap<{ value: User }, `id-${string}`>(),
onlineUsers: Latest<User>({ photo: "" }),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is empty string special for the photo property? Can we document why we're setting it that way?

photoUrlsMap.set(update.key, update.value.value.photo);
setPhotoUrls([...photoUrlsMap.values()]);
userPresenceGroup.props.onlineUsers.events.on("updated", (update) => {
console.debug("Presence - 'updated' event", JSON.stringify(update));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to keep the debug logs here? Seems reasonable to keep, just checking 🙂

@@ -125,11 +107,11 @@ const UserPresenceGroup: React.FC<UserPresenceProps> = ({
<Avatar alt="User Photo" src={photo} sx={{ width: 56, height: 56 }} />
</StyledBadge>
))}
{photoUrls.length > 4 && (
{photoUrls.size > 4 && (

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Magic number 4: can we extract and document this?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. Adding comments here. It just looks prettier if there are more than 4 users. We will only show 4 users and a + remaining_number

@chentong7 chentong7 force-pushed the ai-tong branch 2 times, most recently from 73717f3 to f45f4ea Compare December 18, 2024 02:06

// Takes a presence object and returns the user presence object that contains the shared object states
export function buildUserPresence(presence: IPresence): UserPresence {
const states = presence.getStates(`name:user-avatar-states`, statesSchema);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is name:user-avatar-states a special reserved string?

Comment on lines +47 to +49
if (isFirstRender.current) {
updateUserPresenceGroup().catch((error) => console.error(error));
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: This pattern is fine, but it's more common to have a useEffect with an empty dependency array (will only run during first render) and then use a property of photoUrls's to determine whether it has been initialized, for example
isInitialized = photoUrls.get(presence.getMyself().sessionId) !== undefined

@@ -20,6 +20,7 @@
"paths": {
"@/*": ["./src/*"],
},
"allowJs": true,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably got added back by accident right? @alexvy86

@alexvy86
Copy link
Author

The relevant changes were already ported to microsoft#22850, we'll continue work there.

@alexvy86 alexvy86 closed this Dec 19, 2024
@alexvy86 alexvy86 deleted the fix-presence branch January 7, 2025 22:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants