Sectioned diff view: one sticky section per file with expandable context - #12
Open
devin-ai-integration[bot] wants to merge 1 commit into
Open
Sectioned diff view: one sticky section per file with expandable context#12devin-ai-integration[bot] wants to merge 1 commit into
devin-ai-integration[bot] wants to merge 1 commit into
Conversation
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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
Adds
DiffFilesViewController(UIKit/visionOS): a "Files Changed" screen that renders a multi-file patch as aUICollectionViewwith one section per file, the file header pinned while its hunks scroll (header.pinToVisibleBounds = true), and the gaps the patch omits rendered as tappable expander rows that pull in more of the original file, showing a spinner in the tapped arrow until the lines arrive.The existing parser already recognized files and hunks internally but flattened everything into one
[DiffRenderBlock.Row], which loses the file/hunk boundaries and old-file line ranges a sectioned view needs.DiffPatchDocumentre-derives that structure from the flattened block and owns all the expansion math; the UI layer is a thin renderer over it.Where the lines come from is the host's problem — the controller only asks:
Expanders are hidden until
contextProvideris set; the expander below the last hunk additionally needsfileLineCountProvider, since without the file's length there is no way to know whether more lines follow.Expansion modes fall out of the gap's shape (
DiffExpander.Direction):.upexpansionChunkSize(20).both— one arrow per end.downinsertContextsplices the fetched lines into the hunk the arrow grows (prepend for.up, append for.down) and then merges hunks that now touch, so filling a gap collapses two hunks into one:It trims lines the target hunk already covers before splicing, so an over-long or stale provider response can't duplicate rows.
Hunk cells reuse the existing
DiffViewwith block headers/rounding/border suppressed (the section header names the file) and are sized up front withDiffViewConfiguration.intrinsicHeight, avoiding a Core Text self-sizing pass per cell.Also adds a "Files Changed" screen to the Example app, driven by a generated stand-in repo so expanded context matches the diff, with a 600 ms delay in the provider to make the loading state visible.
Verification
The package only builds on Apple platforms, so the model layer (
DiffPatchDocument+UnifiedDiffparsing + the Example fixture's patch generation) was compiled and exercised on Linux in a scratch package with the same sources; those cases ship asTests/MarkdownViewTests/DiffPatchDocumentTests.swift(splitting, expander placement/direction, requested ranges, up/down/full-gap expansion, hunk merging, duplicate trimming). The UIKit layer and the Example app are unverified locally and rely on CI.Link to Devin session: https://app.devin.ai/sessions/02792c188b7b4e948c6262ed086f8e66
Requested by: @gtokman