Skip to content

Add Other PRs: monitor any PR by URL#5

Open
SeanMcTex wants to merge 14 commits intomainfrom
feature/pin-any-pr
Open

Add Other PRs: monitor any PR by URL#5
SeanMcTex wants to merge 14 commits intomainfrom
feature/pin-any-pr

Conversation

@SeanMcTex
Copy link
Owner

Summary

  • Adds an Other PRs section (between Awaiting My Review and My PRs) for monitoring teammates' pull requests
  • New Add PR… command in the footer Commands menu accepts any GitHub or GHE PR URL
  • Pinned PRs persist across restarts via UserDefaults and are deduplicated from authored/reviewing lists
  • Hover over any Other PR to reveal a red trash icon; clicking shows an NSAlert confirmation before removal

Details

  • PinnedPRsService: JSON-encoded persistence of PR identifiers
  • GitHubService: URL parser (https://<host>/<owner>/<repo>/pull/<number>) + fetchPinnedPR for arbitrary PR access
  • PRMonitorViewModel: concurrent pinned fetch alongside main search, addPinnedPR(urlString:) / removePinnedPR(_:)
  • PinPRView: URL entry panel with auto-focus, Return-to-submit, inline error display
  • Fixed section header identity bug in LazyVStack (stable IDs prevent SwiftUI view recycling when sections appear/disappear)

Test plan

  • Add a teammate's PR by URL — confirm it appears in Other PRs with correct build status
  • Restart the app — confirm pinned PRs persist
  • Add a PR you authored — confirm it appears only in Other PRs, not in My PRs (dedup)
  • Hover over an Other PR — confirm red trash icon appears; confirm NSAlert fires; confirm removal works
  • Try an invalid URL — confirm error message appears in the Add PR dialog
  • Try adding a PR already in Other PRs — confirm "already in Other PRs" error
  • Run unit tests: URL parsing and PinnedPRsService

Adds a "Pin a PR..." command to the footer menu that accepts any GitHub
PR URL, fetches it, and displays it in a new Pinned section (between
Awaiting My Review and My PRs). Pinned PRs persist across restarts via
UserDefaults and are deduplicated from the authored/reviewing lists.

- PinnedPRsService: JSON-encoded persistence of PinnedPRIdentifier list
- GitHubService: URL parser + fetchPinnedPR for arbitrary PR access
- PRMonitorViewModel: concurrent pinned fetch, add/remove, dedup
- MenuBarView: Commands menu (Pin/Settings/Updates), Pinned section
- PRRowView: pin.slash unpin button on hover for pinned PRs
- PinPRView: URL entry panel with auto-focus, Return-to-submit
- Tests: URL parsing and PinnedPRsService unit tests
Completes the rename started in the previous commit: PinnedPRsService →
OtherPRsService, PinPRView → AddPRView, .pinned → .other, addPinnedPR →
addOtherPR, removePinnedPR → removeOtherPR, fetchPinnedPR → fetchOtherPR,
and all related local variables and comments. UserDefaults key "pinnedPRs"
preserved for backward compatibility.
Prevent adding a PR via URL if it's already in the authored or reviewing
list (case-insensitive repo name comparison). Dismiss the menu before
showing the remove confirmation alert.
…move

- Filter Other PRs by selected repository (via filteredOtherPRs computed property)
- Namespace PRRowView IDs by section to prevent cross-section state bleed
- Reset selected repository to All Repositories when the last Other PR
  from the selected repo is removed
- Fix section height calculation to use filteredOtherPRs count
Tests cover: addOtherPR throwing invalidURL and alreadyTracked (including
case-insensitive repo matching), filteredOtherPRs respecting the selected
repository filter, and removeOtherPR resetting the repo selection when the
last PR for that repo is removed (and not resetting when others remain).
…t isolation

Tests now create per-test UserDefaults suites via makeIsolatedServices(),
eliminating save/restore boilerplate and preventing contamination of
production watchlist and pinned PR data.
Users can set a local alias for any PR via a pencil button that appears
on hover. Custom names survive polls (GitHub title is re-fetched but the
override is re-applied from UserDefaults). Clearing the name restores the
GitHub title. Stale entries are pruned after each successful refresh and
immediately when a pinned PR is removed.

Action buttons are now arranged in a compact 2×2 grid (Watch/Open on top,
Delete/Rename on bottom) with fixed 16pt cells and vertical centering, saving
horizontal space compared to the previous flat HStack.
Default parameter expressions are evaluated in a nonisolated context even
when the init is @mainactor, causing warnings with SWIFT_DEFAULT_ACTOR_ISOLATION
= MainActor. Move service instantiation into the init body using nil-coalescing
so defaults are evaluated in the correct @mainactor context.
Add displayTitle(count:) to PRType so 'Other PRs' becomes 'Other PR'
and 'My PRs' becomes 'My PR' when there is exactly one. 'Awaiting My
Review' opts out of pluralization as it reads correctly either way.
sectionHeader in MenuBarView now takes PRType instead of a raw string.
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