Iceshrimp.NET/Iceshrimp.Frontend/Components/LazyNote.razor

73 lines
No EOL
2.7 KiB
Text

@using Iceshrimp.Shared.Schemas
@using Ljbc1994.Blazor.IntersectionObserver
@using Ljbc1994.Blazor.IntersectionObserver.API
@using Ljbc1994.Blazor.IntersectionObserver.Components
@inject IJSRuntime Js
@if(_init) // FIXME: We need to wait for the Component to render once before initializing the Intersection Observer.
// With the <IntersectionObserver> Component this is AFAIK only possible by not rendering it until then.
// The proper fix for this is to change to the Service Pattern.
// But that requires the IntersectionObserver Library to be modified to return what element an observation update is for.
{
<IntersectionObserve Options="new IntersectionObserverOptions(){ Root = Scroller, RootMargin = margin}" OnChange="@(entry => Change(entry))">
<div class="tgt" @ref="context.Ref.Current">
@if (_isIntersecting)
{
<TimelineNote Note="Note" />
}else {
<div class="placeholder" style="height: @(Height ?? 150)px"></div>
}
</div>
</IntersectionObserve>
}
@code {
[Parameter][EditorRequired] public required NoteResponse Note { get; set; }
[Parameter][EditorRequired] public ElementReference Scroller { get; set; }
private IJSObjectReference? _module;
private int? Height { get; set; } = null;
private bool _isIntersecting = true;
private string margin = "200%";
private bool _init = false;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
_module = await Js.InvokeAsync<IJSObjectReference>("import",
"./Components/LazyNote.razor.js");
}
}
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
_init = true;
}
}
private async Task Change (IntersectionObserverEntry entry)
{
if (entry.IsIntersecting == false)
{
Height = await GetHeight();
_isIntersecting = false;
StateHasChanged();
return;
}
if (entry.IsIntersecting)
{
_isIntersecting = true;
}
}
private async Task<int?> GetHeight()
{
var height = await (_module ?? throw new Exception("Call to JS module was made before it was loaded, this should not have happened"))
.InvokeAsync<int?>("getScrollHeight", Note.Id);
return height;
}
}