Render deck cover image + author avatar, @you, and cleanup - #18
Merged
Conversation
DeckDetailUiState.Content only carried coverEmoji, so a deck's actual cover image (Deck.coverImageRef) was never surfaced to the UI. Add coverImageUrl (remote/Unsplash) and coverImageBase64 (homeserver blob, fetched via MediaRepository and Base64-encoded for transport) to Content so native UIs can render the real cover, falling back to the emoji box. Blob fetching stays in the ViewModel (viewModelScope) per the shared-logic rule; remote URLs are carried synchronously. Inject MediaRepository into the VM and its Koin binding. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
DeckDetailView drew only an emoji box, so decks with a real cover image showed a letter/emoji placeholder. Render the cover in priority order: remote URL (AsyncImage) → homeserver blob (Base64 → UIImage) → the accent-soft emoji box. The emoji box now blank-guards coverEmoji and falls back to the title initial, then a book glyph. Owned decks now read "@you" in the author row (dropping the redundant pk:… subtitle), matching the decks-list convention. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
For a self-created deck the AuthorRow showed the full pubky plus a Follow button — you can't follow yourself. Add an isOwned flag: when owned, the row reads "@you", drops the pubky subtitle, and hides the Follow button, matching the iOS deck-detail author treatment. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CoverSection drew only the emoji box, so a deck's real cover image (saved on creation via coverImageRef) never showed. Render the cover from the shared ViewModel fields in priority order: remote URL → homeserver blob (Base64 bytes already loaded by the VM, decoded to a ByteArray) → the accent-soft emoji box. Coil's AsyncImage renders both a URL and a ByteArray, so no second fetch is needed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The deck-detail author row only had the pubky initial. Fetch the author's pubky.app profile (IdentityRepository.fetchProfile) and fold its avatar URL into Content.authorAvatarUrl so native UIs can render the real picture, falling back to the initial when absent. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
AuthorRow drew only the initial letter. Add an optional avatarUrl: when set, render the picture via Coil over the initial (which stays underneath as the placeholder/error fallback while the image loads or if it fails). DeckDetail passes the author's avatar from the shared state. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The deck's "last studied" date was never tracked — Deck.lastStudiedAt was always null (never read or written) and the OwnedBadgeRow showed a static "Last studied..." placeholder. Remove the dead field, the unused string resource, and the placeholder line, leaving just the "In your library" badge. Real last-studied tracking can be added later via SRS review state. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes deck-detail rendering across both platforms. The deck cover is an image (
Deck.coverImageRef— remote Unsplash URL or homeserver blob), but nothing rendered it: the presentation state only exposedcoverEmojiand both UIs drew an emoji box. This surfaces the cover image from the shared ViewModel and renders it natively, adds the author avatar, fixes the owned-author label, and removes an untracked placeholder.Changes
Shared (
DeckDetailViewModel)coverImageUrl(remote) +coverImageBase64(homeserver blob, fetched once inviewModelScopeviaMediaRepositoryand Base64-encoded) onContent.authorAvatarUrl.MediaRepositoryinto the VM + Koin binding.iOS (
DeckDetailView/DeckDetailScreen)AsyncImage→ blobUIImagefrom Base64 → accent-soft emoji box (blank-guarded to the title initial → 📚).Android (
DeckDetailScreen/AuthorRow)CoverSectionrenders the cover via Coil (URL or decodedByteArray), same fallback.AuthorRowgainedisOwned(→ "@you", no pubky line, no Follow button for your own deck) andavatarUrl(Coil avatar over the initial as graceful fallback).Cleanup
Deck.lastStudiedAtfield (always null, never read/written) and its unused string resource.Notes
http(s)URLs render via Coil; apubky://blob avatar would gracefully fall back to the initial — a possible follow-up.Verification
./gradlew :shared:compileKotlinMetadata :composeApp:compileDebugKotlin— compiles../gradlew detektAll— clean../gradlew lintSwift— 0 violations.🤖 Generated with Claude Code