feat: add About tab with developer profile and product links

New sidebar tab (⌘7) showing author info, AI coding philosophy quote,
AtomStorm Studio product link, GitHub open-source link, and social channels.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
zhukang
2026-03-10 20:22:08 +08:00
parent e37927b143
commit 0346e47b46
6 changed files with 226 additions and 13 deletions

View File

@@ -1,5 +1,6 @@
import AtlasDesignSystem
import AtlasDomain
import AtlasFeaturesAbout
import AtlasFeaturesApps
import AtlasFeaturesHistory
import AtlasFeaturesOverview
@@ -133,7 +134,21 @@ struct AppShellView: View {
case .overview:
OverviewFeatureView(
snapshot: model.filteredSnapshot,
isRefreshingHealthSnapshot: model.isHealthSnapshotRefreshing
isRefreshingHealthSnapshot: model.isHealthSnapshotRefreshing,
onStartSmartClean: {
model.navigate(to: .smartClean)
Task { await model.runSmartCleanScan() }
},
onNavigateToSmartClean: {
model.navigate(to: .smartClean)
},
onNavigateToHistory: {
model.navigate(to: .history)
},
onNavigateToPermissions: {
model.navigate(to: .permissions)
Task { await model.inspectPermissions() }
}
)
case .smartClean:
SmartCleanFeatureView(
@@ -209,6 +224,8 @@ struct AppShellView: View {
Task { await model.setNotificationsEnabled(isEnabled) }
}
)
case .about:
AboutFeatureView()
}
}
@@ -223,18 +240,7 @@ private struct SidebarRouteRow: View {
let route: AtlasRoute
var body: some View {
Label {
VStack(alignment: .leading, spacing: AtlasSpacing.xxs) {
Text(route.title)
.font(AtlasTypography.rowTitle)
Text(route.subtitle)
.font(AtlasTypography.captionSmall)
.foregroundStyle(.secondary)
.lineLimit(1)
.truncationMode(.tail)
}
} icon: {
HStack(alignment: .center, spacing: AtlasSpacing.md) {
ZStack {
RoundedRectangle(cornerRadius: AtlasRadius.sm, style: .continuous)
.fill(AtlasColor.brand.opacity(0.1))
@@ -245,6 +251,17 @@ private struct SidebarRouteRow: View {
.foregroundStyle(AtlasColor.brand)
.accessibilityHidden(true)
}
VStack(alignment: .leading, spacing: AtlasSpacing.xxs) {
Text(route.title)
.font(AtlasTypography.rowTitle)
Text(route.subtitle)
.font(.caption2)
.foregroundStyle(.tertiary)
.lineLimit(1)
.truncationMode(.tail)
}
}
.padding(.vertical, AtlasSpacing.sm)
.contentShape(Rectangle())
@@ -275,6 +292,8 @@ private extension AtlasRoute {
return "5"
case .settings:
return "6"
case .about:
return "7"
}
}
}

View File

@@ -7,6 +7,7 @@ public enum AtlasRoute: String, CaseIterable, Codable, Hashable, Identifiable, S
case history
case permissions
case settings
case about
public var id: String { rawValue }
@@ -24,6 +25,8 @@ public enum AtlasRoute: String, CaseIterable, Codable, Hashable, Identifiable, S
return AtlasL10n.string("route.permissions.title")
case .settings:
return AtlasL10n.string("route.settings.title")
case .about:
return AtlasL10n.string("route.about.title")
}
}
@@ -41,6 +44,8 @@ public enum AtlasRoute: String, CaseIterable, Codable, Hashable, Identifiable, S
return AtlasL10n.string("route.permissions.subtitle")
case .settings:
return AtlasL10n.string("route.settings.subtitle")
case .about:
return AtlasL10n.string("route.about.subtitle")
}
}
@@ -58,6 +63,8 @@ public enum AtlasRoute: String, CaseIterable, Codable, Hashable, Identifiable, S
return "lock.shield"
case .settings:
return "gearshape"
case .about:
return "person.crop.circle"
}
}
}

