public MainWindow() { InitializeComponent(); if (Dispatcher != null) { Dispatcher.UnhandledException += Dispatcher_UnhandledException; } CommandBinding cb = new CommandBinding(ApplicationCommands.Copy, this.CopyCmdExecuted, this.CopyCmdCanExecute); this.ConversationView.ConversationHistory.CommandBindings.Add(cb); this.ActivitiesPane.CommandBindings.Add(cb); this.ActivityPayloadPane.CommandBindings.Add(cb); this.DataContext = this; this.player.PlaybackStopped += this.Player_PlaybackStopped; Services.Tracker.Track(settings); Services.Tracker.Track(this); this.renderer = new AdaptiveCardRenderer(); this.renderer.UseXceedElementRenderers(); var configFile = Path.Combine(System.Reflection.Assembly.GetExecutingAssembly().Location, "AdaptiveCardsHostConfig.json"); if (File.Exists(configFile)) { this.renderer.HostConfig = AdaptiveHostConfig.FromJson(File.ReadAllText(configFile)); } }
public MainWindow() { this.InitializeComponent(); this.Dispatcher.UnhandledException += this.Dispatcher_UnhandledException; CommandBinding cb = new CommandBinding(ApplicationCommands.Copy, this.CopyCmdExecuted, this.CopyCmdCanExecute); this.ConversationView.ConversationHistory.CommandBindings.Add(cb); this.ActivitiesPane.CommandBindings.Add(cb); this.ActivityPayloadPane.CommandBindings.Add(cb); this.DataContext = this; this.player.PlaybackStopped += this.Player_PlaybackStopped; Services.Tracker.Configure(this.settings).Apply(); this.renderer = new AdaptiveCardRenderer(); /* * Xceed Enhanced Input Package * This optional package enhances the Adaptive Card input controls beyond what WPF provides out of the box. * To enable it: * 1. Add the NuGet package Extended.Wpf.Toolkit by Xceed to the project * 2. Add the NuGet package AdaptiveCards.Rendering.Wpf.Xceed by Microsoft to the project * 3. Uncomment the one line below * This option is not included here because of its license terms. * For more info: https://docs.microsoft.com/en-us/adaptive-cards/sdk/rendering-cards/net-wpf/getting-started */ // this.renderer.UseXceedElementRenderers(); var configFile = Path.Combine(System.Reflection.Assembly.GetExecutingAssembly().Location, "AdaptiveCardsHostConfig.json"); if (File.Exists(configFile)) { this.renderer.HostConfig = AdaptiveHostConfig.FromJson(File.ReadAllText(configFile)); } }
public void MediaConfig() { // Default values var defaultHostConfig = AdaptiveHostConfig.FromJson(@"{}"); Assert.IsNotNull(defaultHostConfig); Assert.IsNotNull(defaultHostConfig.Media); Assert.IsNull(defaultHostConfig.Media.DefaultPoster); Assert.IsNull(defaultHostConfig.Media.PlayButton); Assert.AreEqual(true, defaultHostConfig.Media.AllowInlinePlayback); // Default values var hostConfig = AdaptiveHostConfig.FromJson(@"{ ""media"": { ""defaultPoster"": ""http://adaptivecards.io/content/media/poster.png"", ""playButton"": ""http://adaptivecards.io/content/media/playButton.png"", ""allowInlinePlayback"": false } }"); Assert.IsNotNull(hostConfig); Assert.IsNotNull(hostConfig.Media); Assert.AreEqual("http://adaptivecards.io/content/media/poster.png", hostConfig.Media.DefaultPoster); Assert.AreEqual("http://adaptivecards.io/content/media/playButton.png", hostConfig.Media.PlayButton); Assert.AreEqual(false, hostConfig.Media.AllowInlinePlayback); }
public MainView() { DataContextChanged += MainView_DataContextChanged; InitializeComponent(); string json; try { var fileHelper = IoC.Get <IFileHelper>(); json = fileHelper.ReadTextFile(fileHelper.ActualPath + "Assets/WindowsNotificationHostConfig.json"); } catch { json = null; } if (json == null) { _renderer = new AdaptiveCardRenderer(); } else { var hostConfig = AdaptiveHostConfig.FromJson(json); _renderer = new AdaptiveCardRenderer(hostConfig); } _card = CreateCard(); }
private void Update() { try { var renderer = new AdaptiveCardRenderer(AdaptiveHostConfig.FromJson(HostConfigs.CortanaHostConfig)); CardContainer.Child = renderer.RenderCard(AdaptiveCard.FromJson(TextBoxCard.Text).Card).FrameworkElement; } catch { } }
private AdaptiveHostConfig LoadHostConfig() { Assembly assembly = typeof(AdaptiveCardView).Assembly; using (Stream stream = assembly.GetManifestResourceStream("Blastic.Themes.AdaptiveCardConfig.json")) using (StreamReader reader = new StreamReader(stream)) { return(AdaptiveHostConfig.FromJson(reader.ReadToEnd())); } }
/// <inheritdoc /> protected override void Load(ContainerBuilder builder) { // Create a default AdaptiveHostConfig if no other is specified builder.Register(context => { var resourceProvider = context.Resolve <IResourceProvider>(); var resources = resourceProvider.GetCachedManifestResourceNames(ThisAssembly); using var stream = resourceProvider.LocateResourceAsStream(ThisAssembly, @"HostConfigs\Windows10Toast.json"); using var streamReader = new StreamReader(stream); return(AdaptiveHostConfig.FromJson(streamReader.ReadToEnd())); }) .IfNotRegistered(typeof(AdaptiveHostConfig)) .As <AdaptiveHostConfig>() .SingleInstance(); }
public void TestParsingHostConfig() { var result = AdaptiveHostConfig.FromJson(@"{ ""fontSizes"": { ""small"": 25, ""default"": 26, ""medium"": 27, ""large"": 28, ""extraLarge"": 29 } }"); Assert.IsNotNull(result); Assert.AreEqual(25, result.FontSizes.Small); Assert.AreEqual(26, result.FontSizes.Default); Assert.AreEqual(27, result.FontSizes.Medium); Assert.AreEqual(28, result.FontSizes.Large); Assert.AreEqual(29, result.FontSizes.ExtraLarge); }
static int Main(string[] args) { Console.OutputEncoding = Encoding.UTF8; var app = new CommandLineApplication(); app.HelpOption("-h|--help"); var pathArg = app.Argument("path", "The path that contains JSON card payloads"); var optionRecurse = app.Option("-r|--recursive", "Recurse the directory for all JSON files", CommandOptionType.NoValue); var optionOutput = app.Option("-o|--out", "The file to output the HTML to", CommandOptionType.SingleValue); var optionSupportsInteracitivty = app.Option("-i|--supports-interactivity", "Include actions and inputs in the output", CommandOptionType.NoValue); var hostConfigOption = app.Option("--host-config", "Specify a host config file", CommandOptionType.SingleValue); app.OnExecute(() => { FileStream outputFile = null; var writer = Console.Out; // Output to file instead of console if (optionOutput.HasValue()) { outputFile = File.Open(optionOutput.Value(), FileMode.Create); writer = new StreamWriter(outputFile); } // Get payload search path var payloadPath = pathArg.Value ?? "..\\..\\..\\..\\samples\\v1.0\\Scenarios"; if (pathArg.Value == null) { Console.WriteLine($"No path argument specified, trying {payloadPath}..."); } var files = new List <string>(); if (File.Exists(payloadPath)) { files.Add(payloadPath); } else if (Directory.Exists(payloadPath)) { var recurse = optionRecurse.HasValue() ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; files = Directory.GetFiles(payloadPath, "*.json", recurse).ToList(); Console.WriteLine($"Found {files.Count} card payloads..."); } else { Console.WriteLine($"{payloadPath} does not contain any JSON files/. Nothing to do."); return; } writer.WriteLine(@"<!DOCTYPE html>"); writer.WriteLine(@"<html>"); writer.WriteLine(@"<head>"); writer.WriteLine(@" <title>Adaptive Cards HTML Renderer Test Bed</title>"); writer.WriteLine(@" <meta charset=""UTF-8"">"); writer.WriteLine(@" <link rel='stylesheet' type='text/css' href='AdaptiveCards.css' />"); writer.WriteLine(@"</head>"); writer.WriteLine(@"<body>"); AdaptiveHostConfig hostConfig = new AdaptiveHostConfig() { SupportsInteractivity = optionSupportsInteracitivty.HasValue() }; if (hostConfigOption.HasValue()) { hostConfig = AdaptiveHostConfig.FromJson(File.ReadAllText(hostConfigOption.Value())); } AdaptiveCardRenderer renderer = new AdaptiveCardRenderer(hostConfig); writer.WriteLine($"<h3>Renderer schema version: {renderer.SupportedSchemaVersion}</h3>"); writer.WriteLine($"<h4>Interactivty Enabled: {hostConfig.SupportsInteractivity}</h4>"); writer.WriteLine($"<h4>Generated at: {DateTime.Now:G}</h4>"); foreach (var file in files) { try { writer.WriteLine("<hr/>"); writer.WriteLine($"<h2>{Path.GetFileName(file)}</h2>"); AdaptiveCardParseResult parseResult = AdaptiveCard.FromJson(File.ReadAllText(file, Encoding.UTF8)); AdaptiveCard card = parseResult.Card; RenderedAdaptiveCard renderedCard = renderer.RenderCard(card); // Report any warnings foreach (var warning in parseResult.Warnings.Union(renderedCard.Warnings)) { writer.WriteLine($"<p class='warning'>WARNING: {warning.Message}</p>"); } writer.WriteLine($"<div class='cardcontainer'>{renderedCard.Html}</div>"); } catch (Exception err) { Debugger.Break(); writer.WriteLine($"<p class='error'>ERROR: {err.Message}</p>"); } } writer.WriteLine("</body>"); writer.WriteLine("</html>"); if (outputFile != null) { writer.Flush(); outputFile.Flush(); outputFile.Dispose(); Console.WriteLine($"All cards were written to {outputFile.Name}"); } // if output, launch the file if (Debugger.IsAttached) { Console.ReadLine(); } }); return(app.Execute(args)); }
static void Main(string[] args) { var app = new CommandLineApplication(); app.HelpOption("-h|--help"); var pathArg = app.Argument("path", "The path that contains JSON card payloads"); var optionRecurse = app.Option("-r|--recursive", "Recurse the directory for all JSON files", CommandOptionType.NoValue); var optionOutput = app.Option("-o|--out", "The directory to output the image(s) to", CommandOptionType.SingleValue); var optionSupportsInteracitivty = app.Option("-i|--supports-interactivity", "Include actions and inputs in the output", CommandOptionType.NoValue); var hostConfigOption = app.Option("--host-config", "Specify a host config file", CommandOptionType.SingleValue); app.OnExecute(() => { var outPath = optionOutput.HasValue() ? optionOutput.Value() : Environment.CurrentDirectory; if (!Directory.Exists(outPath)) { Directory.CreateDirectory(outPath); } // Get payload search path var payloadPath = pathArg.Value ?? "..\\..\\..\\..\\samples\\v1.0\\Scenarios"; if (pathArg.Value == null) { Console.WriteLine($"No path argument specified, trying {payloadPath}..."); } var files = new List <string>(); if (File.Exists(payloadPath)) { files.Add(payloadPath); } else if (Directory.Exists(payloadPath)) { var recurse = optionRecurse.HasValue() ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; files = Directory.GetFiles(payloadPath, "*.json", recurse).ToList(); Console.WriteLine($"Found {files.Count} card payloads..."); } else { Console.WriteLine($"{payloadPath} does not contain any JSON files. Nothing to do."); return; } AdaptiveHostConfig hostConfig = new AdaptiveHostConfig() { SupportsInteractivity = optionSupportsInteracitivty.HasValue() }; if (hostConfigOption.HasValue()) { hostConfig = AdaptiveHostConfig.FromJson(File.ReadAllText(hostConfigOption.Value())); } AdaptiveCardRenderer renderer = new AdaptiveCardRenderer(hostConfig); foreach (var file in files) { RenderCard(file, renderer, outPath).Wait(); } Console.WriteLine($"All cards were written to {Path.GetFullPath(outPath)}"); }); app.Execute(args); // if output, launch the file if (Debugger.IsAttached) { Console.ReadLine(); } }
static int Main(string[] args) { Console.OutputEncoding = Encoding.UTF8; var app = new CommandLineApplication(); app.HelpOption("-h|--help"); var pathArg = app.Argument("path", "The path that contains JSON card payloads"); var optionRecurse = app.Option("-r|--recursive", "Recurse the directory for all JSON files", CommandOptionType.NoValue); var optionOutput = app.Option("-o|--out", "The file to output the HTML to", CommandOptionType.SingleValue); var optionSupportsInteracitivty = app.Option("-i|--supports-interactivity", "Include actions and inputs in the output", CommandOptionType.NoValue); var hostConfigOption = app.Option("--host-config", "Specify a host config file", CommandOptionType.SingleValue); app.OnExecute(() => { FileStream outputFile = null; var writer = Console.Out; // Output to file instead of console if (optionOutput.HasValue()) { outputFile = File.Open(optionOutput.Value(), FileMode.Create); writer = new StreamWriter(outputFile); } // Get payload search path var payloadPath = pathArg.Value ?? "..\\..\\..\\..\\samples\\v1.0\\Scenarios"; if (pathArg.Value == null) { Console.WriteLine($"No path argument specified, trying {payloadPath}..."); } var files = new List <string>(); if (File.Exists(payloadPath)) { files.Add(payloadPath); } else if (Directory.Exists(payloadPath)) { var recurse = optionRecurse.HasValue() ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; files = Directory.GetFiles(payloadPath, "*.json", recurse).ToList(); Console.WriteLine($"Found {files.Count} card payloads..."); } else { Console.WriteLine($"{payloadPath} does not contain any JSON files. Nothing to do."); return; } writer.WriteLine(@"<!DOCTYPE html> <html> <head> <title>Adaptive Cards HTML Renderer Test Bed</title> <meta charset=""UTF-8""> <style type""text/css""> * { box-sizing: border-box; font-family: 'Segoe UI' } .cardcontainer { width: 400px; border-width: 1px; border-color: #808080; border-style: solid; } .error { border: solid 1px maroon; color: white; background: maroon; padding: 5px; width: 400px; } .warning { border: solid 1px orange; color: white; background: orange; padding: 5px; width: 400px; } </style> </head> <body>"); AdaptiveHostConfig hostConfig = new AdaptiveHostConfig() { SupportsInteractivity = optionSupportsInteracitivty.HasValue() }; if (hostConfigOption.HasValue()) { hostConfig = AdaptiveHostConfig.FromJson(File.ReadAllText(hostConfigOption.Value())); } AdaptiveCardRenderer renderer = new AdaptiveCardRenderer(hostConfig); writer.WriteLine($"<h3>Renderer schema version: {renderer.SupportedSchemaVersion}</h3>"); writer.WriteLine($"<h4>Interactivty Enabled: {hostConfig.SupportsInteractivity}</h4>"); writer.WriteLine($"<h4>Generated at: {DateTime.Now:G}</h4>"); foreach (var file in files) { try { writer.WriteLine("<hr/>"); writer.WriteLine($"<h2>{Path.GetFileName(file)}</h2>"); AdaptiveCardParseResult parseResult = AdaptiveCard.FromJson(File.ReadAllText(file, Encoding.UTF8)); AdaptiveCard card = parseResult.Card; RenderedAdaptiveCard renderedCard = renderer.RenderCard(card); // Report any warnings foreach (var warning in parseResult.Warnings.Union(renderedCard.Warnings)) { writer.WriteLine($"<p class='warning'>WARNING: {warning.Message}</p>"); } writer.WriteLine($"<div class='cardcontainer'>{renderedCard.Html}</div>"); } catch (Exception err) { Debugger.Break(); writer.WriteLine($"<p class='error'>ERROR: {err.Message}</p>"); } } bool allowInlinePlayback = hostConfig.Media.AllowInlinePlayback; // Convert to JavaScript boolean values (False -> false, True -> true) string jsAllowInlinePlayback = allowInlinePlayback.ToString().ToLower(); writer.WriteLine("</body>"); writer.WriteLine($@" <script> // Sample JavaScript code to make media elements work const mediaPosterButtons = document.getElementsByClassName('ac-media-poster'); const allowInlinePlayback = false; function activateMedia(button) {{ const mediaId = button.dataset.acMediaid; const mediaPlayerContainer = document.getElementById(mediaId); if (mediaPlayerContainer) {{ // Hide the poster button.style.display = 'none'; // Show the media player container mediaPlayerContainer.style.display = ''; // Play the media const mediaPlayer = document.getElementById(`${{mediaId}}-player`); mediaPlayer.play(); }} }} for (var i = 0; i < mediaPosterButtons.length; i++) {{ const button = mediaPosterButtons[i]; button.addEventListener('click', function() {{ if ({jsAllowInlinePlayback}) {{ activateMedia(button); }} else {{ const mediaSources = button.dataset.acMediaSources; alert(mediaSources); }} }}); button.addEventListener('keydown', function(e) {{ if (e.key == "" "") {{ if ({jsAllowInlinePlayback}) {{ activateMedia(button); }} else {{ const mediaSources = button.dataset.acMediaSources; alert(mediaSources); }} }} }}); }} // Sample JavaScript code to test showCard action const showCardActions = document.getElementsByClassName('ac-action-showCard'); for (var i = 0; i < showCardActions.length; i++) {{ const showCardAction = showCardActions[i]; showCardAction.addEventListener('click', function() {{ if (true) {{ const showCardId = showCardAction.dataset.acShowcardid; const showCard = document.getElementById(showCardId); if(showCard.style.display == 'none') {{ showCard.style.display = 'inline'; }} else {{ showCard.style.display = 'none' }} }} else {{ const showCardId = showCardAction.dataset.acShowCardId; alert(showCardId); }} }}); }} // Sample JavaScript code to test inlienaction's keyboard event handler const textinputWithInlineAction = document.getElementsByClassName('ac-textinput-inlineaction'); for (var i = 0; i < textinputWithInlineAction.length; i++) {{ const container = textinputWithInlineAction[i]; const textinputId = container.dataset.acTextinputId; const textinput = document.getElementById(textinputId); textinput.addEventListener('keydown', function (e) {{ if (e.key == ""Enter"") {{ const inlineactionId = container.dataset.acInlineactionId; const inlineaction = document.getElementById(inlineactionId); if (inlineaction) {{ var actionAttribute = inlineaction.getAttribute('data-ac-url'); if (actionAttribute != null) {{ window.open(actionAttribute); }} else {{ actionAttribute = inlineaction.getAttribute('data-ac-submitData') if (actionAttribute != null) {{ alert(textinput.value); }} }} }} }} }}); }} // Sample JavaScript code to test toggleVisibility action const toggleVisibilityActions = document.getElementsByClassName('ac-action-toggleVisibility'); for (var i = 0; i < toggleVisibilityActions.length; i++) {{ const toggleVisibilityAction = toggleVisibilityActions[i]; toggleVisibilityAction.addEventListener('click', function() {{ if ({jsAllowInlinePlayback}) {{ // Read list of targets with defined behaviour // List will be in format id-targets='id1:True,id2:Toggle,id3:False' const targetElementsString = toggleVisibilityAction.dataset.acTargetelements; var targetElements = targetElementsString.split(','); // For each target in list of targets for(var j = 0; j < targetElements.length; j++) {{ /// Do a split for commas and for each element, find the : to divide both strings const targetElementIdWithAction = targetElements[j].split(':'); const targetElementId = targetElementIdWithAction[0]; const targetElementAction = targetElementIdWithAction[1]; var targetElementsInDocument = document.getElementsByName(targetElementId); // There is no singular version of getElementByName so just take the first element var targetElement = targetElementsInDocument[0]; // The way to discern between checkbox elements and inline-actions is that inline-actions contain a textinput var isCheckBoxElement = ((targetElementsInDocument.length > 1) && !(targetElement.className.includes('ac-textinput'))); const targetSeparatorId = targetElement.dataset.acSeparatorid; const separator = document.getElementById(targetSeparatorId); if(targetElementAction == 'True' || (targetElementAction == 'Toggle' && targetElement.style.display == 'none')) {{ if( isCheckBoxElement ) {{ targetElement.style.display = 'inline-block'; }} else {{ targetElement.style.display = 'flex'; }} if(targetElement.className.includes('ac-container')){{ targetElement.style.display = 'block'; }} if(separator != null) {{ separator.style.display = 'block'; }} }} else if(targetElementAction == 'False' || (targetElementAction == 'Toggle' && targetElement.style.display != 'none')) {{ targetElement.style.display = 'none'; if(separator != null) {{ separator.style.display = 'none'; }} }} const parent = targetElement.parentNode; var isFirstElement = true; for(var k = 0; k < parent.childNodes.length; k++){{ var child = parent.childNodes[k]; <!-- if element is separator -> skip (As we don't care of this one) --> if(child.className.includes('ac-separator') || child.className.includes('ac-columnseparator')){{ continue; }} <!-- if element is not visible -> skip (The separator was hidden in the previous step) --> if(child.style.display == 'none'){{ continue; }} const childSeparatorId = child.dataset.acSeparatorid; var childSeparator = document.getElementById(childSeparatorId); if(isFirstElement){{ <!-- if element is visible -> hide separator --> if(childSeparator != null){{ childSeparator.style.display = 'none'; }} isFirstElement = false; }} else{{ <!-- if element is visible -> show separator --> if(childSeparator != null){{ childSeparator.style.display = 'block'; }} }} }} }} }} else {{ const targetElementsString = toggleVisibilityAction.dataset.acTargetelements; alert(targetElementsString); }} }}); }} </script>"); writer.WriteLine("</html>"); if (outputFile != null) { writer.Flush(); outputFile.Flush(); outputFile.Dispose(); Console.WriteLine($"All cards were written to {outputFile.Name}"); } // if output, launch the file if (Debugger.IsAttached) { Console.ReadLine(); } }); return(app.Execute(args)); }
static int Main(string[] args) { Console.OutputEncoding = Encoding.UTF8; var app = new CommandLineApplication(); app.HelpOption("-h|--help"); var pathArg = app.Argument("path", "The path that contains JSON card payloads"); var optionRecurse = app.Option("-r|--recursive", "Recurse the directory for all JSON files", CommandOptionType.NoValue); var optionOutput = app.Option("-o|--out", "The file to output the HTML to", CommandOptionType.SingleValue); var optionSupportsInteracitivty = app.Option("-i|--supports-interactivity", "Include actions and inputs in the output", CommandOptionType.NoValue); var hostConfigOption = app.Option("--host-config", "Specify a host config file", CommandOptionType.SingleValue); app.OnExecute(() => { FileStream outputFile = null; var writer = Console.Out; // Output to file instead of console if (optionOutput.HasValue()) { outputFile = File.Open(optionOutput.Value(), FileMode.Create); writer = new StreamWriter(outputFile); } // Get payload search path var payloadPath = pathArg.Value ?? "..\\..\\..\\..\\samples\\v1.0\\Scenarios"; if (pathArg.Value == null) { Console.WriteLine($"No path argument specified, trying {payloadPath}..."); } var files = new List <string>(); if (File.Exists(payloadPath)) { files.Add(payloadPath); } else if (Directory.Exists(payloadPath)) { var recurse = optionRecurse.HasValue() ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; files = Directory.GetFiles(payloadPath, "*.json", recurse).ToList(); Console.WriteLine($"Found {files.Count} card payloads..."); } else { Console.WriteLine($"{payloadPath} does not contain any JSON files. Nothing to do."); return; } writer.WriteLine(@"<!DOCTYPE html> <html> <head> <title>Adaptive Cards HTML Renderer Test Bed</title> <meta charset=""UTF-8""> <style type""text/css""> * { box-sizing: border-box; font-family: 'Segoe UI' } .cardcontainer { width: 400px; border-width: 1px; border-color: #808080; border-style: solid; } .error { border: solid 1px maroon; color: white; background: maroon; padding: 5px; width: 400px; } .warning { border: solid 1px orange; color: white; background: orange; padding: 5px; width: 400px; } </style> </head> <body>"); AdaptiveHostConfig hostConfig = new AdaptiveHostConfig() { SupportsInteractivity = optionSupportsInteracitivty.HasValue() }; if (hostConfigOption.HasValue()) { hostConfig = AdaptiveHostConfig.FromJson(File.ReadAllText(hostConfigOption.Value())); } AdaptiveCardRenderer renderer = new AdaptiveCardRenderer(hostConfig); writer.WriteLine($"<h3>Renderer schema version: {renderer.SupportedSchemaVersion}</h3>"); writer.WriteLine($"<h4>Interactivty Enabled: {hostConfig.SupportsInteractivity}</h4>"); writer.WriteLine($"<h4>Generated at: {DateTime.Now:G}</h4>"); foreach (var file in files) { try { writer.WriteLine("<hr/>"); writer.WriteLine($"<h2>{Path.GetFileName(file)}</h2>"); AdaptiveCardParseResult parseResult = AdaptiveCard.FromJson(File.ReadAllText(file, Encoding.UTF8)); AdaptiveCard card = parseResult.Card; RenderedAdaptiveCard renderedCard = renderer.RenderCard(card); // Report any warnings foreach (var warning in parseResult.Warnings.Union(renderedCard.Warnings)) { writer.WriteLine($"<p class='warning'>WARNING: {warning.Message}</p>"); } writer.WriteLine($"<div class='cardcontainer'>{renderedCard.Html}</div>"); } catch (Exception err) { Debugger.Break(); writer.WriteLine($"<p class='error'>ERROR: {err.Message}</p>"); } } bool allowInlinePlayback = hostConfig.Media.AllowInlinePlayback; // Convert to JavaScript boolean values (False -> false, True -> true) string jsAllowInlinePlayback = allowInlinePlayback.ToString().ToLower(); writer.WriteLine("</body>"); writer.WriteLine($@" <script> // Sample JavaScript code to make media elements work const mediaPosterButtons = document.getElementsByClassName('ac-media-poster'); const allowInlinePlayback = false; for (var i = 0; i < mediaPosterButtons.length; i++) {{ const button = mediaPosterButtons[i]; button.addEventListener('click', function() {{ if ({jsAllowInlinePlayback}) {{ const mediaId = button.dataset.acMediaid; const mediaPlayerContainer = document.getElementById(mediaId); if (mediaPlayerContainer) {{ // Hide the poster button.style.display = 'none'; // Show the media player container mediaPlayerContainer.style.display = ''; // Play the media const mediaPlayer = document.getElementById(`${{mediaId}}-player`); mediaPlayer.play(); }} }} else {{ const mediaSources = button.dataset.acMediaSources; alert(mediaSources); }} }}); }} </script>"); writer.WriteLine("</html>"); if (outputFile != null) { writer.Flush(); outputFile.Flush(); outputFile.Dispose(); Console.WriteLine($"All cards were written to {outputFile.Name}"); } // if output, launch the file if (Debugger.IsAttached) { Console.ReadLine(); } }); return(app.Execute(args)); }
public void TestParsingFullHostConfig() { var hostConfig = AdaptiveHostConfig.FromJson(@"{ ""spacing"": { ""small"": 3, ""default"": 4, ""medium"": 5, ""large"": 6, ""extraLarge"": 7, ""padding"": 8 }, ""separator"": { ""lineThickness"": 4, ""lineColor"": ""#ABCDEF"" }, ""supportsInteractivity"": true, ""fontFamily"": ""Segoe UI"", ""fontSizes"": { ""small"": 12, ""default"": 14, ""medium"": 17, ""large"": 21, ""extraLarge"": 26 }, ""fontWeights"": { ""lighter"": 100, ""default"": 200, ""bolder"": 300 }, ""containerStyles"": { ""default"": { ""backgroundColor"": ""#AABBCC"", ""foregroundColors"": { ""default"": { ""default"": ""#333333"", ""subtle"": ""#EE333333"" }, ""accent"": { ""default"": ""#2E89FC"", ""subtle"": ""#882E89FC"" }, ""attention"": { ""default"": ""#cc3300"", ""subtle"": ""#DDcc3300"" }, ""good"": { ""default"": ""#54a254"", ""subtle"": ""#DD54a254"" }, ""warning"": { ""default"": ""#e69500"", ""subtle"": ""#DDe69500"" } } }, ""emphasis"": { ""backgroundColor"": ""#08000000"", ""foregroundColors"": { ""default"": { ""default"": ""#333333"", ""subtle"": ""#EE333333"" }, ""accent"": { ""default"": ""#2E89FC"", ""subtle"": ""#882E89FC"" }, ""attention"": { ""default"": ""#cc3300"", ""subtle"": ""#DDcc3300"" }, ""good"": { ""default"": ""#54a254"", ""subtle"": ""#DD54a254"" }, ""warning"": { ""default"": ""#e69500"", ""subtle"": ""#DDe69500"" } } } }, ""imageSizes"": { ""small"": 40, ""medium"": 80, ""large"": 160 }, ""actions"": { ""maxActions"": 20, ""spacing"": ""default"", ""buttonSpacing"": 10, ""showCard"": { ""actionMode"": ""inline"", ""inlineTopMargin"": 16 }, ""actionsOrientation"": ""vertical"", ""actionAlignment"": ""stretch"", ""iconPlacement"": ""LeftOfTitle"", ""iconSize"": 20 }, ""adaptiveCard"": { ""allowCustomStyle"": false }, ""image"": { ""size"": ""medium"" }, ""imageSet"": { ""imageSize"": ""small"", ""maxImageHeight"": 100 }, ""media"": { ""defaultPoster"": ""http://adaptivecards.io/content/media/poster.png"" }, ""factSet"": { ""title"": { ""color"": ""accent"", ""size"": ""default"", ""isSubtle"": false, ""weight"": ""bolder"", ""wrap"": true, ""maxWidth"": 150 }, ""value"": { ""color"": ""default"", ""size"": ""default"", ""isSubtle"": false, ""weight"": ""default"", ""wrap"": true }, ""spacing"": 10 } }"); Assert.IsNotNull(hostConfig); Assert.AreEqual(3, hostConfig.Spacing.Small); Assert.AreEqual(4, hostConfig.Spacing.Default); Assert.AreEqual(5, hostConfig.Spacing.Medium); Assert.AreEqual(6, hostConfig.Spacing.Large); Assert.AreEqual(7, hostConfig.Spacing.ExtraLarge); Assert.AreEqual(8, hostConfig.Spacing.Padding); Assert.AreEqual(4, hostConfig.Separator.LineThickness); Assert.AreEqual("#ABCDEF", hostConfig.Separator.LineColor); Assert.AreEqual(true, hostConfig.SupportsInteractivity); Assert.AreEqual("Segoe UI", hostConfig.FontFamily); Assert.AreEqual(12, hostConfig.FontSizes.Small); Assert.AreEqual(14, hostConfig.FontSizes.Default); Assert.AreEqual(17, hostConfig.FontSizes.Medium); Assert.AreEqual(21, hostConfig.FontSizes.Large); Assert.AreEqual(26, hostConfig.FontSizes.ExtraLarge); // TODO: FontWeights aren't supported Assert.AreEqual("#AABBCC", hostConfig.ContainerStyles.Default.BackgroundColor); Assert.AreEqual("#333333", hostConfig.ContainerStyles.Default.ForegroundColors.Default.Default); Assert.AreEqual("#EE333333", hostConfig.ContainerStyles.Default.ForegroundColors.Default.Subtle); Assert.AreEqual("#2E89FC", hostConfig.ContainerStyles.Default.ForegroundColors.Accent.Default); Assert.AreEqual("#882E89FC", hostConfig.ContainerStyles.Default.ForegroundColors.Accent.Subtle); Assert.AreEqual("#cc3300", hostConfig.ContainerStyles.Default.ForegroundColors.Attention.Default); Assert.AreEqual("#DDcc3300", hostConfig.ContainerStyles.Default.ForegroundColors.Attention.Subtle); Assert.AreEqual("#54a254", hostConfig.ContainerStyles.Default.ForegroundColors.Good.Default); Assert.AreEqual("#DD54a254", hostConfig.ContainerStyles.Default.ForegroundColors.Good.Subtle); Assert.AreEqual("#e69500", hostConfig.ContainerStyles.Default.ForegroundColors.Warning.Default); Assert.AreEqual("#DDe69500", hostConfig.ContainerStyles.Default.ForegroundColors.Warning.Subtle); Assert.AreEqual("#08000000", hostConfig.ContainerStyles.Emphasis.BackgroundColor); Assert.AreEqual(40, hostConfig.ImageSizes.Small); Assert.AreEqual(80, hostConfig.ImageSizes.Medium); Assert.AreEqual(160, hostConfig.ImageSizes.Large); Assert.AreEqual(20, hostConfig.Actions.MaxActions); // TODO: Spacing property not supported Assert.AreEqual(10, hostConfig.Actions.ButtonSpacing); Assert.AreEqual(ShowCardActionMode.Inline, hostConfig.Actions.ShowCard.ActionMode); Assert.AreEqual(16, hostConfig.Actions.ShowCard.InlineTopMargin); Assert.AreEqual(ActionsOrientation.Vertical, hostConfig.Actions.ActionsOrientation); Assert.AreEqual(AdaptiveHorizontalAlignment.Stretch, hostConfig.Actions.ActionAlignment); Assert.AreEqual(IconPlacement.LeftOfTitle, hostConfig.Actions.IconPlacement); Assert.AreEqual(20, hostConfig.Actions.IconSize); // TODO: Image property not supported (I assume this is where you can set the default image size?) Assert.AreEqual(AdaptiveImageSize.Small, hostConfig.ImageSet.ImageSize); // TODO: MaxImageHeight property not supported Assert.AreEqual(AdaptiveTextColor.Accent, hostConfig.FactSet.Title.Color); Assert.AreEqual(false, hostConfig.FactSet.Title.IsSubtle); Assert.AreEqual(10, hostConfig.FactSet.Spacing); // Media config Assert.AreEqual("http://adaptivecards.io/content/media/poster.png", hostConfig.Media.DefaultPoster); }
public void TestParsingInvalidHostConfig() { Assert.ThrowsException <AdaptiveSerializationException>(() => AdaptiveHostConfig.FromJson("not json")); }