Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
B
bit-pm
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
燕伟桐
bit-pm
Commits
66e37c3e
Unverified
提交
66e37c3e
authored
3月 19, 2026
作者:
Mohamed Aziz Mejri
提交者:
GitHub
3月 19, 2026
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Adding notification for planning questionnaire (#3028)
closes #2808 --------- Co-authored-by:
Claude Opus 4.5
<
noreply@anthropic.com
>
上级
4fb6701b
隐藏空白字符变更
内嵌
并排
正在显示
10 个修改的文件
包含
55 行增加
和
34 行删除
+55
-34
notification_banner.spec.ts
e2e-tests/notification_banner.spec.ts
+3
-5
notification_banner.spec.ts_notification-banner---Enable-enables-notifications-and-hides-banner-1.txt
...ner---Enable-enables-notifications-and-hides-banner-1.txt
+2
-2
ChatEventNotificationSwitch.tsx
src/components/ChatEventNotificationSwitch.tsx
+3
-5
NotificationBanner.tsx
src/components/chat/NotificationBanner.tsx
+2
-2
useEnableNotifications.ts
src/hooks/useEnableNotifications.ts
+4
-4
usePlanEvents.ts
src/hooks/usePlanEvents.ts
+17
-1
useStreamChat.ts
src/hooks/useStreamChat.ts
+1
-1
schemas.ts
src/lib/schemas.ts
+6
-1
settingsSearchIndex.ts
src/lib/settingsSearchIndex.ts
+12
-5
settings.tsx
src/pages/settings.tsx
+5
-8
没有找到文件。
e2e-tests/notification_banner.spec.ts
浏览文件 @
66e37c3e
...
...
@@ -9,7 +9,7 @@ const testWithNotificationsEnabled = testWithConfig({
fs
.
mkdirSync
(
userDataDir
,
{
recursive
:
true
});
fs
.
writeFileSync
(
path
.
join
(
userDataDir
,
"user-settings.json"
),
JSON
.
stringify
({
enableChat
Completion
Notifications
:
true
},
null
,
2
),
JSON
.
stringify
({
enableChat
Event
Notifications
:
true
},
null
,
2
),
);
},
});
...
...
@@ -21,9 +21,7 @@ test("notification banner - skip hides permanently", async ({ po }) => {
// Banner should be visible since notifications are not enabled
const
banner
=
po
.
page
.
getByTestId
(
"notification-tip-banner"
);
await
expect
(
banner
).
toBeVisible
();
await
expect
(
banner
).
toContainText
(
"Get notified when chat responses finish."
,
);
await
expect
(
banner
).
toContainText
(
"Get notified about chat events."
);
// Record settings before skipping
const
beforeSettings
=
po
.
settings
.
recordSettings
();
...
...
@@ -69,7 +67,7 @@ test("notification banner - Enable enables notifications and hides banner", asyn
// Banner should be hidden after enabling
await
expect
(
banner
).
not
.
toBeVisible
();
// Verify settings were updated with enableChat
Completion
Notifications: true
// Verify settings were updated with enableChat
Event
Notifications: true
po
.
settings
.
snapshotSettingsDelta
(
beforeSettings
);
// Navigate away and back to verify banner stays hidden
...
...
e2e-tests/snapshots/notification_banner.spec.ts_notification-banner---Enable-enables-notifications-and-hides-banner-1.txt
浏览文件 @
66e37c3e
+ "enableChatCompletionNotifications": true
\ No newline at end of file
+ "enableChatEventNotifications": true
\ No newline at end of file
src/components/Chat
Completion
NotificationSwitch.tsx
→
src/components/Chat
Event
NotificationSwitch.tsx
浏览文件 @
66e37c3e
...
...
@@ -3,7 +3,7 @@ import { Switch } from "@/components/ui/switch";
import
{
MacNotificationGuideDialog
}
from
"./MacNotificationGuideDialog"
;
import
{
useEnableNotifications
}
from
"@/hooks/useEnableNotifications"
;
export
function
Chat
Completion
NotificationSwitch
()
{
export
function
Chat
Event
NotificationSwitch
()
{
const
{
isEnabled
,
enable
,
disable
,
showMacGuide
,
setShowMacGuide
}
=
useEnableNotifications
();
...
...
@@ -11,7 +11,7 @@ export function ChatCompletionNotificationSwitch() {
<>
<
div
className=
"flex items-center space-x-2"
>
<
Switch
id=
"chat-
completion
-notifications"
id=
"chat-
event
-notifications"
checked=
{
isEnabled
}
onCheckedChange=
{
async
(
checked
)
=>
{
if
(
checked
)
{
...
...
@@ -21,9 +21,7 @@ export function ChatCompletionNotificationSwitch() {
}
}
}
/>
<
Label
htmlFor=
"chat-completion-notifications"
>
Show notification when chat completes
</
Label
>
<
Label
htmlFor=
"chat-event-notifications"
>
Enable notifications
</
Label
>
</
div
>
<
MacNotificationGuideDialog
open=
{
showMacGuide
}
...
...
src/components/chat/NotificationBanner.tsx
浏览文件 @
66e37c3e
...
...
@@ -10,7 +10,7 @@ export function NotificationBanner() {
const
showBanner
=
settings
&&
settings
.
enableChat
Completion
Notifications
!==
true
&&
settings
.
enableChat
Event
Notifications
!==
true
&&
settings
.
skipNotificationBanner
!==
true
;
const
handleSkip
=
()
=>
{
...
...
@@ -22,7 +22,7 @@ export function NotificationBanner() {
{
showBanner
&&
(
<
SkippableBanner
icon=
{
Bell
}
message=
"Get notified
when chat responses finish
."
message=
"Get notified
about chat events
."
enableLabel=
"Enable"
onEnable=
{
enable
}
onSkip=
{
handleSkip
}
...
...
src/hooks/useEnableNotifications.ts
浏览文件 @
66e37c3e
...
...
@@ -5,7 +5,7 @@ import { detectIsMac } from "@/hooks/useChatModeToggle";
function
sendTestNotification
()
{
if
(
Notification
.
permission
===
"granted"
)
{
new
Notification
(
"Dyad"
,
{
body
:
"Notifications are working! You'll be notified when
chat responses complete
."
,
body
:
"Notifications are working! You'll be notified when
responses finish or input is needed
."
,
});
}
}
...
...
@@ -13,7 +13,7 @@ function sendTestNotification() {
export
function
useEnableNotifications
()
{
const
{
settings
,
updateSettings
}
=
useSettings
();
const
[
showMacGuide
,
setShowMacGuide
]
=
useState
(
false
);
const
isEnabled
=
settings
?.
enableChat
Completion
Notifications
===
true
;
const
isEnabled
=
settings
?.
enableChat
Event
Notifications
===
true
;
const
isMac
=
detectIsMac
();
const
openMacGuide
=
useCallback
(()
=>
{
if
(
isMac
)
{
...
...
@@ -33,13 +33,13 @@ export function useEnableNotifications() {
return
;
}
}
await
updateSettings
({
enableChat
Completion
Notifications
:
true
});
await
updateSettings
({
enableChat
Event
Notifications
:
true
});
sendTestNotification
();
openMacGuide
();
},
[
updateSettings
,
openMacGuide
]);
const
disable
=
useCallback
(
async
()
=>
{
await
updateSettings
({
enableChat
Completion
Notifications
:
false
});
await
updateSettings
({
enableChat
Event
Notifications
:
false
});
},
[
updateSettings
]);
return
{
isEnabled
,
enable
,
disable
,
showMacGuide
,
setShowMacGuide
};
...
...
src/hooks/usePlanEvents.ts
浏览文件 @
66e37c3e
...
...
@@ -18,7 +18,7 @@ import {
type
PlanExitPayload
,
type
PlanQuestionnairePayload
,
}
from
"@/ipc/types/plan"
;
import
{
ipc
}
from
"@/ipc/types"
;
import
{
ipc
,
type
App
}
from
"@/ipc/types"
;
import
{
showError
}
from
"@/lib/toast"
;
/**
...
...
@@ -177,6 +177,22 @@ export function usePlanEvents() {
next
.
set
(
payload
.
chatId
,
payload
);
return
next
;
});
// Show native notification if enabled and window is not focused
const
notificationsEnabled
=
settingsRef
.
current
?.
enableChatEventNotifications
===
true
;
if
(
notificationsEnabled
&&
Notification
.
permission
===
"granted"
&&
!
document
.
hasFocus
()
)
{
const
app
=
queryClient
.
getQueryData
<
App
|
null
>
(
queryKeys
.
apps
.
detail
({
appId
:
selectedAppIdRef
.
current
!
}),
);
new
Notification
(
app
?.
name
??
"Dyad"
,
{
body
:
"A questionnaire needs your input"
,
});
}
},
);
...
...
src/hooks/useStreamChat.ts
浏览文件 @
66e37c3e
...
...
@@ -229,7 +229,7 @@ export function useStreamChat({
// Show native notification if enabled and window is not focused
// Fire-and-forget to avoid blocking UI updates
const
notificationsEnabled
=
settings
?.
enableChat
Completion
Notifications
===
true
;
settings
?.
enableChat
Event
Notifications
===
true
;
if
(
notificationsEnabled
&&
Notification
.
permission
===
"granted"
&&
...
...
src/lib/schemas.ts
浏览文件 @
66e37c3e
...
...
@@ -331,7 +331,7 @@ const BaseUserSettingsFields = {
enableAutoFixProblems
:
z
.
boolean
().
optional
(),
autoExpandPreviewPanel
:
z
.
boolean
().
optional
(),
enableChat
Completion
Notifications
:
z
.
boolean
().
optional
(),
enableChat
Event
Notifications
:
z
.
boolean
().
optional
(),
enableNativeGit
:
z
.
boolean
().
optional
(),
enableMcpServersForBuildMode
:
z
.
boolean
().
optional
(),
enableAutoUpdate
:
z
.
boolean
(),
...
...
@@ -365,6 +365,8 @@ export const StoredUserSettingsSchema = z
// Use StoredChatModeSchema to allow deprecated "agent" value
selectedChatMode
:
StoredChatModeSchema
.
optional
(),
defaultChatMode
:
StoredChatModeSchema
.
optional
(),
// Deprecated: renamed to enableChatEventNotifications
enableChatCompletionNotifications
:
z
.
boolean
().
optional
(),
})
// Allow unknown properties to pass through (e.g. future settings
// that should be preserved if user downgrades to an older version)
...
...
@@ -419,6 +421,9 @@ export function migrateStoredSettings(
...
stored
,
selectedChatMode
:
migrateStoredChatMode
(
stored
.
selectedChatMode
),
defaultChatMode
:
migrateStoredChatMode
(
stored
.
defaultChatMode
),
enableChatEventNotifications
:
stored
.
enableChatEventNotifications
??
stored
.
enableChatCompletionNotifications
,
};
}
...
...
src/lib/settingsSearchIndex.ts
浏览文件 @
66e37c3e
...
...
@@ -22,7 +22,7 @@ export const SETTING_IDS = {
autoApprove
:
"setting-auto-approve"
,
autoFix
:
"setting-auto-fix"
,
autoExpandPreview
:
"setting-auto-expand-preview"
,
chat
CompletionNotification
:
"setting-chat-completion
-notification"
,
chat
EventNotification
:
"setting-chat-event
-notification"
,
thinkingBudget
:
"setting-thinking-budget"
,
maxChatTurns
:
"setting-max-chat-turns"
,
maxToolCallSteps
:
"setting-max-tool-call-steps"
,
...
...
@@ -134,11 +134,18 @@ export const SETTINGS_SEARCH_INDEX: SearchableSettingItem[] = [
sectionLabel
:
"Workflow"
,
},
{
id
:
SETTING_IDS
.
chat
Completion
Notification
,
label
:
"
Chat Completion Notification
"
,
id
:
SETTING_IDS
.
chat
Event
Notification
,
label
:
"
Notifications
"
,
description
:
"Show a native notification when a chat response completes while the app is not focused"
,
keywords
:
[
"notification"
,
"chat"
,
"complete"
,
"alert"
,
"background"
],
"Show native notifications when a chat response completes or a questionnaire needs your input while the app is not focused"
,
keywords
:
[
"notification"
,
"chat"
,
"complete"
,
"questionnaire"
,
"alert"
,
"background"
,
],
sectionId
:
SECTION_IDS
.
workflow
,
sectionLabel
:
"Workflow"
,
},
...
...
src/pages/settings.tsx
浏览文件 @
66e37c3e
...
...
@@ -22,7 +22,7 @@ import { Switch } from "@/components/ui/switch";
import
{
Label
}
from
"@/components/ui/label"
;
import
{
AutoFixProblemsSwitch
}
from
"@/components/AutoFixProblemsSwitch"
;
import
{
AutoExpandPreviewSwitch
}
from
"@/components/AutoExpandPreviewSwitch"
;
import
{
Chat
CompletionNotificationSwitch
}
from
"@/components/ChatCompletion
NotificationSwitch"
;
import
{
Chat
EventNotificationSwitch
}
from
"@/components/ChatEvent
NotificationSwitch"
;
import
{
AutoUpdateSwitch
}
from
"@/components/AutoUpdateSwitch"
;
import
{
ReleaseChannelSelector
}
from
"@/components/ReleaseChannelSelector"
;
import
{
NeonIntegration
}
from
"@/components/NeonIntegration"
;
...
...
@@ -408,14 +408,11 @@ export function WorkflowSettings() {
</
div
>
</
div
>
<
div
id=
{
SETTING_IDS
.
chatCompletionNotification
}
className=
"space-y-1 mt-4"
>
<
ChatCompletionNotificationSwitch
/>
<
div
id=
{
SETTING_IDS
.
chatEventNotification
}
className=
"space-y-1 mt-4"
>
<
ChatEventNotificationSwitch
/>
<
div
className=
"text-sm text-gray-500 dark:text-gray-400"
>
Show
a native notification when a chat response completes while the
app is not focused.
Show
native notifications when a chat response completes or a
questionnaire needs your input while the
app is not focused.
</
div
>
</
div
>
</
div
>
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论