Skip to content

Commit 9f21071

Browse files
move sheet into customization
1 parent ecb6037 commit 9f21071

File tree

2 files changed

+662
-0
lines changed

2 files changed

+662
-0
lines changed
Lines changed: 386 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,386 @@
1+
//
2+
// CustomizationPlayground.swift
3+
// GitDiffExample
4+
//
5+
// Created by Tornike Gomareli on 18.06.25.
6+
//
7+
8+
import SwiftUI
9+
import gitdiff
10+
11+
struct CustomizationPlayground: View {
12+
@State private var showLineNumbers = true
13+
@State private var fontSize: CGFloat = 13
14+
@State private var lineSpacing: DiffConfiguration.LineSpacing = .compact
15+
@State private var wordWrap = true
16+
@State private var fontWeight: Font.Weight = .regular
17+
@State private var selectedTheme: DiffTheme = .light
18+
@State private var showCustomizationSheet = false
19+
20+
var body: some View {
21+
NavigationView {
22+
ScrollView {
23+
VStack(alignment: .leading, spacing: 16) {
24+
Text("Live Preview")
25+
.font(.title2.bold())
26+
.padding(.horizontal)
27+
.padding(.top)
28+
29+
DiffRenderer(diffText: SampleDiffs.configPlaygroundDiff)
30+
.diffTheme(selectedTheme)
31+
.diffLineNumbers(showLineNumbers)
32+
.diffFont(size: fontSize, weight: fontWeight)
33+
.diffLineSpacing(lineSpacing)
34+
.diffWordWrap(wordWrap)
35+
.padding()
36+
.background(Color.white)
37+
.cornerRadius(12)
38+
.shadow(color: .black.opacity(0.05), radius: 5)
39+
.padding(.horizontal)
40+
41+
ConfigurationSummary(
42+
theme: themeName,
43+
fontSize: fontSize,
44+
fontWeight: fontWeight,
45+
lineNumbers: showLineNumbers,
46+
wordWrap: wordWrap,
47+
lineSpacing: lineSpacing
48+
)
49+
.padding()
50+
}
51+
}
52+
.navigationTitle("Customization Playground")
53+
.navigationBarTitleDisplayMode(.inline)
54+
.toolbar {
55+
ToolbarItem(placement: .navigationBarTrailing) {
56+
Button(action: { showCustomizationSheet = true }) {
57+
Label("Customize", systemImage: "slider.horizontal.3")
58+
}
59+
}
60+
}
61+
.sheet(isPresented: $showCustomizationSheet) {
62+
CustomizationSheet(
63+
showLineNumbers: $showLineNumbers,
64+
fontSize: $fontSize,
65+
lineSpacing: $lineSpacing,
66+
wordWrap: $wordWrap,
67+
fontWeight: $fontWeight,
68+
selectedTheme: $selectedTheme
69+
)
70+
}
71+
}
72+
}
73+
74+
private var themeName: String {
75+
switch selectedTheme {
76+
case .light: return "Light"
77+
case .dark: return "Dark"
78+
case .gitlab: return "GitLab"
79+
default: return "Custom"
80+
}
81+
}
82+
}
83+
84+
struct CustomizationSheet: View {
85+
@Binding var showLineNumbers: Bool
86+
@Binding var fontSize: CGFloat
87+
@Binding var lineSpacing: DiffConfiguration.LineSpacing
88+
@Binding var wordWrap: Bool
89+
@Binding var fontWeight: Font.Weight
90+
@Binding var selectedTheme: DiffTheme
91+
92+
@Environment(\.dismiss) var dismiss
93+
@State private var showSavedConfigs = false
94+
95+
var body: some View {
96+
NavigationView {
97+
ScrollView {
98+
VStack(alignment: .leading, spacing: 20) {
99+
VStack(alignment: .leading, spacing: 12) {
100+
Label("Theme", systemImage: "paintbrush.fill")
101+
.font(.headline)
102+
103+
Picker("Theme", selection: $selectedTheme) {
104+
Text("Light").tag(DiffTheme.light)
105+
Text("Dark").tag(DiffTheme.dark)
106+
Text("GitLab").tag(DiffTheme.gitlab)
107+
}
108+
.pickerStyle(.segmented)
109+
}
110+
111+
Divider()
112+
113+
VStack(alignment: .leading, spacing: 12) {
114+
Label("Font Settings", systemImage: "textformat")
115+
.font(.headline)
116+
117+
VStack(alignment: .leading, spacing: 8) {
118+
HStack {
119+
Text("Size")
120+
Spacer()
121+
Text("\(Int(fontSize))pt")
122+
.font(.caption)
123+
.foregroundColor(.secondary)
124+
}
125+
126+
Slider(value: $fontSize, in: 10...20, step: 1)
127+
.accentColor(.blue)
128+
}
129+
130+
VStack(alignment: .leading, spacing: 8) {
131+
Text("Weight")
132+
133+
Picker("Weight", selection: $fontWeight) {
134+
Text("Regular").tag(Font.Weight.regular)
135+
Text("Medium").tag(Font.Weight.medium)
136+
Text("Semibold").tag(Font.Weight.semibold)
137+
Text("Bold").tag(Font.Weight.bold)
138+
}
139+
.pickerStyle(.segmented)
140+
}
141+
}
142+
143+
Divider()
144+
145+
VStack(alignment: .leading, spacing: 12) {
146+
Label("Layout", systemImage: "square.grid.3x3")
147+
.font(.headline)
148+
149+
Toggle("Show Line Numbers", isOn: $showLineNumbers)
150+
151+
Toggle("Word Wrap", isOn: $wordWrap)
152+
153+
VStack(alignment: .leading, spacing: 8) {
154+
Text("Line Spacing")
155+
156+
Picker("Spacing", selection: $lineSpacing) {
157+
Text("Compact").tag(DiffConfiguration.LineSpacing.compact)
158+
Text("Comfortable").tag(DiffConfiguration.LineSpacing.comfortable)
159+
Text("Spacious").tag(DiffConfiguration.LineSpacing.spacious)
160+
}
161+
.pickerStyle(.segmented)
162+
}
163+
}
164+
165+
Divider()
166+
167+
VStack(alignment: .leading, spacing: 12) {
168+
Label("Presets", systemImage: "star.fill")
169+
.font(.headline)
170+
171+
VStack(spacing: 8) {
172+
PresetButton(title: "Default", icon: "house") {
173+
applyPreset(.default)
174+
}
175+
176+
PresetButton(title: "Code Review", icon: "eye") {
177+
applyPreset(.codeReview)
178+
}
179+
180+
PresetButton(title: "Mobile", icon: "iphone") {
181+
applyPreset(.mobile)
182+
}
183+
184+
PresetButton(title: "Presentation", icon: "tv") {
185+
applyPreset(.presentation)
186+
}
187+
}
188+
}
189+
190+
Divider()
191+
192+
VStack(spacing: 12) {
193+
Button(action: resetToDefaults) {
194+
Label("Reset to Defaults", systemImage: "arrow.counterclockwise")
195+
.frame(maxWidth: .infinity)
196+
}
197+
.buttonStyle(.bordered)
198+
199+
Button(action: { showSavedConfigs = true }) {
200+
Label("Save Configuration", systemImage: "square.and.arrow.down")
201+
.frame(maxWidth: .infinity)
202+
}
203+
.buttonStyle(.borderedProminent)
204+
}
205+
}
206+
.padding()
207+
}
208+
.navigationTitle("Customize Diff View")
209+
.navigationBarTitleDisplayMode(.inline)
210+
.toolbar {
211+
ToolbarItem(placement: .navigationBarTrailing) {
212+
Button("Done") {
213+
dismiss()
214+
}
215+
}
216+
}
217+
.sheet(isPresented: $showSavedConfigs) {
218+
SavedConfigurationsView()
219+
}
220+
}
221+
}
222+
223+
private func applyPreset(_ config: DiffConfiguration) {
224+
withAnimation {
225+
selectedTheme = config.theme
226+
showLineNumbers = config.showLineNumbers
227+
fontSize = config.fontSize
228+
fontWeight = config.fontWeight
229+
lineSpacing = config.lineSpacing
230+
wordWrap = config.wordWrap
231+
}
232+
}
233+
234+
private func resetToDefaults() {
235+
withAnimation {
236+
showLineNumbers = true
237+
fontSize = 13
238+
lineSpacing = .compact
239+
wordWrap = true
240+
fontWeight = .regular
241+
selectedTheme = .light
242+
}
243+
}
244+
}
245+
246+
struct PresetButton: View {
247+
let title: String
248+
let icon: String
249+
let action: () -> Void
250+
251+
var body: some View {
252+
Button(action: action) {
253+
HStack {
254+
Image(systemName: icon)
255+
Text(title)
256+
Spacer()
257+
Image(systemName: "chevron.right")
258+
.font(.caption)
259+
.foregroundColor(.secondary)
260+
}
261+
.padding()
262+
.background(Color(.systemBackground))
263+
.cornerRadius(8)
264+
}
265+
.buttonStyle(PlainButtonStyle())
266+
}
267+
}
268+
269+
struct ConfigurationSummary: View {
270+
let theme: String
271+
let fontSize: CGFloat
272+
let fontWeight: Font.Weight
273+
let lineNumbers: Bool
274+
let wordWrap: Bool
275+
let lineSpacing: DiffConfiguration.LineSpacing
276+
277+
var body: some View {
278+
VStack(alignment: .leading, spacing: 12) {
279+
Text("Current Configuration")
280+
.font(.headline)
281+
282+
LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible())], spacing: 12) {
283+
ConfigItem(label: "Theme", value: theme)
284+
ConfigItem(label: "Font Size", value: "\(Int(fontSize))pt")
285+
ConfigItem(label: "Font Weight", value: fontWeightName)
286+
ConfigItem(label: "Line Numbers", value: lineNumbers ? "On" : "Off")
287+
ConfigItem(label: "Word Wrap", value: wordWrap ? "On" : "Off")
288+
ConfigItem(label: "Line Spacing", value: lineSpacingName)
289+
}
290+
}
291+
.padding()
292+
.background(Color(.secondarySystemBackground))
293+
.cornerRadius(12)
294+
}
295+
296+
private var fontWeightName: String {
297+
switch fontWeight {
298+
case .regular: return "Regular"
299+
case .medium: return "Medium"
300+
case .semibold: return "Semibold"
301+
case .bold: return "Bold"
302+
default: return "Regular"
303+
}
304+
}
305+
306+
private var lineSpacingName: String {
307+
switch lineSpacing {
308+
case .compact: return "Compact"
309+
case .comfortable: return "Comfortable"
310+
case .spacious: return "Spacious"
311+
}
312+
}
313+
}
314+
315+
struct ConfigItem: View {
316+
let label: String
317+
let value: String
318+
319+
var body: some View {
320+
VStack(alignment: .leading, spacing: 4) {
321+
Text(label)
322+
.font(.caption)
323+
.foregroundColor(.secondary)
324+
Text(value)
325+
.font(.footnote.bold())
326+
}
327+
.frame(maxWidth: .infinity, alignment: .leading)
328+
}
329+
}
330+
331+
struct SavedConfigurationsView: View {
332+
@Environment(\.dismiss) var dismiss
333+
334+
var body: some View {
335+
NavigationView {
336+
VStack {
337+
Text("Saved Configurations")
338+
.font(.largeTitle)
339+
Text("Coming Soon")
340+
.foregroundColor(.secondary)
341+
}
342+
.navigationBarTitleDisplayMode(.inline)
343+
.toolbar {
344+
ToolbarItem(placement: .navigationBarTrailing) {
345+
Button("Done") { dismiss() }
346+
}
347+
}
348+
}
349+
}
350+
}
351+
352+
extension DiffConfiguration {
353+
static let codeReview = DiffConfiguration(
354+
theme: .light,
355+
showLineNumbers: true,
356+
fontFamily: .monospaced, fontSize: 12,
357+
fontWeight: .regular,
358+
lineSpacing: .comfortable,
359+
wordWrap: false,
360+
contentPadding: EdgeInsets(top: 8, leading: 12, bottom: 8, trailing: 12)
361+
)
362+
363+
static let mobile = DiffConfiguration(
364+
theme: .light,
365+
showLineNumbers: false,
366+
fontFamily: .monospaced, fontSize: 11,
367+
fontWeight: .regular,
368+
lineSpacing: .compact,
369+
wordWrap: true,
370+
contentPadding: EdgeInsets(top: 4, leading: 8, bottom: 4, trailing: 8)
371+
)
372+
373+
static let presentation = DiffConfiguration(
374+
theme: .dark,
375+
showLineNumbers: true,
376+
fontFamily: .monospaced, fontSize: 16,
377+
fontWeight: .semibold,
378+
lineSpacing: .spacious,
379+
wordWrap: true,
380+
contentPadding: EdgeInsets(top: 12, leading: 16, bottom: 12, trailing: 16)
381+
)
382+
}
383+
384+
#Preview {
385+
CustomizationPlayground()
386+
}

0 commit comments

Comments
 (0)