View File

@@ -14,6 +14,8 @@
"route.permissions.subtitle" = "Explain why access is needed before asking for it.";
"route.settings.title" = "Settings";
"route.settings.subtitle" = "Preferences, exclusions, acknowledgement, and notices.";
"route.about.title" = "About";
"route.about.subtitle" = "Meet the developer and explore more products.";
"risk.safe" = "Safe";
"risk.review" = "Review";
@@ -244,6 +246,14 @@
"overview.risk.safe" = "Low-risk cleanup";
"overview.risk.review" = "Review before removing";
"overview.risk.advanced" = "Advanced inspection recommended";
"overview.actions.viewAll" = "View all %d findings";
"overview.activity.viewAll" = "View all activity";
"overview.snapshot.viewAllOptimizations" = "Show all %d suggestions";
"overview.snapshot.collapseOptimizations" = "Collapse suggestions";
"overview.action.smartClean" = "Run Smart Clean";
"overview.action.smartClean.hint" = "Navigate to Smart Clean and start a scan.";
"overview.action.permissions" = "Fix Permissions";
"overview.action.permissions.hint" = "Navigate to Permissions to check and grant access.";
"smartclean.screen.title" = "Smart Clean";
"smartclean.screen.subtitle" = "Turn scan results into a clear cleanup plan before you decide to run anything destructive.";
@@ -559,3 +569,33 @@
"settings.acknowledgement.subtitle" = "The in-app attribution text users can read without leaving the product.";
"settings.notices.title" = "Third-Party Notices";
"settings.notices.subtitle" = "A concise notice surface for shipped third-party attributions.";
"confirm.title" = "Confirm";
"confirm.cancel" = "Cancel";
"smartclean.confirm.execute.title" = "Run this cleanup plan?";
"smartclean.confirm.execute.message" = "This will process the reviewed plan. Items marked recoverable can be restored from History.";
"apps.confirm.uninstall.title" = "Uninstall this app?";
"apps.confirm.uninstall.message" = "This will remove %@ and its leftovers. Recoverable items can be restored from History.";
"emptystate.action.scan" = "Run Smart Clean";
"emptystate.action.refresh" = "Refresh Apps";
"emptystate.action.viewHistory" = "View History";
"emptystate.action.startScan" = "Start Scan";
"about.screen.title" = "About";
"about.screen.subtitle" = "The person and vision behind Atlas for Mac.";
"about.author.title" = "Developer";
"about.author.name" = "Lizi KK";
"about.author.role" = "Ex-Baidu & Alibaba Tech Lead · Hands On AI Coding";
"about.author.bio" = "Built Atlas from 0 to 1 solo. Every line is AI-assisted, but passed through human decision-making, taste, and architectural judgment.";
"about.author.quote" = "AI is incredibly powerful hands and feet, but you must be the clear-headed brain.";
"about.product.title" = "Also by the Developer";
"about.product.name" = "AtomStorm Studio";
"about.product.detail" = "AI Agent-powered design platform — from idea to presentations, landing pages, and posters in minutes.";
"about.product.visit" = "Visit AtomStorm Studio";
"about.opensource.title" = "Open Source";
"about.opensource.name" = "Atlas for Mac (Mole Installer)";
"about.opensource.detail" = "This project is open source. Star, fork, or contribute on GitHub.";
"about.opensource.visit" = "View on GitHub";
"about.social.title" = "Follow Me";
"about.social.detail" = "WeChat Official Account & Xiaohongshu";
"smartclean.preview.callout.review.title" = "Some steps in this plan need a closer review";

View File

