Files
openless/Sources/OpenLessApp/Settings/Tabs/HelpTab.swift
T
baiqing c36ec22618 fix(help): correct GitHub URL + clean up FAQ / link layout
- HelpTab GitHub 链接 baiqing → appergb,老地址 404
- helpLink 不再把整段 URL 当 label(中间截断 + 和标题挤一行),
  改成右侧「打开 ↗」按钮,hover tooltip 显示完整 URL
- helpFAQ Q/A 间距 4 → 8、加 lineSpacing 2、行 padding 9 → 11,
  提升可读性
2026-04-28 13:28:50 +08:00

121 lines
5.3 KiB
Swift

import SwiftUI
import OpenLessCore
import OpenLessPersistence
struct HelpTab: View {
var body: some View {
SettingsPage(
title: "帮助中心",
subtitle: "快速上手 OpenLess、查阅快捷键、检查授权状态、跳转到文档与反馈渠道。"
) {
GlassSection(title: "快速上手", symbol: "play.circle") {
helpStep(num: 1, title: "配置火山 ASR", body: "在「设置」里填入火山 APP ID 和 Access Token;没有 ASR 凭据时只能走演示模式。")
DividerLine()
helpStep(num: 2, title: "(可选)配置润色", body: "在「设置」里填入 Ark API Key 后,识别结果会按「风格」中所选模式润色;不填也能用,会直接插入原文。")
DividerLine()
helpStep(num: 3, title: "授权辅助功能 + 麦克风", body: "首次启动会请求权限。授权后必须完全退出 OpenLess 再重新打开,全局快捷键才会生效。")
DividerLine()
helpStep(num: 4, title: "开始说话", body: "默认按右 Option 开始/停止录音;说完后文字自动插入到当前光标位置。Esc 取消本次。")
}
GlassSection(title: "快捷键速查", symbol: "keyboard") {
helpKey("开始 / 停止录音", value: UserPreferences.shared.hotkeyTrigger.displayName)
DividerLine()
helpKey("取消本次录音", value: "Esc")
DividerLine()
helpKey("胶囊确认插入", value: "点击右侧 ✓")
}
GlassSection(title: "常见问题", symbol: "questionmark.bubble") {
helpFAQ(
q: "全局快捷键没反应?",
a: "到「系统设置 → 隐私与安全 → 辅助功能」勾选 OpenLess。首次授权后必须完全退出再重启 App,全局快捷键才会生效。"
)
DividerLine()
helpFAQ(
q: "胶囊一直显示「演示」?",
a: "缺少火山 ASR 凭据。到「设置」里填入 APP ID 和 Access Token 即可。"
)
DividerLine()
helpFAQ(
q: "插入失败 / 只复制到剪贴板?",
a: "目标 App 不支持 AX 写入或粘贴模拟。OpenLess 会自动降级为复制到剪贴板,按 ⌘V 粘贴即可。"
)
}
GlassSection(title: "更多", symbol: "link") {
helpLink(title: "GitHub 仓库", url: "https://github.com/appergb/openless")
DividerLine()
helpLink(title: "提交问题或建议", url: "https://github.com/appergb/openless/issues")
}
}
}
private func helpStep(num: Int, title: String, body: String) -> some View {
HStack(alignment: .top, spacing: 12) {
Text("\(num)")
.font(.system(size: 13, weight: .bold, design: .rounded))
.foregroundStyle(.white)
.frame(width: 22, height: 22)
.background(Color.accentColor, in: Circle())
VStack(alignment: .leading, spacing: 4) {
Text(title).font(.system(size: 14, weight: .semibold))
Text(body).font(.callout).foregroundStyle(.secondary)
.fixedSize(horizontal: false, vertical: true)
}
Spacer(minLength: 0)
}
.padding(.vertical, 9)
}
private func helpKey(_ title: String, value: String) -> some View {
HStack {
Text(title)
Spacer()
Text(value)
.font(.system(size: 13, weight: .medium, design: .monospaced))
.padding(.horizontal, 9)
.padding(.vertical, 3)
.background(Color.primary.opacity(0.06), in: RoundedRectangle(cornerRadius: 6, style: .continuous))
}
.padding(.vertical, 9)
}
private func helpFAQ(q: String, a: String) -> some View {
VStack(alignment: .leading, spacing: 8) {
Text(q)
.font(.system(size: 14, weight: .semibold))
.foregroundStyle(.primary)
Text(a)
.font(.callout)
.foregroundStyle(.secondary)
.fixedSize(horizontal: false, vertical: true)
.lineSpacing(2)
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.vertical, 11)
}
/// 链接行:左标题、右图标按钮。
/// 之前把整段 URL 作为 label 渲染会被中间截断、和标题挤在一行,视觉很乱。
private func helpLink(title: String, url: String) -> some View {
HStack {
Text(title)
Spacer()
if let parsed = URL(string: url) {
Link(destination: parsed) {
HStack(spacing: 5) {
Text("打开")
.font(.callout)
Image(systemName: "arrow.up.right.square")
.font(.system(size: 12))
}
.foregroundStyle(.blue)
}
.help(url)
}
}
.padding(.vertical, 9)
}
}