Skip to content

Commit 843ad07

Browse files
committed
Prefix Legacy* and allow extraneous activity props
1 parent d24b30f commit 843ad07

10 files changed

Lines changed: 71 additions & 54 deletions

File tree

packages/api/src/hooks/Composer.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { PolyMiddlewareComposer, type PolyMiddleware } from '@msinternal/botframework-webchat-middleware';
2-
import { type ActivityMiddleware, type AttachmentMiddleware } from '@msinternal/botframework-webchat-middleware/legacy';
2+
import {
3+
type AttachmentMiddleware,
4+
type LegacyActivityMiddleware
5+
} from '@msinternal/botframework-webchat-middleware/legacy';
36
import { ReduxStoreComposer } from '@msinternal/botframework-webchat-redux-store';
47
import {
58
clearSuggestedActions,
@@ -210,7 +213,7 @@ type ComposerCoreProps = Readonly<{
210213
*
211214
* @deprecated
212215
*/
213-
activityMiddleware?: OneOrMany<ActivityMiddleware>;
216+
activityMiddleware?: OneOrMany<LegacyActivityMiddleware>;
214217
activityStatusMiddleware?: OneOrMany<ActivityStatusMiddleware>;
215218
attachmentForScreenReaderMiddleware?: OneOrMany<AttachmentForScreenReaderMiddleware>;
216219
attachmentMiddleware?: OneOrMany<AttachmentMiddleware>;
Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,25 @@
11
import {
2-
type ActivityComponentFactory,
3-
type RenderAttachment
2+
type LegacyActivityComponentFactory,
3+
type LegacyActivityProps
44
} from '@msinternal/botframework-webchat-middleware/legacy';
55
import { useCallback } from 'react';
66

77
import { useBuildRenderActivityCallback } from '@msinternal/botframework-webchat-middleware';
88

99
// TODO: [P*] Add tests.
10-
export default function useCreateActivityRendererInternal(
11-
/**
12-
* TODO: [P*] Need a deprecation path.
13-
*
14-
* @deprecated
15-
*/
16-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
17-
renderAttachmentOverride?: RenderAttachment
18-
): ActivityComponentFactory {
10+
export default function useCreateActivityRendererInternal(): LegacyActivityComponentFactory {
1911
const render = useBuildRenderActivityCallback();
2012

2113
return useCallback(
2214
({ activity }) =>
23-
() =>
24-
render({ activity })?.({}),
15+
// TODO: [P2] TypeScript turns `{ children?: never | undefined }` into `{ children?: undefined }`.
16+
// Thus we are getting a typing error here.
17+
// Maybe moving to a stricter tsconfig would help removing the line below.
18+
//
19+
// Use the following commented line once we move to stricter tsconfig.
20+
// (props: LegacyActivityProps) =>
21+
(props: LegacyActivityProps & { children?: never }) =>
22+
render({ activity })?.(props),
2523
[render]
2624
);
2725
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { type ActivityComponentFactory } from '@msinternal/botframework-webchat-middleware/legacy';
1+
import { type LegacyActivityComponentFactory } from '@msinternal/botframework-webchat-middleware/legacy';
22
import useCreateActivityRendererInternal from './internal/useCreateActivityRendererInternal';
33

44
// The newer useCreateActivityRenderer() hook does not support override renderAttachment().
55
// Only the deprecated useRenderActivity() hook support overriding renderAttachment().
6-
export default function useCreateActivityRenderer(): ActivityComponentFactory {
6+
export default function useCreateActivityRenderer(): LegacyActivityComponentFactory {
77
return useCreateActivityRendererInternal();
88
}

packages/api/src/index.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// TODO: Move the pattern to re-export.
22
import {
3-
type ActivityComponentFactory,
4-
type ActivityMiddleware,
53
type AttachmentMiddleware,
4+
type LegacyActivityComponentFactory,
5+
type LegacyActivityMiddleware,
66
type RenderAttachment
77
} from '@msinternal/botframework-webchat-middleware/legacy';
88
import StyleOptions, { StrictStyleOptions } from './StyleOptions';
@@ -63,8 +63,10 @@ const buildInfo = { buildTool, moduleFormat, version };
6363
export { buildInfo, Composer, concatMiddleware, defaultStyleOptions, hooks, localize, normalizeStyleOptions, version };
6464

6565
export type {
66-
ActivityComponentFactory,
67-
ActivityMiddleware,
66+
/** @deprecated Use `polyMiddleware` instead, this will be removed on or after 2027-08-16. */
67+
LegacyActivityComponentFactory as ActivityComponentFactory,
68+
/** @deprecated Use `polyMiddleware` instead, this will be removed on or after 2027-08-16. */
69+
LegacyActivityMiddleware as ActivityMiddleware,
6870
ActivityStatusMiddleware,
6971
ActivityStatusRenderer,
7072
AttachmentForScreenReaderComponentFactory,

packages/api/src/internal.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import LowPriorityDecoratorComposer from './decorator/internal/LowPriorityDecora
22
import useSetDictateState from './hooks/internal/useSetDictateState';
33

44
export {
5-
bridgeComponentPropsSchema,
65
createActivityPolyMiddlewareFromLegacy,
7-
type BridgeComponentProps
6+
legacyActivityBridgeComponentPropsSchema,
7+
type LegacyActivityBridgeComponentProps
88
} from '@msinternal/botframework-webchat-middleware';
99

1010
export { LowPriorityDecoratorComposer, useSetDictateState };

packages/component/src/Middleware/Activity/private/LegacyActivityBridge.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import { validateProps } from '@msinternal/botframework-webchat-react-valibot';
22
import { hooks } from 'botframework-webchat-api';
3-
import { bridgeComponentPropsSchema, type BridgeComponentProps } from 'botframework-webchat-api/internal';
4-
import React, { Fragment, memo, useMemo } from 'react';
3+
import {
4+
legacyActivityBridgeComponentPropsSchema,
5+
type LegacyActivityBridgeComponentProps
6+
} from 'botframework-webchat-api/internal';
7+
import React, { Fragment, memo, useMemo, type ReactNode } from 'react';
58

69
import isZeroOrPositive from '../../../Utils/isZeroOrPositive';
710
import useFirstActivityInSenderGroup from '../../ActivityGrouping/ui/SenderGrouping/useFirstActivity';
@@ -11,8 +14,13 @@ import useLastActivityInStatusGroup from '../../ActivityGrouping/ui/StatusGroupi
1114

1215
const { useCreateActivityStatusRenderer, useCreateAvatarRenderer, useRenderAttachment, useStyleOptions } = hooks;
1316

14-
function LegacyActivityBridge(props: BridgeComponentProps) {
15-
const { activity, render } = validateProps(bridgeComponentPropsSchema, props);
17+
function LegacyActivityBridge(
18+
props: LegacyActivityBridgeComponentProps & {
19+
readonly renderActivityStatus: (options: { hideTimestamp: boolean }) => ReactNode;
20+
}
21+
) {
22+
const { activity, render } = validateProps(legacyActivityBridgeComponentPropsSchema, props);
23+
const { renderActivityStatus: renderActivityStatusFromProps } = props;
1624

1725
const [{ bubbleFromUserNubOffset, bubbleNubOffset, groupTimestamp, showAvatarInGroup }] = useStyleOptions();
1826
const [firstActivityInSenderGroup] = useFirstActivityInSenderGroup();
@@ -40,11 +48,12 @@ function LegacyActivityBridge(props: BridgeComponentProps) {
4048
const isTopSideUserNub = isZeroOrPositive(bubbleFromUserNubOffset);
4149
const renderActivityStatus = useMemo(
4250
() =>
51+
renderActivityStatusFromProps ||
4352
createActivityStatusRenderer({
4453
activity,
4554
nextVisibleActivity: undefined
4655
}),
47-
[activity, createActivityStatusRenderer]
56+
[activity, createActivityStatusRenderer, renderActivityStatusFromProps]
4857
);
4958

5059
const hideTimestamp = hideAllTimestamps || !isLastInStatusGroup;

packages/middleware/src/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ export {
1616
} from './activityPolyMiddleware';
1717

1818
export {
19-
bridgeComponentPropsSchema,
2019
default as createActivityPolyMiddlewareFromLegacy,
2120
fallbackComponentPropsSchema,
22-
type BridgeComponentProps,
23-
type FallbackComponentProps
21+
legacyActivityBridgeComponentPropsSchema,
22+
type FallbackComponentProps,
23+
type LegacyActivityBridgeComponentProps
2424
} from './internal/createActivityPolyMiddlewareFromLegacy';
2525

2626
export { default as PolyMiddlewareComposer } from './PolyMiddlewareComposer';

packages/middleware/src/internal/createActivityPolyMiddlewareFromLegacy.tsx

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { type WebChatActivity } from 'botframework-webchat-core';
22
import { composeEnhancer } from 'handler-chain';
33
import React, { type ComponentType, type ReactNode } from 'react';
4-
import type ActivityMiddleware from '../legacy/activityMiddleware';
4+
import { type LegacyActivityMiddleware } from '../legacy/activityMiddleware';
55
import { type RenderAttachment } from '../legacy/attachmentMiddleware';
66

77
import { custom, function_, never, object, optional, pipe, readonly, safeParse, type InferInput } from 'valibot';
@@ -23,7 +23,7 @@ type LegacyRenderFunction = (
2323
}
2424
) => Exclude<ReactNode, boolean>;
2525

26-
const bridgeComponentPropsSchema = pipe(
26+
const legacyActivityBridgeComponentPropsSchema = pipe(
2727
object({
2828
activity: webChatActivitySchema,
2929
children: optional(never()),
@@ -32,7 +32,9 @@ const bridgeComponentPropsSchema = pipe(
3232
readonly()
3333
);
3434

35-
type BridgeComponentProps = Readonly<InferInput<typeof bridgeComponentPropsSchema> & { children?: never }>;
35+
type LegacyActivityBridgeComponentProps = Readonly<
36+
InferInput<typeof legacyActivityBridgeComponentPropsSchema> & { children?: never }
37+
>;
3638

3739
const fallbackComponentPropsSchema = pipe(
3840
object({
@@ -45,16 +47,16 @@ const fallbackComponentPropsSchema = pipe(
4547
type FallbackComponentProps = Readonly<InferInput<typeof fallbackComponentPropsSchema> & { children?: never }>;
4648

4749
function createActivityPolyMiddlewareFromLegacy(
48-
bridgeComponent: ComponentType<BridgeComponentProps>,
50+
bridgeComponent: ComponentType<LegacyActivityBridgeComponentProps>,
4951
// Use lowercase for argument name, but we need uppercase for JSX.
5052
fallbackComponent: ComponentType<FallbackComponentProps>,
51-
...middleware: readonly ActivityMiddleware[]
53+
...middleware: readonly LegacyActivityMiddleware[]
5254
): ActivityPolyMiddleware;
5355

5456
function createActivityPolyMiddlewareFromLegacy(
55-
bridgeComponent: ComponentType<BridgeComponentProps>,
57+
bridgeComponent: ComponentType<LegacyActivityBridgeComponentProps>,
5658
FallbackComponent: ComponentType<FallbackComponentProps>,
57-
...middleware: readonly ActivityMiddleware[]
59+
...middleware: readonly LegacyActivityMiddleware[]
5860
): ActivityPolyMiddleware {
5961
const legacyEnhancer = composeEnhancer(...middleware.map(middleware => middleware()));
6062

@@ -77,8 +79,8 @@ function createActivityPolyMiddlewareFromLegacy(
7779
export default createActivityPolyMiddlewareFromLegacy;
7880

7981
export {
80-
bridgeComponentPropsSchema,
8182
fallbackComponentPropsSchema,
82-
type BridgeComponentProps,
83-
type FallbackComponentProps
83+
legacyActivityBridgeComponentPropsSchema,
84+
type FallbackComponentProps,
85+
type LegacyActivityBridgeComponentProps
8486
};

packages/middleware/src/legacy.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export {
2-
type ActivityComponentFactory,
3-
type default as ActivityMiddleware,
2+
type LegacyActivityComponentFactory,
3+
type LegacyActivityMiddleware,
4+
type LegacyActivityProps,
45
type LegacyActivityRenderer
56
} from './legacy/activityMiddleware';
67
export { type default as AttachmentMiddleware, type RenderAttachment } from './legacy/attachmentMiddleware';

packages/middleware/src/legacy/activityMiddleware.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,37 @@ import { type ReactNode } from 'react';
44

55
import { type RenderAttachment } from './attachmentMiddleware';
66

7-
type ActivityProps = {
7+
// TODO: [P*] Consider prefixing all these with Legacy*.
8+
type LegacyActivityProps = {
9+
children?: never | undefined;
810
hideTimestamp: boolean;
911
renderActivityStatus: (options: { hideTimestamp: boolean }) => ReactNode;
1012
renderAvatar: false | (() => Exclude<ReactNode, boolean | null | undefined>);
1113
showCallout: boolean;
1214
};
1315

14-
type ActivityComponent = (props: ActivityProps) => Exclude<ReactNode, boolean | null | undefined>;
16+
type LegacyActivityComponent = (props: LegacyActivityProps) => Exclude<ReactNode, boolean | null | undefined>;
1517

16-
type ActivityComponentFactoryOptions = {
18+
type LegacyActivityComponentFactoryOptions = {
1719
activity: WebChatActivity;
1820
nextVisibleActivity: WebChatActivity;
1921
};
2022

21-
type ActivityComponentFactory = (options: ActivityComponentFactoryOptions) => ActivityComponent | false;
23+
type LegacyActivityComponentFactory = (
24+
options: LegacyActivityComponentFactoryOptions
25+
) => LegacyActivityComponent | false;
2226

2327
// TODO: [P2] This is inherited from our older signature (pre-hook) which requires passing "renderAttachment" argument.
2428
// With hooks, the middleware should not need "renderAttachment", they can grab it from "useCreateAttachmentRenderer" hook.
2529
type LegacyRenderActivity = (
2630
renderAttachment: RenderAttachment,
27-
{ hideTimestamp, renderActivityStatus, renderAvatar, showCallout }: ActivityProps
31+
{ hideTimestamp, renderActivityStatus, renderAvatar, showCallout }: LegacyActivityProps
2832
) => Exclude<ReactNode, boolean>;
2933

30-
type LegacyActivityRenderer = (options: ActivityComponentFactoryOptions) => LegacyRenderActivity | false;
34+
type LegacyActivityRenderer = (options: LegacyActivityComponentFactoryOptions) => LegacyRenderActivity | false;
3135

3236
// The middleware created by the web developer, are using the legacy signature (with "renderAttachment" argument).
33-
type ActivityEnhancer = (next: LegacyActivityRenderer) => LegacyActivityRenderer;
34-
type ActivityMiddleware = () => ActivityEnhancer;
37+
type LegacyActivityEnhancer = (next: LegacyActivityRenderer) => LegacyActivityRenderer;
38+
type LegacyActivityMiddleware = () => LegacyActivityEnhancer;
3539

36-
export default ActivityMiddleware;
37-
38-
export type { ActivityComponentFactory, LegacyActivityRenderer };
40+
export type { LegacyActivityComponentFactory, LegacyActivityMiddleware, LegacyActivityProps, LegacyActivityRenderer };

0 commit comments

Comments
 (0)