From 3acc79472e9868a5f2c5b60afb59ef8a9ed295dc Mon Sep 17 00:00:00 2001 From: ysicing Date: Sun, 27 Sep 2026 20:09:00 +0800 Subject: [PATCH] =?UTF-8?q?feat(feedback):=20=E6=B7=BB=E5=8A=A0=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E6=8A=A5=E5=91=8A=E4=B8=8E=E9=82=AE=E4=BB=B6=E5=8F=8D?= =?UTF-8?q?=E9=A6=88=E5=85=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/ISSUE_TEMPLATE/bug_report.md | 31 ++++++++++ .../Sources/Localization/Resources/ar.tsv | 2 + .../Sources/Localization/Resources/de.tsv | 2 + .../Sources/Localization/Resources/es.tsv | 2 + .../Sources/Localization/Resources/fr.tsv | 2 + .../Sources/Localization/Resources/ja.tsv | 2 + .../Sources/Localization/Resources/ko.tsv | 2 + .../Localization/Resources/zh-Hant.tsv | 2 + .../Sources/Localization/Translations.swift | 2 + .../Sources/XStatsUI/Design/Components.swift | 2 +- .../XStatsUI/Panel/MainWindowView.swift | 56 +++++++++++++++++++ .../XStatsUITests/FeedbackLinksTests.swift | 28 ++++++++++ 12 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 Packages/XStatsKit/Tests/XStatsUITests/FeedbackLinksTests.swift diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..09a475b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,31 @@ +--- +name: 问题反馈 / Bug report +about: 反馈 XStats 的故障或异常 / Report an XStats bug +title: "[Bug] " +--- + +## 问题描述 / Description + +请简要描述遇到的问题。Describe the problem. + +## 复现步骤 / Steps to reproduce + +1. +2. +3. + +## 预期结果 / Expected behavior + + +## 实际结果 / Actual behavior + + +## 环境 / Environment + +- XStats 版本与构建号 / version and build: +- macOS 版本 / version: + +## 截图与日志 / Screenshots and logs + +如有帮助,可在 XStats 的“设置 → 关于”中导出诊断信息并附上。请先检查附件,避免公开密码、令牌等敏感信息。 +If useful, export diagnostics from XStats Settings → About and attach them after reviewing the archive for sensitive information. diff --git a/Packages/XStatsKit/Sources/Localization/Resources/ar.tsv b/Packages/XStatsKit/Sources/Localization/Resources/ar.tsv index b3d2b3d..1527799 100644 --- a/Packages/XStatsKit/Sources/Localization/Resources/ar.tsv +++ b/Packages/XStatsKit/Sources/Localization/Resources/ar.tsv @@ -397,6 +397,7 @@ uv 下载的 Python 包与构建缓存,由 uv 自行清理 ذاكرة حزم P 发现问题:{} وُجدت مشكلة: {} 发生这些状况时发送系统通知,点通知打开对应页面 إرسال إشعار عند حدوث هذه الحالات؛ انقر عليه لفتح الصفحة المعنية 发送 إرسال +发送反馈邮件 إرسال ملاحظات عبر البريد الإلكتروني 发送测试通知 إرسال إشعار اختبار 取消 إلغاء 受保护 محمي @@ -467,6 +468,7 @@ uv 下载的 Python 包与构建缓存,由 uv 自行清理 ذاكرة حزم P 图标 أيقونة 圆环 حلقة 圆环表示当前占用比例 تعرض الحلقة الاستخدام الحالي +在 GitHub 提交问题 الإبلاغ عن مشكلة على GitHub 在 cleanip.io 查看这个 IP 的完整报告 فتح التقرير الكامل لعنوان IP هذا في cleanip.io 在主窗口打开“{}” فتح «{}» في النافذة الرئيسية 在程序坞显示图标 عرض الرمز في Dock diff --git a/Packages/XStatsKit/Sources/Localization/Resources/de.tsv b/Packages/XStatsKit/Sources/Localization/Resources/de.tsv index 1b2709b..4083336 100644 --- a/Packages/XStatsKit/Sources/Localization/Resources/de.tsv +++ b/Packages/XStatsKit/Sources/Localization/Resources/de.tsv @@ -397,6 +397,7 @@ uv 下载的 Python 包与构建缓存,由 uv 自行清理 Von uv geladener Py 发现问题:{} Problem gefunden: {} 发生这些状况时发送系统通知,点通知打开对应页面 Bei diesen Ereignissen eine Mitteilung senden; ein Klick öffnet die entsprechende Seite 发送 Senden +发送反馈邮件 Feedback per E-Mail senden 发送测试通知 Testmitteilung senden 取消 Abbrechen 受保护 Geschützt @@ -467,6 +468,7 @@ uv 下载的 Python 包与构建缓存,由 uv 自行清理 Von uv geladener Py 图标 Symbol 圆环 Ring 圆环表示当前占用比例 Ein Ring zeigt die aktuelle Auslastung +在 GitHub 提交问题 Problem auf GitHub melden 在 cleanip.io 查看这个 IP 的完整报告 Vollständigen Bericht zu dieser IP auf cleanip.io öffnen 在主窗口打开“{}” „{}“ im Hauptfenster öffnen 在程序坞显示图标 Symbol im Dock anzeigen diff --git a/Packages/XStatsKit/Sources/Localization/Resources/es.tsv b/Packages/XStatsKit/Sources/Localization/Resources/es.tsv index aad5f7a..3ed8445 100644 --- a/Packages/XStatsKit/Sources/Localization/Resources/es.tsv +++ b/Packages/XStatsKit/Sources/Localization/Resources/es.tsv @@ -397,6 +397,7 @@ uv 下载的 Python 包与构建缓存,由 uv 自行清理 Cachés de paquetes 发现问题:{} Problema encontrado: {} 发生这些状况时发送系统通知,点通知打开对应页面 Enviar una notificación cuando ocurra; púlsala para abrir la página correspondiente 发送 Enviar +发送反馈邮件 Enviar correo de comentarios 发送测试通知 Enviar notificación de prueba 取消 Cancelar 受保护 Protegido @@ -467,6 +468,7 @@ uv 下载的 Python 包与构建缓存,由 uv 自行清理 Cachés de paquetes 图标 Icono 圆环 Anillo 圆环表示当前占用比例 Un anillo muestra el uso actual +在 GitHub 提交问题 Informar de un problema en GitHub 在 cleanip.io 查看这个 IP 的完整报告 Abrir el informe completo de esta IP en cleanip.io 在主窗口打开“{}” Abrir «{}» en la ventana principal 在程序坞显示图标 Mostrar icono en el Dock diff --git a/Packages/XStatsKit/Sources/Localization/Resources/fr.tsv b/Packages/XStatsKit/Sources/Localization/Resources/fr.tsv index c6ed596..c90d364 100644 --- a/Packages/XStatsKit/Sources/Localization/Resources/fr.tsv +++ b/Packages/XStatsKit/Sources/Localization/Resources/fr.tsv @@ -397,6 +397,7 @@ uv 下载的 Python 包与构建缓存,由 uv 自行清理 Caches de paquets P 发现问题:{} Problème détecté : {} 发生这些状况时发送系统通知,点通知打开对应页面 Envoyer une notification lors de ces événements ; cliquer dessus ouvre la page correspondante 发送 Envoyer +发送反馈邮件 Envoyer un retour par e-mail 发送测试通知 Envoyer une notification de test 取消 Annuler 受保护 Protégé @@ -467,6 +468,7 @@ uv 下载的 Python 包与构建缓存,由 uv 自行清理 Caches de paquets P 图标 Icône 圆环 Anneau 圆环表示当前占用比例 Un anneau représente l’utilisation actuelle +在 GitHub 提交问题 Signaler un problème sur GitHub 在 cleanip.io 查看这个 IP 的完整报告 Ouvrir le rapport complet de cette IP sur cleanip.io 在主窗口打开“{}” Ouvrir « {} » dans la fenêtre principale 在程序坞显示图标 Afficher l’icône dans le Dock diff --git a/Packages/XStatsKit/Sources/Localization/Resources/ja.tsv b/Packages/XStatsKit/Sources/Localization/Resources/ja.tsv index cbc6b00..2eed6d9 100644 --- a/Packages/XStatsKit/Sources/Localization/Resources/ja.tsv +++ b/Packages/XStatsKit/Sources/Localization/Resources/ja.tsv @@ -397,6 +397,7 @@ uv 下载的 Python 包与构建缓存,由 uv 自行清理 uvのPythonパッ 发现问题:{} 問題が見つかりました:{} 发生这些状况时发送系统通知,点通知打开对应页面 これらの状態で通知を送信します。通知をクリックすると関連ページが開きます 发送 送信 +发送反馈邮件 フィードバックをメールで送信 发送测试通知 テスト通知を送信 取消 キャンセル 受保护 保護されています @@ -467,6 +468,7 @@ uv 下载的 Python 包与构建缓存,由 uv 自行清理 uvのPythonパッ 图标 アイコン 圆环 リング 圆环表示当前占用比例 リングは現在の使用率を示します +在 GitHub 提交问题 GitHubで問題を報告 在 cleanip.io 查看这个 IP 的完整报告 cleanip.ioでこのIPの詳細レポートを開く 在主窗口打开“{}” メインウインドウで「{}」を開く 在程序坞显示图标 Dockにアイコンを表示 diff --git a/Packages/XStatsKit/Sources/Localization/Resources/ko.tsv b/Packages/XStatsKit/Sources/Localization/Resources/ko.tsv index 7c3ab28..4160137 100644 --- a/Packages/XStatsKit/Sources/Localization/Resources/ko.tsv +++ b/Packages/XStatsKit/Sources/Localization/Resources/ko.tsv @@ -397,6 +397,7 @@ uv 下载的 Python 包与构建缓存,由 uv 自行清理 uv의 Python 패키 发现问题:{} 문제 발견: {} 发生这些状况时发送系统通知,点通知打开对应页面 이러한 상황에서 알림을 보냅니다. 알림을 클릭하면 관련 페이지가 열립니다 发送 보내기 +发送反馈邮件 피드백 이메일 보내기 发送测试通知 테스트 알림 보내기 取消 취소 受保护 보호됨 @@ -467,6 +468,7 @@ uv 下载的 Python 包与构建缓存,由 uv 自行清理 uv의 Python 패키 图标 아이콘 圆环 링 圆环表示当前占用比例 링은 현재 사용률을 표시합니다 +在 GitHub 提交问题 GitHub에 문제 신고 在 cleanip.io 查看这个 IP 的完整报告 cleanip.io에서 이 IP의 전체 보고서 열기 在主窗口打开“{}” 주 윈도우에서 “{}” 열기 在程序坞显示图标 Dock에 아이콘 표시 diff --git a/Packages/XStatsKit/Sources/Localization/Resources/zh-Hant.tsv b/Packages/XStatsKit/Sources/Localization/Resources/zh-Hant.tsv index 371b190..79c1c1b 100644 --- a/Packages/XStatsKit/Sources/Localization/Resources/zh-Hant.tsv +++ b/Packages/XStatsKit/Sources/Localization/Resources/zh-Hant.tsv @@ -398,6 +398,7 @@ uv 下载的 Python 包与构建缓存,由 uv 自行清理 uv 下載的 Python 发现问题:{} 發現問題:{} 发生这些状况时发送系统通知,点通知打开对应页面 發生這些狀況時發送系統通知,點通知打開對應頁面 发送 發送 +发送反馈邮件 傳送回饋郵件 发送测试通知 發送測試通知 取消 取消 受保护 受保護 @@ -468,6 +469,7 @@ uv 下载的 Python 包与构建缓存,由 uv 自行清理 uv 下載的 Python 图标 圖標 圆环 圓環 圆环表示当前占用比例 圓環表示當前佔用比例 +在 GitHub 提交问题 在 GitHub 提交問題 在 cleanip.io 查看这个 IP 的完整报告 在 cleanip.io 查看這個 IP 的完整報告 在主窗口打开“{}” 在主窗口打開“{}” 在程序坞显示图标 在程序塢顯示圖標 diff --git a/Packages/XStatsKit/Sources/Localization/Translations.swift b/Packages/XStatsKit/Sources/Localization/Translations.swift index 4663cbc..80b456e 100644 --- a/Packages/XStatsKit/Sources/Localization/Translations.swift +++ b/Packages/XStatsKit/Sources/Localization/Translations.swift @@ -518,6 +518,7 @@ uv 下载的 Python 包与构建缓存,由 uv 自行清理 Python package and 发现问题:{} Problem found: {} 发生这些状况时发送系统通知,点通知打开对应页面 Send a notification when these happen; click it to open the related page 发送 Send +发送反馈邮件 Send Feedback Email 发送测试通知 Send Test Notification 取消 Cancel 受保护 Protected @@ -588,6 +589,7 @@ uv 下载的 Python 包与构建缓存,由 uv 自行清理 Python package and 图标 Icon 圆环 Ring 圆环表示当前占用比例 A ring shows current usage +在 GitHub 提交问题 Report a Problem on GitHub 在 cleanip.io 查看这个 IP 的完整报告 Open this IP's full report on cleanip.io 在主窗口打开“{}” Open “{}” in the main window 在程序坞显示图标 Show Icon in Dock diff --git a/Packages/XStatsKit/Sources/XStatsUI/Design/Components.swift b/Packages/XStatsKit/Sources/XStatsUI/Design/Components.swift index b456ab7..41f8440 100644 --- a/Packages/XStatsKit/Sources/XStatsUI/Design/Components.swift +++ b/Packages/XStatsKit/Sources/XStatsUI/Design/Components.swift @@ -477,7 +477,7 @@ private struct GlassButtonSurface: ViewModifier { } } -private struct IconButtonSurface: ViewModifier { +struct IconButtonSurface: ViewModifier { let hovering: Bool let glass: Bool diff --git a/Packages/XStatsKit/Sources/XStatsUI/Panel/MainWindowView.swift b/Packages/XStatsKit/Sources/XStatsUI/Panel/MainWindowView.swift index d9be5e4..b742767 100644 --- a/Packages/XStatsKit/Sources/XStatsUI/Panel/MainWindowView.swift +++ b/Packages/XStatsKit/Sources/XStatsUI/Panel/MainWindowView.swift @@ -153,6 +153,7 @@ private struct MainSidebar: View { HStack(spacing: DS.Space.s1) { ThemeToggle() + FeedbackMenu() Spacer(minLength: 0) IconButton(systemName: "power", help: tr("退出 XStats")) { model.quit() } } @@ -208,6 +209,61 @@ private struct MainSidebar: View { } } +private struct FeedbackMenu: View { + @Environment(\.isInsideGlass) private var isInsideGlass + @State private var hovering = false + + var body: some View { + let glass = DS.Glass.isAvailable && !isInsideGlass + Menu { + Button { + NSWorkspace.shared.open(FeedbackLinks.githubBugReport) + } label: { + Label(tr("在 GitHub 提交问题"), systemImage: "ladybug") + } + Button { + let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? tr("开发版") + let build = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String + let systemVersion = ProcessInfo.processInfo.operatingSystemVersionString + if let url = FeedbackLinks.email(version: version, build: build, systemVersion: systemVersion) { + NSWorkspace.shared.open(url) + } + } label: { + Label(tr("发送反馈邮件"), systemImage: "envelope") + } + } label: { + Image(systemName: "ladybug") + .font(.system(size: DS.TextSize.sm.rawValue, weight: .medium)) + .foregroundStyle(hovering ? DS.Palette.primary : glass ? DS.Palette.textPrimary : DS.Palette.textSecondary) + .frame(width: DS.Size.controlHeight, height: DS.Size.controlHeight) + .modifier(IconButtonSurface(hovering: hovering, glass: glass)) + .contentShape(Circle()) + } + .menuStyle(.borderlessButton) + .menuIndicator(.hidden) + .frame(width: DS.Size.controlHeight) + .onHover { hovering = $0 } + .help(tr("反馈问题")) + .accessibilityLabel(tr("反馈问题")) + } +} + +enum FeedbackLinks { + static let githubBugReport = URL(string: "https://github.com/ysicing/XStats/issues/new?template=bug_report.md")! + + static func email(version: String, build: String?, systemVersion: String) -> URL? { + let appVersion = build.map { "\(version) (\($0))" } ?? version + var components = URLComponents() + components.scheme = "mailto" + components.path = "i@xiai.me" + components.queryItems = [ + URLQueryItem(name: "subject", value: tr("反馈问题")), + URLQueryItem(name: "body", value: "XStats \(appVersion)\nmacOS \(systemVersion)\n\n"), + ] + return components.url + } +} + private struct PageHeader: View { @Environment(AppModel.self) private var model diff --git a/Packages/XStatsKit/Tests/XStatsUITests/FeedbackLinksTests.swift b/Packages/XStatsKit/Tests/XStatsUITests/FeedbackLinksTests.swift new file mode 100644 index 0000000..bb95723 --- /dev/null +++ b/Packages/XStatsKit/Tests/XStatsUITests/FeedbackLinksTests.swift @@ -0,0 +1,28 @@ +// Copyright (C) 2026 ysicing +// SPDX-License-Identifier: AGPL-3.0-or-later + +import Foundation +import Testing +@testable import XStatsUI + +@Suite struct FeedbackLinksTests { + @Test func githubOpensTheBugReportTemplate() { + let url = FeedbackLinks.githubBugReport + let components = URLComponents(url: url, resolvingAgainstBaseURL: false) + #expect(url.scheme == "https") + #expect(url.host == "github.com") + #expect(url.path == "/ysicing/XStats/issues/new") + #expect(components?.queryItems?.first(where: { $0.name == "template" })?.value == "bug_report.md") + } + + @Test func emailPrefillsAppBuildAndSystemVersion() throws { + let url = try #require(FeedbackLinks.email(version: "0.10.0", build: "119", + systemVersion: "Version 26.0 (Build 25A123)")) + let components = try #require(URLComponents(url: url, resolvingAgainstBaseURL: false)) + #expect(components.scheme == "mailto") + #expect(components.path == "i@xiai.me") + #expect(components.queryItems?.first(where: { $0.name == "subject" })?.value?.isEmpty == false) + #expect(components.queryItems?.first(where: { $0.name == "body" })?.value + == "XStats 0.10.0 (119)\nmacOS Version 26.0 (Build 25A123)\n\n") + } +}