Skip to content

Commit 68c788b

Browse files
committed
Fix that the other chat tab can't scroll up
1 parent 7a4f12e commit 68c788b

2 files changed

Lines changed: 33 additions & 16 deletions

File tree

Core/Sources/ChatGPTChatTab/Chat.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ struct Chat {
6666
var isReceivingMessage = false
6767
var chatMenu = ChatMenu.State()
6868
var focusedField: Field?
69+
var isEnabled = true
70+
var isPinnedToBottom = true
6971

7072
enum Field: String, Hashable {
7173
case textField
@@ -77,13 +79,16 @@ struct Chat {
7779

7880
case appear
7981
case refresh
82+
case setIsEnabled(Bool)
8083
case sendButtonTapped
8184
case returnButtonTapped
8285
case stopRespondingButtonTapped
8386
case clearButtonTap
8487
case deleteMessageButtonTapped(MessageID)
8588
case resendMessageButtonTapped(MessageID)
8689
case setAsExtraPromptButtonTapped(MessageID)
90+
case manuallyScrolledUp
91+
case scrollToBottomButtonTapped
8792
case focusOnTextField
8893
case referenceClicked(DisplayedChatMessage.Reference)
8994

@@ -143,6 +148,10 @@ struct Chat {
143148
await send(.chatMenu(.refresh))
144149
}
145150

151+
case let .setIsEnabled(isEnabled):
152+
state.isEnabled = isEnabled
153+
return .none
154+
146155
case .sendButtonTapped:
147156
guard !state.typedMessage.isEmpty else { return .none }
148157
let message = state.typedMessage
@@ -204,6 +213,14 @@ struct Chat {
204213
await openURL(url)
205214
}
206215
}
216+
217+
case .manuallyScrolledUp:
218+
state.isPinnedToBottom = false
219+
return .none
220+
221+
case .scrollToBottomButtonTapped:
222+
state.isPinnedToBottom = true
223+
return .none
207224

208225
case .focusOnTextField:
209226
state.focusedField = .textField
@@ -365,6 +382,9 @@ struct Chat {
365382

366383
case .isReceivingMessageChanged:
367384
state.isReceivingMessage = service.isReceivingMessage
385+
if service.isReceivingMessage {
386+
state.isPinnedToBottom = true
387+
}
368388
return .none
369389

370390
case .systemPromptChanged:

Core/Sources/ChatGPTChatTab/ChatPanel.swift

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ struct ChatPanelMessages: View {
4343
let chat: StoreOf<Chat>
4444
@State var cancellable = Set<AnyCancellable>()
4545
@State var isScrollToBottomButtonDisplayed = true
46-
@State var isPinnedToBottom = true
4746
@Namespace var bottomID
4847
@Namespace var topID
4948
@Namespace var scrollSpace
@@ -128,11 +127,7 @@ struct ChatPanelMessages: View {
128127
scrollToBottomButton(proxy: proxy)
129128
}
130129
.background {
131-
PinToBottomHandler(
132-
chat: chat,
133-
isBottomHidden: isBottomHidden,
134-
pinnedToBottom: $isPinnedToBottom
135-
) {
130+
PinToBottomHandler(chat: chat, isBottomHidden: isBottomHidden) {
136131
proxy.scrollTo(bottomID, anchor: .bottom)
137132
}
138133
}
@@ -151,22 +146,26 @@ struct ChatPanelMessages: View {
151146
cancellable.forEach { $0.cancel() }
152147
cancellable = []
153148
}
149+
.onChange(of: isEnabled) { isEnabled in
150+
chat.send(.setIsEnabled(isEnabled))
151+
}
154152
}
155153
}
156154

157155
func trackScrollWheel() {
158156
NSApplication.shared.publisher(for: \.currentEvent)
159-
.filter {
160-
if !isEnabled { return false }
157+
.receive(on: DispatchQueue.main)
158+
.filter { [chat] in
159+
guard chat.withState(\.isEnabled) else { return false }
161160
return $0?.type == .scrollWheel
162161
}
163162
.compactMap { $0 }
164163
.sink { event in
165-
guard isPinnedToBottom else { return }
164+
guard chat.withState(\.isPinnedToBottom) else { return }
166165
let delta = event.deltaY
167166
let scrollUp = delta > 0
168167
if scrollUp {
169-
isPinnedToBottom = false
168+
chat.send(.manuallyScrolledUp)
170169
}
171170
}
172171
.store(in: &cancellable)
@@ -184,7 +183,7 @@ struct ChatPanelMessages: View {
184183
@ViewBuilder
185184
func scrollToBottomButton(proxy: ScrollViewProxy) -> some View {
186185
Button(action: {
187-
isPinnedToBottom = true
186+
chat.send(.scrollToBottomButtonTapped)
188187
withAnimation(.easeInOut(duration: 0.1)) {
189188
proxy.scrollTo(bottomID, anchor: .bottom)
190189
}
@@ -222,18 +221,16 @@ struct ChatPanelMessages: View {
222221
struct PinToBottomHandler: View {
223222
let chat: StoreOf<Chat>
224223
let isBottomHidden: Bool
225-
@Binding var pinnedToBottom: Bool
226224
let scrollToBottom: () -> Void
227225

228226
@State var isInitialLoad = true
229-
227+
230228
var body: some View {
231229
WithPerceptionTracking {
232230
EmptyView()
233231
.onChange(of: chat.isReceivingMessage) { isReceiving in
234232
if isReceiving {
235233
Task {
236-
pinnedToBottom = true
237234
await Task.yield()
238235
withAnimation(.easeInOut(duration: 0.1)) {
239236
scrollToBottom()
@@ -242,7 +239,7 @@ struct ChatPanelMessages: View {
242239
}
243240
}
244241
.onChange(of: chat.history.last) { _ in
245-
if pinnedToBottom || isInitialLoad {
242+
if chat.withState(\.isPinnedToBottom) || isInitialLoad {
246243
if isInitialLoad {
247244
isInitialLoad = false
248245
}
@@ -256,7 +253,7 @@ struct ChatPanelMessages: View {
256253
}
257254
.onChange(of: isBottomHidden) { value in
258255
// This is important to prevent it from jumping to the top!
259-
if value, pinnedToBottom {
256+
if value, chat.withState(\.isPinnedToBottom) {
260257
scrollToBottom()
261258
}
262259
}

0 commit comments

Comments
 (0)