Skip to content

Commit 4987cd3

Browse files
committed
Merge branch 'feature/custom-scroll-view' into develop
2 parents de01a8d + bde63ac commit 4987cd3

10 files changed

Lines changed: 301 additions & 155 deletions

File tree

Copilot for Xcode.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Copilot for Xcode/DebugView.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ final class DebugSettings: ObservableObject {
99
var preCacheOnFileOpen: Bool
1010
@AppStorage(\.runNodeWithInteractiveLoggedInShell)
1111
var runNodeWithInteractiveLoggedInShell: Bool
12+
@AppStorage(\.useCustomScrollViewWorkaround) var useCustomScrollViewWorkaround
1213
init() {}
1314
}
1415

@@ -30,6 +31,10 @@ struct DebugSettingsView: View {
3031
Text("Run node with interactive logged-in bash")
3132
}
3233
.toggleStyle(.switch)
34+
Toggle(isOn: $settings.useCustomScrollViewWorkaround) {
35+
Text("Use custom scroll view workaround for smooth scrolling")
36+
}
37+
.toggleStyle(.switch)
3338
}
3439
}.buttonStyle(.copilot)
3540
}

Core/Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ let package = Package(
3737
.package(url: "https://github.com/raspu/Highlightr", from: "2.1.0"),
3838
.package(url: "https://github.com/JohnSundell/Splash", branch: "master"),
3939
.package(url: "https://github.com/nmdias/FeedKit", from: "9.1.2"),
40-
.package(url: "https://github.com/intitni/swift-markdown-ui", branch: "main"),
40+
.package(url: "https://github.com/gonzalezreal/swift-markdown-ui", from: "2.1.0"),
4141
.package(url: "https://github.com/sparkle-project/Sparkle", from: "2.0.0"),
4242
],
4343
targets: [

Core/Sources/Preferences/Keys.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ public struct UserDefaultPreferenceKeys {
174174
public var preCacheOnFileOpen: FeatureFlags.PreCacheOnFileOpen { .init() }
175175
public var runNodeWithInteractiveLoggedInShell: FeatureFlags
176176
.RunNodeWithInteractiveLoggedInShell { .init() }
177+
public var useCustomScrollViewWorkaround: FeatureFlags.UseCustomScrollViewWorkaround { .init() }
177178
}
178179

179180
public enum FeatureFlags {
@@ -191,4 +192,9 @@ public enum FeatureFlags {
191192
public let defaultValue = true
192193
public let key = "FeatureFlag-RunNodeWithInteractiveLoggedInShell"
193194
}
195+
196+
public struct UseCustomScrollViewWorkaround: UserDefaultPreferenceKey {
197+
public let defaultValue = true
198+
public let key = "FeatureFlag-UseCustomScrollViewWorkaround"
199+
}
194200
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import AppKit
2+
import SwiftUI
3+
4+
struct CopyButton: View {
5+
var copy: () -> Void
6+
@State var isCopied = false
7+
var body: some View {
8+
Button(action: {
9+
withAnimation(.linear(duration: 0.1)) {
10+
isCopied = true
11+
}
12+
copy()
13+
Task {
14+
try await Task.sleep(nanoseconds: 1_000_000_000)
15+
withAnimation(.linear(duration: 0.1)) {
16+
isCopied = false
17+
}
18+
}
19+
}) {
20+
Image(systemName: isCopied ? "checkmark.circle" : "doc.on.doc")
21+
.resizable()
22+
.aspectRatio(contentMode: .fit)
23+
.frame(width: 14, height: 14)
24+
.frame(width: 20, height: 20, alignment: .center)
25+
.foregroundColor(.secondary)
26+
.background(
27+
.regularMaterial,
28+
in: RoundedRectangle(cornerRadius: 4, style: .circular)
29+
)
30+
.padding(4)
31+
}
32+
.buttonStyle(.borderless)
33+
}
34+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import AppKit
2+
import SwiftUI
3+
import Combine
4+
5+
/// Used to workaround a SwiftUI bug. https://github.com/intitni/CopilotForXcode/issues/122
6+
struct CustomScrollView<Content: View>: View {
7+
@ViewBuilder var content: () -> Content
8+
@State var height: Double = 100
9+
@AppStorage(\.useCustomScrollViewWorkaround) var useNSScrollViewWrapper
10+
11+
var body: some View {
12+
if useNSScrollViewWrapper {
13+
List {
14+
content()
15+
.listRowInsets(EdgeInsets(top: 0, leading: -8, bottom: 0, trailing: -8))
16+
}
17+
.listStyle(.plain)
18+
.frame(idealHeight: height)
19+
.background {
20+
ComputeHeight(height: $height) {
21+
content()
22+
}
23+
.frame(maxWidth: .infinity)
24+
.opacity(0)
25+
}
26+
} else {
27+
ScrollView {
28+
content()
29+
}
30+
}
31+
}
32+
}
33+
34+
private struct ComputeHeight<Content: View>: NSViewRepresentable {
35+
@Binding var height: Double
36+
@ViewBuilder var content: () -> Content
37+
38+
func makeNSView(context: Context) -> NSView {
39+
let view = NSView()
40+
return view
41+
}
42+
43+
func updateNSView(_ nsView: NSView, context: Context) {
44+
updateHeight(nsView)
45+
}
46+
47+
func updateHeight(_ nsView: NSView) {
48+
let contentView = content()
49+
let hostingView = NSHostingView(
50+
rootView: contentView.frame(width: nsView.frame.width == 0 ? 200 : nsView.frame.width)
51+
)
52+
let size = hostingView.fittingSize
53+
54+
if height != size.height {
55+
Task { @MainActor in
56+
height = size.height
57+
}
58+
}
59+
}
60+
}

Core/Sources/SuggestionWidget/Styles.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import AppKit
2+
import MarkdownUI
23
import SwiftUI
34

45
enum Style {
@@ -53,3 +54,29 @@ extension View {
5354
)
5455
}
5556
}
57+
58+
extension MarkdownUI.Theme {
59+
static var custom: MarkdownUI.Theme {
60+
.gitHub.text {
61+
BackgroundColor(Color.clear)
62+
}
63+
.codeBlock { configuration in
64+
configuration.label
65+
.relativeLineSpacing(.em(0.225))
66+
.markdownTextStyle {
67+
FontFamilyVariant(.monospaced)
68+
FontSize(.em(0.85))
69+
}
70+
.padding(16)
71+
.background(Color(nsColor: .textBackgroundColor).opacity(0.7))
72+
.clipShape(RoundedRectangle(cornerRadius: 6))
73+
.overlay(alignment: .topTrailing) {
74+
CopyButton {
75+
NSPasteboard.general.clearContents()
76+
NSPasteboard.general.setString(configuration.content, forType: .string)
77+
}
78+
}
79+
.markdownMargin(top: 0, bottom: 16)
80+
}
81+
}
82+
}

0 commit comments

Comments
 (0)