Skip to content

Commit 0a3c616

Browse files
committed
Add CustomScrollView backed by single cell List
1 parent de01a8d commit 0a3c616

File tree

6 files changed

+77
-5
lines changed

6 files changed

+77
-5
lines changed

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/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: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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+
print(size)
54+
55+
if height != size.height {
56+
Task { @MainActor in
57+
height = size.height
58+
}
59+
}
60+
}
61+
}

Core/Sources/SuggestionWidget/SuggestionPanelContent/ChatPanel.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ struct ChatPanelMessages: View {
7878
}
7979

8080
var body: some View {
81-
ScrollView {
81+
CustomScrollView {
8282
vstack {
8383
let r = 8 as Double
8484

@@ -103,7 +103,7 @@ struct ChatPanelMessages: View {
103103
.stroke(Color(nsColor: .separatorColor), lineWidth: 1)
104104
}
105105
}
106-
.buttonStyle(.plain)
106+
.buttonStyle(.borderless)
107107
.scaleEffect(x: -1, y: 1, anchor: .center)
108108
}
109109

@@ -403,7 +403,7 @@ struct CopyButton: View {
403403
)
404404
.padding(4)
405405
}
406-
.buttonStyle(.plain)
406+
.buttonStyle(.borderless)
407407
}
408408
}
409409

Core/Sources/SuggestionWidget/SuggestionPanelContent/CodeBlockSuggestionPanel.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ struct CodeBlockSuggestionPanel: View {
4848

4949
var body: some View {
5050
VStack(spacing: 0) {
51-
ScrollView {
51+
CustomScrollView {
5252
CodeBlock(
5353
code: suggestion.code,
5454
language: suggestion.language,

Core/Sources/SuggestionWidget/SuggestionPanelContent/PromptToCodePanel.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ struct PromptToCodePanel: View {
77

88
var body: some View {
99
VStack(spacing: 0) {
10-
ScrollView {
10+
CustomScrollView {
1111
VStack(spacing: 0) {
1212
if !provider.errorMessage.isEmpty {
1313
Text(provider.errorMessage)

0 commit comments

Comments
 (0)