No longer loads the person's full album/asset graph into memory; uses ID-first
paging, ILike search against the trgm GIN index, and DB-level counts. Slims
Find() to a PK lookup for write paths.
- Extract PathFromGuid to shared PathUtils.cs (PreviewJob + ThumbnailJob)
- Consolidate RegexHighlighter duplicate methods via delegation
- Fix default port 3306 -> 5432 in appsettings.json + docker-compose.yml
- Remove port gotcha section from AGENTS.md
- Fix ITagRepository XML docs after parameter rename (id -> tag)
- Remove 16 unused using System; imports from migration files (implicit usings available)
- Fix 6 empty catch blocks with proper exception logging
- Remove unused import (false positive flagged as wontfix)
- Skip test coverage, orphaned, and stale exclude issues as false positives
- Add missing namespace to IPersonRepository.cs
- Rename IFolderRepository Create/Delete to Insert/Remove for CRUD consistency
- Fix ITagRepository.Delete parameter name from 'id' to 'tag'
- Add missing IDisposable to IMediaRepository
- Rename SettingsExtensions to SettingsExtension for naming consistency
- Rename PagedParametersDTO.cs to PagedParametersDto.cs
- Add .desloppify/ to .gitignore
Inject git describe output into the assembly's InformationalVersion at build
time via an MSBuild target (local dev) or Docker build arg (CI/Docker).
Local builds use v1.0.2-21-g9e67c59-dirty; Docker builds take
APP_VERSION as a build arg to avoid MSBuild property collision with VERSION.
Co-authored-by: opencode <opencode@anomaly.co>
- Remove IntersectionObserver, sentinel elements, and scroll reattach
from albumObserver and cosplayerObserver
- Add wheel, keydown, and touch event listeners that react only to
explicit user input commands (scroll down/up, arrow keys, swipe)
- Check page position (isAtBottom/isAtTop) before invoking load
- No observer to get stuck, no cascade from auto-scroll/load completion
- Replace per-frame scroll reattach with 300ms debounced scroll-end
reattach to prevent cascade during fast/momentum scrolling
- Add overflow-anchor: none to grid containers and sentinels to
prevent browsers from auto-scrolling when content is added below
- Add PageBuffer<T> utility class (capped at 10 pages, drops oldest) to keep
DOM and memory bounded during infinite scroll
- Refactor AlbumGrid and CosplayerGrid to use PageBuffer instead of unbounded
List/Dictionary, add top sentinel for bi-directional scroll-back loading
- Add observeTop and scroll-based sentinel reattach to albumObserver and
cosplayerObserver in masonryObserver.js — prevents IntersectionObserver
getting stuck when sentinel stays visible after load by re-evaluating on
each scroll frame
Root cause: ViewMode="ViewMode" (no @ prefix) was interpreted as string
literal "ViewMode" by Blazor, not property value "masonry". GetCardStyle()
never produced aspect-ratio, so off-screen lazy-loaded images had 0 height
and _doApply stacked them 8px apart in one column.
Fixes:
- AlbumGrid.razor: ViewMode="ViewMode" -> ViewMode="@ViewMode"
- AlbumCard.razor: GetCardStyle() always returns aspect-ratio for masonry
- AlbumGrid.razor.css / AlbumDetail.razor.css: CSS aspect-ratio fallback
- masonryObserver.js: MutationObserver-based setup/teardown replaces
OnAfterRenderAsync-based apply, eliminating layout-timing races
- AlbumGrid.razor / AlbumDetail.razor: one-time setup with _masonrySetup guard
ProgressBar segments now use the same --status-* CSS custom properties as the status dots, ensuring visual consistency. ProgressBar applies CSS variable colors via inline background-color style.
Add AlbumTotalCount [NotMapped] to Person model, set before pagination in FindVisible, read in PersonMapper instead of paginated Albums.Count. Also apply inline aspect-ratio only in masonry mode so grid mode uses CSS aspect-ratio: 1 for square crops.
Added overflow-y: scroll to html element to always reserve scrollbar
space. When content grows beyond viewport, the scrollbar appearance
would reduce container width by ~17px, causing CSS column masonry to
recalculate and shift items leftward. Fixes#146.
QueueFileSystemCrawl() relied on the 'folders' field which is only
populated when FolderScanEnabled is true. Now falls back to fetching
active folders from the DB when the cached list is empty. Fixes#151.
Adds GET /api/auth/register endpoint to check registration status.
Register page now pre-checks on load and shows EmptyState instead of
the form when registration is disabled. Fixes#149.
LoginService.Register() now returns HttpStatusCode instead of bool,
so the frontend can distinguish between 403 (registration disabled),
409 (duplicate), and other failures. Fixes#149.
Frontend was requesting page 1 as the first page, but the backend
uses zero-based pagination (page 0 = first). The past jobs tab never
loaded any results. Fixes#145.
Removed the explicit AddJsonFile calls in Program.cs — WebApplication.CreateBuilder
already adds them internally, but in the wrong order (after env vars). This caused
DatabaseAddress__Host env var from docker-compose to be silently overridden by
appsettings.json defaults, resulting in connection to 127.0.0.1:3306 instead of
database:5432.
Also updated docker-compose.yml to set DatabaseAddress__Host and DatabaseAddress__Port
explicitly, and default ASPNETCORE_ENVIRONMENT to Production.
AuthController.Register() never checked the UserRegistrationEnabled
server setting, allowing anyone to register even when disabled.
- Inject ISettingsRepository into AuthController
- Return 403 Forbidden at top of Register() if setting is not 'true'
- Add setup test #3.5 to enable registration for the main test flow
Closes#141