summaryrefslogtreecommitdiffhomepage
path: root/packages/app/src
diff options
context:
space:
mode:
authorShoubhit Dash <[email protected]>2026-04-03 19:21:54 +0530
committerGitHub <[email protected]>2026-04-03 13:51:54 +0000
commitfbfa148e4eb968751a3fa29b7b2dab52815e4ebc (patch)
tree6450d250fdfe51ce12b836547ec2760f68b7aba5 /packages/app/src
parent9d57f21f9fedddc753908d2727f0422408eaa878 (diff)
downloadopencode-fbfa148e4eb968751a3fa29b7b2dab52815e4ebc.tar.gz
opencode-fbfa148e4eb968751a3fa29b7b2dab52815e4ebc.zip
fix(app): hide default session timestamps (#20892)
Diffstat (limited to 'packages/app/src')
-rw-r--r--packages/app/src/pages/layout/sidebar-items.tsx77
-rw-r--r--packages/app/src/pages/session/message-timeline.tsx15
-rw-r--r--packages/app/src/utils/session-title.ts7
3 files changed, 57 insertions, 42 deletions
diff --git a/packages/app/src/pages/layout/sidebar-items.tsx b/packages/app/src/pages/layout/sidebar-items.tsx
index 75dada05f..058bb5a0d 100644
--- a/packages/app/src/pages/layout/sidebar-items.tsx
+++ b/packages/app/src/pages/layout/sidebar-items.tsx
@@ -16,6 +16,7 @@ import { getAvatarColors, type LocalProject, useLayout } from "@/context/layout"
import { useNotification } from "@/context/notification"
import { usePermission } from "@/context/permission"
import { messageAgentColor } from "@/utils/agent"
+import { sessionTitle } from "@/utils/session-title"
import { sessionPermissionRequest } from "../session/composer/session-request-tree"
import { hasProjectPermissions } from "./helpers"
@@ -101,42 +102,46 @@ const SessionRow = (props: {
warmPress: () => void
warmFocus: () => void
cancelHoverPrefetch: () => void
-}): JSX.Element => (
- <A
- 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"}`}
- onPointerDown={props.warmPress}
- onPointerEnter={props.warmHover}
- onPointerLeave={props.cancelHoverPrefetch}
- onFocus={props.warmFocus}
- onClick={() => {
- props.setHoverSession(undefined)
- if (props.sidebarOpened()) return
- props.clearHoverProjectSoon()
- }}
- >
- <div
- class="shrink-0 size-6 flex items-center justify-center"
- style={{ color: props.tint() ?? "var(--icon-interactive-base)" }}
+}) => {
+ const title = () => sessionTitle(props.session.title)
+
+ return (
+ <A
+ 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"}`}
+ onPointerDown={props.warmPress}
+ onPointerEnter={props.warmHover}
+ onPointerLeave={props.cancelHoverPrefetch}
+ onFocus={props.warmFocus}
+ onClick={() => {
+ props.setHoverSession(undefined)
+ if (props.sidebarOpened()) return
+ props.clearHoverProjectSoon()
+ }}
>
- <Switch fallback={<Icon name="dash" size="small" class="text-icon-weak" />}>
- <Match when={props.isWorking()}>
- <Spinner class="size-[15px]" />
- </Match>
- <Match when={props.hasPermissions()}>
- <div class="size-1.5 rounded-full bg-surface-warning-strong" />
- </Match>
- <Match when={props.hasError()}>
- <div class="size-1.5 rounded-full bg-text-diff-delete-base" />
- </Match>
- <Match when={props.unseenCount() > 0}>
- <div class="size-1.5 rounded-full bg-text-interactive-base" />
- </Match>
- </Switch>
- </div>
- <span class="text-14-regular text-text-strong min-w-0 flex-1 truncate">{props.session.title}</span>
- </A>
-)
+ <div
+ 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" />}>
+ <Match when={props.isWorking()}>
+ <Spinner class="size-[15px]" />
+ </Match>
+ <Match when={props.hasPermissions()}>
+ <div class="size-1.5 rounded-full bg-surface-warning-strong" />
+ </Match>
+ <Match when={props.hasError()}>
+ <div class="size-1.5 rounded-full bg-text-diff-delete-base" />
+ </Match>
+ <Match when={props.unseenCount() > 0}>
+ <div class="size-1.5 rounded-full bg-text-interactive-base" />
+ </Match>
+ </Switch>
+ </div>
+ <span class="text-14-regular text-text-strong min-w-0 flex-1 truncate">{title()}</span>
+ </A>
+ )
+}
const SessionHoverPreview = (props: {
mobile?: boolean
@@ -319,7 +324,7 @@ export const SessionItem = (props: SessionItemProps): JSX.Element => {
fallback={
<Tooltip
placement={props.mobile ? "bottom" : "right"}
- value={props.session.title}
+ value={sessionTitle(props.session.title)}
gutter={10}
class="min-w-0 w-full"
>
diff --git a/packages/app/src/pages/session/message-timeline.tsx b/packages/app/src/pages/session/message-timeline.tsx
index e1d6da195..cbabbda72 100644
--- a/packages/app/src/pages/session/message-timeline.tsx
+++ b/packages/app/src/pages/session/message-timeline.tsx
@@ -29,6 +29,7 @@ import { useSettings } from "@/context/settings"
import { useSDK } from "@/context/sdk"
import { useSync } from "@/context/sync"
import { messageAgentColor } from "@/utils/agent"
+import { sessionTitle } from "@/utils/session-title"
import { parseCommentNote, readCommentMetadata } from "@/utils/comment-note"
import { makeTimer } from "@solid-primitives/timer"
@@ -43,7 +44,6 @@ type MessageComment = {
const emptyMessages: MessageType[] = []
const idle = { type: "idle" as const }
-
type UserActions = {
fork?: (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)
})
const titleValue = createMemo(() => info()?.title)
+ const titleLabel = createMemo(() => sessionTitle(titleValue()))
const shareUrl = createMemo(() => info()?.share?.url)
const shareEnabled = createMemo(() => sync.data.config.share !== "disabled")
const parentID = createMemo(() => info()?.parentID)
@@ -399,7 +400,7 @@ export function MessageTimeline(props: {
const openTitleEditor = () => {
if (!sessionID()) return
- setTitle({ editing: true, draft: titleValue() ?? "" })
+ setTitle({ editing: true, draft: titleLabel() ?? "" })
requestAnimationFrame(() => {
titleRef?.focus()
titleRef?.select()
@@ -417,7 +418,7 @@ export function MessageTimeline(props: {
if (titleMutation.isPending) return
const next = title.draft.trim()
- if (!next || next === (titleValue() ?? "")) {
+ if (!next || next === (titleLabel() ?? "")) {
setTitle("editing", false)
return
}
@@ -532,7 +533,9 @@ export function MessageTimeline(props: {
}
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 () => {
await deleteSession(props.sessionID)
dialog.close()
@@ -673,7 +676,7 @@ export function MessageTimeline(props: {
</div>
</Show>
</div>
- <Show when={titleValue() || title.editing}>
+ <Show when={titleLabel() || title.editing}>
<Show
when={title.editing}
fallback={
@@ -681,7 +684,7 @@ export function MessageTimeline(props: {
class="text-14-medium text-text-strong truncate grow-1 min-w-0"
onDblClick={openTitleEditor}
>
- {titleValue()}
+ {titleLabel()}
</h1>
}
>
diff --git a/packages/app/src/utils/session-title.ts b/packages/app/src/utils/session-title.ts
new file mode 100644
index 000000000..ca04c0104
--- /dev/null
+++ b/packages/app/src/utils/session-title.ts
@@ -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
+}