|
|
@@ -26,12 +26,10 @@ func runTray(cfg *Config, log *Logger) {
|
|
|
}
|
|
|
|
|
|
func trayReady(sup *Supervisor, cfg *Config, log *Logger) {
|
|
|
- // 菜单标题保持短文本(长 URL 会撑宽整个菜单)。
|
|
|
- // 注意:getlantern/systray 在 Windows 上不支持"菜单项 tooltip"(只有图标 tooltip 有效),
|
|
|
- // 因此完整地址通过"托盘图标悬停提示"与"复制 Web 地址"提供。
|
|
|
+ // 菜单标题一律使用短文本:长文本会撑宽整个菜单、视觉不协调。
|
|
|
+ // 因此菜单内不显示访问地址——需要时点"打开 Web 界面"直接打开。
|
|
|
mStatus := systray.AddMenuItem("初始化…", "当前服务状态")
|
|
|
mURL := systray.AddMenuItem("打开 Web 界面", "服务就绪后可用(自动带 token)")
|
|
|
- mCopyURL := systray.AddMenuItem("复制 Web 地址", "把含 token 的完整地址复制到剪贴板")
|
|
|
systray.AddSeparator()
|
|
|
mStart := systray.AddMenuItem("启动服务", "启动 dsh web")
|
|
|
mStop := systray.AddMenuItem("停止服务", "停止 dsh web")
|
|
|
@@ -49,7 +47,6 @@ func trayReady(sup *Supervisor, cfg *Config, log *Logger) {
|
|
|
|
|
|
mStop.Disable()
|
|
|
mURL.Disable() // 服务就绪前不可点(避免打开无 token 的无效地址)
|
|
|
- mCopyURL.Disable()
|
|
|
|
|
|
// 临时通知:覆盖状态标题若干秒,让"点完看不到变化"的操作有回显。
|
|
|
var noticeMu sync.Mutex
|
|
|
@@ -89,7 +86,7 @@ func trayReady(sup *Supervisor, cfg *Config, log *Logger) {
|
|
|
go func() {
|
|
|
ticker := time.NewTicker(3 * time.Second)
|
|
|
defer ticker.Stop()
|
|
|
- var lastTitle, lastTip, lastURL, lastIconTip string
|
|
|
+ var lastTitle, lastTip, lastIconTip string
|
|
|
lastRunning, lastWebEnabled := false, false
|
|
|
for range ticker.C {
|
|
|
st := sup.Status()
|
|
|
@@ -107,33 +104,19 @@ func trayReady(sup *Supervisor, cfg *Config, log *Logger) {
|
|
|
lastTip = tip
|
|
|
}
|
|
|
|
|
|
- // Web 相关菜单:标题短文本;完整地址走托盘图标 tooltip(Windows 上唯一有效的悬停提示)
|
|
|
- addr := fmt.Sprintf("%s:%d", cfg.WebHost, cfg.WebPort)
|
|
|
- webEnable, webText := false, "打开 Web 界面(服务未运行)"
|
|
|
- iconTip := "DeepSeek Tray · " + statusTitle(st)
|
|
|
- switch {
|
|
|
- case st.Ready || st.External:
|
|
|
- webEnable, webText = true, "打开 Web 界面 ("+addr+")"
|
|
|
- // 地址放在最前:Windows 图标 tooltip 上限 128 字符,避免地址被截断
|
|
|
- iconTip = st.URL + "\n" + statusTitle(st)
|
|
|
- case st.Running:
|
|
|
- webText = "打开 Web 界面(启动中…)"
|
|
|
- iconTip = "DeepSeek Tray · 启动中…(就绪后此处显示地址)"
|
|
|
- }
|
|
|
- if webText != lastURL {
|
|
|
- mURL.SetTitle(webText)
|
|
|
- lastURL = webText
|
|
|
- }
|
|
|
+ // Web 菜单只切换可用状态,标题恒为短文本
|
|
|
+ webEnable := st.Ready || st.External
|
|
|
if webEnable != lastWebEnabled {
|
|
|
if webEnable {
|
|
|
mURL.Enable()
|
|
|
- mCopyURL.Enable()
|
|
|
} else {
|
|
|
mURL.Disable()
|
|
|
- mCopyURL.Disable()
|
|
|
}
|
|
|
lastWebEnabled = webEnable
|
|
|
}
|
|
|
+
|
|
|
+ // 托盘图标 tooltip 同样保持简洁(不含地址)
|
|
|
+ iconTip := "DeepSeek Tray · " + statusTitle(st)
|
|
|
if iconTip != lastIconTip {
|
|
|
systray.SetTooltip(iconTip)
|
|
|
lastIconTip = iconTip
|
|
|
@@ -189,19 +172,6 @@ func trayReady(sup *Supervisor, cfg *Config, log *Logger) {
|
|
|
log.Printf("打开 Web 界面失败: %v", err)
|
|
|
setNotice("打开失败(详见日志)", 6*time.Second)
|
|
|
}
|
|
|
- case <-mCopyURL.ClickedCh:
|
|
|
- st := sup.Status()
|
|
|
- if !st.Ready && !st.External {
|
|
|
- log.Printf("菜单:复制 Web 地址被忽略(服务未就绪)")
|
|
|
- continue
|
|
|
- }
|
|
|
- log.Printf("菜单:复制 Web 地址")
|
|
|
- if err := copyToClipboard(st.URL); err != nil {
|
|
|
- log.Printf("复制 Web 地址失败: %v", err)
|
|
|
- setNotice("复制失败(详见日志)", 6*time.Second)
|
|
|
- } else {
|
|
|
- setNotice("Web 地址已复制到剪贴板", 4*time.Second)
|
|
|
- }
|
|
|
case <-mAutoStart.ClickedCh:
|
|
|
next := !mAutoStart.Checked()
|
|
|
if err := setAutoStart(next); err != nil {
|
|
|
@@ -315,7 +285,7 @@ func statusTooltip(st Status) string {
|
|
|
|
|
|
// firstLine 取多行输出的首行,便于日志摘要。
|
|
|
func firstLine(s string) string {
|
|
|
- if i := strings.IndexByte(s, '\n'); i >= 0 {
|
|
|
+ if i := strings.IndexByte(s, 10); i >= 0 { // 10 = LF
|
|
|
return s[:i]
|
|
|
}
|
|
|
return s
|