Skip to content

Add Poll/Question support#162

Merged
malkoG merged 16 commits into
hackers-pub:mainfrom
malkoG:poll-question-support
Jul 18, 2026
Merged

Add Poll/Question support#162
malkoG merged 16 commits into
hackers-pub:mainfrom
malkoG:poll-question-support

Conversation

@malkoG

@malkoG malkoG commented Jul 18, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds full Poll/Question support to the Android app, matching the server's GraphQL poll API — rendering, voting, authoring, and poll-ended notifications.

What's included

  • Schema & operations — refreshed the GraphQL schema snapshot, added a PollFields fragment on Poll, and wired poll data into PostFields/SharedPostFields.
  • Rendering — polls display in feeds and post detail with proportional result bars, percentages, voted markers, voter/mode/status footer, and a live countdown to ends.
  • VotingvoteOnPoll mutation wired through every feed (timeline, explore, bookmarks, search, profile) and post detail; the poll view self-updates from the server response.
  • Authoring — a dedicated full-screen poll editor opened from the compose toolbar (title, add/remove options, duration, single/multiple choice), returning to the composer with a compact chip that floats over the text area. Backed by createQuestion.
  • Notifications — poll-ended notifications render in the notifications screen and in system notifications.

Checks

  • ./gradlew :app:lintDebug passes.
  • No new !! in production code.

malkoG added 16 commits July 18, 2026 15:08
Re-introspect the server schema, which now exposes Poll.closed/viewerHasVoted, PollOption.index/viewerHasVoted, and the voteOnPoll and createQuestion mutations. Remove the local markNotificationsAsRead extension now that the server provides it natively (with an optional upTo argument).
Add a PollFields fragment and select it via ... on Question { poll } in both PostFields and SharedPostFields so poll state travels with every post query.
Add Poll and PollOption domain classes, a nullable Post.poll field, and a PollFields.toPoll() mapper wired into both PostFields.toPost and SharedPostFields.toPost.
Add a PollView composable showing each option with a proportional result bar, percentage, voted marker, total voters, choice mode, and a live open/closed status. Render it for Question posts in NoteCard and the post detail screen.
Add a VoteOnPoll operation returning the updated Question and a repository voteOnPoll(questionId, optionIndices) that maps the payload back to a Post, branching on the result union.
Let PollView select options and submit a vote, replacing its displayed state with the server response. Thread an onVotePoll callback through PostCard/NoteCard and wire it in the post detail screen and personal timeline; add voteOnPoll to PostDetailViewModel and TimelineViewModel.
Add voteOnPoll to the explore, bookmarks, search, and profile view models and pass onVotePoll into their PostCard usages so polls are votable everywhere they render, not only in the timeline and detail screens.
Add a CreateQuestion operation and a repository createQuestion(...) that builds CreateQuestionPollInput (title, options, multiple, ISO-8601 ends) and maps the payload to a Post, branching on the result union.
Add poll-draft state (title, 2-20 options, multiple-choice, duration) to ComposeViewModel with validation, and branch post() to createQuestion when a poll is attached. Add a poll toggle to the composer toolbar and a PollComposerSection for editing the poll.
Always show the remove-option button but disable it when only two options remain, and move the multiple-choice toggle to the bottom-left of the poll editor as a plain inline switch.
Give the multiple-choice toggle its own full-width row with spacing so it no longer overlaps the duration control, keep the duration dropdown, and make the media/poll/quoted section scroll vertically so poll fields stay reachable while the keyboard is open.
Fetch PollEndedNotification in the notifications query, map it to a Notification.PollEnded domain type, and render it in the notifications list and push notification text with a poll icon and "<actor>'s poll ended" copy.
Add a chevron in the poll editor header that collapses the fields to just the header (poll icon, label, chevron, remove), keeping the poll attached. Animate the size change so the compose area stays compact.
When the poll editor is collapsed, hide the inline form and show a small floating action button in the compose area to reopen it; when expanded, render the full editor as before. Lift the expanded state to ComposeScreen so the collapsed state can render the FAB overlay.
Replace the inline poll editor (and its collapse chevron/floating button) with a full-screen poll editor opened from the compose toolbar. The editor has a back/Save top bar (Save enabled only when the poll is valid) and, once saved, the note shows a compact poll summary chip that reopens the editor or removes the poll. Poll draft state stays in ComposeViewModel, so the editor swaps in without extra navigation plumbing.
@malkoG
malkoG merged commit 197b6cc into hackers-pub:main Jul 18, 2026
1 of 2 checks passed
@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: eb335c5d-25d6-4c40-9a07-b3f74f3022bb

📥 Commits

Reviewing files that changed from the base of the PR and between fc06e3c and b69968a.

