Skip to content

Make showFileHeaders flag functional with diffFileHeaders(_:) modifier#7

Open
paololeonardi wants to merge 2 commits intotornikegomareli:mainfrom
paololeonardi:showfileheaders
Open

Make showFileHeaders flag functional with diffFileHeaders(_:) modifier#7
paololeonardi wants to merge 2 commits intotornikegomareli:mainfrom
paololeonardi:showfileheaders

Conversation

@paololeonardi
Copy link
Copy Markdown

@paololeonardi paololeonardi commented Apr 24, 2026

@tornikegomareli great project, thanks for open sourcing it!

Summary

The showFileHeaders flag in DiffConfiguration existed but was never consulted — file headers were always rendered. This PR makes it work, exposes it as a first-class view modifier, and documents it.

Changes

  • DiffFileView: conditionally render the file header based on configuration.showFileHeaders
  • DiffEnvironment: add public diffFileHeaders(_:) view modifier, matching the ergonomics of diffLineNumbers(_:)
  • DiffConfigurationBuilder: add withFileHeaders(_:) builder method for consistency with the rest of the builder API
  • README: add .diffFileHeaders(_:) to the modifiers list and showFileHeaders to the configuration object example
  • Example app: surface a toggle in both CustomizationPlayground and ExamplesView

Testing

Verified manually via the example app — toggling the control in both the Customization Playground and Examples view shows/hides file headers as expected.

Before After
Simulator Screenshot - iPhone 17 Pro - 2026-04-24 at 23 36 54 Simulator Screenshot - iPhone 17 Pro - 2026-04-24 at 23 36 27

Summary by CodeRabbit

  • New Features

    • Added "File Headers" toggle to show or hide file header lines in diffs
    • New .diffFileHeaders() view modifier for controlling header visibility in the configuration chain
    • File headers visibility now configurable via customization UI and presets
  • Documentation

    • Updated README with examples demonstrating the new file headers configuration option

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 24, 2026

📝 Walkthrough

Walkthrough

A new showFileHeaders configuration option (default: true) is introduced to control file header visibility in the diff renderer. The feature is integrated via builder methods, view modifiers, UI toggles, and conditional rendering logic across playground, examples, and core renderer components.

Changes

Cohort / File(s) Summary
Configuration & Builders
Sources/gitdiff/DiffConfigurationBuilder.swift, Sources/gitdiff/DiffEnvironment.swift
New public builder method withFileHeaders(_:) and view modifier diffFileHeaders(_:) added to DiffConfiguration for controlling file header visibility via configuration chain.
UI Integration
GitDiffExample/GitDiffExample/CustomizationPlayground.swift, GitDiffExample/GitDiffExample/ExamplesView.swift
Added showFileHeaders state variable, "File Headers" toggle UI control, and configuration pipeline threading through diffFileHeaders(showFileHeaders) modifier. Configuration summary extended to display header visibility state.
Rendering
Sources/gitdiff/Views/DiffFileView.swift
File header HStack (icon, file name, binary indicator) and its styling now rendered conditionally based on configuration.showFileHeaders.
Documentation
README.md
Updated examples and "View Modifiers" section to document DiffConfiguration.showFileHeaders property and .diffFileHeaders(_:) modifier.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A toggle so neat, a feature divine,
File headers fade when the switch does decline,
Through builders and modifiers, clean as can be,
Threading true and false for all eyes to see!
With diffs now flexible, the UI takes flight,
Configuration-driven, everything right!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly describes the main objective of the PR: making the showFileHeaders flag functional and exposing it via the diffFileHeaders(_:) modifier.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
GitDiffExample/GitDiffExample/CustomizationPlayground.swift (1)

242-251: Avoid hardcoded reset values for new config fields.

Using DiffConfiguration.default here prevents drift if defaults evolve.

