Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,13 @@ final class PaneController: SurfacePresenter, PresentablePane {
let machine = daemon.isLocal ? nil : services.machines.machineBadge(daemon.machineID)
let workspaceID = store.workspace(containing: pane.handle)?.id
var items = pane.tabs.filter { !pendingClosed.contains($0.id) }.map { tab -> StripTabItem in
// A new tab page is "New Tab" until it becomes a chat (then the chat's title).
// A new tab page is "New Tab", with the new-tab icon, until it
// becomes a chat (then the chat's title and icon).
let isNewTabPage = tab.agentSession != nil && services.agentTabs.pageTabs.ids.contains(tab.id)
let untitled = tab.agentSession != nil
? services.agentTabs.pageTabs.ids.contains(tab.id) ? Strings.untitledBrowser : AgentPaneModel.tabTitle
? isNewTabPage ? Strings.untitledBrowser : AgentPaneModel.tabTitle
: tab.kind == .conversation ? services.home.tabTitle(for: tab) : tab.kind == .browser ? Strings.untitledBrowser : fallback
var item = TabItemMapping.shared.item(tab, fallbackTitle: untitled)
var item = TabItemMapping.shared.item(tab, fallbackTitle: untitled, isNewTabPage: isNewTabPage)
if tab.page != nil, let page = services.pages.storeTabItem(tab) {
// A page tab names and badges itself like the page it shows.
item.title = page.title
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ public struct TabItemMapping {
/// page, whose recorded title is that page's address.
/// A conversation tab (conversation-tabs-v1) rides a frontend browser
/// record titled with the blank page's address: it shows `fallbackTitle`
/// (the conversation's) and the agent chat icon.
/// (the conversation's) and the agent chat icon. `isNewTabPage` marks a
/// tab still on the New Tab page, which draws the new-tab icon instead.

public func item(_ tab: TabModel, fallbackTitle: String) -> StripTabItem {
public func item(_ tab: TabModel, fallbackTitle: String, isNewTabPage: Bool = false) -> StripTabItem {
let isBrowser = tab.kind == .browser
let isConversation = tab.kind == .conversation
let untitled = tab.displayTitle.isEmpty || ((isBrowser || isConversation) && Self.isBlankPageAddress(tab.displayTitle))
Expand All @@ -28,7 +29,7 @@ public struct TabItemMapping {
id: StripTabID(tab.id),
title: title,
subtitle: isConversation ? nil : isBrowser ? tab.url : tab.cwd.map(SidebarMapping.shared.abbreviate),
icon: icon(tab, isBrowser: isBrowser, isConversation: isConversation),
icon: isNewTabPage ? .icon(.tabNew) : icon(tab, isBrowser: isBrowser, isConversation: isConversation),
isPinned: tab.pinned,
isUnread: tab.hasUnread,
isBusy: busy.state.isLoading || isReportingProgress(tab),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,21 @@ struct ConversationTabItemTests {
#expect(item.icon == .icon(.agentChat))
#expect(item.subtitle == nil)
}

/// A tab still on the New Tab page draws the registry's new-tab icon, so
/// it is told apart from an Agent chat tab by more than its title.
@Test func aNewTabPageTabDrawsTheNewTabIcon() throws {
let tab = TabSnapshot(surface: 5, kind: .conversation, title: "about:blank", url: "about:blank")
let pane = PaneSnapshot(id: 3, tabs: [tab])
let workspace = WorkspaceSnapshot(id: 1, key: WorkspaceKey(rawValue: "0b6c4a52-6d3f-4c55-9d53-8f1f4e0f1a02"), name: "Home",
screens: [ScreenSnapshot(id: 4, layout: .leaf(3), panes: [pane])])
let store = DaemonStore()
store.apply(snapshot: DaemonTree(workspaceRevision: 1, workspaces: [workspace]))
let model = try #require(store.workspaces.first?.screens.first?.panes.first?.tabs.first)
let page = TabItemMapping.shared.item(model, fallbackTitle: "New Tab", isNewTabPage: true)
let chat = TabItemMapping.shared.item(model, fallbackTitle: "Agent")
#expect(page.icon == .icon(.tabNew))
#expect(chat.icon == .icon(.agentChat))
#expect(page.icon != chat.icon)
}
}
Loading