a fork of iceshrimp.net but a tweaked frontend to my personal liking. waow
fediverse social-media social iceshrimp fedi
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

[frontend/services] Create JsService and dedupe dialog showing and closing

pancakes 9ac412a4 3519344a

+100 -175
+1
Iceshrimp.Backend/Pages/Shared/FrontendSPA.razor
··· 45 45 environment: "@Env.EnvironmentName" 46 46 }); 47 47 </script> 48 + <script src="/@Assets["js-interop.js"]"></script> 48 49 <script src="/@Assets["Utility.js"]"></script> 49 50 <script>navigator.serviceWorker.register('service-worker.js', { updateViaCache: 'none' });</script> 50 51 </body>
+4 -7
Iceshrimp.Frontend/Components/AnnouncementsDialog.razor
··· 6 6 @using Microsoft.Extensions.Localization 7 7 @inject AnnouncementService AnnouncementService; 8 8 @inject ApiService Api; 9 - @inject IJSRuntime Js; 9 + @inject JsService Js; 10 10 @inject IStringLocalizer<Localization> Loc; 11 11 12 12 <dialog @onkeyup="HandleKeys" class="dialog" @ref="Dialog"> ··· 82 82 83 83 @code { 84 84 private ElementReference Dialog { get; set; } 85 - private IJSObjectReference _module = null!; 86 85 private StateButton? NextButton { get; set; } 87 86 private int Current { get; set; } 88 87 private PaginationData? PaginationData { get; set; } ··· 91 90 private async Task CloseDialog() 92 91 { 93 92 Announcements = []; 94 - await _module.InvokeVoidAsync("closeDialog", Dialog); 93 + await Js.CloseDialogAsync(Dialog); 95 94 } 96 95 97 96 public async Task Display() ··· 111 110 112 111 StateHasChanged(); 113 112 114 - await _module.InvokeVoidAsync("openDialog", Dialog); 113 + await Js.ShowDialogAsync(Dialog); 115 114 } 116 115 117 116 private void Previous() ··· 172 171 } 173 172 } 174 173 175 - protected override async Task OnInitializedAsync() 174 + protected override void OnInitialized() 176 175 { 177 - _module = await Js.InvokeAsync<IJSObjectReference>("import", 178 - "./Components/AnnouncementsDialog.razor.js"); 179 176 AnnouncementService.AnnouncementsDialog = this; 180 177 } 181 178 }
-7
Iceshrimp.Frontend/Components/AnnouncementsDialog.razor.js
··· 1 - export function openDialog(element) { 2 - element.showModal() 3 - } 4 - 5 - export function closeDialog(element) { 6 - element.close() 7 - }
+5 -8
Iceshrimp.Frontend/Components/ConfirmDialog.razor
··· 3 3 @using Iceshrimp.Frontend.Localization 4 4 @using Microsoft.Extensions.Localization 5 5 @inject GlobalComponentSvc GlobalComponentSvc; 6 - @inject IJSRuntime Js; 6 + @inject JsService Js; 7 7 @inject IStringLocalizer<Localization> Loc; 8 8 9 9 <dialog @onkeyup="HandleKeys" class="dialog" @ref="Dialog"> ··· 25 25 </dialog> 26 26 27 27 @code { 28 - private ElementReference Dialog { get; set; } 29 - private IJSObjectReference _module = null!; 28 + private ElementReference Dialog { get; set; } 30 29 private EventCallback<bool> Action { get; set; } 31 30 private string Question { get; set; } = ""; 32 31 private IconName? ConfirmIcon { get; set; } ··· 35 34 36 35 private async Task CloseDialog() 37 36 { 38 - await _module.InvokeVoidAsync("closeDialog", Dialog); 37 + await Js.CloseDialogAsync(Dialog); 39 38 } 40 39 41 40 public async Task Confirm(EventCallback<bool> action, string question, IconName? icon = null, string? buttonText = null) ··· 48 47 49 48 StateHasChanged(); 50 49 51 - await _module.InvokeVoidAsync("openDialog", Dialog); 50 + await Js.ShowDialogAsync(Dialog); 52 51 } 53 52 54 53 private async Task ConfirmAction() ··· 78 77 } 79 78 } 80 79 81 - protected override async Task OnInitializedAsync() 80 + protected override void OnInitialized() 82 81 { 83 - _module = await Js.InvokeAsync<IJSObjectReference>("import", 84 - "./Components/ConfirmDialog.razor.js"); 85 82 GlobalComponentSvc.ConfirmDialog = this; 86 83 } 87 84 }
-7
Iceshrimp.Frontend/Components/ConfirmDialog.razor.js
··· 1 - export function openDialog(element) { 2 - element.showModal() 3 - } 4 - 5 - export function closeDialog(element) { 6 - element.close() 7 - }
+1
Iceshrimp.Frontend/Components/GlobalComponents.razor
··· 1 + <JsInteropWrapper /> 1 2 <EmojiPicker /> 2 3 <BannerContainer /> 3 4 <AnnouncementsDialog />
+13
Iceshrimp.Frontend/Components/JsInteropWrapper.razor
··· 1 + @using Iceshrimp.Frontend.Core.Services 2 + @inject JsService JsSvc; 3 + @inject IJSRuntime Js; 4 + 5 + @code { 6 + protected override async Task OnAfterRenderAsync(bool firstRender) 7 + { 8 + if (firstRender) 9 + { 10 + JsSvc.Module = await Js.InvokeAsync<IJSObjectReference>("import", "./js-interop.js"); 11 + } 12 + } 13 + }
+9 -12
Iceshrimp.Frontend/Components/NoticeDialog.razor
··· 3 3 @using Iceshrimp.Frontend.Localization 4 4 @using Microsoft.Extensions.Localization 5 5 @inject GlobalComponentSvc GlobalComponentSvc; 6 - @inject IJSRuntime Js; 6 + @inject JsService Js; 7 7 @inject IStringLocalizer<Localization> Loc; 8 8 9 9 <dialog @onkeyup="HandleKeys" class="dialog" @ref="Dialog"> ··· 33 33 </dialog> 34 34 35 35 @code { 36 - private ElementReference Dialog { get; set; } 37 - private IJSObjectReference _module = null!; 38 - private NoticeType Type { get; set; } 39 - private string[] Text { get; set; } = []; 36 + private ElementReference Dialog { get; set; } 37 + private NoticeType Type { get; set; } 38 + private string[] Text { get; set; } = []; 40 39 41 40 public enum NoticeType 42 41 { ··· 47 46 48 47 private async Task CloseDialog() 49 48 { 50 - await _module.InvokeVoidAsync("closeDialog", Dialog); 49 + await Js.CloseDialogAsync(Dialog); 51 50 } 52 51 53 52 public async Task Display(string text, NoticeType type = NoticeType.Notice) ··· 56 55 Text = text.Split('\n'); 57 56 58 57 StateHasChanged(); 59 - 60 - await _module.InvokeVoidAsync("openDialog", Dialog); 58 + 59 + await Js.ShowDialogAsync(Dialog); 61 60 } 62 - 61 + 63 62 private async Task HandleKeys(KeyboardEventArgs e) 64 63 { 65 64 if (e is { Code: "Enter" or "Escape" }) ··· 68 67 } 69 68 } 70 69 71 - protected override async Task OnInitializedAsync() 70 + protected override void OnInitialized() 72 71 { 73 - _module = await Js.InvokeAsync<IJSObjectReference>("import", 74 - "./Components/NoticeDialog.razor.js"); 75 72 GlobalComponentSvc.NoticeDialog = this; 76 73 } 77 74 }
-7
Iceshrimp.Frontend/Components/NoticeDialog.razor.js
··· 1 - export function openDialog(element) { 2 - element.showModal() 3 - } 4 - 5 - export function closeDialog(element) { 6 - element.close() 7 - }
+5 -8
Iceshrimp.Frontend/Components/PromptDialog.razor
··· 2 2 @using Iceshrimp.Frontend.Localization 3 3 @using Microsoft.Extensions.Localization 4 4 @inject GlobalComponentSvc GlobalComponentSvc; 5 - @inject IJSRuntime Js; 5 + @inject JsService Js; 6 6 @inject IStringLocalizer<Localization> Loc; 7 7 8 8 <dialog @onkeyup="HandleKeys" class="dialog" @ref="Dialog"> ··· 33 33 </dialog> 34 34 35 35 @code { 36 - private ElementReference Dialog { get; set; } 37 - private IJSObjectReference _module = null!; 36 + private ElementReference Dialog { get; set; } 38 37 private EventCallback<string?> Action { get; set; } 39 38 private string Text { get; set; } = ""; 40 39 private string Placeholder { get; set; } = ""; ··· 46 45 47 46 private async Task CloseDialog() 48 47 { 49 - await _module.InvokeVoidAsync("closeDialog", Dialog); 48 + await Js.CloseDialogAsync(Dialog); 50 49 } 51 50 52 51 public async Task Prompt(EventCallback<string?> action, string text, string placeholder, string? defaultValue, bool allowEmpty = false, bool multiLine = false, string? buttonText = null) ··· 62 61 63 62 StateHasChanged(); 64 63 65 - await _module.InvokeVoidAsync("openDialog", Dialog); 64 + await Js.ShowDialogAsync(Dialog); 66 65 } 67 66 68 67 private async Task ConfirmAction() ··· 92 91 } 93 92 } 94 93 95 - protected override async Task OnInitializedAsync() 94 + protected override void OnInitialized() 96 95 { 97 - _module = await Js.InvokeAsync<IJSObjectReference>("import", 98 - "./Components/PromptDialog.razor.js"); 99 96 GlobalComponentSvc.PromptDialog = this; 100 97 } 101 98 }
-7
Iceshrimp.Frontend/Components/PromptDialog.razor.js
··· 1 - export function openDialog(element) { 2 - element.showModal() 3 - } 4 - 5 - export function closeDialog(element) { 6 - element.close() 7 - }
+5 -8
Iceshrimp.Frontend/Components/ReportDialog.razor
··· 6 6 @using Microsoft.Extensions.Localization 7 7 @inject ApiService Api; 8 8 @inject GlobalComponentSvc GlobalComponentSvc; 9 - @inject IJSRuntime Js; 9 + @inject JsService Js; 10 10 @inject IStringLocalizer<Localization> Loc; 11 11 12 12 <dialog class="dialog" @ref="Dialog"> ··· 86 86 </dialog> 87 87 88 88 @code { 89 - private ElementReference Dialog { get; set; } 90 - private IJSObjectReference _module = null!; 89 + private ElementReference Dialog { get; set; } 91 90 private List<RuleResponse> Rules { get; set; } = []; 92 91 private string Comment { get; set; } = ""; 93 92 private List<string> RuleIds { get; set; } = []; ··· 99 98 100 99 private async Task CloseDialog() 101 100 { 102 - await _module.InvokeVoidAsync("closeDialog", Dialog); 101 + await Js.CloseDialogAsync(Dialog); 103 102 } 104 103 105 104 public async Task ReportNote(NoteBase note) ··· 113 112 114 113 StateHasChanged(); 115 114 116 - await _module.InvokeVoidAsync("openDialog", Dialog); 115 + await Js.ShowDialogAsync(Dialog); 117 116 } 118 117 119 118 public async Task ReportUser(UserResponse user) ··· 127 126 128 127 StateHasChanged(); 129 128 130 - await _module.InvokeVoidAsync("openDialog", Dialog); 129 + await Js.ShowDialogAsync(Dialog); 131 130 } 132 131 133 132 private async Task Submit() ··· 223 222 224 223 protected override async Task OnInitializedAsync() 225 224 { 226 - _module = await Js.InvokeAsync<IJSObjectReference>("import", 227 - "./Components/ReportDialog.razor.js"); 228 225 Rules = await Api.Instance.GetRulesAsync(); 229 226 GlobalComponentSvc.ReportDialog = this; 230 227 }
-7
Iceshrimp.Frontend/Components/ReportDialog.razor.js
··· 1 - export function openDialog(element) { 2 - element.showModal() 3 - } 4 - 5 - export function closeDialog(element) { 6 - element.close() 7 - }
+5 -8
Iceshrimp.Frontend/Components/SelectDialog.razor
··· 2 2 @using Iceshrimp.Frontend.Localization 3 3 @using Microsoft.Extensions.Localization 4 4 @inject GlobalComponentSvc GlobalComponentSvc; 5 - @inject IJSRuntime Js; 5 + @inject JsService Js; 6 6 @inject IStringLocalizer<Localization> Loc; 7 7 8 8 <dialog @onkeyup="HandleKeys" class="dialog" @ref="Dialog"> ··· 29 29 </dialog> 30 30 31 31 @code { 32 - private ElementReference Dialog { get; set; } 33 - private IJSObjectReference _module = null!; 32 + private ElementReference Dialog { get; set; } 34 33 private EventCallback<object?> Action { get; set; } 35 34 private string Text { get; set; } = ""; 36 35 private List<(string Label, object Value)> Options { get; set; } = []; ··· 40 39 41 40 private async Task CloseDialog() 42 41 { 43 - await _module.InvokeVoidAsync("closeDialog", Dialog); 42 + await Js.CloseDialogAsync(Dialog); 44 43 } 45 44 46 45 public async Task Select(EventCallback<object?> action, string text, List<(string, object)> options, string? buttonText = null) ··· 54 53 55 54 StateHasChanged(); 56 55 57 - await _module.InvokeVoidAsync("openDialog", Dialog); 56 + await Js.ShowDialogAsync(Dialog); 58 57 } 59 58 60 59 private async Task ConfirmAction() ··· 84 83 } 85 84 } 86 85 87 - protected override async Task OnInitializedAsync() 86 + protected override void OnInitialized() 88 87 { 89 - _module = await Js.InvokeAsync<IJSObjectReference>("import", 90 - "./Components/SelectDialog.razor.js"); 91 88 GlobalComponentSvc.SelectDialog = this; 92 89 } 93 90 }
-7
Iceshrimp.Frontend/Components/SelectDialog.razor.js
··· 1 - export function openDialog(element) { 2 - element.showModal() 3 - } 4 - 5 - export function closeDialog(element) { 6 - element.close() 7 - }
+4 -8
Iceshrimp.Frontend/Components/UpdateNotice.razor
··· 2 2 @using Iceshrimp.Frontend.Localization 3 3 @using Microsoft.Extensions.Localization 4 4 @inject UpdateService UpdateSvc; 5 - @inject IJSRuntime Js; 5 + @inject JsService Js; 6 6 @inject IStringLocalizer<Localization> Loc; 7 7 @inject NavigationManager Nav; 8 8 @implements IDisposable ··· 38 38 </dialog> 39 39 40 40 @code { 41 - private ElementReference Dialog { get; set; } 42 - private IJSObjectReference _module = null!; 43 - private StateButton UpdateButton { get; set; } = null!; 41 + private ElementReference Dialog { get; set; } 42 + private StateButton UpdateButton { get; set; } = null!; 44 43 45 44 private void OnUpdateStatusChange(object? _, UpdateService.UpdateStates newState) 46 45 { ··· 56 55 57 56 private void OpenDialog() 58 57 { 59 - var module = (IJSInProcessObjectReference)_module; 60 - module.InvokeVoid("openDialog", Dialog); 58 + Js.ShowDialogAsync(Dialog); 61 59 62 60 UpdateSvc.DialogOpen = true; 63 61 } 64 62 65 63 protected override async Task OnInitializedAsync() 66 64 { 67 - _module = await Js.InvokeAsync<IJSObjectReference>("import", 68 - "./Components/UpdateNotice.razor.js"); 69 65 UpdateSvc.UpdateStatusEvent += OnUpdateStatusChange; 70 66 await UpdateSvc.ServiceWorkerUpdateAsync(); 71 67 }
-7
Iceshrimp.Frontend/Components/UpdateNotice.razor.js
··· 1 - export function openDialog(element) { 2 - element.showModal() 3 - } 4 - 5 - export function closeDialog(element) { 6 - element.close() 7 - }
+5 -8
Iceshrimp.Frontend/Components/UserDialog.razor
··· 5 5 @using Microsoft.Extensions.Localization 6 6 @inject ApiService Api; 7 7 @inject GlobalComponentSvc GlobalComponentSvc; 8 - @inject IJSRuntime Js; 8 + @inject JsService Js; 9 9 @inject IStringLocalizer<Localization> Loc; 10 10 11 11 <dialog @onkeyup="HandleKeys" class="dialog" @ref="Dialog"> ··· 44 44 </dialog> 45 45 46 46 @code { 47 - private ElementReference Dialog { get; set; } 48 - private IJSObjectReference _module = null!; 47 + private ElementReference Dialog { get; set; } 49 48 private EventCallback<UserResponse?> Action { get; set; } 50 49 private string Text { get; set; } = ""; 51 50 private List<UserResponse> Users { get; set; } = []; ··· 59 58 60 59 private async Task CloseDialog() 61 60 { 62 - await _module.InvokeVoidAsync("closeDialog", Dialog); 61 + await Js.CloseDialogAsync(Dialog); 63 62 } 64 63 65 64 public async Task Select(EventCallback<UserResponse?> action, string text, string? buttonText = null) ··· 77 76 78 77 StateHasChanged(); 79 78 80 - await _module.InvokeVoidAsync("openDialog", Dialog); 79 + await Js.ShowDialogAsync(Dialog); 81 80 await Search(); 82 81 } 83 82 ··· 140 139 } 141 140 } 142 141 143 - protected override async Task OnInitializedAsync() 142 + protected override void OnInitialized() 144 143 { 145 - _module = await Js.InvokeAsync<IJSObjectReference>("import", 146 - "./Components/UserDialog.razor.js"); 147 144 GlobalComponentSvc.UserDialog = this; 148 145 } 149 146 }
-7
Iceshrimp.Frontend/Components/UserDialog.razor.js
··· 1 - export function openDialog(element) { 2 - element.showModal() 3 - } 4 - 5 - export function closeDialog(element) { 6 - element.close() 7 - }
+16
Iceshrimp.Frontend/Core/Services/JsService.cs
··· 1 + using Microsoft.AspNetCore.Components; 2 + using Microsoft.JSInterop; 3 + 4 + namespace Iceshrimp.Frontend.Core.Services; 5 + 6 + /// <summary> 7 + /// This service is used to wrap any calls to JS interop for functionality that is used in multiple places around the frontend (e.g. showing/closing a dialog) 8 + /// </summary> 9 + public class JsService 10 + { 11 + public IJSObjectReference? Module { private get; set; } 12 + 13 + public ValueTask ShowDialogAsync(ElementReference dialog) => Module!.InvokeVoidAsync("showDialog", dialog); 14 + 15 + public ValueTask CloseDialogAsync(ElementReference dialog, string? returnValue = null) => Module!.InvokeVoidAsync("closeDialog", dialog, returnValue); 16 + }
+4 -17
Iceshrimp.Frontend/Pages/Login.razor
··· 13 13 @inject NavigationManager Navigation 14 14 @inject IStringLocalizer<Localization> Loc; 15 15 @inject MetadataService Metadata; 16 - @inject IJSRuntime Js; 16 + @inject JsService Js; 17 17 @inject ILogger<Login> Logger; 18 18 @layout UnauthLayout 19 19 ··· 94 94 private ElementReference Dialog { get; set; } 95 95 private string? Otp { get; set; } 96 96 private StateButton OtpButton { get; set; } = null!; 97 - private readonly Lazy<Task<IJSObjectReference>> _moduleTask; 98 97 private Registrations Registration { get; set; } 99 98 100 - public Login() 101 - { 102 - _moduleTask = new Lazy<Task<IJSObjectReference>>(() => 103 - Js.InvokeAsync<IJSObjectReference>( 104 - "import", 105 - "./Pages/Settings/Account.razor.js") 106 - .AsTask()); 107 - } 108 - 109 99 private async Task Submit() 110 100 { 111 - var module = await _moduleTask.Value; 112 101 Loading = true; 113 102 try 114 103 { ··· 148 137 Loading = false; 149 138 break; 150 139 case AuthStatusEnum.TwoFactor: 151 - await module.InvokeVoidAsync("openDialog", Dialog); 140 + await Js.ShowDialogAsync(Dialog); 152 141 Api.SetBearerToken(res.Token!); 153 142 break; 154 143 } ··· 163 152 164 153 private async Task TwoFactorLogin() 165 154 { 166 - var module = await _moduleTask.Value; 167 155 if (Otp is null) 168 156 { 169 157 return; ··· 200 188 Failure = true; 201 189 Loading = false; 202 190 OtpButton.State = StateButton.StateEnum.Failed; 203 - await module.InvokeVoidAsync("closeDialog", Dialog); 191 + await Js.CloseDialogAsync(Dialog); 204 192 OtpButton.State = StateButton.StateEnum.Initial; 205 193 } 206 194 } ··· 228 216 229 217 private async Task CloseDialog(ElementReference dialog) 230 218 { 231 - var module = await _moduleTask.Value; 232 - await module.InvokeVoidAsync("closeDialog", dialog); 219 + await Js.CloseDialogAsync(Dialog); 233 220 } 234 221 }
-7
Iceshrimp.Frontend/Pages/Login.razor.js
··· 1 - export function openDialog(element) { 2 - element.show() 3 - } 4 - 5 - export function closeDialog(element) { 6 - element.close() 7 - }
+6 -21
Iceshrimp.Frontend/Pages/Settings/Account.razor
··· 15 15 @inject GlobalComponentSvc Global; 16 16 @inject ILogger<Profile> Logger; 17 17 @inject IStringLocalizer<Localization> Loc; 18 - @inject IJSRuntime Js; 18 + @inject JsService Js; 19 19 20 20 <HeadTitle Text="@Loc["Account settings"]"/> 21 21 ··· 177 177 private TwoFactorEnrollmentResponse? TwoFactorResponse { get; set; } 178 178 private string? OtpEnable { get; set; } 179 179 private string? OtpDisable { get; set; } 180 - private readonly Lazy<Task<IJSObjectReference>> _moduleTask; 181 - 182 - public Account() 183 - { 184 - _moduleTask = new Lazy<Task<IJSObjectReference>>(() => 185 - Js.InvokeAsync<IJSObjectReference>( 186 - "import", 187 - "./Pages/Settings/Account.razor.js") 188 - .AsTask()); 189 - } 190 180 191 181 protected override async Task OnInitializedAsync() 192 182 { ··· 245 235 246 236 private async Task Enroll2FA() 247 237 { 248 - var module = await _moduleTask.Value; 249 238 TwoFactorResponse = await Api.Settings.EnrollTwoFactorAsync(); 250 - await module.InvokeVoidAsync("openDialog", EnrollDialog); 239 + await Js.ShowDialogAsync(EnrollDialog); 251 240 } 252 241 253 242 private async Task Disable2FAMenu() 254 243 { 255 - var module = await _moduleTask.Value; 256 - await module.InvokeVoidAsync("openDialog", DisableDialog); 244 + await Js.ShowDialogAsync(DisableDialog); 257 245 } 258 246 259 247 private async Task Disable2FA() 260 248 { 261 - var module = await _moduleTask.Value; 262 249 if (OtpDisable is null) 263 250 { 264 251 return; ··· 273 260 StateHasChanged(); 274 261 await Task.Delay(1000); 275 262 SettingsForm = await Api.Settings.GetSettingsAsync(); 276 - await module.InvokeVoidAsync("closeDialog", DisableDialog); 263 + await Js.CloseDialogAsync(DisableDialog); 277 264 } 278 265 279 266 catch (ApiException e) ··· 285 272 286 273 private async Task Confirm2FA() 287 274 { 288 - var module = await _moduleTask.Value; 289 275 if (OtpEnable is null) 290 276 { 291 277 return; ··· 300 286 StateHasChanged(); 301 287 await Task.Delay(1000); 302 288 SettingsForm = await Api.Settings.GetSettingsAsync(); 303 - await module.InvokeVoidAsync("closeDialog", EnrollDialog); 289 + await Js.CloseDialogAsync(EnrollDialog); 304 290 } 305 291 306 292 catch (ApiException e) ··· 312 298 313 299 private async Task CloseDialog(ElementReference dialog) 314 300 { 315 - var module = await _moduleTask.Value; 316 - await module.InvokeVoidAsync("closeDialog", dialog); 301 + await Js.CloseDialogAsync(dialog); 317 302 } 318 303 }
-7
Iceshrimp.Frontend/Pages/Settings/Account.razor.js
··· 1 - export function openDialog(element) { 2 - element.show() 3 - } 4 - 5 - export function closeDialog(element) { 6 - element.close() 7 - }
+1
Iceshrimp.Frontend/Startup.cs
··· 24 24 builder.Services.AddSingleton<SessionService>(); 25 25 builder.Services.AddSingleton<StreamingService>(); 26 26 builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthStateProvider>(); 27 + builder.Services.AddSingleton<JsService>(); 27 28 builder.Services.AddSingleton<ComposeService>(); 28 29 builder.Services.AddSingleton<StateService>(); 29 30 builder.Services.AddSingleton<EmojiService>();
+16
Iceshrimp.Frontend/wwwroot/js-interop.js
··· 1 + /** 2 + * Displays a dialog 3 + * @param {HTMLDialogElement} dialog Element reference 4 + */ 5 + export function showDialog(dialog) { 6 + dialog.showModal(); 7 + } 8 + 9 + /** 10 + * Close a dialog 11 + * @param {HTMLDialogElement} dialog Element reference 12 + * @param {string?} returnValue Value to set for 13 + */ 14 + export function closeDialog(dialog, returnValue) { 15 + dialog.close(returnValue); 16 + }