Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Notes: web developers are advised to use [`~` (tilde range)](https://github.com/
- `activityMiddleware` is being deprecated in favor of [`polymiddleware`](./docs/MIDDLEWARE.md). It will be removed on or after 2027-08-16, related to PR [#5515](https://github.com/microsoft/BotFramework-WebChat/pull/5515)
- Root-level (unconnected) `Claim` entity is being deprecated, in PR [#5564](https://github.com/microsoft/BotFramework-WebChat/pull/5564), by [@compulim](https://github.com/compulim). It will be removed on or after 2027-08-29
- Use `entities[@id=""][@type="Message"].citation[@type="Claim"]` instead
- `activityStatusMiddleware.nextVisibleActivity` and `activityStatusMiddleware.sameTimestampGroup` is removed after deprecation, in PR [#5565](https://github.com/microsoft/BotFramework-WebChat/issues/5565), by [@compulim](https://github.com/compulim)

### Added

Expand Down Expand Up @@ -296,6 +297,8 @@ Notes: web developers are advised to use [`~` (tilde range)](https://github.com/
- `activityMiddleware` is being deprecated in favor of [`polymiddleware`](./docs/MIDDLEWARE.md). It will be removed on or after 2027-08-16, related to PR [#5515](https://github.com/microsoft/BotFramework-WebChat/pull/5515)
- Root-level (unconnected) `Claim` entity is being deprecated, in PR [#5564](https://github.com/microsoft/BotFramework-WebChat/pull/5564), by [@compulim](https://github.com/compulim). It will be removed on or after 2027-08-29
- Use `entities[@id=""][@type="Message"].citation[@type="Claim"]` instead
- `activityStatusMiddleware.nextVisibleActivity` and `activityStatusMiddleware.sameTimestampGroup` is being deprecated and will be removed on or after 2022-07-22, in PR [#4362](https://github.com/microsoft/BotFramework-WebChat/issues/4362), by [@compulim](https://github.com/compulim)
- Completed deprecation, in PR [#5565](https://github.com/microsoft/BotFramework-WebChat/issues/5565), by [@compulim](https://github.com/compulim)

### Samples

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en-US">
<head>
<link href="/assets/activityGrouping.css" rel="stylesheet" type="text/css" />
Expand Down Expand Up @@ -58,10 +58,10 @@
}
} = window;

const PasswordInputActivity = ({ activity, nextVisibleActivity }) => {
const PasswordInputActivity = ({ activity }) => {
const [twoFACode, setTwoFACode] = useState('');
const [submitted, setSubmitted] = useState(false);
const renderActivityStatus = useCreateActivityStatusRenderer()({ activity, nextVisibleActivity });
const renderActivityStatus = useCreateActivityStatusRenderer()({ activity });
const sendPostBack = useSendPostBack();

const handleCodeChange = useCallback(
Expand Down Expand Up @@ -101,15 +101,18 @@
);
};

const activityMiddleware = () => next => (...args) => {
const [{ activity, nextVisibleActivity }] = args;
const activityMiddleware =
() =>
next =>
(...args) => {
const [{ activity }] = args;

if (activity.type === 'password-input') {
return () => <PasswordInputActivity activity={activity} nextVisibleActivity={nextVisibleActivity} />;
}
if (activity.type === 'password-input') {
return () => <PasswordInputActivity activity={activity} />;
}

return next(...args);
};
return next(...args);
};

run(async function () {
const now = Date.now();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en-US">
<head>
<link href="/assets/index.css" rel="stylesheet" type="text/css" />
Expand Down Expand Up @@ -38,8 +38,8 @@
activity: {
from: { role }
},
sendState,
sameTimestampGroup
hideTimestamp,
sendState
}
] = args;

Expand All @@ -56,7 +56,7 @@
<span className="activity-status__send-failed">Send failed.</span>
</span>
);
} else if (!sameTimestampGroup) {
} else if (!hideTimestamp) {
return (
<span className="activity-status">
<span className="activity-status__timestamp-pretext">{role === 'user' ? 'User at ' : 'Bot at '}</span>
Expand Down
2 changes: 2 additions & 0 deletions docs/HOOKS.md
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,8 @@ This hook will return a function that, when called with a `Date` object, `number

## `useRenderActivity`

> Deprecation notes: this hook is being deprecated and replaced by `useBuildRenderActivityCallback`, it will be removed on or after 2027-08-16.

<!-- prettier-ignore-start -->
```js
useRenderActivity(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,7 @@ function createActivityPolymiddlewareFromLegacy(
);

return ({ activity }) => {
// TODO: [P1] `nextVisibleActivity` is deprecated and should be removed.
const legacyResult = legacyHandler({ activity, nextVisibleActivity: undefined as any });
const legacyResult = legacyHandler({ activity });

if (!legacyResult) {
// Legacy cannot fallback to poly middleware due to signature incompatibility.
Expand Down
1 change: 0 additions & 1 deletion packages/api-middleware/src/legacy/activityMiddleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ type LegacyActivityComponent = (props: LegacyActivityProps) => Exclude<ReactNode

type LegacyActivityComponentFactoryOptions = {
activity: WebChatActivity;
nextVisibleActivity: WebChatActivity;
};

type LegacyActivityComponentFactory = (
Expand Down
46 changes: 13 additions & 33 deletions packages/api/src/hooks/useCreateActivityStatusRenderer.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,29 @@
/* eslint react/prop-types: "off" */
/* eslint react/require-default-props: "off" */

import type { WebChatActivity } from 'botframework-webchat-core';
import { type WebChatActivity } from 'botframework-webchat-core';
Comment thread
compulim marked this conversation as resolved.
import React, { memo, useMemo, type ReactNode } from 'react';

import useGetKeyByActivity from '../hooks/useGetKeyByActivity';
import useSendStatusByActivityKey from '../hooks/useSendStatusByActivityKey';
import type { RenderActivityStatus } from '../types/ActivityStatusMiddleware';
import type { SendStatus } from '../types/SendStatus';
import { type RenderActivityStatus } from '../types/ActivityStatusMiddleware';
import { type SendStatus } from '../types/SendStatus';
Comment thread
compulim marked this conversation as resolved.
import useWebChatAPIContext from './internal/useWebChatAPIContext';

type ActivityStatusContainerCoreProps = Readonly<{
activity: WebChatActivity;
hideTimestamp: boolean;
nextVisibleActivity: WebChatActivity;
sendStatus: SendStatus;
}>;

const ActivityStatusContainerCore = memo(
({ activity, hideTimestamp, nextVisibleActivity, sendStatus }: ActivityStatusContainerCoreProps) => {
({ activity, hideTimestamp, sendStatus }: ActivityStatusContainerCoreProps) => {
const { activityStatusRenderer: createActivityStatusRenderer }: { activityStatusRenderer: RenderActivityStatus } =
useWebChatAPIContext();

return createActivityStatusRenderer({
activity,
hideTimestamp,
nextVisibleActivity, // "nextVisibleActivity" is for backward compatibility, please remove this line on or after 2022-07-22.
sameTimestampGroup: hideTimestamp, // "sameTimestampGroup" is for backward compatibility, please remove this line on or after 2022-07-22.
sendState: sendStatus === 'send failed' || sendStatus === 'sent' ? sendStatus : 'sending'
});
}
Expand All @@ -35,45 +32,28 @@ const ActivityStatusContainerCore = memo(
type ActivityStatusContainerProps = Readonly<{
activity: WebChatActivity;
hideTimestamp: boolean;
nextVisibleActivity: WebChatActivity;
}>;

const ActivityStatusContainer = memo(
({ activity, hideTimestamp, nextVisibleActivity }: ActivityStatusContainerProps) => {
const [sendStatusByActivityKey] = useSendStatusByActivityKey();
const getKeyByActivity = useGetKeyByActivity();
const ActivityStatusContainer = memo(({ activity, hideTimestamp }: ActivityStatusContainerProps) => {
const [sendStatusByActivityKey] = useSendStatusByActivityKey();
const getKeyByActivity = useGetKeyByActivity();

const key = getKeyByActivity(activity);
const key = getKeyByActivity(activity);

const sendStatus = (typeof key === 'string' && sendStatusByActivityKey.get(key)) || 'sent';
const sendStatus = (typeof key === 'string' && sendStatusByActivityKey.get(key)) || 'sent';

return (
<ActivityStatusContainerCore
activity={activity}
hideTimestamp={hideTimestamp}
nextVisibleActivity={nextVisibleActivity}
sendStatus={sendStatus}
/>
);
}
);
return <ActivityStatusContainerCore activity={activity} hideTimestamp={hideTimestamp} sendStatus={sendStatus} />;
});

export type ActivityStatusRenderer = (renderOptions: {
activity: WebChatActivity;
nextVisibleActivity: WebChatActivity;
}) => (props?: { hideTimestamp?: boolean }) => ReactNode;

export default function useCreateActivityStatusRenderer(): ActivityStatusRenderer {
return useMemo<ActivityStatusRenderer>(
() =>
({ activity, nextVisibleActivity }) =>
({ hideTimestamp } = {}) => (
<ActivityStatusContainer
activity={activity}
hideTimestamp={hideTimestamp}
nextVisibleActivity={nextVisibleActivity}
/>
),
({ activity }) =>
({ hideTimestamp } = {}) => <ActivityStatusContainer activity={activity} hideTimestamp={hideTimestamp} />,
[]
);
}
8 changes: 1 addition & 7 deletions packages/api/src/legacy/LegacyActivityBridge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,7 @@ function LegacyActivityBridge(props: LegacyActivityBridgeComponentProps) {
const renderAvatarRaw = useCreateAvatarRenderer();

const renderActivityStatus = useMemo(
() =>
createActivityStatusRenderer(
Object.freeze({
activity,
nextVisibleActivity: undefined
})
),
() => createActivityStatusRenderer(Object.freeze({ activity })),
[activity, createActivityStatusRenderer]
);
const renderAvatar = useMemo(
Expand Down
10 changes: 1 addition & 9 deletions packages/api/src/types/ActivityStatusMiddleware.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ReactElement } from 'react';
import type { WebChatActivity } from 'botframework-webchat-core';
import type { ReactElement } from 'react';
Comment thread
compulim marked this conversation as resolved.

import type { SendStatus } from '../types/SendStatus';

Expand All @@ -8,14 +8,6 @@ type RenderActivityStatusOptions = {
activity: WebChatActivity;
hideTimestamp: boolean;
sendState: SendStatus;

// "nextVisibleActivity" is for backward compatibility, please remove this line on or after 2022-07-22.
/** @deprecated */
nextVisibleActivity: WebChatActivity;

// "sameTimestampGroup" is for backward compatibility, please remove this line on or after 2022-07-22.
/** @deprecated */
sameTimestampGroup: boolean;
};

type RenderActivityStatus = (options: RenderActivityStatusOptions) => ReactElement;
Expand Down
8 changes: 4 additions & 4 deletions samples/05.custom-components/f.password-input/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@

const { useCallback, useState } = window.React;

const PasswordInputActivity = ({ activity, nextVisibleActivity }) => {
const PasswordInputActivity = ({ activity }) => {
const [twoFACode, setTwoFACode] = useState('');
const [submitted, setSubmitted] = useState(false);
const renderActivityStatus = useCreateActivityStatusRenderer()({ activity, sendState: 'sent' });
Expand Down Expand Up @@ -140,13 +140,13 @@
const activityMiddleware =
() =>
next =>
({ activity, nextVisibleActivity, ...otherArgs }) => {
({ activity, ...otherArgs }) => {
const { name, type } = activity;

if (type === 'event' && name === 'passwordInput') {
return () => <PasswordInputActivity activity={activity} nextVisibleActivity={nextVisibleActivity} />;
return () => <PasswordInputActivity activity={activity} />;
} else {
return next({ activity, nextVisibleActivity, ...otherArgs });
return next({ activity, ...otherArgs });
}
};

Expand Down
6 changes: 3 additions & 3 deletions samples/05.custom-components/g.activity-status/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,16 @@
activity: {
from: { role }
},
sendState,
sameTimestampGroup
hideTimestamp,
sendState
} = args;

if (sendState === 'sending') {
return <span className="activityStatus activityStatus__sendStatus">Sending&hellip;</span>;
} else if (sendState === 'send failed') {
// Custom retry logic can be added when rendering the "Send failed." status.
return <span className="activityStatus">Send failed.</span>;
} else if (!sameTimestampGroup) {
} else if (!hideTimestamp) {
return (
<span className="activityStatus activityStatus__timestamp">
<span className="activityStatus__timestampPretext">{role === 'user' ? 'User at ' : 'Bot at '}</span>
Expand Down
Loading