@@ -14,6 +14,8 @@
"route.permissions.subtitle" = "先解释原因,再请求访问。";
"route.settings.title" = "设置";
"route.settings.subtitle" = "偏好、排除项、致谢和通知。";
"route.about.title" = "关于";
"route.about.subtitle" = "了解作者,探索更多产品。";
"risk.safe" = "安全";
"risk.review" = "复核";
@@ -244,6 +246,14 @@
"overview.risk.safe" = "低风险清理";
"overview.risk.review" = "建议删除前先复核";
"overview.risk.advanced" = "建议高级检查";
"overview.actions.viewAll" = "查看全部 %d 项发现";
"overview.activity.viewAll" = "查看全部活动";
"overview.snapshot.viewAllOptimizations" = "展开全部 %d 条建议";
"overview.snapshot.collapseOptimizations" = "收起建议";
"overview.action.smartClean" = "运行智能清理";
"overview.action.smartClean.hint" = "前往智能清理并开始扫描。";
"overview.action.permissions" = "修复权限";
"overview.action.permissions.hint" = "前往权限页面检查并授权。";
"smartclean.screen.title" = "智能清理";
"smartclean.screen.subtitle" = "先把扫描结果变成清晰的清理计划,再决定是否执行任何具有破坏性的操作。";
@@ -559,3 +569,33 @@
"settings.acknowledgement.subtitle" = "用户无需离开产品,就能查看应用内致谢文本。";
"settings.notices.title" = "第三方说明";
"settings.notices.subtitle" = "用于展示随产品一起分发的第三方说明信息。";
"confirm.title" = "确认";
"confirm.cancel" = "取消";
"smartclean.confirm.execute.title" = "执行这份清理计划?";
"smartclean.confirm.execute.message" = "将按复核后的计划执行清理。标记为可恢复的项目可以在历史中找回。";
"apps.confirm.uninstall.title" = "卸载这个应用?";
"apps.confirm.uninstall.message" = "将移除 %@ 及其残留文件。可恢复的项目可以在历史中找回。";
"emptystate.action.scan" = "运行智能清理";
"emptystate.action.refresh" = "刷新应用";
"emptystate.action.viewHistory" = "查看历史";
"emptystate.action.startScan" = "开始扫描";
"about.screen.title" = "关于";
"about.screen.subtitle" = "Atlas for Mac 背后的开发者与愿景。";
"about.author.title" = "关于作者";
"about.author.name" = "Lizi KK";
"about.author.role" = "前百度 & 阿里技术负责人 · AI 全栈独立开发";
"about.author.bio" = "从 0 到 1 独立构建 Atlas。每一行代码都由 AI 辅助,但都经过了人的决策、审美和架构判断。";
"about.author.quote" = "AI 是极其强大的手和脚,但你必须做那个头脑清醒的大脑。";
"about.product.title" = "作者的其他产品";
"about.product.name" = "AtomStorm Studio";
"about.product.detail" = "AI Agent 驱动的设计创作平台——从想法到演示文稿、落地页和海报,几分钟搞定。";
"about.product.visit" = "访问 AtomStorm Studio";
"about.opensource.title" = "开源项目";
"about.opensource.name" = "Atlas for Mac (Mole Installer)";
"about.opensource.detail" = "本项目已开源。欢迎在 GitHub 上 Star、Fork 或参与贡献。";
"about.opensource.visit" = "在 GitHub 上查看";
"about.social.title" = "关注作者";
"about.social.detail" = "微信公众号 & 小红书";
"smartclean.preview.callout.review.title" = "这份计划中仍有步骤需要复核";

View File

