botframework-webchat-core 4.15.1 → 4.15.2-main.20220413.af6e8a3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/babel.config.json +1 -1
- package/lib/actions/clearSuggestedActions.js +1 -1
- package/lib/actions/connect.js +1 -1
- package/lib/actions/connectionStatusUpdate.js +1 -1
- package/lib/actions/deleteActivity.d.ts +13 -0
- package/lib/actions/deleteActivity.d.ts.map +1 -0
- package/lib/actions/deleteActivity.js +5 -3
- package/lib/actions/disconnect.js +1 -1
- package/lib/actions/dismissNotification.js +1 -1
- package/lib/actions/emitTypingIndicator.js +1 -1
- package/lib/actions/incomingActivity.d.ts +14 -0
- package/lib/actions/incomingActivity.d.ts.map +1 -0
- package/lib/actions/incomingActivity.js +5 -3
- package/lib/actions/markActivity.d.ts +17 -0
- package/lib/actions/markActivity.d.ts.map +1 -0
- package/lib/actions/markActivity.js +5 -3
- package/lib/actions/postActivity.d.ts +52 -0
- package/lib/actions/postActivity.d.ts.map +1 -0
- package/lib/actions/postActivity.js +5 -3
- package/lib/actions/queueIncomingActivity.js +1 -1
- package/lib/actions/sagaError.js +1 -1
- package/lib/actions/sendEvent.js +1 -1
- package/lib/actions/sendFiles.js +1 -1
- package/lib/actions/sendMessage.js +1 -1
- package/lib/actions/sendMessageBack.js +1 -1
- package/lib/actions/sendPostBack.js +1 -1
- package/lib/actions/setDictateInterims.js +1 -1
- package/lib/actions/setDictateState.js +1 -1
- package/lib/actions/setLanguage.js +1 -1
- package/lib/actions/setNotification.js +1 -1
- package/lib/actions/setReferenceGrammarID.js +1 -1
- package/lib/actions/setSendBox.js +1 -1
- package/lib/actions/setSendTimeout.js +1 -1
- package/lib/actions/setSendTypingIndicator.js +1 -1
- package/lib/actions/setSuggestedActions.js +1 -1
- package/lib/actions/startDictate.js +1 -1
- package/lib/actions/startSpeakingActivity.js +1 -1
- package/lib/actions/stopDictate.js +1 -1
- package/lib/actions/stopSpeakingActivity.js +1 -1
- package/lib/actions/submitSendBox.js +1 -1
- package/lib/actions/updateConnectionStatus.js +1 -1
- package/lib/constants/ActivityClientState.js +1 -1
- package/lib/definitions/speakingActivity.js +4 -2
- package/lib/index.d.ts +15 -14
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +4 -3
- package/lib/reducer.d.ts +1 -2
- package/lib/reducer.d.ts.map +1 -1
- package/lib/reducer.js +1 -4
- package/lib/reducers/activities.d.ts +10 -0
- package/lib/reducers/activities.d.ts.map +1 -0
- package/lib/reducers/activities.js +65 -45
- package/lib/reducers/typing.js +13 -7
- package/lib/sagas/effects/observeOnce.js +1 -1
- package/lib/sagas/effects/whileConnected.js +1 -1
- package/lib/sagas/observeActivitySaga.js +21 -3
- package/lib/sagas/postActivitySaga.js +51 -72
- package/lib/sagas/sendFilesToPostActivitySaga.js +4 -4
- package/lib/selectors/activities.js +1 -1
- package/lib/selectors/combineSelectors.js +3 -3
- package/lib/selectors/dictateState.js +1 -1
- package/lib/selectors/language.js +1 -1
- package/lib/selectors/notifications.js +1 -1
- package/lib/selectors/sendBoxValue.js +1 -1
- package/lib/selectors/sendTimeout.js +1 -1
- package/lib/selectors/sendTypingIndicator.js +1 -1
- package/lib/selectors/shouldSpeakIncomingActivity.js +1 -1
- package/lib/types/AnyAnd.d.ts +2 -0
- package/lib/types/AnyAnd.d.ts.map +1 -0
- package/lib/types/AnyAnd.js +6 -0
- package/lib/types/OneOrMany.js +4 -0
- package/lib/types/WebChatActivity.d.ts +81 -0
- package/lib/types/WebChatActivity.d.ts.map +1 -0
- package/lib/types/WebChatActivity.js +6 -0
- package/lib/types/external/DirectLineActivity.d.ts +1 -1
- package/lib/types/external/DirectLineActivity.d.ts.map +1 -1
- package/lib/types/external/DirectLineActivity.js +4 -0
- package/lib/types/external/DirectLineAnimationCard.d.ts +5 -2
- package/lib/types/external/DirectLineAnimationCard.d.ts.map +1 -1
- package/lib/types/external/DirectLineAnimationCard.js +4 -0
- package/lib/types/external/DirectLineAttachment.d.ts +8 -2
- package/lib/types/external/DirectLineAttachment.d.ts.map +1 -1
- package/lib/types/external/DirectLineAttachment.js +4 -0
- package/lib/types/external/DirectLineAudioCard.d.ts +5 -2
- package/lib/types/external/DirectLineAudioCard.d.ts.map +1 -1
- package/lib/types/external/DirectLineAudioCard.js +4 -0
- package/lib/types/external/DirectLineBasicCardEssence.d.ts +12 -0
- package/lib/types/external/DirectLineBasicCardEssence.d.ts.map +1 -0
- package/lib/types/external/DirectLineBasicCardEssence.js +6 -0
- package/lib/types/external/DirectLineCardAction.d.ts +1 -1
- package/lib/types/external/DirectLineCardAction.d.ts.map +1 -1
- package/lib/types/external/DirectLineCardAction.js +4 -0
- package/lib/types/external/DirectLineCardImage.d.ts +8 -0
- package/lib/types/external/DirectLineCardImage.d.ts.map +1 -0
- package/lib/types/external/DirectLineCardImage.js +6 -0
- package/lib/types/external/DirectLineHeroCard.d.ts +5 -2
- package/lib/types/external/DirectLineHeroCard.d.ts.map +1 -1
- package/lib/types/external/DirectLineHeroCard.js +4 -0
- package/lib/types/external/DirectLineJSBotConnection.d.ts +1 -1
- package/lib/types/external/DirectLineJSBotConnection.d.ts.map +1 -1
- package/lib/types/external/DirectLineJSBotConnection.js +4 -0
- package/lib/types/external/DirectLineMediaCardEssence.d.ts +21 -0
- package/lib/types/external/DirectLineMediaCardEssence.d.ts.map +1 -0
- package/lib/types/external/DirectLineMediaCardEssence.js +6 -0
- package/lib/types/external/DirectLineOAuthCard.d.ts +7 -2
- package/lib/types/external/DirectLineOAuthCard.d.ts.map +1 -1
- package/lib/types/external/DirectLineOAuthCard.js +4 -0
- package/lib/types/external/DirectLineReceiptCard.d.ts +27 -2
- package/lib/types/external/DirectLineReceiptCard.d.ts.map +1 -1
- package/lib/types/external/DirectLineReceiptCard.js +4 -0
- package/lib/types/external/DirectLineSignInCard.d.ts +7 -2
- package/lib/types/external/DirectLineSignInCard.d.ts.map +1 -1
- package/lib/types/external/DirectLineSignInCard.js +4 -0
- package/lib/types/external/DirectLineSuggestedAction.d.ts +6 -2
- package/lib/types/external/DirectLineSuggestedAction.d.ts.map +1 -1
- package/lib/types/external/DirectLineSuggestedAction.js +4 -0
- package/lib/types/external/DirectLineThumbnailCard.d.ts +5 -2
- package/lib/types/external/DirectLineThumbnailCard.d.ts.map +1 -1
- package/lib/types/external/DirectLineThumbnailCard.js +4 -0
- package/lib/types/external/DirectLineVideoCard.d.ts +5 -2
- package/lib/types/external/DirectLineVideoCard.d.ts.map +1 -1
- package/lib/types/external/DirectLineVideoCard.js +4 -0
- package/lib/types/external/Observable.js +6 -0
- package/lib/types/internal/Notification.js +6 -0
- package/lib/types/internal/ReduxState.js +6 -0
- package/lib/utils/dateToLocaleISOString.js +5 -5
- package/lib/utils/deleteKey.js +1 -1
- package/lib/utils/sleep.js +1 -1
- package/lib/utils/uniqueID.js +1 -1
- package/package.json +18 -14
- package/src/actions/deleteActivity.ts +19 -0
- package/src/actions/incomingActivity.ts +21 -0
- package/src/actions/markActivity.ts +23 -0
- package/src/actions/postActivity.ts +48 -0
- package/src/definitions/speakingActivity.js +1 -1
- package/src/index.ts +17 -14
- package/src/reducer.ts +0 -2
- package/src/reducers/activities.ts +172 -0
- package/src/reducers/typing.js +6 -5
- package/src/sagas/effects/{observeOnce.js → observeOnce.ts} +6 -4
- package/src/sagas/effects/{whileConnected.js → whileConnected.ts} +20 -1
- package/src/sagas/{observeActivitySaga.js → observeActivitySaga.ts} +25 -6
- package/src/sagas/{postActivitySaga.js → postActivitySaga.ts} +57 -48
- package/src/sagas/sendFilesToPostActivitySaga.js +1 -1
- package/src/selectors/activities.ts +12 -0
- package/src/selectors/{combineSelectors.js → combineSelectors.ts} +7 -2
- package/src/selectors/dictateState.ts +3 -0
- package/src/selectors/language.ts +3 -0
- package/src/selectors/notifications.ts +6 -0
- package/src/selectors/sendBoxValue.ts +3 -0
- package/src/selectors/sendTimeout.ts +3 -0
- package/src/selectors/sendTypingIndicator.ts +3 -0
- package/src/selectors/shouldSpeakIncomingActivity.ts +3 -0
- package/src/types/AnyAnd.ts +1 -0
- package/src/types/WebChatActivity.ts +154 -0
- package/src/types/external/DirectLineActivity.ts +1 -1
- package/src/types/external/DirectLineAnimationCard.ts +6 -3
- package/src/types/external/DirectLineAttachment.ts +10 -4
- package/src/types/external/DirectLineAudioCard.ts +6 -3
- package/src/types/external/DirectLineBasicCardEssence.ts +14 -0
- package/src/types/external/DirectLineCardAction.ts +1 -1
- package/src/types/external/DirectLineCardImage.ts +9 -0
- package/src/types/external/DirectLineHeroCard.ts +6 -3
- package/src/types/external/DirectLineJSBotConnection.ts +1 -1
- package/src/types/external/DirectLineMediaCardEssence.ts +19 -0
- package/src/types/external/DirectLineOAuthCard.ts +7 -3
- package/src/types/external/DirectLineReceiptCard.ts +30 -3
- package/src/types/external/DirectLineSignInCard.ts +8 -3
- package/src/types/external/DirectLineSuggestedAction.ts +6 -3
- package/src/types/external/DirectLineThumbnailCard.ts +6 -3
- package/src/types/external/DirectLineVideoCard.ts +6 -3
- package/src/types/external/Observable.ts +69 -0
- package/src/types/internal/Notification.ts +10 -0
- package/src/types/internal/ReduxState.ts +16 -0
- package/src/utils/{dateToLocaleISOString.js → dateToLocaleISOString.ts} +6 -6
- package/src/utils/deleteKey.ts +9 -0
- package/src/utils/{sleep.js → sleep.ts} +1 -1
- package/src/utils/{uniqueID.js → uniqueID.ts} +1 -1
- package/lib/reducers/clockSkewAdjustment.js +0 -44
- package/lib/sagas/effects/callUntil.js +0 -48
- package/lib/selectors/clockSkewAdjustment.js +0 -14
- package/lib/utils/mime-wrapper.js +0 -47
- package/src/actions/deleteActivity.js +0 -8
- package/src/actions/incomingActivity.js +0 -10
- package/src/actions/markActivity.js +0 -14
- package/src/actions/postActivity.js +0 -14
- package/src/reducers/activities.js +0 -116
- package/src/reducers/clockSkewAdjustment.js +0 -29
- package/src/sagas/effects/callUntil.js +0 -13
- package/src/selectors/activities.js +0 -8
- package/src/selectors/clockSkewAdjustment.js +0 -1
- package/src/selectors/dictateState.js +0 -1
- package/src/selectors/language.js +0 -1
- package/src/selectors/notifications.js +0 -3
- package/src/selectors/sendBoxValue.js +0 -1
- package/src/selectors/sendTimeout.js +0 -1
- package/src/selectors/sendTypingIndicator.js +0 -1
- package/src/selectors/shouldSpeakIncomingActivity.js +0 -1
- package/src/utils/deleteKey.js +0 -9
- package/src/utils/mime-wrapper.js +0 -39
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
type MarkActivityActionType = 'WEB_CHAT/MARK_ACTIVITY';
|
|
2
|
+
|
|
3
|
+
type MarkActivityAction = {
|
|
4
|
+
payload: { activityID: string; name: string; value: any };
|
|
5
|
+
type: MarkActivityActionType;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const MARK_ACTIVITY: MarkActivityActionType = 'WEB_CHAT/MARK_ACTIVITY';
|
|
9
|
+
|
|
10
|
+
function markActivity({ id: activityID }: { id: string }, name: string, value: any): MarkActivityAction {
|
|
11
|
+
return {
|
|
12
|
+
type: MARK_ACTIVITY,
|
|
13
|
+
payload: {
|
|
14
|
+
activityID,
|
|
15
|
+
name,
|
|
16
|
+
value
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default markActivity;
|
|
22
|
+
export { MARK_ACTIVITY };
|
|
23
|
+
export type { MarkActivityAction };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { WebChatActivity } from '../types/WebChatActivity';
|
|
2
|
+
|
|
3
|
+
type PostActivityActionType = 'DIRECT_LINE/POST_ACTIVITY';
|
|
4
|
+
type PostActivityFulfilledActionType = 'DIRECT_LINE/POST_ACTIVITY_FULFILLED';
|
|
5
|
+
type PostActivityPendingActionType = 'DIRECT_LINE/POST_ACTIVITY_PENDING';
|
|
6
|
+
type PostActivityRejectedActionType = 'DIRECT_LINE/POST_ACTIVITY_REJECTED';
|
|
7
|
+
|
|
8
|
+
type PostActivityAction = {
|
|
9
|
+
meta: { method: string };
|
|
10
|
+
payload: { activity: WebChatActivity };
|
|
11
|
+
type: PostActivityActionType;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type PostActivityFulfilledAction = {
|
|
15
|
+
meta: { clientActivityID: string; method: string };
|
|
16
|
+
payload: { activity: WebChatActivity };
|
|
17
|
+
type: PostActivityFulfilledActionType;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
type PostActivityPendingAction = {
|
|
21
|
+
meta: { clientActivityID: string; method: string };
|
|
22
|
+
payload: { activity: WebChatActivity };
|
|
23
|
+
type: PostActivityPendingActionType;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
type PostActivityRejectedAction = {
|
|
27
|
+
error: true;
|
|
28
|
+
meta: { clientActivityID: string; method: string };
|
|
29
|
+
payload: Error;
|
|
30
|
+
type: PostActivityRejectedActionType;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const POST_ACTIVITY: PostActivityActionType = 'DIRECT_LINE/POST_ACTIVITY';
|
|
34
|
+
const POST_ACTIVITY_FULFILLED: PostActivityFulfilledActionType = `${POST_ACTIVITY}_FULFILLED`;
|
|
35
|
+
const POST_ACTIVITY_PENDING: PostActivityPendingActionType = `${POST_ACTIVITY}_PENDING`;
|
|
36
|
+
const POST_ACTIVITY_REJECTED: PostActivityRejectedActionType = `${POST_ACTIVITY}_REJECTED`;
|
|
37
|
+
|
|
38
|
+
function postActivity(activity: WebChatActivity, method = 'keyboard'): PostActivityAction {
|
|
39
|
+
return {
|
|
40
|
+
type: POST_ACTIVITY,
|
|
41
|
+
meta: { method },
|
|
42
|
+
payload: { activity }
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default postActivity;
|
|
47
|
+
export { POST_ACTIVITY, POST_ACTIVITY_FULFILLED, POST_ACTIVITY_PENDING, POST_ACTIVITY_REJECTED };
|
|
48
|
+
export type { PostActivityAction, PostActivityFulfilledAction, PostActivityPendingAction, PostActivityRejectedAction };
|
package/src/index.ts
CHANGED
|
@@ -3,19 +3,6 @@ import * as DictateState from './constants/DictateState';
|
|
|
3
3
|
import clearSuggestedActions from './actions/clearSuggestedActions';
|
|
4
4
|
import connect from './actions/connect';
|
|
5
5
|
import createStore, { withDevTools as createStoreWithDevTools } from './createStore';
|
|
6
|
-
import DirectLineActivity from './types/external/DirectLineActivity';
|
|
7
|
-
import DirectLineAnimationCard from './types/external/DirectLineAnimationCard';
|
|
8
|
-
import DirectLineAttachment from './types/external/DirectLineAttachment';
|
|
9
|
-
import DirectLineAudioCard from './types/external/DirectLineAudioCard';
|
|
10
|
-
import DirectLineCardAction from './types/external/DirectLineCardAction';
|
|
11
|
-
import DirectLineHeroCard from './types/external/DirectLineHeroCard';
|
|
12
|
-
import DirectLineJSBotConnection from './types/external/DirectLineJSBotConnection';
|
|
13
|
-
import DirectLineOAuthCard from './types/external/DirectLineOAuthCard';
|
|
14
|
-
import DirectLineReceiptCard from './types/external/DirectLineReceiptCard';
|
|
15
|
-
import DirectLineSignInCard from './types/external/DirectLineSignInCard';
|
|
16
|
-
import DirectLineSuggestedAction from './types/external/DirectLineSuggestedAction';
|
|
17
|
-
import DirectLineThumbnailCard from './types/external/DirectLineThumbnailCard';
|
|
18
|
-
import DirectLineVideoCard from './types/external/DirectLineVideoCard';
|
|
19
6
|
import disconnect from './actions/disconnect';
|
|
20
7
|
import dismissNotification from './actions/dismissNotification';
|
|
21
8
|
import emitTypingIndicator from './actions/emitTypingIndicator';
|
|
@@ -43,6 +30,21 @@ import stopSpeakingActivity from './actions/stopSpeakingActivity';
|
|
|
43
30
|
import submitSendBox from './actions/submitSendBox';
|
|
44
31
|
import warnOnce from './utils/warnOnce';
|
|
45
32
|
|
|
33
|
+
import type { DirectLineActivity } from './types/external/DirectLineActivity';
|
|
34
|
+
import type { DirectLineAnimationCard } from './types/external/DirectLineAnimationCard';
|
|
35
|
+
import type { DirectLineAttachment } from './types/external/DirectLineAttachment';
|
|
36
|
+
import type { DirectLineAudioCard } from './types/external/DirectLineAudioCard';
|
|
37
|
+
import type { DirectLineCardAction } from './types/external/DirectLineCardAction';
|
|
38
|
+
import type { DirectLineHeroCard } from './types/external/DirectLineHeroCard';
|
|
39
|
+
import type { DirectLineJSBotConnection } from './types/external/DirectLineJSBotConnection';
|
|
40
|
+
import type { DirectLineOAuthCard } from './types/external/DirectLineOAuthCard';
|
|
41
|
+
import type { DirectLineReceiptCard } from './types/external/DirectLineReceiptCard';
|
|
42
|
+
import type { DirectLineSignInCard } from './types/external/DirectLineSignInCard';
|
|
43
|
+
import type { DirectLineSuggestedAction } from './types/external/DirectLineSuggestedAction';
|
|
44
|
+
import type { DirectLineThumbnailCard } from './types/external/DirectLineThumbnailCard';
|
|
45
|
+
import type { DirectLineVideoCard } from './types/external/DirectLineVideoCard';
|
|
46
|
+
import type { WebChatActivity } from './types/WebChatActivity';
|
|
47
|
+
|
|
46
48
|
const Constants = { ActivityClientState, DictateState };
|
|
47
49
|
const version = process.env.npm_package_version;
|
|
48
50
|
|
|
@@ -94,5 +96,6 @@ export type {
|
|
|
94
96
|
DirectLineSuggestedAction,
|
|
95
97
|
DirectLineThumbnailCard,
|
|
96
98
|
DirectLineVideoCard,
|
|
97
|
-
OneOrMany
|
|
99
|
+
OneOrMany,
|
|
100
|
+
WebChatActivity
|
|
98
101
|
};
|
package/src/reducer.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { combineReducers } from 'redux';
|
|
2
2
|
|
|
3
3
|
import activities from './reducers/activities';
|
|
4
|
-
import clockSkewAdjustment from './reducers/clockSkewAdjustment';
|
|
5
4
|
import connectivityStatus from './reducers/connectivityStatus';
|
|
6
5
|
import dictateInterims from './reducers/dictateInterims';
|
|
7
6
|
import dictateState from './reducers/dictateState';
|
|
@@ -19,7 +18,6 @@ import typing from './reducers/typing';
|
|
|
19
18
|
|
|
20
19
|
export default combineReducers({
|
|
21
20
|
activities,
|
|
22
|
-
clockSkewAdjustment,
|
|
23
21
|
connectivityStatus,
|
|
24
22
|
dictateInterims,
|
|
25
23
|
dictateState,
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/* eslint no-magic-numbers: ["error", { "ignore": [0, 1, -1] }] */
|
|
2
|
+
|
|
3
|
+
import updateIn from 'simple-update-in';
|
|
4
|
+
|
|
5
|
+
import { DELETE_ACTIVITY } from '../actions/deleteActivity';
|
|
6
|
+
import { INCOMING_ACTIVITY } from '../actions/incomingActivity';
|
|
7
|
+
import { MARK_ACTIVITY } from '../actions/markActivity';
|
|
8
|
+
import { POST_ACTIVITY_FULFILLED, POST_ACTIVITY_PENDING, POST_ACTIVITY_REJECTED } from '../actions/postActivity';
|
|
9
|
+
import { SEND_FAILED, SENDING, SENT } from '../constants/ActivityClientState';
|
|
10
|
+
import type { DeleteActivityAction } from '../actions/deleteActivity';
|
|
11
|
+
import type { IncomingActivityAction } from '../actions/incomingActivity';
|
|
12
|
+
import type { MarkActivityAction } from '../actions/markActivity';
|
|
13
|
+
import type {
|
|
14
|
+
PostActivityFulfilledAction,
|
|
15
|
+
PostActivityPendingAction,
|
|
16
|
+
PostActivityRejectedAction
|
|
17
|
+
} from '../actions/postActivity';
|
|
18
|
+
import type { WebChatActivity } from '../types/WebChatActivity';
|
|
19
|
+
|
|
20
|
+
type ActivitiesAction =
|
|
21
|
+
| DeleteActivityAction
|
|
22
|
+
| IncomingActivityAction
|
|
23
|
+
| MarkActivityAction
|
|
24
|
+
| PostActivityFulfilledAction
|
|
25
|
+
| PostActivityPendingAction
|
|
26
|
+
| PostActivityRejectedAction;
|
|
27
|
+
|
|
28
|
+
type ActivitiesStateType = WebChatActivity[];
|
|
29
|
+
|
|
30
|
+
const DEFAULT_STATE: ActivitiesStateType = [];
|
|
31
|
+
const DIRECT_LINE_PLACEHOLDER_URL =
|
|
32
|
+
'https://docs.botframework.com/static/devportal/client/images/bot-framework-default-placeholder.png';
|
|
33
|
+
|
|
34
|
+
function getClientActivityID(activity: WebChatActivity): string | undefined {
|
|
35
|
+
return activity.channelData?.clientActivityID;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function findByClientActivityID(clientActivityID: string): (activity: WebChatActivity) => boolean {
|
|
39
|
+
return (activity: WebChatActivity) => getClientActivityID(activity) === clientActivityID;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function patchActivity(activity: WebChatActivity, lastActivity: WebChatActivity): WebChatActivity {
|
|
43
|
+
// Direct Line channel will return a placeholder image for the user-uploaded image.
|
|
44
|
+
// As observed, the URL for the placeholder image is https://docs.botframework.com/static/devportal/client/images/bot-framework-default-placeholder.png.
|
|
45
|
+
// To make our code simpler, we are removing the value if "contentUrl" is pointing to a placeholder image.
|
|
46
|
+
|
|
47
|
+
// TODO: [P2] #2869 This "contentURL" removal code should be moved to DirectLineJS adapter.
|
|
48
|
+
|
|
49
|
+
// Also, if the "contentURL" starts with "blob:", this means the user is uploading a file (the URL is constructed by URL.createObjectURL)
|
|
50
|
+
// Although the copy/reference of the file is temporary in-memory, to make the UX consistent across page refresh, we do not allow the user to re-download the file either.
|
|
51
|
+
|
|
52
|
+
activity = updateIn(activity, ['attachments', () => true, 'contentUrl'], (contentUrl: string) => {
|
|
53
|
+
if (contentUrl !== DIRECT_LINE_PLACEHOLDER_URL && !/^blob:/iu.test(contentUrl)) {
|
|
54
|
+
return contentUrl;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// If the message does not have sequence ID, use these fallback values:
|
|
59
|
+
// 1. "timestamp" field
|
|
60
|
+
// - outgoing activity will not have "timestamp" field
|
|
61
|
+
// 2. last activity sequence ID (or 0) + 0.001
|
|
62
|
+
// - best effort to put this message the last one in the chat history
|
|
63
|
+
activity = updateIn(activity, ['channelData', 'webchat:sequence-id'], (sequenceId?: number) =>
|
|
64
|
+
typeof sequenceId === 'number'
|
|
65
|
+
? sequenceId
|
|
66
|
+
: typeof activity.timestamp !== 'undefined'
|
|
67
|
+
? +new Date(activity.timestamp)
|
|
68
|
+
: // We assume there will be no more than 1,000 messages sent before receiving server response.
|
|
69
|
+
// If there are more than 1,000 messages, some messages will get reordered and appear jumpy after receiving server response.
|
|
70
|
+
// eslint-disable-next-line no-magic-numbers
|
|
71
|
+
(lastActivity?.channelData?.['webchat:sequence-id'] || 0) + 0.001
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
// TODO: [P1] #3953 We should move this patching logic to a DLJS wrapper for simplicity.
|
|
75
|
+
activity = updateIn(activity, ['channelData', 'webchat:sequence-id'], (sequenceId: number) =>
|
|
76
|
+
typeof sequenceId === 'number' ? sequenceId : +new Date(activity.timestamp || 0) || 0
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
return activity;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function upsertActivityWithSort(activities: WebChatActivity[], nextActivity: WebChatActivity): WebChatActivity[] {
|
|
83
|
+
nextActivity = patchActivity(nextActivity, activities[activities.length - 1]);
|
|
84
|
+
|
|
85
|
+
const { channelData: { clientActivityID: nextClientActivityID, 'webchat:sequence-id': nextSequenceId } = {} } =
|
|
86
|
+
nextActivity;
|
|
87
|
+
|
|
88
|
+
const nextActivities = activities.filter(
|
|
89
|
+
({ channelData: { clientActivityID } = {}, id }) =>
|
|
90
|
+
// We will remove all "sending messages" activities and activities with same ID
|
|
91
|
+
// "clientActivityID" is unique and used to track if the message has been sent and echoed back from the server
|
|
92
|
+
!(nextClientActivityID && clientActivityID === nextClientActivityID) && !(id && id === nextActivity.id)
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
// Then, find the right (sorted) place to insert the new activity at, based on timestamp
|
|
96
|
+
// Since clockskew might happen, we will ignore timestamp on messages that are sending
|
|
97
|
+
|
|
98
|
+
const indexToInsert = nextActivities.findIndex(
|
|
99
|
+
({ channelData: { state, 'webchat:sequence-id': sequenceId } = {} }) =>
|
|
100
|
+
(sequenceId || 0) > (nextSequenceId || 0) && state !== SENDING && state !== SEND_FAILED
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
// If no right place are found, append it
|
|
104
|
+
nextActivities.splice(~indexToInsert ? indexToInsert : nextActivities.length, 0, nextActivity);
|
|
105
|
+
|
|
106
|
+
return nextActivities;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export default function activities(
|
|
110
|
+
state: ActivitiesStateType = DEFAULT_STATE,
|
|
111
|
+
action: ActivitiesAction
|
|
112
|
+
): ActivitiesStateType {
|
|
113
|
+
switch (action.type) {
|
|
114
|
+
case DELETE_ACTIVITY:
|
|
115
|
+
state = updateIn(state, [({ id }: WebChatActivity) => id === action.payload.activityID]);
|
|
116
|
+
break;
|
|
117
|
+
|
|
118
|
+
case MARK_ACTIVITY:
|
|
119
|
+
{
|
|
120
|
+
const { payload } = action;
|
|
121
|
+
|
|
122
|
+
state = updateIn(
|
|
123
|
+
state,
|
|
124
|
+
[({ id }: WebChatActivity) => id === payload.activityID, 'channelData', payload.name],
|
|
125
|
+
() => payload.value
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
break;
|
|
130
|
+
|
|
131
|
+
case POST_ACTIVITY_PENDING:
|
|
132
|
+
{
|
|
133
|
+
let {
|
|
134
|
+
payload: { activity }
|
|
135
|
+
} = action;
|
|
136
|
+
|
|
137
|
+
activity = updateIn(activity, ['channelData', 'state'], () => SENDING);
|
|
138
|
+
|
|
139
|
+
state = upsertActivityWithSort(state, activity);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
break;
|
|
143
|
+
|
|
144
|
+
case POST_ACTIVITY_REJECTED:
|
|
145
|
+
state = updateIn(
|
|
146
|
+
state,
|
|
147
|
+
[findByClientActivityID(action.meta.clientActivityID), 'channelData', 'state'],
|
|
148
|
+
() => SEND_FAILED
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
break;
|
|
152
|
+
|
|
153
|
+
case POST_ACTIVITY_FULFILLED:
|
|
154
|
+
state = updateIn(state, [findByClientActivityID(action.meta.clientActivityID)], () =>
|
|
155
|
+
// We will replace the activity with the version from the server
|
|
156
|
+
updateIn(patchActivity(action.payload.activity, state[state.length - 1]), ['channelData', 'state'], () => SENT)
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
break;
|
|
160
|
+
|
|
161
|
+
case INCOMING_ACTIVITY:
|
|
162
|
+
// TODO: [P4] #2100 Move "typing" into Constants.ActivityType
|
|
163
|
+
state = upsertActivityWithSort(state, action.payload.activity);
|
|
164
|
+
|
|
165
|
+
break;
|
|
166
|
+
|
|
167
|
+
default:
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return state;
|
|
172
|
+
}
|
package/src/reducers/typing.js
CHANGED
|
@@ -18,11 +18,12 @@ export default function lastTyping(state = DEFAULT_STATE, { payload, type }) {
|
|
|
18
18
|
} = payload;
|
|
19
19
|
|
|
20
20
|
if (activityType === 'typing') {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
const now = Date.now();
|
|
22
|
+
|
|
23
|
+
state = updateIn(state, [id, 'at'], at => at || now);
|
|
24
|
+
state = updateIn(state, [id, 'last'], () => now);
|
|
25
|
+
state = updateIn(state, [id, 'name'], () => name);
|
|
26
|
+
state = updateIn(state, [id, 'role'], () => role);
|
|
26
27
|
} else if (activityType === 'message') {
|
|
27
28
|
state = updateIn(state, [id]);
|
|
28
29
|
}
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import { call } from 'redux-saga/effects';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { Observable, Observer, Subscription } from '../../types/external/Observable';
|
|
4
|
+
|
|
5
|
+
export default function observeOnceEffect<T>(observable: Observable<T>) {
|
|
4
6
|
return call(function* observeOnce() {
|
|
5
|
-
let subscription;
|
|
7
|
+
let subscription: Subscription;
|
|
6
8
|
|
|
7
9
|
try {
|
|
8
10
|
return yield call(
|
|
9
11
|
() =>
|
|
10
|
-
new Promise((resolve, reject) => {
|
|
12
|
+
new Promise<T>((resolve, reject) => {
|
|
11
13
|
subscription = observable.subscribe({
|
|
12
14
|
complete: resolve,
|
|
13
15
|
error: reject,
|
|
14
16
|
next: resolve
|
|
15
|
-
});
|
|
17
|
+
} as Observer<T>);
|
|
16
18
|
})
|
|
17
19
|
);
|
|
18
20
|
} finally {
|
|
@@ -4,13 +4,32 @@ import { CONNECT_FULFILLING } from '../../actions/connect';
|
|
|
4
4
|
import { DISCONNECT_PENDING } from '../../actions/disconnect';
|
|
5
5
|
import { RECONNECT_PENDING, RECONNECT_FULFILLING } from '../../actions/reconnect';
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
import type { DirectLineJSBotConnection } from '../../types/external/DirectLineJSBotConnection';
|
|
8
|
+
|
|
9
|
+
export default function whileConnectedEffect(
|
|
10
|
+
fn: ({
|
|
11
|
+
directLine,
|
|
12
|
+
userID,
|
|
13
|
+
username
|
|
14
|
+
}: {
|
|
15
|
+
directLine: DirectLineJSBotConnection;
|
|
16
|
+
userID: string;
|
|
17
|
+
username: string;
|
|
18
|
+
}) => void
|
|
19
|
+
) {
|
|
8
20
|
return call(function* whileConnected() {
|
|
9
21
|
for (;;) {
|
|
10
22
|
const {
|
|
11
23
|
meta: { userID, username },
|
|
12
24
|
payload: { directLine }
|
|
25
|
+
}: {
|
|
26
|
+
meta: {
|
|
27
|
+
userID: string;
|
|
28
|
+
username: string;
|
|
29
|
+
};
|
|
30
|
+
payload: { directLine: DirectLineJSBotConnection };
|
|
13
31
|
} = yield take([CONNECT_FULFILLING, RECONNECT_FULFILLING]);
|
|
32
|
+
|
|
14
33
|
const task = yield fork(fn, { directLine, userID, username });
|
|
15
34
|
|
|
16
35
|
// When we receive DISCONNECT_PENDING or RECONNECT_PENDING, the Direct Line connection is currently busy and should not be used.
|
|
@@ -4,10 +4,13 @@ import updateIn from 'simple-update-in';
|
|
|
4
4
|
import observeEach from './effects/observeEach';
|
|
5
5
|
import queueIncomingActivity from '../actions/queueIncomingActivity';
|
|
6
6
|
import whileConnected from './effects/whileConnected';
|
|
7
|
+
import type { DirectLineActivity } from '../types/external/DirectLineActivity';
|
|
8
|
+
import type { DirectLineJSBotConnection } from '../types/external/DirectLineJSBotConnection';
|
|
9
|
+
import type { WebChatActivity } from '../types/WebChatActivity';
|
|
7
10
|
|
|
8
|
-
const PASSTHRU_FN = value => value;
|
|
11
|
+
const PASSTHRU_FN = (value: unknown) => value;
|
|
9
12
|
|
|
10
|
-
function patchActivityWithFromRole(activity, userID) {
|
|
13
|
+
function patchActivityWithFromRole(activity: DirectLineActivity, userID?: string): DirectLineActivity {
|
|
11
14
|
// Some activities, such as "ConversationUpdate", does not have "from" defined.
|
|
12
15
|
// And although "role" is defined in Direct Line spec, it was not sent over the wire.
|
|
13
16
|
// We normalize the activity here to simplify null-check and logic later.
|
|
@@ -28,7 +31,7 @@ function patchActivityWithFromRole(activity, userID) {
|
|
|
28
31
|
return activity;
|
|
29
32
|
}
|
|
30
33
|
|
|
31
|
-
function patchNullAsUndefined(activity) {
|
|
34
|
+
function patchNullAsUndefined(activity: DirectLineActivity): DirectLineActivity {
|
|
32
35
|
// These fields are known used in Web Chat and in any cases, they should not be null, but undefined.
|
|
33
36
|
// The only field omitted is "value", as it could be null purposefully.
|
|
34
37
|
|
|
@@ -56,12 +59,28 @@ function patchNullAsUndefined(activity) {
|
|
|
56
59
|
}, activity);
|
|
57
60
|
}
|
|
58
61
|
|
|
59
|
-
|
|
60
|
-
|
|
62
|
+
// Patching the `from.name` to be a human readable name.
|
|
63
|
+
// We use the `from.name` for typing indicator, such that it read "John is typing...".
|
|
64
|
+
function patchFromName(activity: DirectLineActivity) {
|
|
65
|
+
return updateIn(activity, ['from', 'name'], (name: string | undefined): string => {
|
|
66
|
+
const { channelId, from = {} } = activity;
|
|
67
|
+
|
|
68
|
+
if ((channelId === 'directline' || channelId === 'webchat') && from.id === from.name && from.role === 'bot') {
|
|
69
|
+
return 'Bot';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return name;
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function* observeActivity({ directLine, userID }: { directLine: DirectLineJSBotConnection; userID?: string }) {
|
|
77
|
+
yield observeEach(directLine.activity$, function* observeActivity(activity: DirectLineActivity) {
|
|
78
|
+
// TODO: [P2] #3953 Move the patching logic to a DirectLineJS wrapper, instead of too close to inners of Web Chat.
|
|
61
79
|
activity = patchNullAsUndefined(activity);
|
|
62
80
|
activity = patchActivityWithFromRole(activity, userID);
|
|
81
|
+
activity = patchFromName(activity);
|
|
63
82
|
|
|
64
|
-
yield put(queueIncomingActivity(activity));
|
|
83
|
+
yield put(queueIncomingActivity(activity as WebChatActivity));
|
|
65
84
|
});
|
|
66
85
|
}
|
|
67
86
|
|
|
@@ -1,41 +1,44 @@
|
|
|
1
1
|
import { all, call, cancelled, put, race, select, take, takeEvery } from 'redux-saga/effects';
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import whileConnected from './effects/whileConnected';
|
|
5
|
-
|
|
6
|
-
import clockSkewAdjustmentSelector from '../selectors/clockSkewAdjustment';
|
|
7
|
-
import combineSelectors from '../selectors/combineSelectors';
|
|
8
|
-
import dateToLocaleISOString from '../utils/dateToLocaleISOString';
|
|
9
|
-
import languageSelector from '../selectors/language';
|
|
10
|
-
import sendTimeoutSelector from '../selectors/sendTimeout';
|
|
11
|
-
|
|
12
|
-
import deleteKey from '../utils/deleteKey';
|
|
13
|
-
import sleep from '../utils/sleep';
|
|
14
|
-
import uniqueID from '../utils/uniqueID';
|
|
15
|
-
|
|
3
|
+
import { INCOMING_ACTIVITY } from '../actions/incomingActivity';
|
|
16
4
|
import {
|
|
17
5
|
POST_ACTIVITY,
|
|
18
6
|
POST_ACTIVITY_FULFILLED,
|
|
19
7
|
POST_ACTIVITY_PENDING,
|
|
20
8
|
POST_ACTIVITY_REJECTED
|
|
21
9
|
} from '../actions/postActivity';
|
|
22
|
-
|
|
23
|
-
import
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
10
|
+
import dateToLocaleISOString from '../utils/dateToLocaleISOString';
|
|
11
|
+
import deleteKey from '../utils/deleteKey';
|
|
12
|
+
import languageSelector from '../selectors/language';
|
|
13
|
+
import observeOnce from './effects/observeOnce';
|
|
14
|
+
import sendTimeoutSelector from '../selectors/sendTimeout';
|
|
15
|
+
import sleep from '../utils/sleep';
|
|
16
|
+
import uniqueID from '../utils/uniqueID';
|
|
17
|
+
import whileConnected from './effects/whileConnected';
|
|
18
|
+
import type { DirectLineActivity } from '../types/external/DirectLineActivity';
|
|
19
|
+
import type { DirectLineJSBotConnection } from '../types/external/DirectLineJSBotConnection';
|
|
20
|
+
import type { IncomingActivityAction } from '../actions/incomingActivity';
|
|
21
|
+
import type {
|
|
22
|
+
PostActivityAction,
|
|
23
|
+
PostActivityFulfilledAction,
|
|
24
|
+
PostActivityPendingAction,
|
|
25
|
+
PostActivityRejectedAction
|
|
26
|
+
} from '../actions/postActivity';
|
|
27
|
+
import type { WebChatActivity } from '../types/WebChatActivity';
|
|
28
|
+
|
|
29
|
+
function* postActivity(
|
|
30
|
+
directLine: DirectLineJSBotConnection,
|
|
31
|
+
userID: string,
|
|
32
|
+
username: string,
|
|
33
|
+
numActivitiesPosted: number,
|
|
34
|
+
{ meta: { method }, payload: { activity } }: PostActivityAction
|
|
35
|
+
) {
|
|
36
|
+
const attachments = (activity.type === 'message' && activity.attachments) || [];
|
|
35
37
|
const clientActivityID = uniqueID();
|
|
36
|
-
const
|
|
38
|
+
const locale = yield select(languageSelector);
|
|
37
39
|
const localTimeZone =
|
|
38
40
|
typeof window.Intl === 'undefined' ? undefined : new Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
41
|
+
const now = new Date();
|
|
39
42
|
|
|
40
43
|
activity = {
|
|
41
44
|
...deleteKey(activity, 'id'),
|
|
@@ -49,9 +52,7 @@ function* postActivity(directLine, userID, username, numActivitiesPosted, { meta
|
|
|
49
52
|
})),
|
|
50
53
|
channelData: {
|
|
51
54
|
...deleteKey(activity.channelData, 'state'),
|
|
52
|
-
clientActivityID
|
|
53
|
-
// This is unskewed local timestamp for estimating clock skew.
|
|
54
|
-
clientTimestamp: getTimestamp(now)
|
|
55
|
+
clientActivityID
|
|
55
56
|
},
|
|
56
57
|
channelId: 'webchat',
|
|
57
58
|
from: {
|
|
@@ -61,10 +62,7 @@ function* postActivity(directLine, userID, username, numActivitiesPosted, { meta
|
|
|
61
62
|
},
|
|
62
63
|
locale,
|
|
63
64
|
localTimestamp: dateToLocaleISOString(now),
|
|
64
|
-
localTimezone: localTimeZone
|
|
65
|
-
// This timestamp will be replaced by Direct Line Channel in echoback.
|
|
66
|
-
// We are temporarily adding this timestamp for sorting.
|
|
67
|
-
timestamp: getTimestamp(now, clockSkewAdjustment)
|
|
65
|
+
localTimezone: localTimeZone
|
|
68
66
|
};
|
|
69
67
|
|
|
70
68
|
if (!numActivitiesPosted) {
|
|
@@ -81,9 +79,9 @@ function* postActivity(directLine, userID, username, numActivitiesPosted, { meta
|
|
|
81
79
|
];
|
|
82
80
|
}
|
|
83
81
|
|
|
84
|
-
const meta = { clientActivityID, method };
|
|
82
|
+
const meta: { clientActivityID: string; method: string } = { clientActivityID, method };
|
|
85
83
|
|
|
86
|
-
yield put({ type: POST_ACTIVITY_PENDING, meta, payload: { activity } });
|
|
84
|
+
yield put({ type: POST_ACTIVITY_PENDING, meta, payload: { activity } } as PostActivityPendingAction);
|
|
87
85
|
|
|
88
86
|
try {
|
|
89
87
|
// Quirks: We might receive INCOMING_ACTIVITY before the postActivity call completed
|
|
@@ -93,10 +91,8 @@ function* postActivity(directLine, userID, username, numActivitiesPosted, { meta
|
|
|
93
91
|
for (;;) {
|
|
94
92
|
const {
|
|
95
93
|
payload: { activity }
|
|
96
|
-
} = yield take(INCOMING_ACTIVITY);
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
if (channelData.clientActivityID === clientActivityID && id) {
|
|
94
|
+
}: IncomingActivityAction = yield take(INCOMING_ACTIVITY);
|
|
95
|
+
if (activity.channelData?.clientActivityID === clientActivityID && activity.id) {
|
|
100
96
|
return activity;
|
|
101
97
|
}
|
|
102
98
|
}
|
|
@@ -107,35 +103,48 @@ function* postActivity(directLine, userID, username, numActivitiesPosted, { meta
|
|
|
107
103
|
// - Direct Line service only respond on HTTP after bot respond to Direct Line
|
|
108
104
|
// - Activity may take too long time to echo back
|
|
109
105
|
|
|
110
|
-
const sendTimeout = yield select(sendTimeoutSelector);
|
|
106
|
+
const sendTimeout: number = yield select(sendTimeoutSelector);
|
|
111
107
|
|
|
112
108
|
const {
|
|
113
109
|
send: { echoBack }
|
|
114
|
-
} = yield race({
|
|
110
|
+
}: { send: { echoBack: WebChatActivity } } = yield race({
|
|
115
111
|
send: all({
|
|
116
112
|
echoBack: echoBackCall,
|
|
117
|
-
postActivity: observeOnce(directLine.postActivity(activity))
|
|
113
|
+
postActivity: observeOnce(directLine.postActivity(activity as DirectLineActivity))
|
|
118
114
|
}),
|
|
119
115
|
timeout: call(() => sleep(sendTimeout).then(() => Promise.reject(new Error('timeout'))))
|
|
120
116
|
});
|
|
121
117
|
|
|
122
|
-
yield put({ type: POST_ACTIVITY_FULFILLED, meta, payload: { activity: echoBack } });
|
|
118
|
+
yield put({ type: POST_ACTIVITY_FULFILLED, meta, payload: { activity: echoBack } } as PostActivityFulfilledAction);
|
|
123
119
|
} catch (err) {
|
|
124
120
|
console.error('botframework-webchat: Failed to post activity to chat adapter.', err);
|
|
125
121
|
|
|
126
|
-
yield put({ type: POST_ACTIVITY_REJECTED, error: true, meta, payload: err });
|
|
122
|
+
yield put({ type: POST_ACTIVITY_REJECTED, error: true, meta, payload: err } as PostActivityRejectedAction);
|
|
127
123
|
} finally {
|
|
128
124
|
if (yield cancelled()) {
|
|
129
|
-
yield put({
|
|
125
|
+
yield put({
|
|
126
|
+
type: POST_ACTIVITY_REJECTED,
|
|
127
|
+
error: true,
|
|
128
|
+
meta,
|
|
129
|
+
payload: new Error('cancelled')
|
|
130
|
+
} as PostActivityRejectedAction);
|
|
130
131
|
}
|
|
131
132
|
}
|
|
132
133
|
}
|
|
133
134
|
|
|
134
135
|
export default function* postActivitySaga() {
|
|
135
|
-
yield whileConnected(function* postActivityWhileConnected({
|
|
136
|
+
yield whileConnected(function* postActivityWhileConnected({
|
|
137
|
+
directLine,
|
|
138
|
+
userID,
|
|
139
|
+
username
|
|
140
|
+
}: {
|
|
141
|
+
directLine: DirectLineJSBotConnection;
|
|
142
|
+
userID: string;
|
|
143
|
+
username: string;
|
|
144
|
+
}) {
|
|
136
145
|
let numActivitiesPosted = 0;
|
|
137
146
|
|
|
138
|
-
yield takeEvery(POST_ACTIVITY, function* postActivityWrapper(action) {
|
|
147
|
+
yield takeEvery(POST_ACTIVITY, function* postActivityWrapper(action: PostActivityAction) {
|
|
139
148
|
yield* postActivity(directLine, userID, username, numActivitiesPosted++, action);
|
|
140
149
|
});
|
|
141
150
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { put, takeEvery } from 'redux-saga/effects';
|
|
2
|
+
import mime from 'mime';
|
|
2
3
|
|
|
3
4
|
import { SEND_FILES } from '../actions/sendFiles';
|
|
4
|
-
import mime from '../utils/mime-wrapper';
|
|
5
5
|
import postActivity from '../actions/postActivity';
|
|
6
6
|
import whileConnected from './effects/whileConnected';
|
|
7
7
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ReduxState } from '../types/internal/ReduxState';
|
|
2
|
+
import type { WebChatActivity } from '../types/WebChatActivity';
|
|
3
|
+
|
|
4
|
+
const activities = ({ activities }: ReduxState) => activities;
|
|
5
|
+
|
|
6
|
+
const of = (predicate: (activity: WebChatActivity) => boolean) => (state: ReduxState) =>
|
|
7
|
+
activities(state).filter(predicate);
|
|
8
|
+
const ofID = (targetID: string) => of(({ id }) => id === targetID);
|
|
9
|
+
const ofType = (targetType: string) => of(({ type }) => type === targetType);
|
|
10
|
+
|
|
11
|
+
export default activities;
|
|
12
|
+
export { of, ofID, ofType };
|