From 6326ec2f3512f3a7530e53208c80b877e61928f2 Mon Sep 17 00:00:00 2001 From: uye <99072975+ABA2396@users.noreply.github.com> Date: Sat, 16 May 2026 00:56:53 +0800 Subject: [PATCH 1/7] =?UTF-8?q?chore:=20=E5=88=A0=E9=99=A4=E8=BE=85?= =?UTF-8?q?=E5=8A=A9=E5=BB=BA=E8=AE=BE=E6=A8=A1=E5=BC=8F=E7=9A=84=E6=8F=8F?= =?UTF-8?q?=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/MaaMacGui | 2 +- src/MaaWpfGui/Res/Localizations/en-us.xaml | 2 +- src/MaaWpfGui/Res/Localizations/ja-jp.xaml | 2 +- src/MaaWpfGui/Res/Localizations/ko-kr.xaml | 2 +- src/MaaWpfGui/Res/Localizations/zh-cn.xaml | 2 +- src/MaaWpfGui/Res/Localizations/zh-tw.xaml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/MaaMacGui b/src/MaaMacGui index 5310fcf571..7eed483002 160000 --- a/src/MaaMacGui +++ b/src/MaaMacGui @@ -1 +1 @@ -Subproject commit 5310fcf571606f852cad3db7f1fdc5c967da7053 +Subproject commit 7eed4830027010efb4f8218b1f29ad51dc77d3d4 diff --git a/src/MaaWpfGui/Res/Localizations/en-us.xaml b/src/MaaWpfGui/Res/Localizations/en-us.xaml index c706795006..e57e0b41b9 100644 --- a/src/MaaWpfGui/Res/Localizations/en-us.xaml +++ b/src/MaaWpfGui/Res/Localizations/en-us.xaml @@ -1463,7 +1463,7 @@ Cache files (such as maps, operator avatars, etc.) need to be regenerated after -Relaunch Anchor - Assisted Construction Mode: +Relaunch Anchor: Reward estimate: ~159 tokens + coordination points per run, ~3 min per round diff --git a/src/MaaWpfGui/Res/Localizations/ja-jp.xaml b/src/MaaWpfGui/Res/Localizations/ja-jp.xaml index d2636ac84e..cbc886a3d0 100644 --- a/src/MaaWpfGui/Res/Localizations/ja-jp.xaml +++ b/src/MaaWpfGui/Res/Localizations/ja-jp.xaml @@ -1464,7 +1464,7 @@ DEBUGディレクトリに保存される画像には数量制限があり、超 -再起の錨 - 支援建設モード: +再起の錨: 報酬目安:1回あたり約159トークン+統括ポイント、所要時間約3分 diff --git a/src/MaaWpfGui/Res/Localizations/ko-kr.xaml b/src/MaaWpfGui/Res/Localizations/ko-kr.xaml index d2249241e4..1096acf4c1 100644 --- a/src/MaaWpfGui/Res/Localizations/ko-kr.xaml +++ b/src/MaaWpfGui/Res/Localizations/ko-kr.xaml @@ -1465,7 +1465,7 @@ DEBUG 디렉토리에 저장된 이미지는 수량 제한이 있으며 초과 -재시작 앵커 - 지원 건설 모드: +재시작 앵커: 수익 참고: 회당 약 159토큰 + 통괄 포인트, 소요 시간 약 3분 diff --git a/src/MaaWpfGui/Res/Localizations/zh-cn.xaml b/src/MaaWpfGui/Res/Localizations/zh-cn.xaml index 38fb3ddbd5..7188865210 100644 --- a/src/MaaWpfGui/Res/Localizations/zh-cn.xaml +++ b/src/MaaWpfGui/Res/Localizations/zh-cn.xaml @@ -1464,7 +1464,7 @@ DEBUG 目录下保存的图片有数量限制,超出后会自动清理旧图 -重启锚点 - 辅助建设模式: +重启锚点: 收益参考:每把约 159 代币 + 统筹点数,单轮耗时约 3 分钟 diff --git a/src/MaaWpfGui/Res/Localizations/zh-tw.xaml b/src/MaaWpfGui/Res/Localizations/zh-tw.xaml index 5c6838e530..d60320ffdb 100644 --- a/src/MaaWpfGui/Res/Localizations/zh-tw.xaml +++ b/src/MaaWpfGui/Res/Localizations/zh-tw.xaml @@ -1464,7 +1464,7 @@ DEBUG 目錄下儲存的圖片有數量限制,超出後會自動清理舊圖 -重啟錨點 - 輔助建設模式: +重啟錨點: 收益參考:每把約 159 代幣 + 統籌點數,單輪耗時約 3 分 From 24886bb695cd749ae19aabd0d1654b9f7f00c27d Mon Sep 17 00:00:00 2001 From: uye <99072975+ABA2396@users.noreply.github.com> Date: Sat, 16 May 2026 02:02:07 +0800 Subject: [PATCH 2/7] =?UTF-8?q?chore:=20=E6=B7=BB=E5=8A=A0=E6=8B=86?= =?UTF-8?q?=E9=99=A4=E8=AE=BE=E6=96=BD=E7=9A=84=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/MaaWpfGui/Res/Localizations/en-us.xaml | 2 +- src/MaaWpfGui/Res/Localizations/ja-jp.xaml | 2 +- src/MaaWpfGui/Res/Localizations/ko-kr.xaml | 2 +- src/MaaWpfGui/Res/Localizations/zh-cn.xaml | 2 +- src/MaaWpfGui/Res/Localizations/zh-tw.xaml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/MaaWpfGui/Res/Localizations/en-us.xaml b/src/MaaWpfGui/Res/Localizations/en-us.xaml index e57e0b41b9..726859e906 100644 --- a/src/MaaWpfGui/Res/Localizations/en-us.xaml +++ b/src/MaaWpfGui/Res/Localizations/en-us.xaml @@ -1471,7 +1471,7 @@ Relaunch Anchor: 1. Manually enter RA-1, complete the tutorial, and return to the map 2. After that, the task can be started when "Start Construction" appears at the bottom-right after clicking RA-1 - Note: If the "Start with Extra Device" technology is unlocked, this task will not work properly + Note: If you have unlocked technologies related to starting with extra items, please dismantle the facilities in the base that cause starting with extra items, such as Food Supply Stations, Drink Supply Stations, Large Animal Pens, etc. Task flow: Automatically executes farming, construction, resource delivery, and settlement loop diff --git a/src/MaaWpfGui/Res/Localizations/ja-jp.xaml b/src/MaaWpfGui/Res/Localizations/ja-jp.xaml index cbc886a3d0..931001ed7c 100644 --- a/src/MaaWpfGui/Res/Localizations/ja-jp.xaml +++ b/src/MaaWpfGui/Res/Localizations/ja-jp.xaml @@ -1472,7 +1472,7 @@ DEBUGディレクトリに保存される画像には数量制限があり、超 1. 手動でRA-1に入り、チュートリアルを完了してマップに戻る 2. 以降、RA-1をクリックした後に右下に「建設開始」が表示されたらタスクを開始可能 - 注意:「初期追加携帯装置」のテクノロジーをアンロックしていると正常に動作しません + 注意:「初期追加携帯アイテム」に関連するテクノロジーをアンロックしている場合、基地内で初期追加携帯アイテムの原因となる施設(食品供給所、飲料供給所、大型獣舎など)を解体してください タスクの流れ: 精耕細作、建設、資源納入、決済を自動実行 diff --git a/src/MaaWpfGui/Res/Localizations/ko-kr.xaml b/src/MaaWpfGui/Res/Localizations/ko-kr.xaml index 1096acf4c1..4bd5d13fad 100644 --- a/src/MaaWpfGui/Res/Localizations/ko-kr.xaml +++ b/src/MaaWpfGui/Res/Localizations/ko-kr.xaml @@ -1473,7 +1473,7 @@ DEBUG 디렉토리에 저장된 이미지는 수량 제한이 있으며 초과 1. 수동으로 RA-1에 진입하여 튜토리얼을 완료하고 맵으로 돌아옵니다 2. 이후 RA-1 클릭 후 오른쪽 아래에 "건설 시작"이 나타나면 작업을 시작할 수 있습니다 - 참고: "초기 추가 장비 휴대" 기술을 해제한 경우 정상 작동하지 않습니다 + 참고: 초기 추가 아이템 휴대 관련 기술을 해제한 경우, 기지 내에서 초기 추가 아이템을 휴대하게 하는 시설(식품 공급소, 음료 공급소, 대형 축사 등)을 철거하세요 작업 흐름: 정경세작, 건설, 자원 납품, 결제를 자동 실행 diff --git a/src/MaaWpfGui/Res/Localizations/zh-cn.xaml b/src/MaaWpfGui/Res/Localizations/zh-cn.xaml index 7188865210..54c1237baa 100644 --- a/src/MaaWpfGui/Res/Localizations/zh-cn.xaml +++ b/src/MaaWpfGui/Res/Localizations/zh-cn.xaml @@ -1472,7 +1472,7 @@ DEBUG 目录下保存的图片有数量限制,超出后会自动清理旧图 1. 手动进入 RA-1,完成新手教程,直到回到大地图 2. 之后每次任务均可在 RA-1 右下角出现“开启建设”时启动 - 注意:如果已解锁开局额外携带装置的科技,将无法正常使用 + 注意:如果已解锁开局额外携带物品的相关科技,请将基地内会导致开局额外携带物品的设施拆除,如食品供给站、饮品供给站、大型兽栏等 任务流程: 自动执行精耕细作、建设、交付资源、结算循环 diff --git a/src/MaaWpfGui/Res/Localizations/zh-tw.xaml b/src/MaaWpfGui/Res/Localizations/zh-tw.xaml index d60320ffdb..205e32bc81 100644 --- a/src/MaaWpfGui/Res/Localizations/zh-tw.xaml +++ b/src/MaaWpfGui/Res/Localizations/zh-tw.xaml @@ -1472,7 +1472,7 @@ DEBUG 目錄下儲存的圖片有數量限制,超出後會自動清理舊圖 1. 手動進入 RA-1,完成新手教學,直到回到大地圖 2. 之後每次任務均可在 RA-1 右下角出現「開啟建設」時啟動 - 注意:如果已解鎖開局額外攜帶裝置的科技,將無法正常使用 + 注意:如果已解鎖開局額外攜帶物品的相關科技,請將基地內會導致開局額外攜帶物品的設施拆除,如食品供給站、飲品供給站、大型獸欄等 任務流程: 自動執行精耕細作、建設、交付資源、結算循環 From ea8a4ccb33a7182a1c97816f01064ff8b7330e54 Mon Sep 17 00:00:00 2001 From: uye <99072975+ABA2396@users.noreply.github.com> Date: Sat, 16 May 2026 02:37:08 +0800 Subject: [PATCH 3/7] =?UTF-8?q?chore:=20=E6=94=BE=E5=AE=BD=E5=AF=B9=20RA-1?= =?UTF-8?q?=20=E5=85=B3=E5=8D=A1=E5=90=8D=E7=9A=84=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix #16622 --- resource/tasks/RA/Reclamation3.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resource/tasks/RA/Reclamation3.json b/resource/tasks/RA/Reclamation3.json index b323a8cd68..b1029f29d0 100644 --- a/resource/tasks/RA/Reclamation3.json +++ b/resource/tasks/RA/Reclamation3.json @@ -8,7 +8,7 @@ "doc": "步骤 1(任务起点):OCR 识别 RA-1 并点击;右下角出现 <开启建设> 时进入步骤 2", "algorithm": "OcrDetect", "action": "ClickSelf", - "text": ["RA-1"], + "text": ["RA", "-1"], "withoutDet": true, "useRaw": false, "binThreshold": [200, 255], From 24639a0fdddd89ab46141e42c53e76f73f8b03ed Mon Sep 17 00:00:00 2001 From: H2O_MERO <60950002+H2O-MERO@users.noreply.github.com> Date: Sat, 16 May 2026 02:43:28 +0800 Subject: [PATCH 4/7] =?UTF-8?q?feat:=20=E4=BB=BB=E5=8A=A1=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E8=BE=93=E5=87=BA=E5=81=9C=E6=BB=9E=E6=97=B6=E5=8F=91?= =?UTF-8?q?=E9=80=81=E9=80=9A=E7=9F=A5,=20=E6=9B=BF=E6=8D=A2=20=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E8=B6=85=E6=97=B6=E9=80=9A=E7=9F=A5=20(#16511)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### 改动 1. 增加了“任务日志输出停滞时发送通知“功能,具体表现为:当任务日志在设定时间内没有发生更新时,进行日志输出和外部通知推送 2. 修改了选项“任务超时时间(分钟)”的最小值为1 3. 删除了旧有的通知方式 ### 关联issue #13271 ## Summary by Sourcery 为停滞的任务日志输出添加可配置的检测与通知功能,并将其接入现有的运行状态与任务队列流程中。 新功能: - 引入“停滞超时时间”设置:当任务日志输出在配置的时间段内没有更新时,触发警告和外部通知。 - 添加用户可配置开关:在任务发生停滞时,可选择在现有超时通知的基础上同时发送外部通知。 增强内容: - 从任务队列中跟踪日志输出活动,以重置停滞检测计时器,避免误报的停滞告警。 - 将新的停滞超时和通知偏好持久化到配置中,并在游戏内及外部通知设置的 UI 中对其进行暴露。 - 调整超时通知处理逻辑,在记录日志和发送通知之前,先遵从对应的外部通知设置。
Original summary in English ## Summary by Sourcery Add configurable detection and notification for stalled task log output and wire it into the existing running state and task queue flow. New Features: - Introduce a stall timeout setting that triggers warnings and external notifications when task log output has no updates for a configured period. - Add a user-configurable switch to send external notifications on task stalls alongside existing timeout notifications. Enhancements: - Track log output activity from the task queue to reset stall detection timers and avoid false-positive stall alerts. - Persist the new stall timeout and notification preferences in configuration and expose them in the game and external notification settings UI. - Adjust timeout notification handling to respect the corresponding external notification setting before logging and sending notifications.
--- src/MaaWpfGui/Constants/ConfigurationKeys.cs | 3 +- src/MaaWpfGui/Res/Localizations/en-us.xaml | 5 +- src/MaaWpfGui/Res/Localizations/ja-jp.xaml | 5 +- src/MaaWpfGui/Res/Localizations/ko-kr.xaml | 5 +- src/MaaWpfGui/Res/Localizations/zh-cn.xaml | 7 +- src/MaaWpfGui/Res/Localizations/zh-tw.xaml | 7 +- src/MaaWpfGui/States/RunningState.cs | 77 +++++++++++++++++-- .../ViewModels/UI/TaskQueueViewModel.cs | 29 ++++--- ...nalNotificationSettingsUserControlModel.cs | 11 +-- .../Settings/GameSettingsUserControlModel.cs | 12 +++ ...ternalNotificationSettingsUserControl.xaml | 12 +-- .../Settings/GameSettingsUserControl.xaml | 6 +- 12 files changed, 133 insertions(+), 46 deletions(-) diff --git a/src/MaaWpfGui/Constants/ConfigurationKeys.cs b/src/MaaWpfGui/Constants/ConfigurationKeys.cs index 7e2b822bd6..23a0619897 100644 --- a/src/MaaWpfGui/Constants/ConfigurationKeys.cs +++ b/src/MaaWpfGui/Constants/ConfigurationKeys.cs @@ -258,6 +258,7 @@ public static class ConfigurationKeys public const string TaskTimeoutMinutes = "TimeOut.Timer.TaskTimeoutMinutes"; public const string ReminderIntervalMinutes = "TimeOut.Timer.ReminderIntervalMinutes"; + public const string StallTimeoutMinutes = "TimeOut.Timer.StallTimeoutMinutes"; public const string BluestacksConfigPath = "Bluestacks.Config.Path"; public const string BluestacksConfigKeyword = "Bluestacks.Config.Keyword"; @@ -293,7 +294,7 @@ public static class ConfigurationKeys public const string ExternalNotificationSendWhenComplete = "ExternalNotification.SendWhenComplete"; public const string ExternalNotificationEnableDetails = "ExternalNotification.EnableDetails"; public const string ExternalNotificationSendWhenError = "ExternalNotification.SendWhenError"; - public const string ExternalNotificationSendWhenTimeout = "ExternalNotification.SendWhenTimeout"; + public const string ExternalNotificationSendWhenStalled = "ExternalNotification.SendWhenStalled"; public const string ExternalNotificationSmtpServer = "ExternalNotification.Smtp.Server"; public const string ExternalNotificationSmtpPort = "ExternalNotification.Smtp.Port"; public const string ExternalNotificationSmtpUser = "ExternalNotification.Smtp.User"; diff --git a/src/MaaWpfGui/Res/Localizations/en-us.xaml b/src/MaaWpfGui/Res/Localizations/en-us.xaml index 726859e906..35f70b8d46 100644 --- a/src/MaaWpfGui/Res/Localizations/en-us.xaml +++ b/src/MaaWpfGui/Res/Localizations/en-us.xaml @@ -42,7 +42,7 @@ Output Detailed Information Send notification when complete Send notification when task fails - Send notification when task times out + Send notification when task log output stalls Send successfully Send failed Send Test @@ -1525,7 +1525,8 @@ These locations are too high-level and can lead to file overwrites, config write Task timeout duration (minutes) Reminder interval (minutes) - The task has been running for more than {0} minutes (currently running for {1} minutes). If there are no further log updates for a long time, manual intervention may be required. + Log output stall timeout (min) + Task log output has not been updated for {0} minutes (currently stalled for {1} minutes). If there is no further log output for a long time, manual intervention may be required. 🎉 Achievement Unlocked diff --git a/src/MaaWpfGui/Res/Localizations/ja-jp.xaml b/src/MaaWpfGui/Res/Localizations/ja-jp.xaml index 931001ed7c..59d2c380e7 100644 --- a/src/MaaWpfGui/Res/Localizations/ja-jp.xaml +++ b/src/MaaWpfGui/Res/Localizations/ja-jp.xaml @@ -42,7 +42,7 @@ 詳細情報を出力 タスク完了時に通知を送信 タスクが失敗したときに通知を送信 - タスクがタイムアウトしたときに通知を送信する + タスクログ出力停滞時に通知を送信 正常に送信 送信に失敗しました テストを送信する @@ -1526,7 +1526,8 @@ MAA を複数開くには、新しい MAA を他のフォルダにコピーし タスクのタイムアウト時間(分) リマインダー間隔時間(分) - タスクが {0} 分以上実行されています(現在 {1} 分実行中)。長時間ログの更新がない場合、手動で介入する必要があるかもしれません。 + ログ出力停滞タイムアウト(分) + タスクログ出力が {0} 分間更新されていません(現在 {1} 分間停滞)。長時間ログ出力がない場合は、手動での操作が必要になる可能性があります。 🎉 実績を獲得した diff --git a/src/MaaWpfGui/Res/Localizations/ko-kr.xaml b/src/MaaWpfGui/Res/Localizations/ko-kr.xaml index 4bd5d13fad..2b707bc139 100644 --- a/src/MaaWpfGui/Res/Localizations/ko-kr.xaml +++ b/src/MaaWpfGui/Res/Localizations/ko-kr.xaml @@ -42,7 +42,7 @@ 상세 정보 출력 작업 완료 시 알림 전송 작업 실패 시 알림 전송 - 작업 시간 초과 시 알림 전송 + 작업 로그 출력 정지 시 알림 전송 전송 성공 전송 실패 테스트 @@ -1526,7 +1526,8 @@ MAA를 독립된 새 폴더에 압축 해제하거나, MAA에 속하지 않는 D 작업 타임아웃 시간 (분) 알림 간격 (분) - 작업이 {0}분을 초과하여 {1}분째 실행 중입니다\n장시간 로그의 갱신이 없다면 수동 조작이 필요할 수 있습니다 + 로그 출력 정지 타임아웃 (분) + 작업 로그 출력이 {0}분 동안 업데이트되지 않았습니다(현재 {1}분 정지). 오랫동안 로그 출력이 없으면 수동 개입이 필요할 수 있습니다. 🎉 도전과제 달성 diff --git a/src/MaaWpfGui/Res/Localizations/zh-cn.xaml b/src/MaaWpfGui/Res/Localizations/zh-cn.xaml index 54c1237baa..85b4f284e9 100644 --- a/src/MaaWpfGui/Res/Localizations/zh-cn.xaml +++ b/src/MaaWpfGui/Res/Localizations/zh-cn.xaml @@ -42,7 +42,7 @@ 输出详细信息 任务完成后发送通知 任务出错时发送通知 - 任务超时时发送通知 + 任务日志输出停滞时发送通知 发送成功 发送失败 发送测试 @@ -1525,8 +1525,9 @@ DEBUG 目录下保存的图片有数量限制,超出后会自动清理旧图 任务超时时间(分钟) - 提醒间隔时间(分钟) - 任务已运行超过 {0} 分钟(当前已运行 {1} 分钟)。如果长时间无进一步日志更新,可能需要手动干预。 + 通知间隔时间(分钟) + 日志输出停滞超时时间(分钟) + 任务日志输出已超过 {0} 分钟无更新(当前已停滞 {1} 分钟)。如果长时间无进一步日志输出,可能需要手动干预。 🎉 达成成就 diff --git a/src/MaaWpfGui/Res/Localizations/zh-tw.xaml b/src/MaaWpfGui/Res/Localizations/zh-tw.xaml index 205e32bc81..426e45c674 100644 --- a/src/MaaWpfGui/Res/Localizations/zh-tw.xaml +++ b/src/MaaWpfGui/Res/Localizations/zh-tw.xaml @@ -42,7 +42,7 @@ 輸出詳細資訊 任務完成後發送通知 任務出錯時發送通知 - 任務逾時時發送通知 + 任務日誌輸出停滯時發送通知 發送成功 發送失敗 發送測試 @@ -1525,8 +1525,9 @@ DEBUG 目錄下儲存的圖片有數量限制,超出後會自動清理舊圖 任務逾時時間(分鐘) - 提醒間隔時間(分鐘) - 任務已執行超過 {0} 分鐘(目前已執行 {1} 分鐘)。若長時間無進一步日誌更新,可能需要手動干預。 + 通知間隔時間(分鐘) + 日誌輸出停滯超時時間(分鐘) + 任務日誌輸出已超過 {0} 分鐘無更新(當前已停滯 {1} 分鐘)。如果長時間無進一步日誌輸出,可能需要手動干預。 🎉 達成成就 diff --git a/src/MaaWpfGui/States/RunningState.cs b/src/MaaWpfGui/States/RunningState.cs index 179a4c1fe4..99ce0cec3e 100644 --- a/src/MaaWpfGui/States/RunningState.cs +++ b/src/MaaWpfGui/States/RunningState.cs @@ -46,6 +46,7 @@ public class RunningState _timeoutReminderTimer.Interval = ReminderIntervalMinutes * 60 * 1000; _timeoutReminderTimer.Elapsed += TimeoutReminderTimer_Elapsed; + _stallTimer.Elapsed += StallTimer_Elapsed; } public static RunningState Instance @@ -58,6 +59,9 @@ public class RunningState // 超时相关字段 private readonly System.Timers.Timer _timeoutReminderTimer = new(); + private readonly System.Timers.Timer _stallTimer = new(); + private int _stallAccumulatedCount = 0; + private bool _stallIsFirstFire = true; private DateTime? _taskStartTime; public int TaskTimeoutMinutes { get; set; } = SettingsViewModel.GameSettings.TaskTimeoutMinutes; @@ -79,18 +83,61 @@ public class RunningState } } + + private int _stallTimeoutMinutes = SettingsViewModel.GameSettings.StallTimeoutMinutes; + + public int StallTimeoutMinutes + { + get => _stallTimeoutMinutes; + set { + _stallTimeoutMinutes = value; + _stallIsFirstFire = true; + if (_stallTimer.Enabled) + { + _stallTimer.Stop(); + if (value > 0) + { + _stallTimer.Interval = value * 60 * 1000; + _stallTimer.Start(); + } + } + } + } + + public event EventHandler? StallOccurred; + + public void NotifyOutputActivity() + { + _stallAccumulatedCount = 0; + _stallIsFirstFire = true; + if (_stallTimer.Enabled && StallTimeoutMinutes > 0) + { + _stallTimer.Interval = StallTimeoutMinutes * 60 * 1000; + _stallTimer.Stop(); + _stallTimer.Start(); + } + } // 超时事件 - public event EventHandler? TimeoutOccurred; public void StartTimeoutTimer() { _taskStartTime = DateTime.Now; _timeoutReminderTimer.Start(); + _stallAccumulatedCount = 0; + _stallIsFirstFire = true; + if (StallTimeoutMinutes > 0) + { + _stallTimer.Interval = StallTimeoutMinutes * 60 * 1000; + _stallTimer.Start(); + } } public void StopTimeoutTimer() { _timeoutReminderTimer.Stop(); + _stallTimer.Stop(); + _stallAccumulatedCount = 0; + _stallIsFirstFire = true; _taskStartTime = null; } @@ -120,15 +167,29 @@ public class RunningState return; } - // 每隔 ReminderIntervalMinutes 提示一次 - var message = string.Format( - LocalizationHelper.GetString("TaskTimeoutWarning"), - TaskTimeoutMinutes, - Math.Round(elapsedMinutes)); - AchievementTrackerHelper.Instance.Unlock(AchievementIds.LongTaskTimeout); + } - TimeoutOccurred?.Invoke(this, message); + private void StallTimer_Elapsed(object? sender, System.Timers.ElapsedEventArgs e) + { + _stallTimer.Stop(); + _stallAccumulatedCount++; + var accumulatedMinutes = StallTimeoutMinutes + ((_stallAccumulatedCount - 1) * ReminderIntervalMinutes); + var message = string.Format( + LocalizationHelper.GetString("TaskStallWarning"), + StallTimeoutMinutes, + accumulatedMinutes); + StallOccurred?.Invoke(this, message); + if (StallTimeoutMinutes > 0) + { + if (_stallIsFirstFire) + { + _stallTimer.Interval = ReminderIntervalMinutes * 60 * 1000; + _stallIsFirstFire = false; + } + + _stallTimer.Start(); + } } private bool _idle = true; diff --git a/src/MaaWpfGui/ViewModels/UI/TaskQueueViewModel.cs b/src/MaaWpfGui/ViewModels/UI/TaskQueueViewModel.cs index 2d1892b1e6..71e5be9607 100644 --- a/src/MaaWpfGui/ViewModels/UI/TaskQueueViewModel.cs +++ b/src/MaaWpfGui/ViewModels/UI/TaskQueueViewModel.cs @@ -610,7 +610,7 @@ public class TaskQueueViewModel : Screen Instances.Data.ClearCache(); } }; - _runningState.TimeoutOccurred += RunningState_TimeOut; + _runningState.StallOccurred += RunningState_Stalled; if (Instances.VersionUpdateDialogViewModel.IsDebugVersion() || File.Exists("DEBUG") || File.Exists("DEBUG.txt")) { @@ -619,16 +619,17 @@ public class TaskQueueViewModel : Screen } } - private void RunningState_TimeOut(object? sender, string message) - { - Execute.OnUIThread(() => { - AddLog(message, UiLogColor.Warning); - ToastNotification.ShowDirect(message); - if (!SettingsViewModel.ExternalNotificationSettings.ExternalNotificationSendWhenTimeout) - { - return; - } + private void RunningState_Stalled(object? sender, string message) + { + if (!SettingsViewModel.ExternalNotificationSettings.ExternalNotificationSendWhenStalled) + { + return; + } + + Execute.OnUIThread(() => { + AddLog(message, UiLogColor.Warning, notifyActivity: false); + ToastNotification.ShowDirect(message); var lastLogs = LogItemViewModels .TakeLast(5) .Aggregate(string.Empty, (current, logItem) => current + $"[{logItem.Time}][{logItem.Color}]{logItem.Content}\n"); @@ -1185,8 +1186,14 @@ public class TaskQueueViewModel : Screen bool updateCardImage = false, bool fetchLatestImage = false, bool useCardImageAsToolTip = false, - LogCardSplitMode splitMode = LogCardSplitMode.None) + LogCardSplitMode splitMode = LogCardSplitMode.None, + bool notifyActivity = true) { + if (notifyActivity) + { + RunningState.Instance.NotifyOutputActivity(); + } + bool isEmpty = string.IsNullOrEmpty(content); bool needsBeforeSplit = splitMode == LogCardSplitMode.Before || splitMode == LogCardSplitMode.Both; bool needsAfterSplit = splitMode == LogCardSplitMode.After || splitMode == LogCardSplitMode.Both; diff --git a/src/MaaWpfGui/ViewModels/UserControl/Settings/ExternalNotificationSettingsUserControlModel.cs b/src/MaaWpfGui/ViewModels/UserControl/Settings/ExternalNotificationSettingsUserControlModel.cs index 6c6c3ae7f1..d8041ecfd1 100644 --- a/src/MaaWpfGui/ViewModels/UserControl/Settings/ExternalNotificationSettingsUserControlModel.cs +++ b/src/MaaWpfGui/ViewModels/UserControl/Settings/ExternalNotificationSettingsUserControlModel.cs @@ -78,14 +78,15 @@ public class ExternalNotificationSettingsUserControlModel : PropertyChangedBase } } - private bool _externalNotificationSendWhenTimeout = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.ExternalNotificationSendWhenTimeout, bool.TrueString)); - public bool ExternalNotificationSendWhenTimeout + private bool _externalNotificationSendWhenStalled = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.ExternalNotificationSendWhenStalled, bool.FalseString)); + + public bool ExternalNotificationSendWhenStalled { - get => _externalNotificationSendWhenTimeout; + get => _externalNotificationSendWhenStalled; set { - SetAndNotify(ref _externalNotificationSendWhenTimeout, value); - ConfigurationHelper.SetValue(ConfigurationKeys.ExternalNotificationSendWhenTimeout, value.ToString()); + SetAndNotify(ref _externalNotificationSendWhenStalled, value); + ConfigurationHelper.SetValue(ConfigurationKeys.ExternalNotificationSendWhenStalled, value.ToString()); } } diff --git a/src/MaaWpfGui/ViewModels/UserControl/Settings/GameSettingsUserControlModel.cs b/src/MaaWpfGui/ViewModels/UserControl/Settings/GameSettingsUserControlModel.cs index cb90d0a5be..dcfc099d51 100644 --- a/src/MaaWpfGui/ViewModels/UserControl/Settings/GameSettingsUserControlModel.cs +++ b/src/MaaWpfGui/ViewModels/UserControl/Settings/GameSettingsUserControlModel.cs @@ -370,5 +370,17 @@ public class GameSettingsUserControlModel : PropertyChangedBase } } + private int _stallTimeoutMinutes = ConfigurationHelper.GetValue(ConfigurationKeys.StallTimeoutMinutes, 25); + + public int StallTimeoutMinutes + { + get => _stallTimeoutMinutes; + set { + SetAndNotify(ref _stallTimeoutMinutes, value); + _runningState.StallTimeoutMinutes = value; + ConfigurationHelper.SetValue(ConfigurationKeys.StallTimeoutMinutes, value.ToString()); + } + } + #endregion 任务超时 } diff --git a/src/MaaWpfGui/Views/UserControl/Settings/ExternalNotificationSettingsUserControl.xaml b/src/MaaWpfGui/Views/UserControl/Settings/ExternalNotificationSettingsUserControl.xaml index 54b7706216..ff9e987239 100644 --- a/src/MaaWpfGui/Views/UserControl/Settings/ExternalNotificationSettingsUserControl.xaml +++ b/src/MaaWpfGui/Views/UserControl/Settings/ExternalNotificationSettingsUserControl.xaml @@ -91,12 +91,12 @@ VerticalAlignment="Top" Content="{DynamicResource ExternalNotificationSendWhenError}" IsChecked="{Binding ExternalNotificationSendWhenError}" /> - + diff --git a/src/MaaWpfGui/Views/UserControl/Settings/GameSettingsUserControl.xaml b/src/MaaWpfGui/Views/UserControl/Settings/GameSettingsUserControl.xaml index bbace1a613..ee07c21e34 100644 --- a/src/MaaWpfGui/Views/UserControl/Settings/GameSettingsUserControl.xaml +++ b/src/MaaWpfGui/Views/UserControl/Settings/GameSettingsUserControl.xaml @@ -188,11 +188,11 @@ + Minimum="1" + Value="{Binding StallTimeoutMinutes}" /> Date: Sat, 16 May 2026 02:44:00 +0800 Subject: [PATCH 5/7] =?UTF-8?q?feat:=20=E7=82=B9=E5=87=BB=E6=88=90?= =?UTF-8?q?=E5=B0=B1=E6=A8=AA=E5=B9=85=E8=B7=B3=E8=BD=AC=E8=87=B3=E6=88=90?= =?UTF-8?q?=E5=B0=B1=E8=AE=BE=E7=BD=AE=EF=BC=8C=E8=87=AA=E5=8A=A8=E6=89=93?= =?UTF-8?q?=E5=BC=80=E6=88=90=E5=B0=B1=E5=88=97=E8=A1=A8=E5=B9=B6=E7=AD=9B?= =?UTF-8?q?=E9=80=89=E5=AF=B9=E5=BA=94=E6=88=90=E5=B0=B1=20(#16537)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### 改动 可以通过点击右上角弹出的成就横幅跳转至成就设置,并自动打开成就列表并筛选对应成就 ## Summary by Sourcery 为成就通知横幅添加导航功能,可跳转到对应的设置部分和成就列表条目。 New Features: - 允许点击成就的提示(growl)横幅,以打开成就设置页面,并聚焦到相关成就。 - 使成就列表对话框在打开时或加载完成后,可以直接滚动到指定成就。 Enhancements: - 跟踪提示(growl)通知,将其与特定成就关联起来,并绑定点击处理程序,同时不影响现有按钮的行为。 - 引入一个 `RootView` 代码隐藏文件,用于初始化根视图组件。
Original summary in English ## Summary by Sourcery Add navigation from achievement notification banners to the corresponding settings section and achievement list entry. New Features: - Allow clicking achievement growl banners to open the achievement settings page focused on the relevant achievement. - Enable the achievement list dialog to scroll directly to a specific achievement when opened or once loaded. Enhancements: - Track growl notifications to associate them with specific achievements and wire up click handlers without interfering with existing buttons. - Introduce a RootView code-behind file to initialize the root view component.
--- .../Helper/AchievementTrackerHelper.cs | 151 +++++++++++++++++- .../AchievementSettingsUserControlModel.cs | 9 +- .../Dialogs/AchievementListDialogView.xaml | 4 +- .../Dialogs/AchievementListDialogView.xaml.cs | 1 + src/MaaWpfGui/Views/UI/RootView.xaml | 2 +- src/MaaWpfGui/Views/UI/RootView.xaml.cs | 22 +++ 6 files changed, 183 insertions(+), 6 deletions(-) create mode 100644 src/MaaWpfGui/Views/UI/RootView.xaml.cs diff --git a/src/MaaWpfGui/Helper/AchievementTrackerHelper.cs b/src/MaaWpfGui/Helper/AchievementTrackerHelper.cs index 88e2d964d2..e4b306bca5 100644 --- a/src/MaaWpfGui/Helper/AchievementTrackerHelper.cs +++ b/src/MaaWpfGui/Helper/AchievementTrackerHelper.cs @@ -16,6 +16,10 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using System.Windows.Threading; using System.Linq; using System.Threading.Tasks; using System.Windows.Input; @@ -103,9 +107,28 @@ public class AchievementTrackerHelper : PropertyChangedBase public ICommand SearchCmd { get; } + private string _searchText = string.Empty; + + public string SearchText + { + get => _searchText; + set => SetAndNotify(ref _searchText, value ?? string.Empty); + } + + public void SearchAndSyncText(string text = "") + { + SearchText = text.Trim(); + Search(SearchText); + } + public void Search(string text = "") { text = text.Trim(); + if (!string.Equals(SearchText, text, StringComparison.Ordinal)) + { + SearchText = text; + } + if (string.IsNullOrWhiteSpace(text)) { foreach (var achievement in Achievements) @@ -115,9 +138,14 @@ public class AchievementTrackerHelper : PropertyChangedBase } else { - foreach (var (_, value) in Achievements) + foreach (var (key, value) in Achievements) { - value.IsVisibleInSearch = value.Title.Contains(text) || value.Description.Contains(text) || value.Conditions.Contains(text) || value.ReleasePhaseTag.Contains(text); + value.IsVisibleInSearch = + key == text || + value.Title.Contains(text) || + value.Description.Contains(text) || + value.Conditions.Contains(text) || + value.ReleasePhaseTag.Contains(text); } } @@ -223,6 +251,7 @@ public class AchievementTrackerHelper : PropertyChangedBase IconKey = "HangoverGeometry", IconBrushKey = achievement.MedalBrushKey, }; + _growlAchievementMap[growlInfo] = id; ShowInfo(growlInfo, forceStayOpen: forceStayOpen); } @@ -276,6 +305,8 @@ public class AchievementTrackerHelper : PropertyChangedBase Save(); } + private static readonly Dictionary _growlAchievementMap = []; + private static readonly List _pending = []; public static void ShowInfo(GrowlInfo info, bool forceStayOpen = false) @@ -294,16 +325,132 @@ public class AchievementTrackerHelper : PropertyChangedBase return; } + var previousItems = Growl.GrowlPanel?.Children.OfType().ToHashSet() ?? []; Growl.Info(info); + AttachGrowlClickHandler(info, previousItems); }); } + private static void AttachGrowlClickHandler(GrowlInfo info, HashSet previousItems) + { + if (!_growlAchievementMap.TryGetValue(info, out var id)) + { + return; + } + + bool TryAttachToNewItems() + { + if (Growl.GrowlPanel is not { } panel) + { + return false; + } + + bool attached = false; + foreach (var growlItem in panel.Children.OfType().Where(item => !previousItems.Contains(item))) + { + growlItem.RemoveHandler(UIElement.PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(OnGrowlItemMouseDown)); + growlItem.AddHandler( + UIElement.PreviewMouseLeftButtonDownEvent, + new MouseButtonEventHandler(OnGrowlItemMouseDown), + handledEventsToo: true); + + if (growlItem is FrameworkElement element) + { + element.Tag = id; + element.Unloaded -= OnGrowlItemUnloaded; + element.Unloaded += OnGrowlItemUnloaded; + } + + attached = true; + } + + if (attached) + { + _growlAchievementMap.Remove(info); + } + + return attached; + } + + if (!TryAttachToNewItems()) + { + Application.Current.Dispatcher.BeginInvoke( + DispatcherPriority.Loaded, + new Action(() => TryAttachToNewItems())); + } + } + + private static void OnGrowlItemUnloaded(object sender, RoutedEventArgs e) + { + if (sender is UIElement growlItem) + { + growlItem.RemoveHandler(UIElement.PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(OnGrowlItemMouseDown)); + } + + if (sender is FrameworkElement element) + { + element.Tag = null; + element.Unloaded -= OnGrowlItemUnloaded; + } + } + + private static void OnGrowlItemMouseDown(object sender, MouseButtonEventArgs e) + { + if (sender is not UIElement growlItem) + { + return; + } + + var source = e.OriginalSource as DependencyObject; + while (source != null && source != growlItem) + { + if (source is Button) + { + return; + } + + source = VisualTreeHelper.GetParent(source); + } + + if (sender is FrameworkElement { Tag: string id } && !string.IsNullOrWhiteSpace(id)) + { + NavigateToAchievement(id); + } + } + + public static void NavigateToAchievement(string id) + { + if (Instances.SettingsViewModel.Parent is IHaveActiveItem conductor) + { + conductor.ActiveItem = Instances.SettingsViewModel; + } + + Application.Current.Dispatcher.BeginInvoke( + DispatcherPriority.Loaded, + new Action(() => + { + var settings = Instances.SettingsViewModel.Settings; + for (int i = 0; i < settings.Count; i++) + { + if (settings[i].Key == "AchievementSettings") + { + Instances.SettingsViewModel.SelectedIndex = i; + break; + } + } + + AchievementSettingsUserControlModel.Instance.OnShowAchievementsClick(id); + })); + } + public static void TryShowPendingGrowls() { Execute.OnUIThread(() => { foreach (var info in _pending) { + var previousItems = Growl.GrowlPanel?.Children.OfType().ToHashSet() ?? []; Growl.Info(info); + AttachGrowlClickHandler(info, previousItems); } _pending.Clear(); diff --git a/src/MaaWpfGui/ViewModels/UserControl/Settings/AchievementSettingsUserControlModel.cs b/src/MaaWpfGui/ViewModels/UserControl/Settings/AchievementSettingsUserControlModel.cs index e0c088b618..8cd1312f1d 100644 --- a/src/MaaWpfGui/ViewModels/UserControl/Settings/AchievementSettingsUserControlModel.cs +++ b/src/MaaWpfGui/ViewModels/UserControl/Settings/AchievementSettingsUserControlModel.cs @@ -108,9 +108,9 @@ public class AchievementSettingsUserControlModel : PropertyChangedBase } } - private static Window? _achievementsWindow; + private static AchievementListDialogView? _achievementsWindow; - public void OnShowAchievementsClick() + public void OnShowAchievementsClick(string? achievementId = null) { AchievementTrackerHelper.Instance.Unlock(AchievementIds.AchievementObserver); if (_achievementsWindow is null) @@ -125,6 +125,11 @@ public class AchievementSettingsUserControlModel : PropertyChangedBase } WindowManager.ShowWindow(_achievementsWindow); + + if (achievementId != null) + { + AchievementTrackerHelper.Instance.SearchAndSyncText(achievementId); + } } private int _clickCount = 0; diff --git a/src/MaaWpfGui/Views/Dialogs/AchievementListDialogView.xaml b/src/MaaWpfGui/Views/Dialogs/AchievementListDialogView.xaml index 6295e5e4a2..98f893c5b1 100644 --- a/src/MaaWpfGui/Views/Dialogs/AchievementListDialogView.xaml +++ b/src/MaaWpfGui/Views/Dialogs/AchievementListDialogView.xaml @@ -13,6 +13,7 @@ Background="{DynamicResource MdXamlBackground}"> diff --git a/src/MaaWpfGui/Views/Dialogs/AchievementListDialogView.xaml.cs b/src/MaaWpfGui/Views/Dialogs/AchievementListDialogView.xaml.cs index 7bde9ee9b3..ca544f77e1 100644 --- a/src/MaaWpfGui/Views/Dialogs/AchievementListDialogView.xaml.cs +++ b/src/MaaWpfGui/Views/Dialogs/AchievementListDialogView.xaml.cs @@ -33,4 +33,5 @@ public partial class AchievementListDialogView // 关闭窗口时执行一次空搜索,重置可见性 AchievementTrackerHelper.Instance.Search(); } + } diff --git a/src/MaaWpfGui/Views/UI/RootView.xaml b/src/MaaWpfGui/Views/UI/RootView.xaml index 19771d3074..9d6e5e5f56 100644 --- a/src/MaaWpfGui/Views/UI/RootView.xaml +++ b/src/MaaWpfGui/Views/UI/RootView.xaml @@ -199,7 +199,7 @@ d:Height="200" d:Width="100" VerticalScrollBarVisibility="Hidden"> - + +// Part of the MaaWpfGui project, maintained by the MaaAssistantArknights team (Maa Team) +// Copyright (C) 2021-2025 MaaAssistantArknights Contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License v3.0 only as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY +// + +namespace MaaWpfGui.Views.UI; + +public partial class RootView +{ + public RootView() + { + InitializeComponent(); + } +} From fb6e08281cf28d256b9fe40a501f4c3bf7839c9a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 15 May 2026 19:14:24 +0000 Subject: [PATCH 6/7] feat: Update Submodules MAAUnified, MaaMacGui, maa-cli https://github.com/MaaAssistantArknights/MaaAssistantArknights/actions/runs/25936565851 [skip changelog] --- src/MAAUnified | 2 +- src/MaaMacGui | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/MAAUnified b/src/MAAUnified index 1ee09448b3..ee18d23329 160000 --- a/src/MAAUnified +++ b/src/MAAUnified @@ -1 +1 @@ -Subproject commit 1ee09448b3eb2f12e20f5ad186eaa322ce62aa9c +Subproject commit ee18d23329e9c20917363f8851cb07fa40d43054 diff --git a/src/MaaMacGui b/src/MaaMacGui index 7eed483002..5310fcf571 160000 --- a/src/MaaMacGui +++ b/src/MaaMacGui @@ -1 +1 @@ -Subproject commit 7eed4830027010efb4f8218b1f29ad51dc77d3d4 +Subproject commit 5310fcf571606f852cad3db7f1fdc5c967da7053 From 86cf185d25a7ab5f2cbb54d929d79d3673291e63 Mon Sep 17 00:00:00 2001 From: uye <99072975+ABA2396@users.noreply.github.com> Date: Sat, 16 May 2026 03:19:49 +0800 Subject: [PATCH 7/7] docs: Update CHANGELOG for v6.10.0-beta.3 Added new features and made adjustments in the changelog. --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4fad10a1d1..e22e911b07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +## v6.10.0-beta.3 + +### 新增 | New + +* 点击成就横幅跳转至成就设置,自动打开成就列表并筛选对应成就 (#16537) @H2O-MERO @ABA2396 +* 任务日志输出停滞时发送通知, 替换 任务超时通知 (#16511) @H2O-MERO + +### 其他 | Other + +* 放宽对 RA-1 关卡名的检查 @ABA2396 +* 添加拆除设施的描述 @ABA2396 +* 删除辅助建设模式的描述 @ABA2396 + ## v6.10.0-beta.2 ### 新增 | New