diff --git a/SwiftPamphletApp.xcodeproj/project.pbxproj b/SwiftPamphletApp.xcodeproj/project.pbxproj index af01e1b18..04b63fd9a 100644 --- a/SwiftPamphletApp.xcodeproj/project.pbxproj +++ b/SwiftPamphletApp.xcodeproj/project.pbxproj @@ -27,6 +27,9 @@ 08038767276700F100519B15 /* CCYRESTfulAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08038766276700F100519B15 /* CCYRESTfulAPI.swift */; }; 083554E12756503B0095E0EE /* AnimateLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 083554E02756503B0095E0EE /* AnimateLayout.swift */; }; 083554E327572BB60095E0EE /* AppVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 083554E227572BB60095E0EE /* AppVM.swift */; }; + 084417752B99B9060049297D /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 084417742B99B9060049297D /* HomeView.swift */; }; + 084417772B99BA3F0049297D /* SidebarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 084417762B99BA3F0049297D /* SidebarView.swift */; }; + 084417792B99BE720049297D /* DataLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 084417782B99BE720049297D /* DataLink.swift */; }; 08448F092796A83D00B61353 /* SwiftDate in Frameworks */ = {isa = PBXBuildFile; productRef = 08448F082796A83D00B61353 /* SwiftDate */; }; 08448F0B2797F73200B61353 /* PlayArchitecture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08448F0A2797F73200B61353 /* PlayArchitecture.swift */; }; 08448F0D2799035600B61353 /* PlaySecurity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08448F0C2799035600B61353 /* PlaySecurity.swift */; }; @@ -286,6 +289,9 @@ 08038766276700F100519B15 /* CCYRESTfulAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CCYRESTfulAPI.swift; sourceTree = ""; }; 083554E02756503B0095E0EE /* AnimateLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnimateLayout.swift; sourceTree = ""; }; 083554E227572BB60095E0EE /* AppVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppVM.swift; sourceTree = ""; }; + 084417742B99B9060049297D /* HomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = ""; }; + 084417762B99BA3F0049297D /* SidebarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarView.swift; sourceTree = ""; }; + 084417782B99BE720049297D /* DataLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataLink.swift; sourceTree = ""; }; 08448F0A2797F73200B61353 /* PlayArchitecture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayArchitecture.swift; sourceTree = ""; }; 08448F0C2799035600B61353 /* PlaySecurity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaySecurity.swift; sourceTree = ""; }; 08448F0E2799328700B61353 /* css_cn.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = css_cn.html; sourceTree = ""; }; @@ -573,6 +579,16 @@ path = "新鲜事"; sourceTree = ""; }; + 084417732B99B8EA0049297D /* HomeUI */ = { + isa = PBXGroup; + children = ( + 084417742B99B9060049297D /* HomeView.swift */, + 084417762B99BA3F0049297D /* SidebarView.swift */, + 084417782B99BE720049297D /* DataLink.swift */, + ); + path = HomeUI; + sourceTree = ""; + }; 08448F44279E7E0300B61353 /* Syntax */ = { isa = PBXGroup; children = ( @@ -1063,6 +1079,7 @@ 086A5F472744EF0800FECE02 /* Resource */, 086A5F252744ECD700FECE02 /* GitHubAPI */, 08CD61F327758855008C0935 /* RSSReader */, + 084417732B99B8EA0049297D /* HomeUI */, 083554E227572BB60095E0EE /* AppVM.swift */, 086A5F432744EE2800FECE02 /* SwiftPamphletAppConfig.swift */, 086A5F062744E88E00FECE02 /* SwiftPamphletAppApp.swift */, @@ -1607,12 +1624,14 @@ 08BE635A27C6575C002BC6A8 /* PlayGroupBoxView.swift in Sources */, 08BF26D8276B5D7F0064DDAC /* ExploreRepoListView.swift in Sources */, 088EE8F527BD24E000764525 /* PlayLinkView.swift in Sources */, + 084417792B99BE720049297D /* DataLink.swift in Sources */, 08522BEB27CF7744005FF059 /* PlayKeyboard.swift in Sources */, 08C3BBA427CF1B7B00ACF0FE /* PlayPickerView.swift in Sources */, 08448F4B279E872B00B61353 /* GuideView.swift in Sources */, 08BE635027C4C0F2002BC6A8 /* PlayFormView.swift in Sources */, 086A5F402744EDCE00FECE02 /* RepoVM.swift in Sources */, 08BE636627C88750002BC6A8 /* PlayProgressView.swift in Sources */, + 084417772B99BA3F0049297D /* SidebarView.swift in Sources */, 08F4BE6028609D8700733F12 /* PlayCharts.swift in Sources */, 086A5F2E2744ED8600FECE02 /* ActiveDeveloperListView.swift in Sources */, 08BE637227CC6F13002BC6A8 /* PlayScrollView.swift in Sources */, @@ -1640,6 +1659,7 @@ 086A5F302744ED8600FECE02 /* IssuesListFromCustomView.swift in Sources */, 08C3BB7E27CE3EBD00ACF0FE /* PlayTabView.swift in Sources */, 08CD61F927758AF0008C0935 /* ParseStandXMLTagTokens.swift in Sources */, + 084417752B99B9060049297D /* HomeView.swift in Sources */, 08449034279F6D0D00B61353 /* RepoWebView.swift in Sources */, 08522BDC27CF5079005FF059 /* PlayStepperView.swift in Sources */, 08522BE627CF5E9D005FF059 /* PlayEffect.swift in Sources */, @@ -1822,6 +1842,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 14.0; MARKETING_VERSION = 5.0; OTHER_LDFLAGS = ( "-Xlinker", @@ -1863,6 +1884,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 14.0; MARKETING_VERSION = 5.0; PRODUCT_BUNDLE_IDENTIFIER = com.starming.SwiftPamphletAppByMing; PRODUCT_NAME = "戴铭的开发小册子"; diff --git a/SwiftPamphletApp/AppVM.swift b/SwiftPamphletApp/AppVM.swift index eb2f8e3f4..af4d5fb86 100644 --- a/SwiftPamphletApp/AppVM.swift +++ b/SwiftPamphletApp/AppVM.swift @@ -426,17 +426,18 @@ final class AppVM: ObservableObject { showAppBadgeLabel() } + // 更新 Dock 栏,显示未读数 func showAppBadgeLabel() { - var count = devsCountNotis + expCountNotis + rssCountNotis - if count > 0 { - if count > SPC.unreadMagicNumber * 10 { - count = SPC.unreadMagicNumber * 10 - } - NSApp.dockTile.showsApplicationBadge = true - NSApp.dockTile.badgeLabel = "\(count)" - } else { - NSApp.dockTile.badgeLabel = nil - } +// var count = devsCountNotis + expCountNotis + rssCountNotis +// if count > 0 { +// if count > SPC.unreadMagicNumber * 10 { +// count = SPC.unreadMagicNumber * 10 +// } +// NSApp.dockTile.showsApplicationBadge = true +// NSApp.dockTile.badgeLabel = "\(count)" +// } else { +// NSApp.dockTile.badgeLabel = nil +// } } // 订阅网络状态 diff --git a/SwiftPamphletApp/HomeUI/DataLink.swift b/SwiftPamphletApp/HomeUI/DataLink.swift new file mode 100644 index 000000000..290d9893b --- /dev/null +++ b/SwiftPamphletApp/HomeUI/DataLink.swift @@ -0,0 +1,70 @@ +// +// DataLink.swift +// SwiftPamphletApp +// +// Created by Ming Dai on 2024/3/7. +// + +import SwiftUI + +struct DataLink: Identifiable { + let id = UUID() + let title: String + let imageName: String + var children: [DataLink]? + + @ViewBuilder + static func viewToShow(for title: String?) -> some View { + switch title { + case "资料整理": + DataSortingListView() + case "库动态": + ExploreRepoListView(showAsGroup: false) + case "开发者": + ActiveDeveloperListView(vm: IssueVM(repoName: SPC.pamphletIssueRepoName, issueNumber: 30)) + case "探索库": + ExploreRepoListView(showAsGroup: true) + case "库存档": + ExploreRepoListView(showAsGroup: true, isArchive: true) + case "语法速查": + IssuesListFromCustomView(vm: IssueVM(guideName: "guide-syntax")) + case "特性": + IssuesListFromCustomView(vm: IssueVM(guideName:"guide-features")) + case "专题": + IssuesListFromCustomView(vm: IssueVM(guideName:"guide-subject")) + case "SwiftUI": + IssuesListFromCustomView(vm: IssueVM(guideName:"lib-SwiftUI")) + case "Combine": + IssuesListFromCustomView(vm: IssueVM(guideName:"lib-Combine")) + case "Concurrency": + IssuesListFromCustomView(vm: IssueVM(guideName:"lib-Concurrency")) + default: + // 默认是语法速查 + IssuesListFromCustomView(vm: IssueVM(guideName: "guide-syntax")) + } + } +} + +extension DataLink { + static var dataLinks = [ + DataLink(title: "动态", imageName: "", children: [ + DataLink(title: "资料整理", imageName: "p11") + ]), + DataLink(title: "Github", imageName: "", children: [ +// DataLink(title: "库动态", imageName: "p6"), +// DataLink(title: "开发者", imageName: "p5"), + DataLink(title: "探索库", imageName: "p24"), + DataLink(title: "库存档", imageName: "p25") + ]), + DataLink(title: "Swift指南", imageName: "", children: [ + DataLink(title: "语法速查", imageName: "p23"), + DataLink(title: "特性", imageName: "p10"), + DataLink(title: "专题", imageName: "p12") + ]), + DataLink(title: "库使用指南", imageName: "", children: [ + DataLink(title: "SwiftUI", imageName: "p3"), + DataLink(title: "Combine", imageName: "p19"), + DataLink(title: "Concurrency", imageName: "p1") + ]) + ] +} diff --git a/SwiftPamphletApp/HomeUI/HomeView.swift b/SwiftPamphletApp/HomeUI/HomeView.swift new file mode 100644 index 000000000..f62430f38 --- /dev/null +++ b/SwiftPamphletApp/HomeUI/HomeView.swift @@ -0,0 +1,22 @@ +// +// MainView.swift +// SwiftPamphletApp +// +// Created by Ming Dai on 2024/3/7. +// + +import SwiftUI + +struct HomeView: View { + @StateObject var appVM = AppVM() + @State private var selectedDataLinkString: String? + + var body: some View { + NavigationSplitView { + SidebarView(selectedDataLinkString: $selectedDataLinkString) + } detail: { + DataLink.viewToShow(for: selectedDataLinkString) + } + .environmentObject(appVM) + } +} diff --git a/SwiftPamphletApp/HomeUI/SidebarView.swift b/SwiftPamphletApp/HomeUI/SidebarView.swift new file mode 100644 index 000000000..fed0fed1d --- /dev/null +++ b/SwiftPamphletApp/HomeUI/SidebarView.swift @@ -0,0 +1,34 @@ +// +// SidebarView.swift +// SwiftPamphletApp +// +// Created by Ming Dai on 2024/3/7. +// + +import SwiftUI + +struct SidebarView: View { + @Binding var selectedDataLinkString: String? + + var body: some View { +// List(DataLink.dataLinks, children: \.children, selection: $selectedDataLinkString) { link in +// SideBarLabel(title: link.title, imageName: link.imageName) +// .tag(link.title) +// } + List(selection: $selectedDataLinkString, content: { + ForEach(DataLink.dataLinks) { link in + Section { + OutlineGroup(link.children ?? [], children: \.children) { i in + SideBarLabel(title: i.title, imageName: i.imageName) + .tag(i.title) + } + } header: { + Label(link.title, systemImage: "") + } + } + }) + .frame(minWidth: 200) + } +} + + diff --git a/SwiftPamphletApp/SwiftPamphletAppApp.swift b/SwiftPamphletApp/SwiftPamphletAppApp.swift index ece806697..2bac6d058 100644 --- a/SwiftPamphletApp/SwiftPamphletAppApp.swift +++ b/SwiftPamphletApp/SwiftPamphletAppApp.swift @@ -15,6 +15,7 @@ struct SwiftPamphletAppApp: App { var body: some Scene { WindowGroup { SwiftPamphletApp() +// HomeView() // Demo() } .windowToolbarStyle(UnifiedWindowToolbarStyle(showsTitle: true)) // 用来控制是否展示标题 @@ -24,34 +25,6 @@ struct SwiftPamphletAppApp: App { struct Demo: View { var body: some View { Group { -// V() -// PlayCharts() -// PlayTextView() -// PlayLinkView() -// PlayLabelView() -// PlayTextEditorView() -// PlayTextFieldView() -// PlayButtonView() -// PlayStackView() -// PlayFormView() -// PlayToggleView() -// PlayListView() -// PlayControlGroupView() -// PlayGroupBoxView() -// PlayNavigationView() -// PlayLazyVStackAndLazyHStackView() -// PlayProgressView() -// PlayImageView() -// PlayLazyVGridAndLazyHGridView() -// PlayScrollView() -// PlaySuperposedLayerView() -// PlayTabView() -// PlayPickerView() -// PlaySliderView() -// PlayColor() -// PlayEffect() -// PlayKeyboard() -// PlayAnimation() // PlayCanvas() } @@ -164,42 +137,9 @@ class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ notification: Notification) { print("-- AppDelegate Section --") - + // 生成 Markdown 文件 // AutoTask.buildContentMarkdownFile() - -// PlaySecurity.keyChain() -// PlayArchitecture.error() -// PlayArchitecture.codable() - -// PlaySyntax.hashable() -// PlaySyntax.resultBuilder() -// PlaySyntax.dynamicCallable() -// PlaySyntax.dynamicMemberLookup() -// PlaySyntax.function() -// PlaySyntax.method() -// PlaySyntax.property() -// PlaySyntax.generics() -// PlaySyntax.result() -// PlaySyntax.string() -// PlaySyntax.array() -// PlaySyntax.set() -// PlaySyntax.dictionary() -// PlaySyntax.enum() -// PlaySyntax.number() - -// PlayFoundation.userDefaults() -// PlayFoundation.random() -// PlayFoundation.data() -// PlayFoundation.date() -// PlayFoundation.formatter() -// PlayFoundation.measurement() -// PlayFoundation.file() -// PlayFoundation.scanner() -// let _ = PlayFoundation.attributeString() -// PlayFoundation.coaAndCow() - -// self.window.makeKey() } func applicationWillTerminate(_ notification: Notification) {