Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion packages/mgt-chat/src/components/Chat/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { onRenderMessage } from '../../utils/chat';
import { renderMGTMention } from '../../utils/mentions';
import { registerAppIcons } from '../styles/registerIcons';
import { ChatHeader } from '../ChatHeader/ChatHeader';
import { GraphConfig } from '../../statefulClient/GraphConfig';
import { Error } from '../Error/Error';
import { LoadingMessagesErrorIcon } from '../Error/LoadingMessageErrorIcon';
import { OpenTeamsLinkError } from '../Error/OpenTeams';
Expand All @@ -19,6 +20,7 @@ registerAppIcons();

interface IMgtChatProps {
chatId: string;
usePremiumApis?: boolean;
}

const useStyles = makeStyles({
Expand Down Expand Up @@ -105,7 +107,7 @@ const messageThreadStyles: MessageThreadStyles = {
}
};

export const Chat = ({ chatId }: IMgtChatProps) => {
export const Chat = ({ chatId, usePremiumApis }: IMgtChatProps) => {
const styles = useStyles();
const chatClient: StatefulGraphChatClient = useGraphChatClient(chatId);
const [chatState, setChatState] = useState(chatClient.getState());
Expand All @@ -116,6 +118,10 @@ export const Chat = ({ chatId }: IMgtChatProps) => {
};
}, [chatClient]);

useEffect(() => {
GraphConfig.usePremiumApis = usePremiumApis ?? false;
}, [usePremiumApis]);

const isLoading = ['creating server connections', 'subscribing to notifications', 'loading messages'].includes(
chatState.status
);
Expand Down
1 change: 1 addition & 0 deletions packages/mgt-chat/src/statefulClient/GraphConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export class GraphConfig {
public static canarySubscriptionVersion = 'testprodv1.0e2ewebsockets';

public static webSocketsPrefix = 'websockets:';
static usePremiumApis = false;

public static get graphEndpoint(): GraphEndpoint {
return GraphConfig.useCanary ? 'https://canary.graph.microsoft.com' : 'https://graph.microsoft.com';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import type {
import { GraphConfig } from './GraphConfig';
import { SubscriptionsCache } from './Caching/SubscriptionCache';
import { Timer } from '../utils/Timer';
import { addPremiumApiSegment } from '../utils/addPremiumApiSegment';

export const appSettings = {
defaultSubscriptionLifetimeInMinutes: 10,
Expand Down Expand Up @@ -400,7 +401,9 @@ export class GraphNotificationClient {
await this.subscriptionCache.deleteCachedSubscriptions(chatId, sessionId);
}
const promises: Promise<unknown>[] = [];
promises.push(this.subscribeToResource(`/chats/${chatId}/messages`, ['created', 'updated', 'deleted']));
promises.push(
this.subscribeToResource(addPremiumApiSegment(`/chats/${chatId}/messages`), ['created', 'updated', 'deleted'])
);
promises.push(this.subscribeToResource(`/chats/${chatId}/members`, ['created', 'deleted']));
promises.push(this.subscribeToResource(`/chats/${chatId}`, ['updated', 'deleted']));
await Promise.all(promises).catch((e: Error) => {
Expand Down
5 changes: 3 additions & 2 deletions packages/mgt-chat/src/statefulClient/graph.chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { CacheService, IGraph, prepScopes } from '@microsoft/mgt-element';
import { ResponseType } from '@microsoft/microsoft-graph-client';
import { AadUserConversationMember, Chat, ChatMessage } from '@microsoft/microsoft-graph-types';
import { chatOperationScopes } from './chatOperationScopes';
import { addPremiumApiSegment } from '../utils/addPremiumApiSegment';

/**
* Generic collection response from graph
Expand Down Expand Up @@ -59,7 +60,7 @@ export const loadChatThread = async (
messageCount: number
): Promise<MessageCollection> => {
const response = (await graph
.api(`/chats/${chatId}/messages`)
.api(addPremiumApiSegment(`/chats/${chatId}/messages`))
.orderby('createdDateTime DESC')
.top(messageCount)
.middlewareOptions(prepScopes(chatOperationScopes.loadChatMessages))
Expand All @@ -86,7 +87,7 @@ export const loadChatThreadDelta = async (
messageCount: number
): Promise<MessageCollection> => {
const response = (await graph
.api(`/chats/${chatId}/messages`)
.api(addPremiumApiSegment(`/chats/${chatId}/messages`))
.filter(`lastModifiedDateTime gt ${lastModified}`)
.orderby('lastModifiedDateTime DESC')
.top(messageCount)
Expand Down
25 changes: 25 additions & 0 deletions packages/mgt-chat/src/utils/addPremiumApiSegment.tests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { GraphConfig } from '../statefulClient/GraphConfig';
import { addPremiumApiSegment } from './addPremiumApiSegment';
import { expect } from '@open-wc/testing';

describe('addPremiumApiSegment tests', () => {
it('should return the original url if premium apis are not enabled', async () => {
const url = 'https://graph.microsoft.com/v1.0/me';
const result = addPremiumApiSegment(url);
await expect(result).to.eql(url);
});

it('should add the premium api segment to the url', async () => {
const url = 'https://graph.microsoft.com/v1.0/me';
GraphConfig.usePremiumApis = true;
const result = addPremiumApiSegment(url);
await expect(result).to.eql(`${url}?model=B`);
});

it('should add the premium api segment to the url when it already has query params', async () => {
const url = 'https://graph.microsoft.com/v1.0/me?select=id';
GraphConfig.usePremiumApis = true;
const result = addPremiumApiSegment(url);
await expect(result).to.eql(`${url}&model=B`);
});
});
10 changes: 10 additions & 0 deletions packages/mgt-chat/src/utils/addPremiumApiSegment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { GraphConfig } from '../statefulClient/GraphConfig';

export const addPremiumApiSegment = (url: string) => {
// early exit if premium apis are not enabled
if (!GraphConfig.usePremiumApis) {
return url;
}
const urlHasExistingQueryParams = url.includes('?');
return `${url}${urlHasExistingQueryParams ? '&' : '?'}model=B`;
};
2 changes: 1 addition & 1 deletion packages/mgt-chat/src/utils/mentions.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { MgtTemplateProps, Person } from '@microsoft/mgt-react';
import { ChatMessageMention, User } from '@microsoft/microsoft-graph-types';
import { GraphChatClient } from 'src/statefulClient/StatefulGraphChatClient';
import { GraphChatClient } from '../statefulClient/StatefulGraphChatClient';
import { Mention } from '@azure/communication-react';

export const renderMGTMention = (chatState: GraphChatClient) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/mgt-chat/src/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import { ChatMessage, Message } from '@azure/communication-react';
import { GraphChatMessage } from 'src/statefulClient/StatefulGraphChatClient';
import type { GraphChatMessage } from '../statefulClient/StatefulGraphChatClient';

/**
* A typeguard to get the ChatMessage type
Expand Down
2 changes: 2 additions & 0 deletions packages/mgt-spfx/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
release
temp
1 change: 1 addition & 0 deletions samples/react-chat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@fluentui/react-components": "^9.19.1",
"@microsoft/mgt-chat": "*",
"@microsoft/mgt-msal2-provider": "*",
"@microsoft/mgt-react": "*",
Expand Down
53 changes: 31 additions & 22 deletions samples/react-chat/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React, { memo, useCallback, useState } from 'react';
import React, { ChangeEvent, memo, useCallback, useState } from 'react';
import './App.css';
import { Get, Login } from '@microsoft/mgt-react';
import { Chat, NewChat } from '@microsoft/mgt-chat';
import { Chat as GraphChat } from '@microsoft/microsoft-graph-types';
import ChatListTemplate from './components/ChatListTemplate/ChatListTemplate';
import { FluentProvider, Switch, SwitchOnChangeData, teamsLightTheme } from '@fluentui/react-components';

const ChatList = memo(({ chatSelected }: { chatSelected: (e: GraphChat) => void }) => {
return (
Expand All @@ -25,31 +26,39 @@ function App() {
setShowNewChat(false);
}, []);

const [usePremiumApis, setUsePremiumApis] = useState<boolean>(false);
const onToggleChanged = useCallback((ev: ChangeEvent<HTMLInputElement>, data: SwitchOnChangeData) => {
setUsePremiumApis(data.checked ?? false);
}, []);

return (
<div className="App">
<header className="App-header">
Mgt Chat test harness
<br />
<Login />
</header>
<main className="main">
<div className="chat-selector">
<ChatList chatSelected={chatSelected} />
Selected chat: {chatId}
<br />
<button onClick={() => setChatId('')}>Clear selected chat</button>
<FluentProvider theme={teamsLightTheme}>
<header className="App-header">
Mgt Chat test harness
<br />
<button onClick={() => setShowNewChat(true)}>New Chat</button>
{showNewChat && (
<div className="new-chat">
<NewChat onChatCreated={onChatCreated} onCancelClicked={() => setShowNewChat(false)} mode="auto" />
</div>
)}
</div>
<Login />
</header>
<main className="main">
<div className="chat-selector">
<Switch onChange={onToggleChanged} checked={usePremiumApis} label="Use premium APIs?" />
<ChatList chatSelected={chatSelected} />
Selected chat: {chatId}
<br />
<button onClick={() => setChatId('')}>Clear selected chat</button>
<br />
<button onClick={() => setShowNewChat(true)}>New Chat</button>
{showNewChat && (
<div className="new-chat">
<NewChat onChatCreated={onChatCreated} onCancelClicked={() => setShowNewChat(false)} mode="auto" />
</div>
)}
</div>

{/* NOTE: removed the chatId guard as this case has an error state. */}
<div className="chat-pane">{<Chat chatId={chatId} />}</div>
</main>
{/* NOTE: removed the chatId guard as this case has an error state. */}
<div className="chat-pane">{<Chat chatId={chatId} usePremiumApis={usePremiumApis} />}</div>
</main>
</FluentProvider>
</div>
);
}
Expand Down
1 change: 1 addition & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -25931,6 +25931,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "react-chat@workspace:samples/react-chat"
dependencies:
"@fluentui/react-components": ^9.19.1
"@microsoft/mgt-chat": "*"
"@microsoft/mgt-msal2-provider": "*"
"@microsoft/mgt-react": "*"
Expand Down