Skip to content

feat: projects list - #17

Merged
sjungwon03 merged 1 commit into
devfrom
feat/projects-list
Aug 18, 2026
Merged

sjungwon03 merged 1 commit into
devfrom
feat/projects-list

Conversation

@sjungwon03

Copy link
Copy Markdown
Member

Summary

The second M1 slice: the signed-in account's projects, reachable from home.

  • Project model (freezed)
  • GET /projects?membership=true ordered by last activity, page cursor from X-Next-Page
  • ProjectsRepository + Riverpod controller, and an authed GitLabClient provider that rebuilds
    per account
  • ProjectTile in the design system
  • Projects screen with loading / error / empty / data states and pull-to-refresh
  • Home "My Work" entry that opens the list
  • Localized into en, ko, ja, hi, zh

Closes #16

Three bugs caught test-first

  1. A 401 surfaced as a connection error. The endpoint typed its GET as List, so an error
    body (GitLab returns an object) failed the cast before the status could be read. Now the status
    is checked before the cast. Test covers the 401 → GitLabAuthException.
  2. The tile dropped the project name from its path. It was passed project.namespace
    (youthpick) rather than the full path_with_namespace (youthpick/backend), which is the
    identifier. A widget test pins the full path.
  3. Loading state under the test clock. Future.delayed schedules a timer the fake clock flags
    as pending and the state resolved to error; a never-completing Completer holds AsyncLoading
    cleanly. (Test-infra, but worth recording.)

Validation

  • dart format --set-exit-if-changed . — clean
  • flutter analyze --fatal-infos — No issues found!
  • flutter test — 60 passing across five packages
  • Language gate — passes with the four translations present

Checklist

  • Targets dev
  • Linked issue with Closes #
  • Conventional Commits
  • Signed off (DCO)
  • Wrote the test first — the three items above were caught that way
  • Updated documentation where behavior changed — n/a beyond code
  • Checked Mobile (<600) and Desktop (>1000) — the list is width-agnostic; ProjectTile has tile tests
  • Checked Light and Dark — uses theme colors and tokens only
  • New dependencies license-checked — none added
  • No tokens, hostnames, or confidential data
  • English (translations excepted)

Notes for reviewers

  • The authed client provider (gitLabClientProvider) rebuilds when the account changes and closes
    the old client on dispose, so an in-flight request can't end up authenticated as a previous
    account.
  • Default list only (membership, recent-first). Starred/owned/member filters and search are later
    slices. Caching (Drift) lands with the offline work; the repository is a thin pass-through for now.
  • Empty (zero projects) and error are deliberately different states, tested separately.

The second M1 slice: the signed-in account's projects, the entry point to the
rest of the milestone.

- Project model (freezed): id, name, path_with_namespace, description, stars,
  visibility, last activity; unknown fields ignored, omitted fields nullable
- projects endpoint: GET /projects?membership=true ordered by last activity,
  page cursor read from X-Next-Page, never an assumed count
- ProjectsRepository + Riverpod controller, plus an authed GitLabClient provider
  that rebuilds per account so a request can't run as a previous account
- ProjectTile in the design system, taking plain values not a model
- Projects screen with loading / error / empty / data states and pull-to-refresh
- Home gains a My Work entry that opens the list
- Localized into all five locales

TDD caught three things before any manual run:

- The endpoint typed its GET as List, so an error body (GitLab returns an object)
  failed the cast before the status could be read, turning a 401 into a spurious
  connection error. Fixed by checking status before casting. Test covers the 401.
- The tile was passed only the namespace, dropping the project name from the
  path shown under the title. The identifier is the full path_with_namespace;
  a widget test pins it.
- A never-completing Completer, not Future.delayed, is what holds a controller
  in AsyncLoading under the test clock without a pending-timer failure.

Closes #16

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: sjungwon03 <sjungwon03@gmail.com>
@github-actions github-actions Bot added area:api packages/gitlab_api — GitLab REST/GraphQL client area:ui Screens and feature UI area:design-system packages/design_system area:security Tokens, auth, secure storage, TLS feat New feature labels Aug 18, 2026

@sjungwon03-ai sjungwon03-ai left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Clean second M1 slice. All three bugs are genuinely covered test-first: the 401 fix reads status before the List cast (get), verified by a 401→GitLabAuthException test with an object error body; the tile now carries pathWithNamespace, pinned by both a tile test and a screen test asserting 'youthpick/backend'; and the loading-state test uses a never-completing Completer to hold AsyncLoading without a pending timer. The authed client provider rebuilds per account and closes the old client onDispose, so an in-flight request can't authenticate as a previous account. Pagination reads cursors from headers with nullable totals, empty and error are distinct tested states, and ProjectTile stays model-free. CI is green at head (format, analyze, 60 tests, codegen). LGTM.

@sjungwon03
sjungwon03 merged commit d5d06ef into dev Aug 18, 2026
5 checks passed
@sjungwon03
sjungwon03 deleted the feat/projects-list branch August 18, 2026 07:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:api packages/gitlab_api — GitLab REST/GraphQL client area:design-system packages/design_system area:security Tokens, auth, secure storage, TLS area:ui Screens and feature UI feat New feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: projects list

2 participants