SampleCommentsPage.cs
1 // Copyright (c) Microsoft Corporation 2 // The Microsoft Corporation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.Collections.Generic; 6 using System.Diagnostics.CodeAnalysis; 7 using System.Text.Json; 8 using System.Text.Json.Nodes; 9 using System.Text.Json.Serialization; 10 using Microsoft.CommandPalette.Extensions; 11 using Microsoft.CommandPalette.Extensions.Toolkit; 12 13 namespace SamplePagesExtension; 14 15 internal sealed partial class SampleCommentsPage : ContentPage 16 { 17 private readonly TreeContent myContentTree; 18 19 public override IContent[] GetContent() => [myContentTree]; 20 21 public SampleCommentsPage() 22 { 23 Name = "View Posts"; 24 Icon = new IconInfo("\uE90A"); // Comment 25 26 myContentTree = new() 27 { 28 RootContent = new MarkdownContent() 29 { 30 Body = """ 31 # Example of a thread of comments 32 You can use TreeContent in combination with FormContent to build a structure like a page with comments. 33 34 The forms on this page use the AdaptiveCard `Action.ShowCard` action to show a nested, hidden card on the form. 35 """, 36 }, 37 38 Children = [ 39 new PostContent("First") 40 { 41 Replies = [ 42 new PostContent("Oh very insightful. I hadn't considered that"), 43 new PostContent("Second"), 44 new PostContent("ah the ol switcheroo"), 45 ], 46 }, 47 new PostContent("First\nEDIT: shoot") 48 { 49 Replies = [ 50 new PostContent("delete this"), 51 ], 52 }, 53 new PostContent("Do you think they get the picture") 54 { 55 Replies = [ 56 new PostContent("Probably! Now go build and be happy"), 57 ], 58 } 59 ], 60 }; 61 } 62 } 63 64 [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "Sample code")] 65 internal sealed partial class PostContent : TreeContent 66 { 67 public List<IContent> Replies { get; init; } = []; 68 69 private readonly ToastStatusMessage _toast = new(new StatusMessage() { Message = "Reply posted", State = MessageState.Success }); 70 71 public PostContent(string body) 72 { 73 RootContent = new PostForm(body, this); 74 } 75 76 public override IContent[] GetChildren() => Replies.ToArray(); 77 78 public void Post() 79 { 80 RaiseItemsChanged(Replies.Count); 81 _toast.Show(); 82 } 83 } 84 85 [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "Sample code")] 86 internal sealed partial class PostForm : FormContent 87 { 88 private readonly PostContent _parent; 89 90 public PostForm(string postBody, PostContent parent) 91 { 92 _parent = parent; 93 TemplateJson = """ 94 { 95 "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", 96 "type": "AdaptiveCard", 97 "version": "1.6", 98 "body": [ 99 { 100 "type": "TextBlock", 101 "text": "${postBody}", 102 "wrap": true 103 } 104 ], 105 "actions": [ 106 { 107 "type": "Action.ShowCard", 108 "title": "${replyCard.title}", 109 "card": { 110 "type": "AdaptiveCard", 111 "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", 112 "version": "1.6", 113 "body": [ 114 { 115 "type": "Container", 116 "id": "${replyCard.idPrefix}Properties", 117 "items": [ 118 { 119 "$data": "${replyCard.fields}", 120 "type": "Input.Text", 121 "label": "${label}", 122 "id": "${id}", 123 "isRequired": "${required}", 124 "isMultiline": true, 125 "errorMessage": "'${label}' is required" 126 } 127 ] 128 } 129 ], 130 "actions": [ 131 { 132 "type": "Action.Submit", 133 "title": "Post" 134 } 135 ] 136 } 137 }, 138 { 139 "type": "Action.Submit", 140 "title": "Favorite" 141 }, 142 { 143 "type": "Action.Submit", 144 "title": "View on web" 145 } 146 ] 147 } 148 """; 149 DataJson = $$""" 150 { 151 "postBody": {{JsonSerializer.Serialize(postBody, JsonSerializationContext.Default.String)}}, 152 "replyCard": { 153 "title": "Reply", 154 "idPrefix": "reply", 155 "fields": [ 156 { 157 "label": "Reply", 158 "id": "ReplyBody", 159 "required": true, 160 "placeholder": "Write a reply here" 161 } 162 ] 163 } 164 } 165 """; 166 } 167 168 public override ICommandResult SubmitForm(string payload) 169 { 170 var data = JsonNode.Parse(payload); 171 _ = data; 172 var reply = data["ReplyBody"]; 173 var s = reply?.AsValue()?.ToString(); 174 if (!string.IsNullOrEmpty(s)) 175 { 176 _parent.Replies.Add(new PostContent(s)); 177 _parent.Post(); 178 } 179 180 return CommandResult.KeepOpen(); 181 } 182 } 183 184 [JsonSerializable(typeof(float))] 185 [JsonSerializable(typeof(int))] 186 [JsonSerializable(typeof(string))] 187 [JsonSerializable(typeof(bool))] 188 [JsonSourceGenerationOptions(UseStringEnumConverter = true, WriteIndented = true)] 189 [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "Just used here")] 190 internal sealed partial class JsonSerializationContext : JsonSerializerContext 191 { 192 }