summaryrefslogtreecommitdiffhomepage
path: root/packages/app/src/context/notification.tsx
diff options
context:
space:
mode:
authorAdam <[email protected]>2026-01-06 21:38:08 -0600
committerAdam <[email protected]>2026-01-06 21:42:03 -0600
commit761863ae355b3ca1e606ea5eb2106772fa763c19 (patch)
treef8fef26687875e75f4279b6695e35a33977b728c /packages/app/src/context/notification.tsx
parentdadc08ddc7f3c9b1a34e6f401a99406b6714b965 (diff)
downloadopencode-761863ae355b3ca1e606ea5eb2106772fa763c19.tar.gz
opencode-761863ae355b3ca1e606ea5eb2106772fa763c19.zip
chore(app): rework storage approach
Diffstat (limited to 'packages/app/src/context/notification.tsx')
-rw-r--r--packages/app/src/context/notification.tsx33
1 files changed, 28 insertions, 5 deletions
diff --git a/packages/app/src/context/notification.tsx b/packages/app/src/context/notification.tsx
index 09f32a3c4..16b3d306c 100644
--- a/packages/app/src/context/notification.tsx
+++ b/packages/app/src/context/notification.tsx
@@ -1,5 +1,5 @@
import { createStore } from "solid-js/store"
-import { onCleanup } from "solid-js"
+import { createEffect, onCleanup } from "solid-js"
import { createSimpleContext } from "@opencode-ai/ui/context"
import { useGlobalSDK } from "./global-sdk"
import { useGlobalSync } from "./global-sync"
@@ -10,7 +10,7 @@ import { EventSessionError } from "@opencode-ai/sdk/v2"
import { makeAudioPlayer } from "@solid-primitives/audio"
import idleSound from "@opencode-ai/ui/audio/staplebops-01.aac"
import errorSound from "@opencode-ai/ui/audio/nope-03.aac"
-import { persisted } from "@/utils/persist"
+import { Persist, persisted } from "@/utils/persist"
type NotificationBase = {
directory?: string
@@ -31,6 +31,16 @@ type ErrorNotification = NotificationBase & {
export type Notification = TurnCompleteNotification | ErrorNotification
+const MAX_NOTIFICATIONS = 500
+const NOTIFICATION_TTL_MS = 1000 * 60 * 60 * 24 * 30
+
+function pruneNotifications(list: Notification[]) {
+ const cutoff = Date.now() - NOTIFICATION_TTL_MS
+ const pruned = list.filter((n) => n.time >= cutoff)
+ if (pruned.length <= MAX_NOTIFICATIONS) return pruned
+ return pruned.slice(pruned.length - MAX_NOTIFICATIONS)
+}
+
export const { use: useNotification, provider: NotificationProvider } = createSimpleContext({
name: "Notification",
init: () => {
@@ -49,12 +59,25 @@ export const { use: useNotification, provider: NotificationProvider } = createSi
const platform = usePlatform()
const [store, setStore, _, ready] = persisted(
- "notification.v1",
+ Persist.global("notification", ["notification.v1"]),
createStore({
list: [] as Notification[],
}),
)
+ const meta = { pruned: false }
+
+ createEffect(() => {
+ if (!ready()) return
+ if (meta.pruned) return
+ meta.pruned = true
+ setStore("list", pruneNotifications(store.list))
+ })
+
+ const append = (notification: Notification) => {
+ setStore("list", (list) => pruneNotifications([...list, notification]))
+ }
+
const unsub = globalSDK.event.listen((e) => {
const directory = e.name
const event = e.details
@@ -73,7 +96,7 @@ export const { use: useNotification, provider: NotificationProvider } = createSi
try {
idlePlayer?.play()
} catch {}
- setStore("list", store.list.length, {
+ append({
...base,
type: "turn-complete",
session: sessionID,
@@ -92,7 +115,7 @@ export const { use: useNotification, provider: NotificationProvider } = createSi
errorPlayer?.play()
} catch {}
const error = "error" in event.properties ? event.properties.error : undefined
- setStore("list", store.list.length, {
+ append({
...base,
type: "error",
session: sessionID ?? "global",