Skip to content

Commit 6759c8c

Browse files
committed
Support opening chat web page in chat tab
1 parent c756ebb commit 6759c8c

File tree

4 files changed

+80
-10
lines changed

4 files changed

+80
-10
lines changed

Core/Package.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ let package = Package(
126126
"PromptToCodeService",
127127
"ServiceUpdateMigration",
128128
"ChatGPTChatTab",
129+
"PlusFeatureFlag",
129130
.product(name: "XPCShared", package: "Tool"),
130131
.product(name: "SuggestionProvider", package: "Tool"),
131132
.product(name: "Workspace", package: "Tool"),

Core/Sources/Service/GUI/GraphicalUserInterfaceController.swift

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ struct GUI {
5555
enum Action {
5656
case start
5757
case openChatPanel(forceDetach: Bool)
58-
case createChatGPTChatTabIfNeeded
58+
case createAndSwitchToChatGPTChatTabIfNeeded
59+
case createAndSwitchToBrowserTabIfNeeded(url: URL)
5960
case sendCustomCommandToActiveChat(CustomCommand)
6061
case toggleWidgetsHotkeyPressed
6162

@@ -145,11 +146,22 @@ struct GUI {
145146
activateThisApp()
146147
}
147148

148-
case .createChatGPTChatTabIfNeeded:
149-
if state.chatTabGroup.tabInfo.contains(where: {
149+
case .createAndSwitchToChatGPTChatTabIfNeeded:
150+
if let selectedTabInfo = state.chatTabGroup.selectedTabInfo,
151+
chatTabPool.getTab(of: selectedTabInfo.id) is ChatGPTChatTab
152+
{
153+
// Already in ChatGPT tab
154+
return .none
155+
}
156+
157+
if let firstChatGPTTabInfo = state.chatTabGroup.tabInfo.first(where: {
150158
chatTabPool.getTab(of: $0.id) is ChatGPTChatTab
151159
}) {
152-
return .none
160+
return .run { send in
161+
await send(.suggestionWidget(.chatPanel(.tabClicked(
162+
id: firstChatGPTTabInfo.id
163+
))))
164+
}
153165
}
154166
return .run { send in
155167
if let (_, chatTabInfo) = await chatTabPool.createTab(for: nil) {
@@ -159,6 +171,53 @@ struct GUI {
159171
}
160172
}
161173

174+
case let .createAndSwitchToBrowserTabIfNeeded(url):
175+
#if canImport(BrowserChatTab)
176+
func match(_ tabURL: URL?) -> Bool {
177+
guard let tabURL else { return false }
178+
return tabURL == url
179+
|| tabURL.absoluteString.hasPrefix(url.absoluteString)
180+
}
181+
182+
if let selectedTabInfo = state.chatTabGroup.selectedTabInfo,
183+
let tab = chatTabPool.getTab(of: selectedTabInfo.id) as? BrowserChatTab,
184+
match(tab.url)
185+
{
186+
// Already in the target Browser tab
187+
return .none
188+
}
189+
190+
if let firstChatGPTTabInfo = state.chatTabGroup.tabInfo.first(where: {
191+
guard let tab = chatTabPool.getTab(of: $0.id) as? BrowserChatTab,
192+
match(tab.url)
193+
else { return false }
194+
return true
195+
}) {
196+
return .run { send in
197+
await send(.suggestionWidget(.chatPanel(.tabClicked(
198+
id: firstChatGPTTabInfo.id
199+
))))
200+
}
201+
}
202+
203+
return .run { send in
204+
if let (_, chatTabInfo) = await chatTabPool.createTab(
205+
for: .init(BrowserChatTab.urlChatBuilder(
206+
url: url,
207+
externalDependency: ChatTabFactory
208+
.externalDependenciesForBrowserChatTab()
209+
))
210+
) {
211+
await send(
212+
.suggestionWidget(.chatPanel(.appendAndSelectTab(chatTabInfo)))
213+
)
214+
}
215+
}
216+
217+
#else
218+
return .none
219+
#endif
220+
162221
case let .sendCustomCommandToActiveChat(command):
163222
@Sendable func stopAndHandleCommand(_ tab: ChatGPTChatTab) async {
164223
if tab.service.isReceivingMessage {
@@ -320,7 +379,7 @@ public final class GraphicalUserInterfaceController {
320379
suggestionDependency.suggestionWidgetDataSource = widgetDataSource
321380
suggestionDependency.onOpenChatClicked = { [weak self] in
322381
Task { [weak self] in
323-
await self?.store.send(.createChatGPTChatTabIfNeeded).finish()
382+
await self?.store.send(.createAndSwitchToChatGPTChatTabIfNeeded).finish()
324383
self?.store.send(.openChatPanel(forceDetach: false))
325384
}
326385
}

Core/Sources/Service/SuggestionCommandHandler/PseudoCommandHandler.swift

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import ActiveApplicationMonitor
22
import AppKit
33
import Dependencies
4+
import PlusFeatureFlag
45
import Preferences
56
import SuggestionInjector
67
import SuggestionModel
@@ -318,14 +319,19 @@ struct PseudoCommandHandler {
318319
func openChat(forceDetach: Bool) {
319320
switch UserDefaults.shared.value(for: \.openChatMode) {
320321
case .chatPanel:
322+
let store = Service.shared.guiController.store
321323
Task { @MainActor in
322-
let store = Service.shared.guiController.store
323-
await store.send(.createChatGPTChatTabIfNeeded).finish()
324+
await store.send(.createAndSwitchToChatGPTChatTabIfNeeded).finish()
324325
store.send(.openChatPanel(forceDetach: false))
325326
}
326327
case .browser:
327328
let urlString = UserDefaults.shared.value(for: \.openChatInBrowserURL)
328-
let openInApp = UserDefaults.shared.value(for: \.openChatInBrowserInInAppBrowser)
329+
let openInApp = {
330+
if !UserDefaults.shared.value(for: \.openChatInBrowserInInAppBrowser) {
331+
return false
332+
}
333+
return isFeatureAvailable(\.browserTab)
334+
}()
329335
guard let url = URL(string: urlString) else {
330336
let alert = NSAlert()
331337
alert.messageText = "Invalid URL"
@@ -336,7 +342,11 @@ struct PseudoCommandHandler {
336342
}
337343

338344
if openInApp {
339-
return
345+
let store = Service.shared.guiController.store
346+
Task { @MainActor in
347+
await store.send(.createAndSwitchToBrowserTabIfNeeded(url: url)).finish()
348+
store.send(.openChatPanel(forceDetach: false))
349+
}
340350
} else {
341351
Task {
342352
@Dependency(\.openURL) var openURL

Pro

Submodule Pro updated from ff11260 to 2da51b1

0 commit comments

Comments
 (0)