用户报告设置页很多按钮无反应 + 关闭后托盘看不到图标。两处问题:\n\n1. ServerCard 占位按钮无回调:\n- server-card.slint:去掉了 toggled/edit-clicked/remove-clicked 三个回调以及 enabled 切换、Edit / Remove 按钮;变成纯展示卡(状态点 + name + url + 当前标记)\n- settings-page.slint:去掉硬编码的 Home / NAS 占位,改用 active-server-name / active-server-url / active-server-enabled 三个属性(MainWindow → AppConfig 实时填充);空时显示 '(未配置服务器)' 空态提示\n- app.slint:MainWindow 加三个属性 + 转发给 SettingsPage\n- lib.rs:startup 阶段把活跃服务器信息塞进 UI;测试连接成功/失败时更新 enabled 状态\n\n2. 托盘图标看不见:\n- tray.rs:原本 hIcon 写 null,Win10+ 上 Shell_NotifyIconW(NIM_ADD, NULL hIcon) 实际渲染为空白或很弱的小方块。改用 LoadIconW(NULL, IDI_APPLICATION) 加载 Windows 自带的应用程序图标(无需嵌入 .ico 资源,主题感知)。show_toast / Drop 的 hIcon 维持 null(让 NIM_MODIFY/NIM_DELETE 不动原有图标)。AGENTS.md §53 标记真 .ico 资源为 V2 项。
366 lines
12 KiB
Plaintext
366 lines
12 KiB
Plaintext
// AGENTS.md §10 / §11 settings page.
|
||
//
|
||
// Phase 7 C4: 全部翻译为简体中文。
|
||
|
||
import { SectionLabel } from "./components.slint";
|
||
import { ServerCard } from "./server-card.slint";
|
||
|
||
export component SettingsToggleRow inherits Rectangle {
|
||
in property <string> label;
|
||
in-out property <bool> value: false;
|
||
in property <bool> enabled: true;
|
||
callback toggled(string, bool);
|
||
|
||
in property <color> row-bg: #28292d;
|
||
in property <color> row-border: #3a3b40;
|
||
in property <color> label-color: #e6e6e6;
|
||
in property <color> toggle-on: #4ea1ff;
|
||
in property <color> toggle-off: #6a6a6a;
|
||
|
||
width: 100%;
|
||
height: 44px;
|
||
border-radius: 8px;
|
||
background: row-bg;
|
||
border-color: row-border;
|
||
border-width: 1px;
|
||
opacity: enabled ? 1.0 : 0.5;
|
||
|
||
HorizontalLayout {
|
||
padding-top: 0;
|
||
padding-bottom: 0;
|
||
padding-left: 16px;
|
||
padding-right: 16px;
|
||
alignment: center;
|
||
|
||
Text {
|
||
text: label;
|
||
color: label-color;
|
||
font-size: 13px;
|
||
horizontal-stretch: 1;
|
||
}
|
||
|
||
Rectangle {
|
||
width: 36px;
|
||
height: 20px;
|
||
border-radius: 10px;
|
||
background: value ? toggle-on : toggle-off;
|
||
y: parent.height / 2 - self.height / 2;
|
||
|
||
Rectangle {
|
||
width: 16px;
|
||
height: 16px;
|
||
border-radius: 8px;
|
||
background: #ffffff;
|
||
x: value ? parent.width - self.width - 2px : 2px;
|
||
y: (parent.height - self.height) / 2;
|
||
}
|
||
TouchArea {
|
||
enabled: root.enabled;
|
||
clicked => {
|
||
root.value = !root.value;
|
||
root.toggled(root.label, root.value);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
export component AppearanceRadio inherits Rectangle {
|
||
in property <string> label;
|
||
in property <string> description;
|
||
in property <bool> selected: false;
|
||
callback chosen();
|
||
|
||
in property <color> row-bg: #28292d;
|
||
in property <color> row-border: #3a3b40;
|
||
in property <color> row-border-selected: #4ea1ff;
|
||
in property <color> label-color: #e6e6e6;
|
||
in property <color> hint-color: #6a6a6a;
|
||
|
||
width: 160px;
|
||
height: 64px;
|
||
border-radius: 8px;
|
||
background: row-bg;
|
||
border-color: selected ? row-border-selected : row-border;
|
||
border-width: selected ? 2px : 1px;
|
||
|
||
VerticalLayout {
|
||
padding: 12px;
|
||
spacing: 2px;
|
||
|
||
Text {
|
||
text: label;
|
||
color: label-color;
|
||
font-size: 13px;
|
||
font-weight: 600;
|
||
}
|
||
Text {
|
||
text: description;
|
||
color: hint-color;
|
||
font-size: 11px;
|
||
}
|
||
}
|
||
|
||
TouchArea {
|
||
clicked => {
|
||
root.chosen();
|
||
}
|
||
}
|
||
}
|
||
|
||
export component SettingsPage inherits Rectangle {
|
||
in-out property <int> appearance-index: 2;
|
||
callback appearance-changed(int);
|
||
|
||
in-out property <bool> desktop-notify: true;
|
||
in-out property <bool> sound: true;
|
||
in-out property <bool> notify-high: true;
|
||
in-out property <bool> notify-max: true;
|
||
|
||
in-out property <bool> start-with-windows: false;
|
||
in-out property <bool> start-minimized: false;
|
||
in-out property <bool> close-to-tray: true;
|
||
|
||
in-out property <bool> advanced-expanded: false;
|
||
|
||
in-out property <bool> test-in-progress: false;
|
||
callback test-connection-requested();
|
||
|
||
callback toggle-persist(string, bool);
|
||
|
||
// Phase 7 C5: active server config (forwarded from MainWindow →
|
||
// AppConfig). Empty strings mean "未配置服务器". The page used to
|
||
// hardcode two placeholder rows ("Home" / "NAS") with Edit /
|
||
// Remove buttons that didn't do anything — that's what the user
|
||
// reported as "很多都没反应". V1 only has the single active
|
||
// server anyway, so a single card is honest about scope.
|
||
in property <string> active-server-name: "";
|
||
in property <string> active-server-url: "";
|
||
in property <bool> active-server-enabled: false;
|
||
|
||
in property <color> divider-color: #3a3b40;
|
||
in property <color> hint-color: #6a6a6a;
|
||
|
||
background: transparent;
|
||
|
||
VerticalLayout {
|
||
padding: 24px;
|
||
spacing: 24px;
|
||
|
||
// 连接
|
||
VerticalLayout {
|
||
spacing: 8px;
|
||
SectionLabel { label: "连接"; text-color: hint-color; }
|
||
|
||
Rectangle {
|
||
width: 160px;
|
||
height: 32px;
|
||
background: #2f3035;
|
||
border-radius: 6px;
|
||
Text {
|
||
x: (parent.width - self.width) / 2;
|
||
y: (parent.height - self.height) / 2;
|
||
text: root.test-in-progress ? "测试中…" : "测试连接";
|
||
color: #e6e6e6;
|
||
font-size: 12px;
|
||
}
|
||
TouchArea {
|
||
enabled: !root.test-in-progress;
|
||
clicked => {
|
||
root.test-connection-requested();
|
||
}
|
||
}
|
||
}
|
||
|
||
// Phase 7 C5: 单卡显示活跃服务器。多 server 添加/编辑/
|
||
// 删除 UI 在 V2 实现(AGENTS.md §21),V1 只有一个活跃
|
||
// server。空字符串 → 空态。
|
||
if root.active-server-url != "":
|
||
ServerCard {
|
||
server-name: root.active-server-name;
|
||
server-url: root.active-server-url;
|
||
enabled: root.active-server-enabled;
|
||
is-current: true;
|
||
}
|
||
|
||
if root.active-server-url == "":
|
||
Rectangle {
|
||
width: 100%;
|
||
height: 56px;
|
||
border-radius: 8px;
|
||
background: #28292d;
|
||
border-color: #3a3b40;
|
||
border-width: 1px;
|
||
Text {
|
||
x: 16px;
|
||
y: (parent.height - self.height) / 2;
|
||
text: "(未配置服务器 — V1 暂不支持 UI 添加,请手动编辑 %APPDATA%\\WindowsGotify\\config.json)";
|
||
color: #6a6a6a;
|
||
font-size: 12px;
|
||
wrap: word-wrap;
|
||
width: parent.width - 32px;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 通知
|
||
VerticalLayout {
|
||
spacing: 10px;
|
||
SectionLabel { label: "通知"; text-color: hint-color; }
|
||
SettingsToggleRow {
|
||
label: "启用桌面通知";
|
||
value: root.desktop-notify;
|
||
toggled(l, v) => {
|
||
root.desktop-notify = v;
|
||
root.toggle-persist(l, v);
|
||
}
|
||
}
|
||
SettingsToggleRow {
|
||
label: "播放声音";
|
||
value: root.sound;
|
||
enabled: root.desktop-notify;
|
||
toggled(l, v) => {
|
||
root.sound = v;
|
||
root.toggle-persist(l, v);
|
||
}
|
||
}
|
||
SettingsToggleRow {
|
||
label: "高级别时通知";
|
||
value: root.notify-high;
|
||
enabled: root.desktop-notify;
|
||
toggled(l, v) => {
|
||
root.notify-high = v;
|
||
root.toggle-persist(l, v);
|
||
}
|
||
}
|
||
SettingsToggleRow {
|
||
label: "最高级别时通知";
|
||
value: root.notify-max;
|
||
enabled: root.desktop-notify;
|
||
toggled(l, v) => {
|
||
root.notify-max = v;
|
||
root.toggle-persist(l, v);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 开机启动
|
||
VerticalLayout {
|
||
spacing: 10px;
|
||
SectionLabel { label: "开机启动"; text-color: hint-color; }
|
||
SettingsToggleRow {
|
||
label: "随 Windows 一起启动";
|
||
value: root.start-with-windows;
|
||
toggled(l, v) => {
|
||
root.start-with-windows = v;
|
||
root.toggle-persist(l, v);
|
||
}
|
||
}
|
||
SettingsToggleRow {
|
||
label: "启动时最小化到托盘";
|
||
value: root.start-minimized;
|
||
toggled(l, v) => {
|
||
root.start-minimized = v;
|
||
root.toggle-persist(l, v);
|
||
}
|
||
}
|
||
SettingsToggleRow {
|
||
label: "关闭按钮最小化到托盘";
|
||
value: root.close-to-tray;
|
||
toggled(l, v) => {
|
||
root.close-to-tray = v;
|
||
root.toggle-persist(l, v);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 外观
|
||
VerticalLayout {
|
||
spacing: 10px;
|
||
SectionLabel { label: "外观"; text-color: hint-color; }
|
||
|
||
HorizontalLayout {
|
||
spacing: 12px;
|
||
|
||
AppearanceRadio {
|
||
label: "跟随系统";
|
||
description: "跟随 Windows 主题";
|
||
selected: root.appearance-index == 0;
|
||
chosen => {
|
||
root.appearance-index = 0;
|
||
root.appearance-changed(0);
|
||
}
|
||
}
|
||
AppearanceRadio {
|
||
label: "浅色";
|
||
description: "明亮中性色";
|
||
selected: root.appearance-index == 1;
|
||
chosen => {
|
||
root.appearance-index = 1;
|
||
root.appearance-changed(1);
|
||
}
|
||
}
|
||
AppearanceRadio {
|
||
label: "深色";
|
||
description: "石墨灰";
|
||
selected: root.appearance-index == 2;
|
||
chosen => {
|
||
root.appearance-index = 2;
|
||
root.appearance-changed(2);
|
||
}
|
||
}
|
||
}
|
||
|
||
SettingsToggleRow {
|
||
label: "紧凑消息密度";
|
||
value: false;
|
||
enabled: false;
|
||
}
|
||
}
|
||
|
||
// 高级(默认折叠,见 §10)
|
||
VerticalLayout {
|
||
spacing: 10px;
|
||
|
||
HorizontalLayout {
|
||
spacing: 8px;
|
||
alignment: center;
|
||
Text {
|
||
text: advanced-expanded ? "v" : ">";
|
||
color: hint-color;
|
||
font-size: 11px;
|
||
}
|
||
Text {
|
||
text: "高级";
|
||
color: hint-color;
|
||
font-size: 11px;
|
||
font-weight: 700;
|
||
}
|
||
TouchArea {
|
||
clicked => {
|
||
root.advanced-expanded = !root.advanced-expanded;
|
||
}
|
||
}
|
||
}
|
||
|
||
if advanced-expanded: VerticalLayout {
|
||
spacing: 10px;
|
||
SettingsToggleRow {
|
||
label: "日志级别:Info(release 默认)";
|
||
value: false;
|
||
enabled: false;
|
||
}
|
||
SettingsToggleRow {
|
||
label: "清除本地状态(消息 + 窗口大小)";
|
||
value: false;
|
||
enabled: false;
|
||
}
|
||
SettingsToggleRow {
|
||
label: "恢复默认设置";
|
||
value: false;
|
||
enabled: false;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} |