📒 Files selected for processing (24)
  • app/src/main/graphql/pub/hackers/android/extensions.graphqls
  • app/src/main/graphql/pub/hackers/android/operations.graphql
  • app/src/main/graphql/pub/hackers/android/schema.graphqls
  • app/src/main/java/pub/hackers/android/data/repository/HackersPubRepository.kt
  • app/src/main/java/pub/hackers/android/data/worker/NotificationWorker.kt
  • app/src/main/java/pub/hackers/android/domain/model/Models.kt
  • app/src/main/java/pub/hackers/android/ui/components/PollView.kt
  • app/src/main/java/pub/hackers/android/ui/components/PostCard.kt
  • app/src/main/java/pub/hackers/android/ui/screens/bookmarks/BookmarksScreen.kt
  • app/src/main/java/pub/hackers/android/ui/screens/bookmarks/BookmarksViewModel.kt
  • app/src/main/java/pub/hackers/android/ui/screens/compose/ComposeScreen.kt
  • app/src/main/java/pub/hackers/android/ui/screens/compose/ComposeViewModel.kt
  • app/src/main/java/pub/hackers/android/ui/screens/explore/ExploreScreen.kt
  • app/src/main/java/pub/hackers/android/ui/screens/explore/ExploreViewModel.kt
  • app/src/main/java/pub/hackers/android/ui/screens/notifications/NotificationsScreen.kt
  • app/src/main/java/pub/hackers/android/ui/screens/postdetail/PostDetailScreen.kt
  • app/src/main/java/pub/hackers/android/ui/screens/postdetail/PostDetailViewModel.kt
  • app/src/main/java/pub/hackers/android/ui/screens/profile/ProfileScreen.kt
  • app/src/main/java/pub/hackers/android/ui/screens/profile/ProfileViewModel.kt
  • app/src/main/java/pub/hackers/android/ui/screens/search/SearchScreen.kt
  • app/src/main/java/pub/hackers/android/ui/screens/search/SearchViewModel.kt
  • app/src/main/java/pub/hackers/android/ui/screens/timeline/TimelineScreen.kt
  • app/src/main/java/pub/hackers/android/ui/screens/timeline/TimelineViewModel.kt
  • app/src/main/res/values/strings.xml

📝 Walkthrough

Walkthrough

The Android client adds poll creation, voting, rendering, and poll-ended notifications. GraphQL operations and schema types support poll data, while repository mappings, ViewModels, Compose screens, post cards, notifications, and localized strings carry the feature through the application.

Changes

Poll support

Layer / File(s) Summary
GraphQL contracts and data mapping
app/src/main/graphql/pub/hackers/android/operations.graphql, app/src/main/graphql/pub/hackers/android/schema.graphqls, app/src/main/java/pub/hackers/android/data/repository/HackersPubRepository.kt, app/src/main/java/pub/hackers/android/domain/model/Models.kt
Poll fragments, question creation and voting mutations, poll domain models, repository APIs, and poll-ended notification mapping are added.
Poll composer workflow
app/src/main/java/pub/hackers/android/ui/screens/compose/*
The composer adds poll draft state, validation, editing controls, duration selection, and question-post submission.
Poll display and voting
app/src/main/java/pub/hackers/android/ui/components/PollView.kt, app/src/main/java/pub/hackers/android/ui/components/PostCard.kt, app/src/main/java/pub/hackers/android/ui/screens/{bookmarks,explore,postdetail,profile,search,timeline}/*
Poll results and voting controls are rendered in post cards and detail views, with vote callbacks wired through the relevant ViewModels.
Poll-ended notifications
app/src/main/java/pub/hackers/android/data/worker/NotificationWorker.kt, app/src/main/java/pub/hackers/android/ui/screens/notifications/NotificationsScreen.kt, app/src/main/res/values/strings.xml
Poll-ended notification text, icons, pluralization, post navigation, and poll UI strings are added.

GraphQL schema expansion

Layer / File(s) Summary
Account, organization, and actor contracts
app/src/main/graphql/pub/hackers/android/schema.graphqls
Account, organization membership, invitations, actor relationships, suspension, deletion, and authentication schema surfaces are expanded.
Moderation and content contracts
app/src/main/graphql/pub/hackers/android/schema.graphqls
Moderation, reporting, post, article, search, publishing, news-score, and query schema definitions are added or reshaped.
Platform operation contracts
app/src/main/graphql/pub/hackers/android/schema.graphqls
Upload, push-target, relay, translation, sharing, notification, and account-update definitions are added or updated.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant ComposeScreen
  participant ComposeViewModel
  participant HackersPubRepository
  participant GraphQLAPI
  User->>ComposeScreen: Configure poll
  ComposeScreen->>ComposeViewModel: Save poll draft
  User->>ComposeScreen: Publish question
  ComposeScreen->>ComposeViewModel: post()
  ComposeViewModel->>HackersPubRepository: createQuestion(poll)
  HackersPubRepository->>GraphQLAPI: CreateQuestion
  GraphQLAPI-->>HackersPubRepository: Created question with poll
  HackersPubRepository-->>ComposeViewModel: Result<Post>
  ComposeViewModel-->>ComposeScreen: Published state
  User->>ComposeScreen: Select poll options
  ComposeScreen->>HackersPubRepository: voteOnPoll(questionId, optionIndices)
  HackersPubRepository->>GraphQLAPI: VoteOnPoll
  GraphQLAPI-->>HackersPubRepository: Updated question with poll
  HackersPubRepository-->>ComposeScreen: Result<Poll>
Loading

Possibly related PRs

  • hackers-pub/android#157: Both changes update shared post UI and compose/ViewModel plumbing, although this PR adds poll support while that PR adds note editing.

Suggested reviewers: dalinaum


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant