|
| 1 | +using System; |
| 2 | +using System.Threading; |
| 3 | +using System.Threading.Tasks; |
| 4 | +using Microsoft.Bot.Builder.Dialogs; |
| 5 | +using Microsoft.Bot.Schema; |
| 6 | + |
| 7 | +namespace Microsoft.Bot.Builder.Solutions.Skills.Dialogs |
| 8 | +{ |
| 9 | + public class SwitchSkillDialog : ComponentDialog |
| 10 | + { |
| 11 | + private static string _confirmPromptId = "ConfirmSkillSwitch"; |
| 12 | + private IStatePropertyAccessor<string> _skillIdAccessor; |
| 13 | + private IStatePropertyAccessor<Activity> _lastActivityAccessor; |
| 14 | + |
| 15 | + public SwitchSkillDialog(ConversationState conversationState) |
| 16 | + : base(nameof(SwitchSkillDialog)) |
| 17 | + { |
| 18 | + _skillIdAccessor = conversationState.CreateProperty<string>(Properties.SkillId); |
| 19 | + _lastActivityAccessor = conversationState.CreateProperty<Activity>(Properties.LastActivity); |
| 20 | + |
| 21 | + var intentSwitch = new WaterfallStep[] |
| 22 | + { |
| 23 | + PromptToSwitchAsync, |
| 24 | + EndAsync, |
| 25 | + }; |
| 26 | + |
| 27 | + AddDialog(new WaterfallDialog(nameof(SwitchSkillDialog), intentSwitch)); |
| 28 | + AddDialog(new ConfirmPrompt(_confirmPromptId)); |
| 29 | + } |
| 30 | + |
| 31 | + // Runs when this dialog ends. Handles result of prompt to switch skills or resume waiting dialog. |
| 32 | + protected override async Task<DialogTurnResult> EndComponentAsync(DialogContext outerDc, object result, CancellationToken cancellationToken) |
| 33 | + { |
| 34 | + var skillId = await _skillIdAccessor.GetAsync(outerDc.Context, () => null).ConfigureAwait(false); |
| 35 | + var lastActivity = await _lastActivityAccessor.GetAsync(outerDc.Context, () => null).ConfigureAwait(false); |
| 36 | + outerDc.Context.Activity.Text = lastActivity.Text; |
| 37 | + |
| 38 | + // Ends this dialog. |
| 39 | + await outerDc.EndDialogAsync().ConfigureAwait(false); |
| 40 | + |
| 41 | + if ((bool)result) |
| 42 | + { |
| 43 | + // If user decided to switch, replace current skill dialog with new skill dialog. |
| 44 | + return await outerDc.ReplaceDialogAsync(skillId).ConfigureAwait(false); |
| 45 | + } |
| 46 | + else |
| 47 | + { |
| 48 | + // Otherwise, continue the waiting skill dialog with the user's previous utterance. |
| 49 | + return await outerDc.ContinueDialogAsync().ConfigureAwait(false); |
| 50 | + } |
| 51 | + } |
| 52 | + |
| 53 | + // Prompts user to switch to a new skill. |
| 54 | + private async Task<DialogTurnResult> PromptToSwitchAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) |
| 55 | + { |
| 56 | + var options = stepContext.Options as SwitchSkillDialogOptions ?? throw new ArgumentException($"You must provide options of type {typeof(SwitchSkillDialogOptions).FullName}."); |
| 57 | + await _skillIdAccessor.SetAsync(stepContext.Context, options.Skill.Id).ConfigureAwait(false); |
| 58 | + await _lastActivityAccessor.SetAsync(stepContext.Context, stepContext.Context.Activity).ConfigureAwait(false); |
| 59 | + |
| 60 | + return await stepContext.PromptAsync(_confirmPromptId, new PromptOptions() { Prompt = options.Prompt }).ConfigureAwait(false); |
| 61 | + } |
| 62 | + |
| 63 | + // Ends this dialog, returning the prompt result. |
| 64 | + private async Task<DialogTurnResult> EndAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken) |
| 65 | + { |
| 66 | + bool result = (bool)stepContext.Result; |
| 67 | + return await stepContext.EndDialogAsync(result: result).ConfigureAwait(false); |
| 68 | + } |
| 69 | + |
| 70 | + private class Properties |
| 71 | + { |
| 72 | + public const string SkillId = "skillSwitchValue"; |
| 73 | + public const string LastActivity = "skillSwitchActivity"; |
| 74 | + } |
| 75 | + } |
| 76 | +} |
0 commit comments