♻️ Suggested reset update
 private func resetToDefaults() {
   withAnimation {
-    showLineNumbers = true
-    showFileHeaders = true
-    fontSize = 13
-    lineSpacing = .compact
-    wordWrap = true
-    fontWeight = .regular
-    selectedTheme = .light
+    let defaults = DiffConfiguration.default
+    showLineNumbers = defaults.showLineNumbers
+    showFileHeaders = defaults.showFileHeaders
+    fontSize = defaults.fontSize
+    lineSpacing = defaults.lineSpacing
+    wordWrap = defaults.wordWrap
+    fontWeight = defaults.fontWeight
+    selectedTheme = defaults.theme
   }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@GitDiffExample/GitDiffExample/CustomizationPlayground.swift` around lines 242
- 251, The resetToDefaults() function currently hardcodes each config value;
instead fetch the canonical defaults from DiffConfiguration.default and apply
them so new fields won't be missed—e.g., inside withAnimation let defaults =
DiffConfiguration.default and then assign showLineNumbers =
defaults.showLineNumbers, showFileHeaders = defaults.showFileHeaders, fontSize =
defaults.fontSize, lineSpacing = defaults.lineSpacing, wordWrap =
defaults.wordWrap, fontWeight = defaults.fontWeight, selectedTheme =
defaults.selectedTheme (or replace the whole config object if this type supports
assignment), ensuring any newly added DiffConfiguration fields are automatically
picked up.
Sources/gitdiff/DiffEnvironment.swift (1)

64-82: Use the builder to avoid config-field drift in diffFileHeaders(_:).

This works, but rebuilding the entire config here duplicates state-copy logic and can silently miss new fields later. Reuse the builder for single-point maintenance.

♻️ Suggested simplification
 func diffFileHeaders(_ show: Bool) -> some View {
     transformEnvironment(\.diffConfiguration) { config in
-        config = DiffConfiguration(
-            theme: config.theme,
-            showLineNumbers: config.showLineNumbers,
-            showFileHeaders: show,
-            fontFamily: config.fontFamily,
-            fontSize: config.fontSize,
-            fontWeight: config.fontWeight,
-            lineHeight: config.lineHeight,
-            lineSpacing: config.lineSpacing,
-            wordWrap: config.wordWrap,
-            contentPadding: config.contentPadding
-        )
+        config = config.withFileHeaders(show)
     }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/gitdiff/DiffEnvironment.swift` around lines 64 - 82, The
diffFileHeaders(_:) function is rebuilding a full DiffConfiguration which risks
drifting when fields are added; instead use the existing DiffConfiguration's
builder/with-style API to modify only showFileHeaders. In the
transformEnvironment(\.diffConfiguration) closure, call the configuration's
builder/with method (e.g., config.with(showFileHeaders: show) or
config.builder().setShowFileHeaders(show).build()) to produce the new config so
all other fields are preserved via the config's own update helper rather than
reconstructing DiffConfiguration manually.
GitDiffExample/GitDiffExample/ExamplesView.swift (1)

242-249: Consider a responsive layout for the two toggles + action button row.

With larger text sizes, this single HStack can get crowded. A VStack/ViewThatFits split would improve resilience.

♿️ Possible responsive layout
-        HStack {
-          Toggle("Line Numbers", isOn: $showLineNumbers)
-          Toggle("File Headers", isOn: $showFileHeaders)
-          Spacer()
-          Button(action: shareExample) {
-            Image(systemName: "square.and.arrow.up")
-          }
-        }
+        ViewThatFits(in: .horizontal) {
+          HStack {
+            Toggle("Line Numbers", isOn: $showLineNumbers)
+            Toggle("File Headers", isOn: $showFileHeaders)
+            Spacer()
+            Button(action: shareExample) {
+              Image(systemName: "square.and.arrow.up")
+            }
+          }
+          VStack(alignment: .leading, spacing: 8) {
+            Toggle("Line Numbers", isOn: $showLineNumbers)
+            Toggle("File Headers", isOn: $showFileHeaders)
+            HStack {
+              Spacer()
+              Button(action: shareExample) {
+                Image(systemName: "square.and.arrow.up")
+              }
+            }
+          }
+        }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@GitDiffExample/GitDiffExample/ExamplesView.swift` around lines 242 - 249, The
current HStack containing the two Toggles (showLineNumbers, showFileHeaders) and
the shareExample Button can overflow at large accessibility text sizes; refactor
this row to use a responsive container such as ViewThatFits or a conditional
VStack/HStack so the toggles stack vertically when space is constrained. Locate
the HStack block that wraps Toggle("Line Numbers", isOn: $showLineNumbers),
Toggle("File Headers", isOn: $showFileHeaders) and Button(action: shareExample)
and replace it with a ViewThatFits (or use
GeometryReader/Environment(\.sizeCategory) to switch to a VStack) so the layout
automatically switches to a vertical arrangement for larger text sizes while
preserving the same controls and actions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@GitDiffExample/GitDiffExample/CustomizationPlayground.swift`:
- Around line 242-251: The resetToDefaults() function currently hardcodes each
config value; instead fetch the canonical defaults from
DiffConfiguration.default and apply them so new fields won't be missed—e.g.,
inside withAnimation let defaults = DiffConfiguration.default and then assign
showLineNumbers = defaults.showLineNumbers, showFileHeaders =
defaults.showFileHeaders, fontSize = defaults.fontSize, lineSpacing =
defaults.lineSpacing, wordWrap = defaults.wordWrap, fontWeight =
defaults.fontWeight, selectedTheme = defaults.selectedTheme (or replace the
whole config object if this type supports assignment), ensuring any newly added
DiffConfiguration fields are automatically picked up.

In `@GitDiffExample/GitDiffExample/ExamplesView.swift`:
- Around line 242-249: The current HStack containing the two Toggles
(showLineNumbers, showFileHeaders) and the shareExample Button can overflow at
large accessibility text sizes; refactor this row to use a responsive container
such as ViewThatFits or a conditional VStack/HStack so the toggles stack
vertically when space is constrained. Locate the HStack block that wraps
Toggle("Line Numbers", isOn: $showLineNumbers), Toggle("File Headers", isOn:
$showFileHeaders) and Button(action: shareExample) and replace it with a
ViewThatFits (or use GeometryReader/Environment(\.sizeCategory) to switch to a
VStack) so the layout automatically switches to a vertical arrangement for
larger text sizes while preserving the same controls and actions.

In `@Sources/gitdiff/DiffEnvironment.swift`:
- Around line 64-82: The diffFileHeaders(_:) function is rebuilding a full
DiffConfiguration which risks drifting when fields are added; instead use the
existing DiffConfiguration's builder/with-style API to modify only
showFileHeaders. In the transformEnvironment(\.diffConfiguration) closure, call
the configuration's builder/with method (e.g., config.with(showFileHeaders:
show) or config.builder().setShowFileHeaders(show).build()) to produce the new
config so all other fields are preserved via the config's own update helper
rather than reconstructing DiffConfiguration manually.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 24d61140-d091-426a-a1cf-de8ec657ca72

📥 Commits

Reviewing files that changed from the base of the PR and between d773f17 and de02bc7.

📒 Files selected for processing (6)
  • GitDiffExample/GitDiffExample/CustomizationPlayground.swift
  • GitDiffExample/GitDiffExample/ExamplesView.swift
  • README.md
  • Sources/gitdiff/DiffConfigurationBuilder.swift
  • Sources/gitdiff/DiffEnvironment.swift
  • Sources/gitdiff/Views/DiffFileView.swift

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