fix(app): hide default session timestamps (#20892)
parent
9d57f21f9f
commit
fbfa148e4e
|
|
@ -16,6 +16,7 @@ import { getAvatarColors, type LocalProject, useLayout } from "@/context/layout"
|
||||||
import { useNotification } from "@/context/notification"
|
import { useNotification } from "@/context/notification"
|
||||||
import { usePermission } from "@/context/permission"
|
import { usePermission } from "@/context/permission"
|
||||||
import { messageAgentColor } from "@/utils/agent"
|
import { messageAgentColor } from "@/utils/agent"
|
||||||
|
import { sessionTitle } from "@/utils/session-title"
|
||||||
import { sessionPermissionRequest } from "../session/composer/session-request-tree"
|
import { sessionPermissionRequest } from "../session/composer/session-request-tree"
|
||||||
import { hasProjectPermissions } from "./helpers"
|
import { hasProjectPermissions } from "./helpers"
|
||||||
|
|
||||||
|
|
@ -101,42 +102,46 @@ const SessionRow = (props: {
|
||||||
warmPress: () => void
|
warmPress: () => void
|
||||||
warmFocus: () => void
|
warmFocus: () => void
|
||||||
cancelHoverPrefetch: () => void
|
cancelHoverPrefetch: () => void
|
||||||
}): JSX.Element => (
|
}) => {
|
||||||
<A
|
const title = () => sessionTitle(props.session.title)
|
||||||
href={`/${props.slug}/session/${props.session.id}`}
|
|
||||||
class={`flex items-center gap-1 min-w-0 w-full text-left focus:outline-none ${props.dense ? "py-0.5" : "py-1"}`}
|
return (
|
||||||
onPointerDown={props.warmPress}
|
<A
|
||||||
onPointerEnter={props.warmHover}
|
href={`/${props.slug}/session/${props.session.id}`}
|
||||||
onPointerLeave={props.cancelHoverPrefetch}
|
class={`flex items-center gap-1 min-w-0 w-full text-left focus:outline-none ${props.dense ? "py-0.5" : "py-1"}`}
|
||||||
onFocus={props.warmFocus}
|
onPointerDown={props.warmPress}
|
||||||
onClick={() => {
|
onPointerEnter={props.warmHover}
|
||||||
props.setHoverSession(undefined)
|
onPointerLeave={props.cancelHoverPrefetch}
|
||||||
if (props.sidebarOpened()) return
|
onFocus={props.warmFocus}
|
||||||
props.clearHoverProjectSoon()
|
onClick={() => {
|
||||||
}}
|
props.setHoverSession(undefined)
|
||||||
>
|
if (props.sidebarOpened()) return
|
||||||
<div
|
props.clearHoverProjectSoon()
|
||||||
class="shrink-0 size-6 flex items-center justify-center"
|
}}
|
||||||
style={{ color: props.tint() ?? "var(--icon-interactive-base)" }}
|
|
||||||
>
|
>
|
||||||
<Switch fallback={<Icon name="dash" size="small" class="text-icon-weak" />}>
|
<div
|
||||||
<Match when={props.isWorking()}>
|
class="shrink-0 size-6 flex items-center justify-center"
|
||||||
<Spinner class="size-[15px]" />
|
style={{ color: props.tint() ?? "var(--icon-interactive-base)" }}
|
||||||
</Match>
|
>
|
||||||
<Match when={props.hasPermissions()}>
|
<Switch fallback={<Icon name="dash" size="small" class="text-icon-weak" />}>
|
||||||
<div class="size-1.5 rounded-full bg-surface-warning-strong" />
|
<Match when={props.isWorking()}>
|
||||||
</Match>
|
<Spinner class="size-[15px]" />
|
||||||
<Match when={props.hasError()}>
|
</Match>
|
||||||
<div class="size-1.5 rounded-full bg-text-diff-delete-base" />
|
<Match when={props.hasPermissions()}>
|
||||||
</Match>
|
<div class="size-1.5 rounded-full bg-surface-warning-strong" />
|
||||||
<Match when={props.unseenCount() > 0}>
|
</Match>
|
||||||
<div class="size-1.5 rounded-full bg-text-interactive-base" />
|
<Match when={props.hasError()}>
|
||||||
</Match>
|
<div class="size-1.5 rounded-full bg-text-diff-delete-base" />
|
||||||
</Switch>
|
</Match>
|
||||||
</div>
|
<Match when={props.unseenCount() > 0}>
|
||||||
<span class="text-14-regular text-text-strong min-w-0 flex-1 truncate">{props.session.title}</span>
|
<div class="size-1.5 rounded-full bg-text-interactive-base" />
|
||||||
</A>
|
</Match>
|
||||||
)
|
</Switch>
|
||||||
|
</div>
|
||||||
|
<span class="text-14-regular text-text-strong min-w-0 flex-1 truncate">{title()}</span>
|
||||||
|
</A>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const SessionHoverPreview = (props: {
|
const SessionHoverPreview = (props: {
|
||||||
mobile?: boolean
|
mobile?: boolean
|
||||||
|
|
@ -319,7 +324,7 @@ export const SessionItem = (props: SessionItemProps): JSX.Element => {
|
||||||
fallback={
|
fallback={
|
||||||
<Tooltip
|
<Tooltip
|
||||||
placement={props.mobile ? "bottom" : "right"}
|
placement={props.mobile ? "bottom" : "right"}
|
||||||
value={props.session.title}
|
value={sessionTitle(props.session.title)}
|
||||||
gutter={10}
|
gutter={10}
|
||||||
class="min-w-0 w-full"
|
class="min-w-0 w-full"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import { useSettings } from "@/context/settings"
|
||||||
import { useSDK } from "@/context/sdk"
|
import { useSDK } from "@/context/sdk"
|
||||||
import { useSync } from "@/context/sync"
|
import { useSync } from "@/context/sync"
|
||||||
import { messageAgentColor } from "@/utils/agent"
|
import { messageAgentColor } from "@/utils/agent"
|
||||||
|
import { sessionTitle } from "@/utils/session-title"
|
||||||
import { parseCommentNote, readCommentMetadata } from "@/utils/comment-note"
|
import { parseCommentNote, readCommentMetadata } from "@/utils/comment-note"
|
||||||
import { makeTimer } from "@solid-primitives/timer"
|
import { makeTimer } from "@solid-primitives/timer"
|
||||||
|
|
||||||
|
|
@ -43,7 +44,6 @@ type MessageComment = {
|
||||||
|
|
||||||
const emptyMessages: MessageType[] = []
|
const emptyMessages: MessageType[] = []
|
||||||
const idle = { type: "idle" as const }
|
const idle = { type: "idle" as const }
|
||||||
|
|
||||||
type UserActions = {
|
type UserActions = {
|
||||||
fork?: (input: { sessionID: string; messageID: string }) => Promise<void> | void
|
fork?: (input: { sessionID: string; messageID: string }) => Promise<void> | void
|
||||||
revert?: (input: { sessionID: string; messageID: string }) => Promise<void> | void
|
revert?: (input: { sessionID: string; messageID: string }) => Promise<void> | void
|
||||||
|
|
@ -291,6 +291,7 @@ export function MessageTimeline(props: {
|
||||||
return sync.session.get(id)
|
return sync.session.get(id)
|
||||||
})
|
})
|
||||||
const titleValue = createMemo(() => info()?.title)
|
const titleValue = createMemo(() => info()?.title)
|
||||||
|
const titleLabel = createMemo(() => sessionTitle(titleValue()))
|
||||||
const shareUrl = createMemo(() => info()?.share?.url)
|
const shareUrl = createMemo(() => info()?.share?.url)
|
||||||
const shareEnabled = createMemo(() => sync.data.config.share !== "disabled")
|
const shareEnabled = createMemo(() => sync.data.config.share !== "disabled")
|
||||||
const parentID = createMemo(() => info()?.parentID)
|
const parentID = createMemo(() => info()?.parentID)
|
||||||
|
|
@ -399,7 +400,7 @@ export function MessageTimeline(props: {
|
||||||
|
|
||||||
const openTitleEditor = () => {
|
const openTitleEditor = () => {
|
||||||
if (!sessionID()) return
|
if (!sessionID()) return
|
||||||
setTitle({ editing: true, draft: titleValue() ?? "" })
|
setTitle({ editing: true, draft: titleLabel() ?? "" })
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
titleRef?.focus()
|
titleRef?.focus()
|
||||||
titleRef?.select()
|
titleRef?.select()
|
||||||
|
|
@ -417,7 +418,7 @@ export function MessageTimeline(props: {
|
||||||
if (titleMutation.isPending) return
|
if (titleMutation.isPending) return
|
||||||
|
|
||||||
const next = title.draft.trim()
|
const next = title.draft.trim()
|
||||||
if (!next || next === (titleValue() ?? "")) {
|
if (!next || next === (titleLabel() ?? "")) {
|
||||||
setTitle("editing", false)
|
setTitle("editing", false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -532,7 +533,9 @@ export function MessageTimeline(props: {
|
||||||
}
|
}
|
||||||
|
|
||||||
function DialogDeleteSession(props: { sessionID: string }) {
|
function DialogDeleteSession(props: { sessionID: string }) {
|
||||||
const name = createMemo(() => sync.session.get(props.sessionID)?.title ?? language.t("command.session.new"))
|
const name = createMemo(
|
||||||
|
() => sessionTitle(sync.session.get(props.sessionID)?.title) ?? language.t("command.session.new"),
|
||||||
|
)
|
||||||
const handleDelete = async () => {
|
const handleDelete = async () => {
|
||||||
await deleteSession(props.sessionID)
|
await deleteSession(props.sessionID)
|
||||||
dialog.close()
|
dialog.close()
|
||||||
|
|
@ -673,7 +676,7 @@ export function MessageTimeline(props: {
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
<Show when={titleValue() || title.editing}>
|
<Show when={titleLabel() || title.editing}>
|
||||||
<Show
|
<Show
|
||||||
when={title.editing}
|
when={title.editing}
|
||||||
fallback={
|
fallback={
|
||||||
|
|
@ -681,7 +684,7 @@ export function MessageTimeline(props: {
|
||||||
class="text-14-medium text-text-strong truncate grow-1 min-w-0"
|
class="text-14-medium text-text-strong truncate grow-1 min-w-0"
|
||||||
onDblClick={openTitleEditor}
|
onDblClick={openTitleEditor}
|
||||||
>
|
>
|
||||||
{titleValue()}
|
{titleLabel()}
|
||||||
</h1>
|
</h1>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
const pattern = /^(New session|Child session) - \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/
|
||||||
|
|
||||||
|
export function sessionTitle(title?: string) {
|
||||||
|
if (!title) return title
|
||||||
|
const match = title.match(pattern)
|
||||||
|
return match?.[1] ?? title
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue