Skip to content

DISC-138: VideoFeed ViewModel#2505

Open
Arkariang wants to merge 28 commits intomasterfrom
imartin/DISC-138
Open

DISC-138: VideoFeed ViewModel#2505
Arkariang wants to merge 28 commits intomasterfrom
imartin/DISC-138

Conversation

@Arkariang
Copy link
Copy Markdown
Contributor

@Arkariang Arkariang commented Apr 29, 2026

📲 What

Implements the Video Feed query and navigation interactions. This includes a scrollable vertical video powered by a real GraphQL query adding pagination, bookmark/watch toggling with optimistic UI and animation interaction and login gated, project navigation for back this project button, and a Compose-native error snackbar.

🤔 Why

This PR focuses on core interactions — watching/unwatching projects, navigating to project pages, and paginating through the feed — while deferring share(follow up ticket) and more-options actions to a future phase.

🛠 How

GraphQL

  • Added VideoFeed query in project.graphql with cursor-based pagination and badge support.
  • Extracted a videoFeedProject fragment in fragments.graphql to encapsulate the minimal project fields needed for the feed (including isWatched, watchesCount, sharesCount, and verticalVideo for HLS playback).

ViewModel (VideoFeedViewModel)

  • Replaced the hardcoded demo project list with a real paginated getVideoFeed Apollo call.
  • Added cursor tracking (nextPage, hasMore)
  • bookmarkProject(project, index) emits an optimistic state immediately on tap (icon flips without waiting for the network), then reverts on API failure.
  • Exposed isUserLoggedIn state to gate bookmark actions behind authentication.
  • provideErrorAction now wired inside the Compose setContent block via setUpVideoFeedErrorActions.

UI (VideoFeedScreen / VideoFeedActivity)

  • VideoFeedScreen now accepts VideoFeedItem list (badges + project + HLS URL) instead of raw Project list.
  • onLoadMore triggers when the current page is within 3 items of the end (items.size - 3 threshold).
  • SnackbarHost placed as the last child in the root Box so it renders above the pager.
  • VideoFeedActivity uses registerForActivityResult to re-execute a pending bookmark after a successful login redirect.
  • Project tap routes to startProjectActivity or startPreLaunchProjectActivity depending on prelaunch state; profile tap routes to startCreatorBioWebViewActivity.

Bookmark animation (KSVideoActionsColumn)

  • Animation fires instantly on tap and assumes optimistic state emission, will revert back in case of network failure.
  • More-options button hidden for Phase 1 via alpha(0f) + enabled = false (preserves layout space).

Data / Transformers

  • VideoFeedTransformers.kt maps VideoFeedQuery.VideoFeed → VideoFeedEnvelope, decodes relay IDs, maps badges, maps isWatched → isStarred, reads HLS URL from verticalVideo.
  • Added IntExt.toCompactFormat() for compact number display (e.g. 1200 → "1.2k").

Tests

  • VideoFeedViewModelTest: pagination, optimistic bookmark update, revert on failure, login-gate.
  • VideoFeedTransformersTest: all badge types, field mapping, null handling, isWatched → isStarred.
  • VideoFeedScreenTest: load-more threshold, snackbar, bookmark index, empty state. Uses hasAnyAncestor scoping to handle beyondViewportPageCount = 1 pre-composing neighbor pages.
  • KSVideoActionsColumnTest: bookmark content description for both states

👀 See

| --- | --- |
| | |

📋 QA

  • Scroll through the pager — confirm new items load automatically near the end of the list. ⚠️ cannot be tested just yet on staging not enough projects, will carry to QA ticket.
  • Tap the bookmark icon on a project you have not bookmarked — confirm the icon fills immediately, count increments.
  • Tap again to unbookmark — confirm it reverts immediately.
  • Log out and tap bookmark — confirm the login screen appears. After logging in, confirm the bookmark is applied.
  • After bookmarking, leave the screen or kill the app and come back to VideoFeed, confirm the filled bookmark icon appears on first render without any tap.
  • Tap the project card button — confirm navigation to the correct project page (or pre-launch page for pre-launch projects).
  • Tap the creator avatar — confirm navigation to the creator bio web view.
  • Simulate a network error during bookmark (e.g. airplane mode) — confirm the snackbar appears

Story 📖

DISC-138

@Arkariang Arkariang changed the title Imartin/disc 138 DISC-138: VideoFeed ViewModel Apr 29, 2026
@Arkariang Arkariang self-assigned this Apr 29, 2026
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Apr 29, 2026

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 80.23256% with 34 lines in your changes missing coverage. Please review.
✅ Project coverage is 64.37%. Comparing base (6ad3937) to head (1028b01).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
...features/videofeed/viewmodel/VideoFeedViewModel.kt 60.78% 6 Missing and 14 partials ⚠️
...s/transformers/extensions/VideoFeedTransformers.kt 78.43% 0 Missing and 11 partials ⚠️
...pp/src/main/java/com/kickstarter/models/Project.kt 71.42% 0 Missing and 2 partials ⚠️
...es/videofeed/ui/components/KSVideoActionsColumn.kt 95.23% 0 Missing and 1 partial ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Additional details and impacted files
@@             Coverage Diff              @@
##             master    #2505      +/-   ##
============================================
+ Coverage     64.18%   64.37%   +0.18%     
- Complexity     2438     2443       +5     
============================================
  Files           392      393       +1     
  Lines         30077    30220     +143     
  Branches       4355     4395      +40     
============================================
+ Hits          19306    19455     +149     
+ Misses         8432     8398      -34     
- Partials       2339     2367      +28     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Arkariang Arkariang marked this pull request as ready for review April 29, 2026 20:52
@Arkariang Arkariang requested a review from tonyteate April 29, 2026 20:53
data class VideoFeedItem(
val badges: List<KSVideoBadgeType>,
val project: Project,
val hlsUrl: String?
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can potentially add a new VerticalVideo class within Project model, and remove this parameter from the VideoFeedItem, but alas this level of abstraction seems correct to me to stop making Project objects so bloated

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants