diff options
| author | Jake Mannens <jake@asger.xyz> | 2026-03-17 03:04:36 +1100 |
|---|---|---|
| committer | Jake Mannens <jake@asger.xyz> | 2026-06-07 12:32:37 +1000 |
| commit | c51ff4e755f009ca0bc8e935a92c04e583c4ee8a (patch) | |
| tree | 0a9a311c5404a96495df1047e613dc3aea3d0f15 /Pages/Gallery.razor | |
Initial commit
Diffstat (limited to 'Pages/Gallery.razor')
| -rw-r--r-- | Pages/Gallery.razor | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/Pages/Gallery.razor b/Pages/Gallery.razor new file mode 100644 index 0000000..743485e --- /dev/null +++ b/Pages/Gallery.razor @@ -0,0 +1,141 @@ +@page "/" +@page "/Gallery" +@inject ITagService tagService +@inject IFeedService feedService +@inject IUserService userService +@inject IJSRuntime jsRuntime +@implements IDisposable +@attribute [Authorize] + +<PageTitle>@Title</PageTitle> + +@if(Ingest && !userService.UserSessionState.ShowNsfw) { + <div id="feed-error"> + <p><center>Ingest feed is not available unless NSFW mode is enabled!</center></p> + <p><center><i>You must enable NSFW mode to continue...</i></center></p> + </div> +} else if(TagId is not null && Query is not null) { + <div id="feed-error"> + <p><center>Invalid query parameters! Both a search query and</center></p> + <p><center>a tag ID have been specified!</center></p> + </div> +} else { + <div style="padding:var(--size-default-gap);"> + @foreach(var media in displayMedia) { + // Precalculate thumbnail size to help the browser + // lay out the images during initial page load + int width = (int) media.CurrentUploadedFile!.Width! * 200 / (int) media.CurrentUploadedFile.Height!; + <a href="/ViewMedia?m=@(media.Guid)"> + <img src="/media/thumb/@(media.Guid)?h=200" width=@width height="200"/> + </a> + } + <div id="canary" style="height:1px;"></div> + </div> +} + +<script suppress-error="BL9992"> + function registerScrollObserver(dotNetObject) { + var scrollObserver = new IntersectionObserver( + async (e) => { + if(e[0].isIntersecting) { + await dotNetObject.invokeMethodAsync('LoadMedia', false); + } + }, + { + root: document.getElementById('content'), + threshold: 0 + }); + scrollObserver.observe(document.getElementById("canary")); + } +</script> + +@code { + [Parameter] + [SupplyParameterFromQuery(Name = "t")] + public Guid? TagId { get; set; } + + [Parameter] + [SupplyParameterFromQuery(Name = "q")] + public string? Query { get; set; } + + [Parameter] + [SupplyParameterFromQuery(Name = "s")] + public string? SortOrder { get; set; } + + [Parameter] + [SupplyParameterFromQuery] + public bool Ingest { get; set; } = false; + + public const int PageSize = 50; + + private string Title { + get { + if(Query is null) + return Ingest ? "Ingest Feed" : "Gallery"; + else + return "Search Results"; + } + } + + private List<Media> displayMedia; + + protected override void OnInitialized() => + userService.UserSessionState.OnStateChange += ShowNsfwChanged; + + protected override void OnParametersSet() => LoadMedia(true); + + protected override void OnAfterRender(bool firstRender) { + if(firstRender) + jsRuntime.InvokeVoidAsync( + "registerScrollObserver", + DotNetObjectReference.Create(this)); + } + + [JSInvokable("LoadMedia")] + public void LoadMedia(bool initial = false) { + Media? key = displayMedia?.Any() ?? false && !initial ? displayMedia.Last() : null; + + if(initial) + displayMedia = new(); + + ApiModels.SortOrder? sortOrder = null; + if(Enum.TryParse<ApiModels.SortOrder>(SortOrder, true, out var so)) + sortOrder = so; + + if(TagId is not null && Query is null) { + displayMedia!.AddRange(feedService.LoadChunk( + selectIngest: Ingest, + includeNsfw: userService.UserSessionState.ShowNsfw, + tagId: (Guid) TagId!, + key: key, + count: PageSize, + sortOrder: sortOrder ?? default)); + } else if(Query is not null && TagId is null) { + displayMedia!.AddRange(feedService.LoadChunk( + selectIngest: Ingest, + includeNsfw: userService.UserSessionState.ShowNsfw, + query: string.IsNullOrWhiteSpace(Query) ? null : Query, + key: key, + count: PageSize, + sortOrder: sortOrder ?? default)); + } else { + displayMedia!.AddRange(feedService.LoadChunk( + selectIngest: Ingest, + includeNsfw: userService.UserSessionState.ShowNsfw, + key: key, + count: PageSize, + sortOrder: sortOrder ?? default)); + } + + StateHasChanged(); + } + + private async void ShowNsfwChanged(UserSessionState userSessionState) { + await InvokeAsync(() => { + LoadMedia(true); + }); + } + + public void Dispose() => + userService.UserSessionState.OnStateChange -= ShowNsfwChanged; +} |
