- Add AlbumIds parallel list to AssetPreviewDto
- Populate AlbumIds in AssetsMapper
- Home tile hover: album names link to /albums/{id} with onclick:stopPropagation
- ImagePreview ChildContent: album names link to /albums/{id}
- CSS: tile-info-album and preview-info-album support <a> tags with hover underline
- Create ImagePreview.razor component with self-contained url generation, keyboard handling, and download
- Add Filename to AssetPreviewDto and AlbumAssetPreviewDto DTOs
- Update AssetsMapper and AlbumMapper to populate FileName
- Remove duplicate preview overlay HTML/CSS/code from Home.razor and AlbumDetail.razor
- Fix AssetDto.FileName hiding inherited member from AssetPreviewDto
- Add CoverAssetId FK and CoverAsset navigation to Album model
- Add AlbumAssetPreviewDto with resolution/thumbnail info
- Extend AlbumPreviewDto/FullDto with PersonName, CoverAssetId, AssetCount
- Add CoverAssetId to AlbumCreateDto and AlbumUpdateDto
- Update AlbumMapper to populate new fields from eager-loaded relations
- Add EF migration for CoverAssetId column
- Add AlbumNames and CosplayerNames fields to AssetPreviewDto
- Include Albums and PersonOwner in AssetRepository.GetAssets() query
- Populate new fields in AssetsMapper.ToAssetPreviewDto()
UsersMapper.ToGetUsersDto() was not copying LastLogin, BannedAt, or
UpdatedAt from the User entity to the UserInfoDto, causing the client
to always receive null for these fields. Added the missing mappings.
Also added null fallback ('Never') for LastLogin display on the User
page to prevent NullReferenceException when the value has not been set.
- Add PreviewJob (WebP) — same master/sub-job pattern as ThumbnailJob
- Convert ThumbnailJob from JPEG to WebP with configurable quality
- Add ThumbnailQuality/PreviewQuality settings (configurable in settings UI)
- Add PreviewSize, ThumbnailFormat, PreviewFormat fields to Asset model
- Add format-aware repo queries for auto-regeneration of stale JPEGs
- Fix MIME types in MediaRepository/MediaController to return image/webp
- Wire PreviewJob into JobScheduler, JobMapper, JobsController
- Expose quality settings on Settings page (Jobs group, range sliders)
- Add 'Make Previews' button on Jobs page, reorder to scan/metadata/thumb/preview/phash/integrity
Achieves 100% XML doc coverage on non-trivial types with CS1591
enforcement via Directory.Build.props.
Coverage by project:
- Butter: from 6.5% to 100% (DTOs, enums, MIME types)
- Lactose: from ~28% to 100% (controllers, services, repos, jobs, models)
- MilkStream.Client: from ~29% to 100% (all frontend services)
Uses <inheritdoc /> on repository implementations (interfaces
already documented) and full <summary>/<param>/<returns> tags
elsewhere. Enums include member-level docs.
- Split /api/jobs into three endpoints: active roots, paginated past,
children fetched on expand — reduces response from ~1MB to ~5KB
- Persist completed jobs to PostgreSQL via JobRecord entity + migration
- Add configurable job retention cleanup (hourly timer, default 30 days)
- Fix PHashJob master not persisting (missing Complete() call)
- Add PastJobsResponse DTO to fix case-sensitive JsonElement deserialization
- Refactor JobTree/JobRow for lazy-loaded children via FetchChildren callback
- Handle 401 responses in JwtTokenRefresher with token refresh + retry
- Remove JobChildrenSummary component (replaced by inline parent summary)
feat(db): extended amount of settings informations stored on the database
feat(frontend): added support for updating the refreshToken after a refresh request.
feat(backend): added a defaultSettings.json file that defines how the settings are initialized.