1- using System . Threading ;
1+ using System ;
2+ using System . Threading ;
23using System . Threading . Tasks ;
34using Microsoft . Bot . Builder . Dialogs ;
45using Microsoft . Bot . Builder . Solutions . Extensions ;
@@ -14,176 +15,156 @@ public RouterDialog(string dialogId, IBotTelemetryClient telemetryClient)
1415 TelemetryClient = telemetryClient ;
1516 }
1617
17- protected override Task < DialogTurnResult > OnBeginDialogAsync ( DialogContext innerDc , object options , CancellationToken cancellationToken = default ( CancellationToken ) )
18+ protected override Task < DialogTurnResult > OnBeginDialogAsync ( DialogContext innerDc , object options , CancellationToken cancellationToken = default )
1819 {
1920 return OnContinueDialogAsync ( innerDc , cancellationToken ) ;
2021 }
2122
22- protected override async Task < DialogTurnResult > OnContinueDialogAsync ( DialogContext innerDc , CancellationToken cancellationToken = default ( CancellationToken ) )
23+ protected override async Task < DialogTurnResult > OnContinueDialogAsync ( DialogContext innerDc , CancellationToken cancellationToken = default )
2324 {
25+ // Check for any interruptions.
2426 var status = await OnInterruptDialogAsync ( innerDc , cancellationToken ) . ConfigureAwait ( false ) ;
2527
26- if ( status == InterruptionAction . MessageSentToUser )
28+ if ( status == InterruptionAction . Resume )
2729 {
28- // Resume the waiting dialog after interruption
30+ // Interruption message was sent, and the waiting dialog should resume/reprompt.
2931 await innerDc . RepromptDialogAsync ( ) . ConfigureAwait ( false ) ;
30- return EndOfTurn ;
3132 }
32- else if ( status == InterruptionAction . StartedDialog )
33+ else if ( status == InterruptionAction . Waiting )
3334 {
34- // Stack is already waiting for a response, shelve inner stack
35+ // Interruption intercepted conversation and is waiting for user to respond.
3536 return EndOfTurn ;
3637 }
37- else
38+ else if ( status == InterruptionAction . End )
39+ {
40+ // Interruption ended conversation, and current dialog should end.
41+ return await innerDc . EndDialogAsync ( ) . ConfigureAwait ( false ) ;
42+ }
43+ else if ( status == InterruptionAction . NoAction )
3844 {
45+ // No interruption was detected. Process activity normally.
3946 var activity = innerDc . Context . Activity ;
4047
41- if ( activity . IsStartActivity ( ) )
42- {
43- await OnStartAsync ( innerDc ) . ConfigureAwait ( false ) ;
44- }
45-
4648 switch ( activity . Type )
4749 {
4850 case ActivityTypes . Message :
4951 {
50- // Note: This check is a workaround for adaptive card buttons that should map to an event (i.e. startOnboarding button in intro card)
51- if ( activity . Value != null )
52- {
53- await OnEventAsync ( innerDc ) . ConfigureAwait ( false ) ;
54- }
55- else
56- {
57- var result = await innerDc . ContinueDialogAsync ( ) . ConfigureAwait ( false ) ;
58-
59- switch ( result . Status )
60- {
61- case DialogTurnStatus . Empty :
62- {
63- await RouteAsync ( innerDc ) . ConfigureAwait ( false ) ;
64- break ;
65- }
66-
67- case DialogTurnStatus . Complete :
68- {
69- if ( result . Result is RouterDialogTurnResult routerDialogTurnResult && routerDialogTurnResult . Status == RouterDialogTurnStatus . Restart )
70- {
71- await RouteAsync ( innerDc ) . ConfigureAwait ( false ) ;
72- break ;
73- }
74-
75- // End active dialog
76- await innerDc . EndDialogAsync ( ) . ConfigureAwait ( false ) ;
77- break ;
78- }
79-
80- default :
81- {
82- break ;
83- }
84- }
85- }
52+ // Pass message to waiting child dialog.
53+ var result = await innerDc . ContinueDialogAsync ( ) . ConfigureAwait ( false ) ;
8654
87- // If the active dialog was ended on this turn (either on single-turn dialog, or on continueDialogAsync) run CompleteAsync method.
88- if ( innerDc . ActiveDialog == null )
55+ if ( result . Status == DialogTurnStatus . Empty
56+ || ( result . Result is RouterDialogTurnResult routerDialogTurnResult && routerDialogTurnResult . Status == RouterDialogTurnStatus . Restart ) )
8957 {
90- await CompleteAsync ( innerDc ) . ConfigureAwait ( false ) ;
58+ // There was no waiting dialog on the stack, process message normally.
59+ await OnMessageActivityAsync ( innerDc ) . ConfigureAwait ( false ) ;
9160 }
9261
9362 break ;
9463 }
9564
9665 case ActivityTypes . Event :
9766 {
98- await OnEventAsync ( innerDc ) . ConfigureAwait ( false ) ;
67+ await OnEventActivityAsync ( innerDc ) . ConfigureAwait ( false ) ;
9968 break ;
10069 }
10170
102- case ActivityTypes . Invoke :
71+ case ActivityTypes . ConversationUpdate :
10372 {
104- // Used by Teams for Authentication scenarios.
105- await innerDc . ContinueDialogAsync ( ) . ConfigureAwait ( false ) ;
73+ await OnMembersAddedAsync ( innerDc ) . ConfigureAwait ( false ) ;
10674 break ;
10775 }
10876
10977 default :
11078 {
111- await OnSystemMessageAsync ( innerDc ) . ConfigureAwait ( false ) ;
79+ // All other activity types will be routed here. Custom handling should be added in implementation.
80+ await OnUnhandledActivityTypeAsync ( innerDc ) . ConfigureAwait ( false ) ;
11281 break ;
11382 }
11483 }
84+ }
11585
116- return EndOfTurn ;
86+ if ( innerDc . ActiveDialog == null )
87+ {
88+ // If the inner dialog stack completed during this turn, this component should be ended.
89+ return await innerDc . EndDialogAsync ( ) . ConfigureAwait ( false ) ;
11790 }
118- }
11991
120- protected override Task OnEndDialogAsync ( ITurnContext context , DialogInstance instance , DialogReason reason , CancellationToken cancellationToken = default ( CancellationToken ) )
121- {
122- return base . OnEndDialogAsync ( context , instance , reason , cancellationToken ) ;
92+ return EndOfTurn ;
12393 }
12494
125- protected override Task OnRepromptDialogAsync ( ITurnContext turnContext , DialogInstance instance , CancellationToken cancellationToken = default ( CancellationToken ) )
95+ protected override async Task < DialogTurnResult > EndComponentAsync ( DialogContext outerDc , object result , CancellationToken cancellationToken )
12696 {
127- return base . OnRepromptDialogAsync ( turnContext , instance , cancellationToken ) ;
97+ // This happens when an inner dialog ends. Could call complete here
98+ await OnDialogCompleteAsync ( outerDc , result , cancellationToken ) . ConfigureAwait ( false ) ;
99+ return await base . EndComponentAsync ( outerDc , result , cancellationToken ) . ConfigureAwait ( false ) ;
128100 }
129101
130102 /// <summary>
131- /// Called when the inner dialog stack is empty .
103+ /// Called on every turn, enabling interruption scenarios .
132104 /// </summary>
133105 /// <param name="innerDc">The dialog context for the component.</param>
134106 /// <param name="cancellationToken">The cancellation token.</param>
135- /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
136- protected abstract Task RouteAsync ( DialogContext innerDc , CancellationToken cancellationToken = default ( CancellationToken ) ) ;
107+ /// <returns>A <see cref="Task"/> returning an <see cref="InterruptionAction">
108+ /// which indicates what action should be taken after interruption.</returns>.
109+ protected override Task < InterruptionAction > OnInterruptDialogAsync ( DialogContext innerDc , CancellationToken cancellationToken )
110+ {
111+ return Task . FromResult ( InterruptionAction . NoAction ) ;
112+ }
137113
138114 /// <summary>
139- /// Called when the inner dialog stack is complete .
115+ /// Called when an event activity is received .
140116 /// </summary>
141117 /// <param name="innerDc">The dialog context for the component.</param>
142- /// <param name="result">The dialog result when inner dialog completed.</param>
143118 /// <param name="cancellationToken">The cancellation token.</param>
144119 /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
145- protected virtual Task CompleteAsync ( DialogContext innerDc , DialogTurnResult result = null , CancellationToken cancellationToken = default ( CancellationToken ) )
120+ protected virtual Task OnEventActivityAsync ( DialogContext innerDc , CancellationToken cancellationToken = default ( CancellationToken ) )
146121 {
147- innerDc . EndDialogAsync ( result ) . Wait ( cancellationToken ) ;
148122 return Task . CompletedTask ;
149123 }
150124
151125 /// <summary>
152- /// Called when an event activity is received.
126+ /// Called when a message activity is received.
153127 /// </summary>
154128 /// <param name="innerDc">The dialog context for the component.</param>
155129 /// <param name="cancellationToken">The cancellation token.</param>
156130 /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
157- protected virtual Task OnEventAsync ( DialogContext innerDc , CancellationToken cancellationToken = default ( CancellationToken ) )
131+ protected virtual Task OnMessageActivityAsync ( DialogContext innerDc , CancellationToken cancellationToken = default ( CancellationToken ) )
158132 {
159133 return Task . CompletedTask ;
160134 }
161135
162136 /// <summary>
163- /// Called when a system activity is received.
137+ /// Called when a conversationUpdate activity is received.
164138 /// </summary>
165139 /// <param name="innerDc">The dialog context for the component.</param>
166140 /// <param name="cancellationToken">The cancellation token.</param>
167141 /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
168- protected virtual Task OnSystemMessageAsync ( DialogContext innerDc , CancellationToken cancellationToken = default ( CancellationToken ) )
142+ protected virtual Task OnMembersAddedAsync ( DialogContext innerDc , CancellationToken cancellationToken = default ( CancellationToken ) )
169143 {
170144 return Task . CompletedTask ;
171145 }
172146
173147 /// <summary>
174- /// Called when a conversation update activity is received.
148+ /// Called when an activity type other than event, message, or conversationUpdate is received.
175149 /// </summary>
176150 /// <param name="innerDc">The dialog context for the component.</param>
177151 /// <param name="cancellationToken">The cancellation token.</param>
178152 /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
179- protected virtual Task OnStartAsync ( DialogContext innerDc , CancellationToken cancellationToken = default ( CancellationToken ) )
153+ protected virtual Task OnUnhandledActivityTypeAsync ( DialogContext innerDc , CancellationToken cancellationToken = default ( CancellationToken ) )
180154 {
181155 return Task . CompletedTask ;
182156 }
183157
184- protected override Task < InterruptionAction > OnInterruptDialogAsync ( DialogContext dc , CancellationToken cancellationToken = default ( CancellationToken ) )
158+ /// <summary>
159+ /// Called when the inner dialog stack completes.
160+ /// </summary>
161+ /// <param name="outerDc">The dialog context for the component.</param>
162+ /// <param name="result">The dialog turn result for the component.</param>
163+ /// <param name="cancellationToken">The cancellation token.</param>
164+ /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
165+ protected virtual Task OnDialogCompleteAsync ( DialogContext outerDc , object result , CancellationToken cancellationToken )
185166 {
186- return Task . FromResult ( InterruptionAction . NoAction ) ;
167+ return Task . CompletedTask ;
187168 }
188169 }
189- }
170+ }
0 commit comments