fix: 使用有限换行以修复toast无宽度限制的问题 - #3515
Conversation
审阅者指南重构 Toast 通知系统,以支持叠放布局、鼠标悬停暂停、拖拽关闭,以及与详情对话框的联动,同时更新视觉设计并添加调试/测试钩子。 Toast 叠放与变暗生命周期的时序图sequenceDiagram
participant Timer
participant HintService
participant PanHint
participant MyToast
Timer->>HintService: Tick()
HintService->>PanHint: Children.Insert(0, toast)
HintService->>MyToast: Show()
MyToast->>HintService: NotifyToastShown(this)
HintService->>HintService: RearrangeToasts()
Note over HintService,MyToast: When limit reached
Timer->>HintService: Tick()
HintService->>PanHint: LastOrDefault(t)
HintService->>MyToast: Dismiss()
MyToast->>PanHint: Children.Remove(this)
MyToast->>HintService: OnToastRemoved(this)
HintService->>HintService: RearrangeToasts()
文件级变更
可能关联的问题
技巧与指令与 Sourcery 交互
自定义你的体验前往你的 控制面板:
获取帮助Original review guide in EnglishReviewer's GuideRefactors the toast notification system to support stacked layout, hover-pause, drag-close, and coordinated detail dialogs, while updating visual design and adding debug/testing hooks. Sequence diagram for toast stacking and dimming lifecyclesequenceDiagram
participant Timer
participant HintService
participant PanHint
participant MyToast
Timer->>HintService: Tick()
HintService->>PanHint: Children.Insert(0, toast)
HintService->>MyToast: Show()
MyToast->>HintService: NotifyToastShown(this)
HintService->>HintService: RearrangeToasts()
Note over HintService,MyToast: When limit reached
Timer->>HintService: Tick()
HintService->>PanHint: LastOrDefault(t)
HintService->>MyToast: Dismiss()
MyToast->>PanHint: Children.Remove(this)
MyToast->>HintService: OnToastRemoved(this)
HintService->>HintService: RearrangeToasts()
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - 我在这里给出了一些总体反馈:
_hideStartsAtTick标志位目前只会被设置,但当隐藏动画被取消时(例如在Emphasize、Dismiss、拖拽开始或鼠标悬停暂停时)从不会被清除,这可能导致IsHiding持续错误地为 true,从而阻塞变暗/悬停行为;建议在所有会停止隐藏动画的路径中将_hideStartsAtTick重置为 0。PageSetupLauncherMisc中的 toast 测试处理逻辑和 UI 虽然标记为仅用于调试,但目前仍被编译进主代码;建议将其包裹在明确的调试标志中,或者在合并前移除,以避免在生产构建中暴露内部测试入口。
提供给 AI Agents 的提示
请根据以下代码审查意见进行修改:
## 总体说明
- `_hideStartsAtTick` 标志位目前只会被设置,但当隐藏动画被取消时(例如在 `Emphasize`、`Dismiss`、拖拽开始或鼠标悬停暂停时)从不会被清除,这可能导致 `IsHiding` 持续错误地为 true,从而阻塞变暗/悬停行为;建议在所有会停止隐藏动画的路径中将 `_hideStartsAtTick` 重置为 0。
- `PageSetupLauncherMisc` 中的 toast 测试处理逻辑和 UI 虽然标记为仅用于调试,但目前仍被编译进主代码;建议将其包裹在明确的调试标志中,或者在合并前移除,以避免在生产构建中暴露内部测试入口。帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进后续评审。
Original comment in English
Hey - I've left some high level feedback:
- The
_hideStartsAtTickflag is only ever set and never cleared when hide animations are cancelled (e.g. inEmphasize,Dismiss, drag start, or hover pause), which can causeIsHidingto incorrectly remain true and block dimming/hover behavior; consider resetting_hideStartsAtTickto 0 in all paths that stop the hide animation. - The toast test handlers and UI in
PageSetupLauncherMiscare marked as debug-only but currently compiled into the main code; consider wrapping these in a clear debug flag or removing them before merge to avoid exposing internal test entry points in production builds.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The `_hideStartsAtTick` flag is only ever set and never cleared when hide animations are cancelled (e.g. in `Emphasize`, `Dismiss`, drag start, or hover pause), which can cause `IsHiding` to incorrectly remain true and block dimming/hover behavior; consider resetting `_hideStartsAtTick` to 0 in all paths that stop the hide animation.
- The toast test handlers and UI in `PageSetupLauncherMisc` are marked as debug-only but currently compiled into the main code; consider wrapping these in a clear debug flag or removing them before merge to avoid exposing internal test entry points in production builds.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3c9e58cdd4
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| <svgIcon:SvgIcon Grid.Row="0" x:Name="ToastTypeIcon" Width="18" Height="18" | ||
| HorizontalAlignment="Left" VerticalAlignment="Top" Margin="7,4,0,0" | ||
| UseOriginalColor="False" StrokeThickness="0" /> | ||
| <TextBlock Grid.Row="0" FontSize="23" TextTrimming="None" | ||
| HorizontalAlignment="Left" Name="LabTitle" Margin="31,-1,70,9" Text="测试标题文本" |
There was a problem hiding this comment.
Preserve default styling for ordinary dialogs
When existing MyMsgBox(...) calls create a MyMsgText, HintType stays null, so the constructor never assigns ToastTypeIcon.Icon or LabTitle.Foreground. With this unconditional icon slot and the removed ColorBrush2 foreground, ordinary text dialogs now get an empty 18px title gap and the system text brush instead of the previous themed title/divider; keep the default foreground and collapse or omit the icon unless a hint type is supplied.
Useful? React with 👍 / 👎.
| if (_pauseStartedAtTick > 0 && TimeUtils.GetTimeTick() - _pauseStartedAtTick >= _hoverRemainingMs) | ||
| { | ||
| StartHideAnimation(0); | ||
| return; |
There was a problem hiding this comment.
Resume the paused timeout after hover
If a user keeps the pointer over a toast longer than _hoverRemainingMs, this branch hides it immediately on MouseLeave, even though MouseEnter stopped the hide animation and froze the progress bar at the saved remaining width. That makes hover fail to actually pause long enough for users to read a toast—the toast vanishes as soon as they move away instead of resuming the saved remaining time shown by the bar.
Useful? React with 👍 / 👎.
|
既然说的是 toast 为什么要修改 MyMsg? 除此之外你使用了大量的模糊效果,首先这会对性能造成影响,除此之外也并没有很好的去凸显信息,视觉上看起来也没有很好地优化。并且不是很理解为什么堆叠的 MyToast 要加模糊效果。 |
Chiloven945
left a comment
There was a problem hiding this comment.
请严格遵守 技术规范 重新修整你的 PR:
- PR 中的所有 Commit 必须要附带有效的、已验证的签名。参考 提交信息规范-提交签名要求 章节与 GPG 签名配置指南。
- 如果使用了任意 AI 工具,应该在 PR 提交信息或者 Commit 信息内注明使用的模型、工具信息等。参考 项目开发规范-AI 工具使用规范 章节。
关于凸显信息和性能优化上我会再进行进一步处理 |
我认为通过遮挡关系和透明度调整,已经能够明确主次地位,多层窗口+毛玻璃看着像散光() |
Emmmm,我修改下 |
- TitleText MaxHeight 48→96,约 6 行 - 鼠标悬停 toast 时冻结进度条并停住隐藏倒计时,移出后按剩余时间续走;与拖拽互斥 - 重复触发强调动画改为三段回弹(-14/+18/-4),净位移归零
- Info 类型图标、楔形条、底部加载条改用主题色 ColorBrush2(动态跟随主题切换) - MyMsgBoxConverter 新增 HintType 字段,新增 MyMsgBoxByHintType 入口 - 点击 toast 展开的详情弹窗按提示类型显示图标与配色(Info 主题色,Error 标题与按钮变红)
- 滑出 200→150ms、淡出 150→110ms,消失更利落 - 新增 _hideStartsAtTick 记录倒计时终点:进入滑出阶段后悬停不再暂停, 杜绝停掉半途隐藏导致卡半透明、永不消失;MouseLeave 异常路径直接放行消失
- 标题与分割线颜色跟随图标(toast 类型色),仅 HintType 非空时生效;普通警告弹窗的红色标题不受影响 - 按钮区新增复制按钮,点击把正文写入剪贴板(复用 Common.Action.Copy)
- 按叠置次序淡化:最新 1.0,旧弹窗递减至 55% 下限,200ms 过渡 - 入场中/拖拽中/隐藏滑出中的弹窗淡化系统不介入,避免 Opacity 动画冲突 - 入场结束经 NotifyToastShown 复位并重新分层;Emphasize/拖拽中断入场时复位 IsEntering,防止淡化被永久跳过
- 复制按钮从底部右侧按钮组独立到左下,确认/取消按钮组保持右侧 - toast 文本 MaxHeight 96→32(2 行),长文本点击展开看详情 - 关闭按钮 20→26px,图标随按钮自适应放大
- RootGrid 挂 BlurEffect 模糊卡片内容,背景迁移到 RootGrid 一起模糊(8px 圆角裁剪) - 模糊与淡化同组联动:最新清晰,旧弹窗 BlurRadius 按叠置次序 5+i*4.5 递增、封顶 14 - ResetDimBlur 统一复位时机:隐藏滑出/拖拽/强调前清零,防止残留模糊
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c1bd81cdd2
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| var toasts = ModMain.frmMain.PanHint.Children.OfType<MyToast>().Where(t => !t.IsDismissing).ToList(); | ||
| for (var i = 0; i < toasts.Count; i++) | ||
| { | ||
| var t = toasts[i]; // Children 顺序,索引 0 = 最新 |
There was a problem hiding this comment.
Promote duplicate toasts before emphasizing
When a duplicate hint matches a toast that is no longer index 0, this new stacked layout still derives position and z-order from the existing child order, so Emphasize() shakes a card that remains behind newer toasts with only the ToastPeek strip visible and then gets dimmed again by RearrangeToasts(). Duplicate notifications can therefore be effectively hidden instead of being re-shown; move the duplicate child to the front or otherwise promote it before emphasizing.
Useful? React with 👍 / 👎.
|
这 Z 重叠是背后模糊了吗还是只是截图效果 |
做的透明度增加,原来还有个总的毛玻璃罩在上面,取消掉了 |
|
我反倒觉得原来的设计更好: 实际使用过程中,除了调试模式,很少出现一段时间内有大量 toast 的情况,如果之后出现这种情况也应该是发送 toast 方的设计问题。 toast 设计参考的是 Nuxt UI 对于 toast 的设计,其中就是将多条 toast 平铺。新的 toast 在旧的的上面,这样能够增加信息的可读性。不出意外这个新的设计是等前面一条展示完再展示下一条,这并没有很好地改善可读性,或者说原来的可读性并没有被改善的必要,因此完全没有必要将 toast 改为堆叠式,反而会降低信息密度。 除此之外,在 toast 左侧加一个颜色 bar 也不是一个很好的设计。首先从视觉上来看就并不是很好,像是给 toast 做了半个 outline,并且因为圆角的原因会存在看起来很生硬的直角,这和既有的视觉体系冲突。如果去掉底部 bar 单看的话还不错,但是底部 bar 承载除了颜色 toast 类型表示还有对于时间的表示,是不能删除的。 可以采纳的设计有对 toast 实施换行和在 MyMsg 旁添加 SvgIcon。SvgIcon 考虑不在下方横线上,放在横线和文字的左边。但这些功能不应该放在一个 PR 里,不应该出现一堆不相关的功能放进一个 PR 的情况,考虑拆分为多个 PR。 |
|
好的,那我回撤下关于z轴堆叠和左侧颜色的设计,此PR仅对toast的换行、宽度限制、回弹动效进行修改 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d2b244e91b
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| var toasts = ModMain.frmMain.PanHint.Children.OfType<MyToast>().Where(t => !t.IsDismissing).ToList(); | ||
| if (toasts.Count == 0) | ||
| return; | ||
| var available = ModMain.frmMain.PanHint.ActualHeight; |
There was a problem hiding this comment.
Use viewport height when culling stacked toasts
When more than one toast is shown after the first one has laid out, PanHint.ActualHeight is only the auto-sized height of the current toast panel: PanHint is a bottom-aligned Grid in FormMain.xaml, and Tick() keeps it bottom-aligned rather than stretching it to the window. That makes available roughly the height of the existing stack, so the new required value for two toasts exceeds it and this path dismisses the oldest toast; burst or sequential hints therefore never actually stack. Use the parent/window available height for this overflow check, or remove the check until the panel is measured against the viewport.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2ab35e13f0
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| private void ShowDetail() | ||
| { | ||
| if (IsDismissing) return; | ||
| ModMain.MyMsgBox(Context, Lang.Text("Main.Toast.Detail.Title"), Lang.Text("Common.Action.Confirm")); |
There was a problem hiding this comment.
Add a copy path to toast details
When a long or truncated toast is clicked, this path opens the standard MyMsgBox with only an OK button. That dialog renders the caption in MyMsgText as a non-selectable TextBlock and has no clipboard action, so users still cannot copy the full error/warning text from the new detail view; include a copy button/action or selectable text for this detail dialog.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 67174cf7e1
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| System.IO.File.AppendAllText(@"C:\Users\imagi\AppData\Local\Temp\opencode\toast-debug.log", | ||
| $"REMOVED toast={Uuid} tick={TimeUtils.GetTimeTick()}\n"); |
There was a problem hiding this comment.
Remove author-local toast debug logging
When C:\Users\imagi\AppData\Local\Temp\opencode does not exist, which is the normal case for other users, this AppendAllText in the auto-hide callback throws before p.Children.Remove(this) and HintService.OnToastRemoved(this) run. The animation runner catches the exception and drops the code animation, leaving the hidden toast in PanHint; after five expired toasts, the activeCount >= 5 path keeps trying the same debug-writing Dismiss() path and no later hints can be shown. Remove the local-file tracing or route it through the app logger/temp path with directory creation.
Useful? React with 👍 / 👎.
|
https://github.com/user-attachments/assets/d6d896da-830e-432d-952c-a9f0d9aedc8f |
|
请先删除 debug 代码。你可以添加用于调试的代码,但是不应该将他和实际功能代码一并提交至 PR 内。 |
|
相关debug功能已全部删除 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2bef2828bf
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| ModAnimation.AniStop($"Toast Hide {Uuid}"); | ||
| ModAnimation.AniStop($"Toast Emphasize {Uuid}"); | ||
| ModAnimation.AniStop($"Toast Drag Return {Uuid}"); | ||
| _hideStartsAtTick = 0; // 拖拽取消隐藏倒计时,复位标志避免 IsHiding 误判 |
There was a problem hiding this comment.
Clear hover pause state when starting drag
When a toast is already hover-paused and the user drags it far enough to enter BeginDrag but releases without dismissing, this path cancels the hide timer and ReturnFromDrag() starts a fresh timer, but _pausedByHover remains true with the old _hoverRemainingMs. The next Root_MouseLeave then treats the stale hover pause as active and replaces the resumed timer with the old remaining time, or hides immediately if the original pause interval elapsed; clear the hover pause state here when drag takes over the progress/timer.
Useful? React with 👍 / 👎.


概括
本次更新重构 Toast 提示系统:
注意
Important
包含debug用组件,确认合并前请@我删除相关无用代码
Summary by Sourcery
重构 toast 通知系统,以改进布局、堆叠方式和视觉层级,并让详情对话框与 toast 类型保持一致。
New Features:
Bug Fixes:
Enhancements:
Original summary in English
Summary by Sourcery
Refactor the toast notification system to improve layout, stacking, and visual hierarchy while aligning detail dialogs with toast types.
New Features:
Bug Fixes:
Enhancements: