Files
arcrun-collector/cmd/arcrun-app/check-tray.sh
T
Leo c400292c01 新增 check-tray.sh:托盤行為的機械閘(交付警察攔下後補)
leo 真機測出的四個 bug **編得過也跑得起來**,只有真的去點才會發現;
我改完只驗「build ok」就想交 ⇒ 把「點不下去的部分」用可機械檢查的前置條件守住:

① template icon:22/44 RGBA、**不透明 <50%**(否則會顯示成方塊)、顏色種類
② 呼叫順序:AddMenuItem → SetMenuNil → SetOnClick/SetOnRClick
   (順序錯=滑鼠事件全失效,正是 leo 撞到的②③)
③ ShowWindow 必須有 Unminimise/Show/SetAlwaysOnTop 三者(缺一就叫不回被蓋住的窗)
④ 結束路徑:有 signal.Notify+waitCollectorGone(否則只能強制結束、留孤兒)

實跑 7 項全過。這支+check-cis+check-render 三支都要過才准交。
2026-08-05 01:47:58 +08:00

74 lines
3.3 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# check-tray.sh — 托盤行為的機械閘(t194,leo 真機測出四個 bug 後補)
#
# 🔴 為什麼要有:這四個 bug **編得過、也跑得起來**,只有真的去點才會發現。
# 我改完只驗「build ok」就想交,被交付警察攔下。
# ⇒ 把「點不下去的部分」用可機械檢查的**前置條件**守住。
set -uo pipefail
cd "$(dirname "$0")"
FAIL=0
ok(){ printf " ✅ %s\n" "$1"; }
ng(){ printf " ❌ %s\n" "$1"; FAIL=1; }
echo "━━━ 托盤行為前置條件 ━━━"
# ① template icon:純黑+大量透明、尺寸 22/44
python3 - <<'PY' || exit 1
import zlib,struct,sys
d=open('build/trayicon.png','rb').read()
pos=8; idat=b''; w=h=ct=0
while pos<len(d):
ln=struct.unpack('>I',d[pos:pos+4])[0]; t=d[pos+4:pos+8]
if t==b'IHDR': w,h,_,ct=struct.unpack('>IIBB',d[pos+8:pos+18])
if t==b'IDAT': idat+=d[pos+8:pos+8+ln]
pos+=12+ln
if w not in (22,44) or ct!=6:
print(f" ❌ tray icon 應為 22/44 的 RGBAgot {w}x{h} ct={ct}"); sys.exit(1)
raw=zlib.decompress(idat); ch=4; stride=w*ch+1
rows=[];prev=bytearray(w*ch)
for y in range(h):
f=raw[y*stride];line=bytearray(raw[y*stride+1:(y+1)*stride])
for i in range(len(line)):
a=line[i-ch] if i>=ch else 0;b=prev[i];c=prev[i-ch] if i>=ch else 0
if f==1: line[i]=(line[i]+a)&255
elif f==2: line[i]=(line[i]+b)&255
elif f==3: line[i]=(line[i]+(a+b)//2)&255
elif f==4:
pp=a+b-c;pa,pb,pc=abs(pp-a),abs(pp-b),abs(pp-c)
pr=a if(pa<=pb and pa<=pc) else (b if pb<=pc else c)
line[i]=(line[i]+pr)&255
rows.append(bytes(line));prev=line
al=[rows[y][x*4+3] for y in range(h) for x in range(w)]
opq=sum(1 for a in al if a>200)
if opq > len(al)*0.5:
print(f" ❌ tray icon 幾乎全不透明({100*opq//len(al)}%)⇒ 會顯示成方塊"); sys.exit(1)
cols={tuple(rows[y][x*4:x*4+3]) for y in range(h) for x in range(w) if rows[y][x*4+3]>200}
print(f" ✅ template icon{w}x{h}、不透明 {100*opq//len(al)}%、顏色 {len(cols)} 種 {list(cols)[:1]}")
PY
# ② 呼叫順序:AddMenuItem → SetMenuNil → SetOnClick/SetOnRClick
python3 - <<'PY' || exit 1
import sys
s=open('main.go',encoding='utf-8').read()
try:
a=s.index('systray.AddMenuItem'); n=s.index('systray.SetMenuNil')
c=s.index('systray.SetOnClick'); r=s.index('systray.SetOnRClick')
except ValueError as e:
print(f" ❌ 找不到必要呼叫:{e}"); sys.exit(1)
if not (a < n < c and n < r):
print(" ❌ 順序錯:必須 AddMenuItem → SetMenuNil → SetOnClick/SetOnRClick"); sys.exit(1)
print(" ✅ 順序正確(建選單→清掉→註冊滑鼠事件)")
PY
# ③ ShowWindow 要能叫回「已開但被蓋住」的視窗
for f in WindowUnminimise WindowShow WindowSetAlwaysOnTop; do
grep -q "runtime.$f" app.go && ok "ShowWindow 有 $f" || ng "ShowWindow 缺 $f(叫不回被蓋住的視窗)"
done
# ④ 結束路徑:收訊號 → 停子行程 → 等它真的不見
grep -q "signal.Notify" supervise.go && ok "有處理 SIGTERM/SIGINT" || ng "沒有訊號處理(只能強制結束)"
grep -q "waitCollectorGone" supervise.go && ok "結束前會等 collector 真的不見" || ng "沒等子行程 ⇒ 會留孤兒"
echo
[ $FAIL -eq 0 ] && echo "✅ 托盤前置條件全過" || { echo "❌ 未過——不准交貨"; exit 1; }