fix(app): scope session tab indicators to the tab's server (#34861)
This commit is contained in:
parent
27c9b130c7
commit
1fb2ecc721
7 changed files with 139 additions and 30 deletions
|
|
@ -28,7 +28,6 @@ export function TabNavItem(props: {
|
|||
onClose: () => void
|
||||
onNavigate: () => void
|
||||
active?: boolean
|
||||
activeServer: boolean
|
||||
forceTruncate?: boolean
|
||||
suppressNavigation?: () => boolean
|
||||
dragging?: boolean
|
||||
|
|
@ -245,7 +244,7 @@ export function TabNavItem(props: {
|
|||
project={project()}
|
||||
directory={session().directory}
|
||||
sessionId={session().id}
|
||||
activeServer={props.activeServer}
|
||||
server={props.server}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ function SessionTabSlot(props: {
|
|||
id: string
|
||||
index: () => number
|
||||
active: () => boolean
|
||||
activeServerKey: ServerConnection.Key
|
||||
forceTruncate: boolean
|
||||
serverCtx: () => ServerCtx | undefined
|
||||
onNavigate: (element: HTMLDivElement) => void
|
||||
|
|
@ -112,7 +111,6 @@ function SessionTabSlot(props: {
|
|||
onNavigate={() => props.onNavigate(ref)}
|
||||
onClose={props.onClose}
|
||||
active={props.active()}
|
||||
activeServer={props.tab.server === props.activeServerKey}
|
||||
forceTruncate={props.forceTruncate}
|
||||
dragging={sortable.isDragSource()}
|
||||
/>
|
||||
|
|
@ -165,7 +163,6 @@ function DraftTabSlot(props: {
|
|||
export function TitlebarTabStrip(props: {
|
||||
tabs: Tab[]
|
||||
currentTab: () => Tab | undefined
|
||||
activeServerKey: ServerConnection.Key
|
||||
forceTruncate: boolean
|
||||
onNavigate: (tab: Tab, el?: HTMLDivElement) => void
|
||||
onClose: (tab: Tab) => void
|
||||
|
|
@ -271,7 +268,6 @@ export function TitlebarTabStrip(props: {
|
|||
id={id}
|
||||
index={index}
|
||||
active={() => props.currentTab() === tab}
|
||||
activeServerKey={props.activeServerKey}
|
||||
forceTruncate={props.forceTruncate}
|
||||
serverCtx={serverCtx}
|
||||
onNavigate={(element) => {
|
||||
|
|
|
|||
|
|
@ -456,7 +456,6 @@ export function Titlebar(props: { update?: TitlebarUpdate }) {
|
|||
<TitlebarTabStrip
|
||||
tabs={tabsStore}
|
||||
currentTab={currentTab}
|
||||
activeServerKey={server.key}
|
||||
forceTruncate={tabsAreOverflowing()}
|
||||
onOverflowChange={setTabsAreOverflowing}
|
||||
onNavigate={(tab, el) => {
|
||||
|
|
|
|||
|
|
@ -552,7 +552,6 @@ export function NewHome() {
|
|||
results={searchResults()}
|
||||
showProjectName={!selectedProject()}
|
||||
server={selection().server}
|
||||
activeServer={selection().server === server.key}
|
||||
noResultsLabel={language.t("home.sessions.search.noResults", { query: search() })}
|
||||
bindFocus={(focus) => {
|
||||
focusSessionSearch = focus
|
||||
|
|
@ -612,7 +611,6 @@ export function NewHome() {
|
|||
record={record}
|
||||
showProjectName={!selectedProject()}
|
||||
server={selection().server}
|
||||
activeServer={selection().server === server.key}
|
||||
openSession={openSession}
|
||||
archiveSession={archiveSession}
|
||||
/>
|
||||
|
|
@ -996,7 +994,6 @@ function HomeSessionLeading(props: {
|
|||
project: LocalProject
|
||||
session: Session
|
||||
server: ServerConnection.Key
|
||||
activeServer: boolean
|
||||
revealProjectOnHover: boolean
|
||||
}) {
|
||||
const tabs = useTabs()
|
||||
|
|
@ -1014,7 +1011,7 @@ function HomeSessionLeading(props: {
|
|||
project={props.project}
|
||||
directory={props.session.directory}
|
||||
sessionId={props.session.id}
|
||||
activeServer={props.activeServer}
|
||||
server={props.server}
|
||||
revealProjectOnHover={props.revealProjectOnHover}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -1029,7 +1026,6 @@ function HomeSessionSearch(props: {
|
|||
results: HomeSessionRecord[]
|
||||
showProjectName: boolean
|
||||
server: ServerConnection.Key
|
||||
activeServer: boolean
|
||||
noResultsLabel: string
|
||||
bindFocus: (focus: () => void) => void
|
||||
onInput: (value: string) => void
|
||||
|
|
@ -1147,7 +1143,6 @@ function HomeSessionSearch(props: {
|
|||
record={record}
|
||||
showProjectName={props.showProjectName}
|
||||
server={props.server}
|
||||
activeServer={props.activeServer}
|
||||
selected={store.active === homeSessionSearchKey(record)}
|
||||
onHighlight={() => setStore("active", homeSessionSearchKey(record))}
|
||||
onSelect={(session) => props.onSelect(session)}
|
||||
|
|
@ -1228,7 +1223,6 @@ function HomeSessionSearchResultRow(props: {
|
|||
record: HomeSessionRecord
|
||||
showProjectName: boolean
|
||||
server: ServerConnection.Key
|
||||
activeServer: boolean
|
||||
selected: boolean
|
||||
onHighlight: () => void
|
||||
onSelect: (session: Session) => void
|
||||
|
|
@ -1258,7 +1252,6 @@ function HomeSessionSearchResultRow(props: {
|
|||
project={props.record.project}
|
||||
session={props.record.session}
|
||||
server={props.server}
|
||||
activeServer={props.activeServer}
|
||||
revealProjectOnHover={!!showProjectName()}
|
||||
/>
|
||||
<div class="flex min-w-0 flex-1 items-center gap-1.5">
|
||||
|
|
@ -1297,7 +1290,6 @@ function HomeSessionRow(props: {
|
|||
record: HomeSessionRecord
|
||||
showProjectName: boolean
|
||||
server: ServerConnection.Key
|
||||
activeServer: boolean
|
||||
openSession: (session: Session) => void
|
||||
archiveSession: (session: Session) => Promise<void>
|
||||
}) {
|
||||
|
|
@ -1320,7 +1312,6 @@ function HomeSessionRow(props: {
|
|||
project={props.record.project}
|
||||
session={props.record.session}
|
||||
server={props.server}
|
||||
activeServer={props.activeServer}
|
||||
revealProjectOnHover={!!showProjectName()}
|
||||
/>
|
||||
<span
|
||||
|
|
|
|||
|
|
@ -1,29 +1,41 @@
|
|||
import { createMemo, type Accessor } from "solid-js"
|
||||
import { useServerSync } from "@/context/server-sync"
|
||||
import { useGlobal } from "@/context/global"
|
||||
import { useNotification } from "@/context/notification"
|
||||
import { usePermission } from "@/context/permission"
|
||||
import { ServerConnection } from "@/context/server"
|
||||
import { sessionPermissionRequest } from "@/pages/session/composer/session-request-tree"
|
||||
|
||||
export function useSessionTabAvatarState(
|
||||
server: Accessor<ServerConnection.Key>,
|
||||
directory: Accessor<string>,
|
||||
sessionId: Accessor<string>,
|
||||
active: Accessor<boolean> = () => true,
|
||||
) {
|
||||
const globalSync = useServerSync()
|
||||
const global = useGlobal()
|
||||
const notification = useNotification()
|
||||
const permission = usePermission()
|
||||
const connection = createMemo(() => global.servers.list().find((item) => ServerConnection.key(item) === server()))
|
||||
const sync = createMemo(() => {
|
||||
const conn = connection()
|
||||
if (conn) return global.ensureServerCtx(conn).sync
|
||||
})
|
||||
const hasPermissions = createMemo(() => {
|
||||
if (!active()) return false
|
||||
const [store] = globalSync().child(directory(), { bootstrap: false })
|
||||
return !!sessionPermissionRequest(store.session, globalSync().session.data.permission, sessionId(), (item) => {
|
||||
const serverSync = sync()
|
||||
if (!serverSync) return false
|
||||
const [store] = serverSync.child(directory(), { bootstrap: false })
|
||||
return !!sessionPermissionRequest(store.session, serverSync.session.data.permission, sessionId(), (item) => {
|
||||
return !permission.autoResponds(item, directory())
|
||||
})
|
||||
})
|
||||
const unread = createMemo(() => active() && (hasPermissions() || notification.session.unseenCount(sessionId()) > 0))
|
||||
const unread = createMemo(() => {
|
||||
if (hasPermissions()) return true
|
||||
if (!connection()) return false
|
||||
return notification.ensureServerState(server()).session.unseenCount(sessionId()) > 0
|
||||
})
|
||||
const loading = createMemo(() => {
|
||||
if (!active()) return false
|
||||
const serverSync = sync()
|
||||
if (!serverSync) return false
|
||||
if (hasPermissions()) return false
|
||||
return globalSync().session.data.session_working(sessionId())
|
||||
return serverSync.session.data.session_working(sessionId())
|
||||
})
|
||||
return { unread, loading }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import type { LocalProject } from "@/context/layout"
|
||||
import { getProjectAvatarVariant } from "@/context/layout"
|
||||
import type { ServerConnection } from "@/context/server"
|
||||
import { displayName, getProjectAvatarSource } from "@/pages/layout/helpers"
|
||||
import { useSessionTabAvatarState } from "@/pages/layout/project-avatar-state"
|
||||
import { ProjectAvatar } from "@opencode-ai/ui/v2/project-avatar-v2"
|
||||
|
|
@ -10,12 +11,14 @@ export function SessionTabAvatar(props: {
|
|||
project?: LocalProject
|
||||
directory: string
|
||||
sessionId: string
|
||||
activeServer: boolean
|
||||
server: ServerConnection.Key
|
||||
revealProjectOnHover?: boolean
|
||||
}) {
|
||||
const directory = () => props.directory
|
||||
const sessionId = () => props.sessionId
|
||||
const state = useSessionTabAvatarState(directory, sessionId, () => props.activeServer)
|
||||
const state = useSessionTabAvatarState(
|
||||
() => props.server,
|
||||
() => props.directory,
|
||||
() => props.sessionId,
|
||||
)
|
||||
const projectAvatar = () => (
|
||||
<ProjectAvatar
|
||||
fallback={displayName(props.project ?? { worktree: props.directory })}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue