[frontend/components] Fix JS interop being used before initialization on SingleNote Page

This commit is contained in:
Lilian 2025-02-25 16:56:36 +01:00
parent a8e3597811
commit 67a8819ad9
No known key found for this signature in database

View file

@ -21,7 +21,7 @@
@using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Sections @using Microsoft.AspNetCore.Components.Sections
@using Microsoft.Extensions.Localization @using Microsoft.Extensions.Localization
@implements IDisposable @implements IAsyncDisposable
@if (_componentState == State.Loaded) @if (_componentState == State.Loaded)
{ {
@ -138,7 +138,9 @@
{ {
<HeadTitle Text="@Loc["Loading"]"/> <HeadTitle Text="@Loc["Loading"]"/>
<div class="loading"><LoadingSpinner Scale="2" /></div> <div class="loading">
<LoadingSpinner Scale="2"/>
</div>
} }
@if (_componentState == State.NotFound) @if (_componentState == State.NotFound)
{ {
@ -165,6 +167,7 @@
private SortedList<string, NoteResponse>? Descendants { get; set; } private SortedList<string, NoteResponse>? Descendants { get; set; }
private SortedList<string, NoteResponse>? Ascendants { get; set; } private SortedList<string, NoteResponse>? Ascendants { get; set; }
private IJSInProcessObjectReference? Module { get; set; } private IJSInProcessObjectReference? Module { get; set; }
private readonly Lazy<Task<IJSObjectReference>> _moduleTask;
private ElementReference RootNoteRef { get; set; } private ElementReference RootNoteRef { get; set; }
private int _depth = 20; private int _depth = 20;
private IDisposable? _locationChangingHandlerDisposable; private IDisposable? _locationChangingHandlerDisposable;
@ -175,6 +178,8 @@
private async Task Load() private async Task Load()
{ {
Logger.LogTrace($"Opening NoteID: {NoteId}"); Logger.LogTrace($"Opening NoteID: {NoteId}");
Module = (IJSInProcessObjectReference?)await _moduleTask.Value;
Logger.LogInformation("Loaded Module");
_componentState = State.Loading; _componentState = State.Loading;
if (NoteId == null) if (NoteId == null)
{ {
@ -261,20 +266,22 @@
} }
// ReSharper disable once InconsistentNaming // ReSharper disable once InconsistentNaming
private ValueTask LocationChangeHandler(LocationChangingContext arg) private async ValueTask LocationChangeHandler(LocationChangingContext arg)
{ {
SaveState(); await SaveState();
return ValueTask.CompletedTask;
} }
protected override async Task OnAfterRenderAsync(bool firstRender) public SingleNote()
{ {
if (firstRender) _moduleTask = new Lazy<Task<IJSObjectReference>>(() =>
{ Js.InvokeAsync<IJSObjectReference>(
Module = (IJSInProcessObjectReference)await Js.InvokeAsync "import",
<IJSObjectReference>("import", "/Pages/SingleNote.razor.js"); "./Pages/SingleNote.razor.js")
} .AsTask());
}
protected override void OnAfterRender(bool firstRender)
{
if (_componentState == State.Loaded) if (_componentState == State.Loaded)
{ {
var state = StateSvc.SingleNote.GetState(NoteId!); var state = StateSvc.SingleNote.GetState(NoteId!);
@ -332,19 +339,18 @@
} }
} }
private void SaveState() private async Task SaveState()
{ {
if (NoteId == null || _componentState != State.Loaded) return; if (NoteId == null || _componentState != State.Loaded) return;
var scrollTop = (Module ?? throw new Exception("JS Interop used before init")) var module = await _moduleTask.Value;
.Invoke var scrollTop = await module.InvokeAsync<float>("GetScrollY");
<float>("GetScrollY"); var state = new SingleNoteState { ScrollTop = scrollTop };
var state = new SingleNoteState { ScrollTop = scrollTop };
StateSvc.SingleNote.SetState(NoteId, state); StateSvc.SingleNote.SetState(NoteId, state);
} }
public void Dispose() public async ValueTask DisposeAsync()
{ {
SaveState(); await SaveState();
_locationChangingHandlerDisposable?.Dispose(); _locationChangingHandlerDisposable?.Dispose();
StateSynchronizer.NoteDeleted -= OnNoteDeleted; StateSynchronizer.NoteDeleted -= OnNoteDeleted;
NoteStore.AnyNoteChanged -= OnNoteChanged; NoteStore.AnyNoteChanged -= OnNoteChanged;