pi-win-notify 1.0.7 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/extensions/desktop-notify.ts +18 -10
- package/extensions/host.ps1 +11 -4
- package/package.json +1 -1
|
@@ -100,10 +100,10 @@ const config = loadConfig();
|
|
|
100
100
|
|
|
101
101
|
// ── i18n ────────────────────────────────────────────────────────────────────
|
|
102
102
|
const i18n: Record<string, Record<string, string>> = {
|
|
103
|
-
zh: { dismissBtn: " 知 道 了 ", continueBtn: " 继 续 ", completion: "任务完成", switchBack: "可以切回来了", enabled: "通知已开启 🔔", disabled: "通知已关闭 🔕", configTitle: "通知配置", timeoutLabel: "超时", opacityLabel: "不透明度", modeLabel: "模式", langLabel: "语言", statusLabel: "状态", on: "开", off: "关", mute3: "3 分钟", mute30: "30 分钟", mute60: "1 小时", muteOff: "关闭勿扰" },
|
|
104
|
-
en: { dismissBtn: " Dismiss ", continueBtn: "Continue", completion: "Task complete", switchBack: "Switch back", enabled: "Notify ON 🔔", disabled: "Notify OFF 🔕", configTitle: "Notify Config", timeoutLabel: "Timeout", opacityLabel: "Opacity", modeLabel: "Mode", langLabel: "Language", statusLabel: "Status", on: "ON", off: "OFF", mute3: "3 min", mute30: "30 min", mute60: "1 hour", muteOff: "Turn off" },
|
|
105
|
-
ja: { dismissBtn: " 閉じる ", continueBtn: " 続 行 ", completion: "完了", switchBack: "戻れます", enabled: "通知ON 🔔", disabled: "通知OFF 🔕", configTitle: "通知設定", timeoutLabel: "タイムアウト", opacityLabel: "不透明度", modeLabel: "モード", langLabel: "言語", statusLabel: "状態", on: "ON", off: "OFF", mute3: "3 分", mute30: "30 分", mute60: "1 時間", muteOff: "オフ" },
|
|
106
|
-
ko: { dismissBtn: " 닫 기 ", continueBtn: " 계 속 ", completion: "완료", switchBack: "돌아가기", enabled: "알림 ON 🔔", disabled: "알림 OFF 🔕", configTitle: "알림 설정", timeoutLabel: "시간제한", opacityLabel: "불투명도", modeLabel: "모드", langLabel: "언어", statusLabel: "상태", on: "ON", off: "OFF", mute3: "3 분", mute30: "30 분", mute60: "1 시간", muteOff: "끄기" },
|
|
103
|
+
zh: { dismissBtn: " 知 道 了 ", continueBtn: " 继 续 ", completion: "任务完成", switchBack: "可以切回来了", enabled: "通知已开启 🔔", disabled: "通知已关闭 🔕", configTitle: "通知配置", timeoutLabel: "超时", opacityLabel: "不透明度", modeLabel: "模式", langLabel: "语言", statusLabel: "状态", on: "开", off: "关", mute3: "3 分钟", mute30: "30 分钟", mute60: "1 小时", muteOff: "关闭勿扰", muteRemaining: "勿扰剩余{0}分" },
|
|
104
|
+
en: { dismissBtn: " Dismiss ", continueBtn: "Continue", completion: "Task complete", switchBack: "Switch back", enabled: "Notify ON 🔔", disabled: "Notify OFF 🔕", configTitle: "Notify Config", timeoutLabel: "Timeout", opacityLabel: "Opacity", modeLabel: "Mode", langLabel: "Language", statusLabel: "Status", on: "ON", off: "OFF", mute3: "3 min", mute30: "30 min", mute60: "1 hour", muteOff: "Turn off", muteRemaining: "Muted {0}m left" },
|
|
105
|
+
ja: { dismissBtn: " 閉じる ", continueBtn: " 続 行 ", completion: "完了", switchBack: "戻れます", enabled: "通知ON 🔔", disabled: "通知OFF 🔕", configTitle: "通知設定", timeoutLabel: "タイムアウト", opacityLabel: "不透明度", modeLabel: "モード", langLabel: "言語", statusLabel: "状態", on: "ON", off: "OFF", mute3: "3 分", mute30: "30 分", mute60: "1 時間", muteOff: "オフ", muteRemaining: "通知停止 残り{0}分" },
|
|
106
|
+
ko: { dismissBtn: " 닫 기 ", continueBtn: " 계 속 ", completion: "완료", switchBack: "돌아가기", enabled: "알림 ON 🔔", disabled: "알림 OFF 🔕", configTitle: "알림 설정", timeoutLabel: "시간제한", opacityLabel: "불투명도", modeLabel: "모드", langLabel: "언어", statusLabel: "상태", on: "ON", off: "OFF", mute3: "3 분", mute30: "30 분", mute60: "1 시간", muteOff: "끄기", muteRemaining: "방해금지 {0}분 남음" },
|
|
107
107
|
};
|
|
108
108
|
function t(key: string): string { return i18n[config.lang]?.[key] ?? i18n.zh[key] ?? key; }
|
|
109
109
|
function completionMsg(): string { return `${t("completion")},${t("switchBack")} 🎉`; }
|
|
@@ -235,7 +235,7 @@ function spawnHost(): void {
|
|
|
235
235
|
if (code !== 0 && code !== null) {
|
|
236
236
|
psHostCrashCount++;
|
|
237
237
|
psHostLastError = `exit code ${code}`;
|
|
238
|
-
if (piApi) {
|
|
238
|
+
if (piApi?.ui) {
|
|
239
239
|
piApi.ui.notify(`桌面通知服务异常 (${psHostLastError}),下次弹窗时自动恢复`, "warning");
|
|
240
240
|
}
|
|
241
241
|
}
|
|
@@ -489,11 +489,20 @@ export default function (pi: ExtensionAPI) {
|
|
|
489
489
|
|
|
490
490
|
// /notify status
|
|
491
491
|
if (sub === "status") {
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
492
|
+
// 同步检查勿扰过期
|
|
493
|
+
if (config.muteUntil && Date.now() > config.muteUntil) {
|
|
494
|
+
enabled = true;
|
|
495
|
+
saveMuteUntil(undefined);
|
|
496
|
+
log("mute expired (checked on status)");
|
|
497
|
+
}
|
|
498
|
+
const daemonStatus = psHostReady ? "Daemon OK" : "Daemon Down";
|
|
499
|
+
let muteInfo = "";
|
|
500
|
+
if (!enabled && config.muteUntil && config.muteUntil > Date.now()) {
|
|
501
|
+
const remaining = Math.round((config.muteUntil - Date.now()) / 60000);
|
|
502
|
+
muteInfo = " " + t("muteRemaining").replace("{0}", remaining.toString());
|
|
503
|
+
}
|
|
495
504
|
ctx.ui.notify(
|
|
496
|
-
|
|
505
|
+
`${enabled ? t("enabled") : t("disabled")} | Timeout=${config.timeout}s Opacity=${config.opacity} Mode=${config.messageMode} Language=${config.lang} ${daemonStatus}${muteInfo}`,
|
|
497
506
|
psHostReady ? "info" : "warning",
|
|
498
507
|
);
|
|
499
508
|
return;
|
|
@@ -527,7 +536,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
527
536
|
enabled = true;
|
|
528
537
|
saveMuteUntil(undefined);
|
|
529
538
|
log("mute expired (checked on agent_end)");
|
|
530
|
-
if (piApi) piApi.ui.notify("通知已恢复 🔔", "info");
|
|
531
539
|
}
|
|
532
540
|
|
|
533
541
|
log(`agent_end: enabled=${enabled} compacting=${isCompacting}`);
|
package/extensions/host.ps1
CHANGED
|
@@ -157,10 +157,14 @@ function Focus-PiTerminal($hwndNum, $winTitle) {
|
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
$stackFile = "$env:TEMP\pi-notify-stack.txt"
|
|
160
|
+
# 每次宿主启动重置计数器,避免崩溃残留导致窗口位置漂移
|
|
161
|
+
if (Test-Path $stackFile) { Remove-Item $stackFile -Force }
|
|
160
162
|
|
|
161
163
|
function inc-stack {
|
|
162
164
|
$count = 0
|
|
163
165
|
if (Test-Path $stackFile) { try { $count = [int](Get-Content $stackFile -Raw).Trim() } catch {} }
|
|
166
|
+
# 保护:超过 10 层说明 dec-stack 泄露,重置
|
|
167
|
+
if ($count -gt 10) { $count = 0; l '[stack-reset] overflow' }
|
|
164
168
|
$count++
|
|
165
169
|
$count | Out-File -Encoding ascii $stackFile
|
|
166
170
|
return $count
|
|
@@ -241,12 +245,15 @@ function Show-Notify($data) {
|
|
|
241
245
|
$win.FindName('MuteBtn').Add_Click({ $popup.IsOpen = $true })
|
|
242
246
|
|
|
243
247
|
$cursor = [System.Windows.Forms.Cursor]::Position
|
|
244
|
-
$
|
|
245
|
-
$
|
|
248
|
+
$screen = [System.Windows.Forms.Screen]::FromPoint($cursor)
|
|
249
|
+
$waL = $screen.WorkingArea.Left
|
|
250
|
+
$waT = $screen.WorkingArea.Top
|
|
251
|
+
$waW = $screen.WorkingArea.Width
|
|
252
|
+
$waH = $screen.WorkingArea.Height
|
|
246
253
|
$count = inc-stack
|
|
247
254
|
$offset = ($count - 1) * 128
|
|
248
|
-
$win.Left = $waW - $win.Width - 20
|
|
249
|
-
$win.Top = $waH - $win.Height - 10 - $offset
|
|
255
|
+
$win.Left = $waL + $waW - $win.Width - 20
|
|
256
|
+
$win.Top = $waT + $waH - $win.Height - 10 - $offset
|
|
250
257
|
l "[ps-stack] count=$count offset=$offset"
|
|
251
258
|
|
|
252
259
|
$timer = New-Object System.Windows.Threading.DispatcherTimer
|