@@ -0,0 +1,100 @@
import AtlasDesignSystem
import AtlasDomain
import SwiftUI
public struct AboutFeatureView: View {
public init() {}
public var body: some View {
AtlasScreen(
title: AtlasL10n.string("about.screen.title"),
subtitle: AtlasL10n.string("about.screen.subtitle")
) {
AtlasInfoCard(
title: AtlasL10n.string("about.author.title")
) {
HStack(alignment: .center, spacing: AtlasSpacing.md) {
Image(systemName: "person.crop.circle.fill")
.font(.system(size: 40, weight: .light))
.foregroundStyle(AtlasColor.brand)
.accessibilityHidden(true)
VStack(alignment: .leading, spacing: AtlasSpacing.xxs) {
Text(AtlasL10n.string("about.author.name"))
.font(AtlasTypography.sectionTitle)
Text(AtlasL10n.string("about.author.role"))
.font(.caption)
.foregroundStyle(.secondary)
}
}
.padding(.bottom, AtlasSpacing.sm)
Text(AtlasL10n.string("about.author.bio"))
.font(AtlasTypography.body)
.foregroundStyle(.secondary)
}
AtlasCallout(
title: AtlasL10n.string("about.author.quote"),
detail: AtlasL10n.string("about.author.name"),
tone: .neutral,
systemImage: "quote.opening"
)
AtlasInfoCard(
title: AtlasL10n.string("about.product.title")
) {
AtlasDetailRow(
title: AtlasL10n.string("about.product.name"),
subtitle: AtlasL10n.string("about.product.detail"),
systemImage: "sparkle"
)
Link(destination: URL(string: "https://studio.atomstorm.ai")!) {
Text(AtlasL10n.string("about.product.visit"))
.frame(maxWidth: .infinity)
}
.buttonStyle(.atlasPrimary)
.padding(.top, AtlasSpacing.sm)
}
AtlasInfoCard(
title: AtlasL10n.string("about.opensource.title")
) {
AtlasDetailRow(
title: AtlasL10n.string("about.opensource.name"),
subtitle: AtlasL10n.string("about.opensource.detail"),
systemImage: "chevron.left.forwardslash.chevron.right"
)
Link(destination: URL(string: "https://github.com/CSZHK/mole-installer")!) {
Text(AtlasL10n.string("about.opensource.visit"))
.frame(maxWidth: .infinity)
}
.buttonStyle(.atlasSecondary)
.padding(.top, AtlasSpacing.sm)
}
AtlasInfoCard(
title: AtlasL10n.string("about.social.title")
) {
HStack(spacing: AtlasSpacing.md) {
Image(systemName: "ellipsis.bubble")
.font(.title3)
.foregroundStyle(AtlasColor.brand)
.accessibilityHidden(true)
Text(AtlasL10n.string("about.social.detail"))
.font(AtlasTypography.body)
.foregroundStyle(.secondary)
}
}
}
.accessibilityIdentifier("about.screen")
}
}
#Preview {
AboutFeatureView()
}

View File

@@ -14,6 +14,7 @@ let package = Package(
.library(name: "AtlasFeaturesHistory", targets: ["AtlasFeaturesHistory"]),
.library(name: "AtlasFeaturesOverview", targets: ["AtlasFeaturesOverview"]),
.library(name: "AtlasFeaturesPermissions", targets: ["AtlasFeaturesPermissions"]),
.library(name: "AtlasFeaturesAbout", targets: ["AtlasFeaturesAbout"]),
.library(name: "AtlasFeaturesSettings", targets: ["AtlasFeaturesSettings"]),
.library(name: "AtlasFeaturesSmartClean", targets: ["AtlasFeaturesSmartClean"]),
.library(name: "AtlasFeaturesStorage", targets: ["AtlasFeaturesStorage"]),
@@ -23,6 +24,7 @@ let package = Package(
targets: [
.target(
name: "AtlasDesignSystem",
dependencies: ["AtlasDomain"],
path: "AtlasDesignSystem/Sources/AtlasDesignSystem",
resources: [.process("Resources")]
),
@@ -62,6 +64,11 @@ let package = Package(
dependencies: ["AtlasApplication", "AtlasDesignSystem", "AtlasDomain"],
path: "AtlasFeaturesSmartClean/Sources/AtlasFeaturesSmartClean"
),
.target(
name: "AtlasFeaturesAbout",
dependencies: ["AtlasDesignSystem", "AtlasDomain"],
path: "AtlasFeaturesAbout/Sources/AtlasFeaturesAbout"
),
.target(
name: "AtlasFeaturesApps",
dependencies: ["AtlasDesignSystem", "AtlasDomain"],