diff --git a/README5.md b/README5.md deleted file mode 100644 index d9b6ba7d9..000000000 --- a/README5.md +++ /dev/null @@ -1,61 +0,0 @@ -# 戴铭的开发小册子 5.0 - -Swift开发的手册,是个 macOS 程序。[在线文字版](https://ming1016.github.io/2021/11/23/daiming-swift-pamphlet/) - -![](https://user-images.githubusercontent.com/251980/153746040-8379ad07-4f64-4cb2-b162-40a80fb87d6b.PNG) - -## 下载 - -直接下载最新 dmg 使用:[戴铭的开发小册子5.0.dmg.zip](https://github.com/KwaiAppTeam/SwiftPamphletApp/files/9052632/5.0.dmg.zip) - -## 编译 - -自己编译生成程序的方法是: - -### 方式一:本地编译 - -* 拉代码。直接编译生成无 Github 功能的手册程序。 -* 如要带 Github 功能可在 SwiftPamphletAppConfig.swift 里 gitHubAccessToken 加入你的 GitHub Access Token。GitHub Access Token 在 [Personal Access Tokens](https://github.com/settings/tokens) 这里获取。记得scope 勾上 repo 和 user。 -* 使用Xcode编译生成这个手册程序或是连点两下compile.command。 - -Xcode 和 macOS 都需要升到最新版。如果遇到 swift package 下载不下来的情况,参看这个议题来解决:[Issue #88](https://github.com/KwaiAppTeam/SwiftPamphletApp/issues/88) - -### 方式二:云编译 - -***无需 Xcode 设置开发人员帐号编译*** - -* 可使用 compile.command 编译手册程序,无需开启 Xcode 设置个人开发帐号,只需在 SwiftPamphletAppConfig.swift 里 gitHubAccessToken 加入你的 [GitHub Access Token](https://github.com/settings/tokens),完成后连点 compile.command 两下等待作业完成。 -* 或使用 Github action workflow 编译(感谢[@powenn](https://github.com/powenn)),无需在本地操作、也无需开启 Xcode 设置个人开发帐号,只需设置 personal access token(PAT) 在 repository 设定中 action secrets,并命名为 PAT。Fork 此 repository,设置 PAT,手动启用 action,等候约3分钟即可下载档案,往后专案更新时,只需 fetch and merge,action 会自动进行。 - -英文说明: -Requires storaging PAT to actions secrets and name it to PAT - -- Fork this repository. -- Go to get a Personal Access Token(PAT) if you haven't done it yet.(GitHub Access Token in [Personal Access Tokens](https://github.com/settings/tokens),scope checked repo and user) -- Set your token in action secrets ,and name it to PAT. -- Get the compiled app package after Github action complete. - -While project update ,you won't need to compile it manually in local, only need to fetch and merge commits and wait for about 3 minutes then download it - -### 介绍 -小册子能够方便的查看 Swift 语法,还有一些主要库的使用指南,内容还在完善中,选择的库主要就是开发小册子应用使用到的 SwitUI、Combine、Swift Concurrency - -除了这些速查和库的使用内容外,这个应用还有一些开发者的动态,当他们有新的动作,比如提交了代码、star 了什么项目,提交和留言了议题都会直接在程序坞中提醒你。 - -![](https://ming1016.github.io/uploads/develop-macos-with-swiftui-combine-concurrency-aysnc-await-actor/15.png) - -我对一些库做了分类,方便按需查找,库有新的提交也会在程序坞中提醒。 - -![](https://ming1016.github.io/uploads/develop-macos-with-swiftui-combine-concurrency-aysnc-await-actor/16.png) - -还能方便的查看库的议题。比如在阮一峰的《科技爱好者周刊》的议题中可以看到有很多人推荐和自荐了一些信息。保留议题有一千六百多个。 - -![](https://ming1016.github.io/uploads/develop-macos-with-swiftui-combine-concurrency-aysnc-await-actor/17.png) - -博客动态的功能,可以跟进一些博客内容的更新。 - -代码说明参看这篇[《如何用 SwiftUI + Combine + Swift Concurrency Aysnc/Await Actor 欢畅开发》](https://ming1016.github.io/2022/01/03/develop-macos-with-swiftui-combine-concurrency-aysnc-await-actor/)文章 - -小册子文字版 《[戴铭的 Swift 小册子](https://ming1016.github.io/2021/11/23/daiming-swift-pamphlet/)》 - - diff --git a/SwiftPamphletApp.xcodeproj/project.pbxproj b/SwiftPamphletApp.xcodeproj/project.pbxproj index 6fb51f8e3..869fc4acd 100644 --- a/SwiftPamphletApp.xcodeproj/project.pbxproj +++ b/SwiftPamphletApp.xcodeproj/project.pbxproj @@ -24,9 +24,9 @@ 08026C512869B43500792EF1 /* Table(ap).md in Resources */ = {isa = PBXBuildFile; fileRef = 08026C502869B41B00792EF1 /* Table(ap).md */; }; 08026C522869B43D00792EF1 /* SF Symbol(ap).md in Resources */ = {isa = PBXBuildFile; fileRef = 08026C3E2869AD7800792EF1 /* SF Symbol(ap).md */; }; 08026C532869B44400792EF1 /* macOS技术演进(ap).md in Resources */ = {isa = PBXBuildFile; fileRef = 08026C3F2869B00D00792EF1 /* macOS技术演进(ap).md */; }; - 0805F4962BAAABEA0008BB52 /* ViewStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0805F4952BAAABEA0008BB52 /* ViewStyle.swift */; }; 08069CAB2BDE01E800D48E24 /* GuideListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08069CAA2BDE01E800D48E24 /* GuideListView.swift */; }; 08069CAD2BDE7A6B00D48E24 /* GuideDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08069CAC2BDE7A6B00D48E24 /* GuideDetailView.swift */; }; + 0820367A2C02EEA7002FB5E3 /* SMUI in Frameworks */ = {isa = PBXBuildFile; productRef = 082036792C02EEA7002FB5E3 /* SMUI */; }; 0825E4872BC6596F00332378 /* EditCustomSearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0825E4862BC6596F00332378 /* EditCustomSearchView.swift */; }; 08397E252B9EEE1300DFDD02 /* InfoListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08397E242B9EEE1300DFDD02 /* InfoListView.swift */; }; 08397E292B9F0A9100DFDD02 /* EditInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08397E282B9F0A9100DFDD02 /* EditInfoView.swift */; }; @@ -354,7 +354,6 @@ 08026C402869B1BF00792EF1 /* 性能技术演进(ap).md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = "性能技术演进(ap).md"; sourceTree = ""; }; 08026C422869B22E00792EF1 /* Regex(ap).md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = "Regex(ap).md"; sourceTree = ""; }; 08026C502869B41B00792EF1 /* Table(ap).md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "Table(ap).md"; sourceTree = ""; }; - 0805F4952BAAABEA0008BB52 /* ViewStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewStyle.swift; sourceTree = ""; }; 08069CAA2BDE01E800D48E24 /* GuideListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GuideListView.swift; sourceTree = ""; }; 08069CAC2BDE7A6B00D48E24 /* GuideDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GuideDetailView.swift; sourceTree = ""; }; 0825E4862BC6596F00332378 /* EditCustomSearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditCustomSearchView.swift; sourceTree = ""; }; @@ -660,6 +659,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 0820367A2C02EEA7002FB5E3 /* SMUI in Frameworks */, 086923412BF2BFCC006779A3 /* AVKit.framework in Frameworks */, 0868D00B2BDD37280023C871 /* SMGitHub in Frameworks */, 08448F4E279E8CA400B61353 /* Ink in Frameworks */, @@ -1274,7 +1274,6 @@ 086A5F512744EF4C00FECE02 /* ViewComponent.swift */, 08A9E1A12BC25D0700A73764 /* ViewComponentMarkdown.swift */, 08F14B432BBE2865005B46CC /* ViewComponentImage.swift */, - 0805F4952BAAABEA0008BB52 /* ViewStyle.swift */, ); path = ViewComponet; sourceTree = ""; @@ -1642,6 +1641,7 @@ 3ACA74FA2BD7964A0024B18E /* SMFile */, 3A46DEF42BD7AAB2008AD993 /* SMDate */, 0868D00A2BDD37280023C871 /* SMGitHub */, + 082036792C02EEA7002FB5E3 /* SMUI */, ); productName = SwiftPamphletApp; productReference = 086A5F032744E88E00FECE02 /* 戴铭的开发小册子.app */; @@ -1683,6 +1683,7 @@ 3ACA74F92BD7964A0024B18E /* XCLocalSwiftPackageReference "SwiftPamphletApp/SharePackage/SMFile" */, 3A46DEF32BD7AAB2008AD993 /* XCLocalSwiftPackageReference "SwiftPamphletApp/SharePackage/SMDate" */, 0868D0092BDD37280023C871 /* XCLocalSwiftPackageReference "SwiftPamphletApp/SharePackage/SMGitHub" */, + 082036782C02EEA7002FB5E3 /* XCLocalSwiftPackageReference "SwiftPamphletApp/SharePackage/SMUI" */, ); productRefGroup = 086A5F042744E88E00FECE02 /* Products */; projectDirPath = ""; @@ -2014,7 +2015,6 @@ 08A7FF312BEB02EA00E12E5A /* GithubAccessTokenView.swift in Sources */, 086A5F372744ED9600FECE02 /* UserView.swift in Sources */, 086A5F522744EF4C00FECE02 /* ViewComponent.swift in Sources */, - 0805F4962BAAABEA0008BB52 /* ViewStyle.swift in Sources */, 08CD61FF27758B8A008C0935 /* Token.swift in Sources */, 3AE0D59E2BAB183100D6D925 /* EditDeveloper.swift in Sources */, 08EF35D22BECFDA80098E2D4 /* BookmarkModel.swift in Sources */, @@ -2246,6 +2246,10 @@ /* End XCConfigurationList section */ /* Begin XCLocalSwiftPackageReference section */ + 082036782C02EEA7002FB5E3 /* XCLocalSwiftPackageReference "SwiftPamphletApp/SharePackage/SMUI" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = SwiftPamphletApp/SharePackage/SMUI; + }; 0868D0092BDD37280023C871 /* XCLocalSwiftPackageReference "SwiftPamphletApp/SharePackage/SMGitHub" */ = { isa = XCLocalSwiftPackageReference; relativePath = SwiftPamphletApp/SharePackage/SMGitHub; @@ -2312,6 +2316,10 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ + 082036792C02EEA7002FB5E3 /* SMUI */ = { + isa = XCSwiftPackageProductDependency; + productName = SMUI; + }; 08397E312B9F39C100DFDD02 /* SwiftSoup */ = { isa = XCSwiftPackageProductDependency; package = 08397E302B9F39C100DFDD02 /* XCRemoteSwiftPackageReference "SwiftSoup" */; diff --git a/SwiftPamphletApp/App/IntroView.swift b/SwiftPamphletApp/App/IntroView.swift index 067a777c5..472c977d5 100644 --- a/SwiftPamphletApp/App/IntroView.swift +++ b/SwiftPamphletApp/App/IntroView.swift @@ -8,6 +8,7 @@ import SwiftUI import MarkdownUI import SMFile +import SMUI struct LightingView: View { @Environment(\.colorScheme) var colorSchemeMode diff --git a/SwiftPamphletApp/InfoOrganizer/Info/EditInfoView.swift b/SwiftPamphletApp/InfoOrganizer/Info/EditInfoView.swift index c945a27d7..26846fc6e 100644 --- a/SwiftPamphletApp/InfoOrganizer/Info/EditInfoView.swift +++ b/SwiftPamphletApp/InfoOrganizer/Info/EditInfoView.swift @@ -13,6 +13,7 @@ import PhotosUI import InfoOrganizer import SMFile import SMNetwork +import SMUI struct EditInfoView: View { @Environment(\.modelContext) var modelContext @@ -203,7 +204,7 @@ struct EditInfoView: View { if info.imageUrls.isEmpty == false { LazyVGrid(columns: [GridItem(.adaptive(minimum: 150), spacing: 10)]) { ForEach(info.imageUrls, id:\.self) { img in - NukeImage(url: img) + NukeImage(height: 150, url: img) .contextMenu { Button { IOInfo.updateCoverImage(info: info, img: IOImg(url: img)) diff --git "a/SwiftPamphletApp/Resource/Guide/SwiftUI/\345\233\276\346\226\207\347\273\204\344\273\266/Image(ap).md" "b/SwiftPamphletApp/Resource/Guide/SwiftUI/\345\233\276\346\226\207\347\273\204\344\273\266/Image(ap).md" index c8869eb20..3c747e193 100644 --- "a/SwiftPamphletApp/Resource/Guide/SwiftUI/\345\233\276\346\226\207\347\273\204\344\273\266/Image(ap).md" +++ "b/SwiftPamphletApp/Resource/Guide/SwiftUI/\345\233\276\346\226\207\347\273\204\344\273\266/Image(ap).md" @@ -1,5 +1,7 @@ ![](https://ming1016.github.io/qdimg/240505/image-ap01.png) +## Image 使用 + ```swift struct PlayImageView: View { var body: some View { @@ -30,3 +32,41 @@ struct PlayImageView: View { } } ``` + +## AsyncImage + +```swift +struct AsyncImageWithPlaceholder: View { + enum Size { + case tinySize, smallSize,normalSize, bigSize + + var v: CGFloat { + switch self { + case .tinySize: + return 20 + case .smallSize: + return 40 + case .normalSize: + return 60 + case .bigSize: + return 100 + } + } + } + var size: Size + var url: String + var body: some View { + AsyncImage(url: URL(string: url), content: { image in + image + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: size.v, height: size.v) + .cornerRadius(5) + }, + placeholder: { + Image(systemName: "person") + .frame(width: size.v, height: size.v) + }) + } +} +``` diff --git a/SwiftPamphletApp/SharePackage/SMUI/.gitignore b/SwiftPamphletApp/SharePackage/SMUI/.gitignore new file mode 100644 index 000000000..0023a5340 --- /dev/null +++ b/SwiftPamphletApp/SharePackage/SMUI/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +/.build +/Packages +xcuserdata/ +DerivedData/ +.swiftpm/configuration/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/SwiftPamphletApp/SharePackage/SMUI/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/SwiftPamphletApp/SharePackage/SMUI/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/SwiftPamphletApp/SharePackage/SMUI/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/SwiftPamphletApp/SharePackage/SMUI/Package.swift b/SwiftPamphletApp/SharePackage/SMUI/Package.swift new file mode 100644 index 000000000..a70bd46ff --- /dev/null +++ b/SwiftPamphletApp/SharePackage/SMUI/Package.swift @@ -0,0 +1,24 @@ +// swift-tools-version: 5.10 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "SMUI", + platforms: [.iOS(.v17), .macOS(.v14)], + products: [ + // Products define the executables and libraries a package produces, making them visible to other packages. + .library( + name: "SMUI", + targets: ["SMUI"]), + ], + targets: [ + // Targets are the basic building blocks of a package, defining a module or a test suite. + // Targets can depend on other targets in this package and products from dependencies. + .target( + name: "SMUI"), + .testTarget( + name: "SMUITests", + dependencies: ["SMUI"]), + ] +) diff --git a/SwiftPamphletApp/SharePackage/SMUI/Sources/SMUI/SMUI.swift b/SwiftPamphletApp/SharePackage/SMUI/Sources/SMUI/SMUI.swift new file mode 100644 index 000000000..ea407d73d --- /dev/null +++ b/SwiftPamphletApp/SharePackage/SMUI/Sources/SMUI/SMUI.swift @@ -0,0 +1,36 @@ +// The Swift Programming Language +// https://docs.swift.org/swift-book +import SwiftUI + +// MARK: Text +extension Text { + public func gradientTitle(color: Color = .primary) -> some View { + self + .font(.largeTitle) + .fontWeight(.bold) + .foregroundStyle(color.gradient) + .fontDesign(.rounded) + } +} + +// MARK: TextEidtor +extension TextEditor { + public func border() -> some View { + self + .overlay( + Rectangle() + .stroke(.secondary, lineWidth: 1) + .opacity(0.5) + ) + .disableAutocorrection(true) + } +} + +// MARK: TextField +// 圆角 +extension TextField { + public func rounded() -> some View { + self + .textFieldStyle(RoundedBorderTextFieldStyle()) + } +} diff --git a/SwiftPamphletApp/SharePackage/SMUI/Tests/SMUITests/SMUITests.swift b/SwiftPamphletApp/SharePackage/SMUI/Tests/SMUITests/SMUITests.swift new file mode 100644 index 000000000..77f8e0dea --- /dev/null +++ b/SwiftPamphletApp/SharePackage/SMUI/Tests/SMUITests/SMUITests.swift @@ -0,0 +1,12 @@ +import XCTest +@testable import SMUI + +final class SMUITests: XCTestCase { + func testExample() throws { + // XCTest Documentation + // https://developer.apple.com/documentation/xctest + + // Defining Test Cases and Test Methods + // https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods + } +} diff --git a/SwiftPamphletApp/ViewComponet/ViewComponentImage.swift b/SwiftPamphletApp/ViewComponet/ViewComponentImage.swift index 2ccb9cadf..f987a360b 100644 --- a/SwiftPamphletApp/ViewComponet/ViewComponentImage.swift +++ b/SwiftPamphletApp/ViewComponet/ViewComponentImage.swift @@ -48,36 +48,4 @@ struct NukeImage: View { } } -struct AsyncImageWithPlaceholder: View { - enum Size { - case tinySize, smallSize,normalSize, bigSize - var v: CGFloat { - switch self { - case .tinySize: - return 20 - case .smallSize: - return 40 - case .normalSize: - return 60 - case .bigSize: - return 100 - } - } - } - var size: Size - var url: String - var body: some View { - AsyncImage(url: URL(string: url), content: { image in - image - .resizable() - .aspectRatio(contentMode: .fit) - .frame(width: size.v, height: size.v) - .cornerRadius(5) - }, - placeholder: { - Image(systemName: "person") - .frame(width: size.v, height: size.v) - }) - } -} diff --git a/SwiftPamphletApp/ViewComponet/ViewStyle.swift b/SwiftPamphletApp/ViewComponet/ViewStyle.swift deleted file mode 100644 index 80070315a..000000000 --- a/SwiftPamphletApp/ViewComponet/ViewStyle.swift +++ /dev/null @@ -1,77 +0,0 @@ -// -// ViewStyle.swift -// SwiftPamphletApp -// -// Created by Ming Dai on 2024/3/20. -// - -import SwiftUI - -// MARK: Text -extension Text { - func gradientTitle(color: Color = .primary) -> some View { - self - .font(.largeTitle) - .fontWeight(.bold) - .foregroundStyle(color.gradient) - .fontDesign(.rounded) - } -} - -// MARK: TextEidtor -extension TextEditor { - func border() -> some View { - self - .overlay( - Rectangle() - .stroke(.secondary, lineWidth: 1) - .opacity(0.5) - ) - .disableAutocorrection(true) - } -} - - -// MARK: TextField - -// 圆角 -extension TextField { - func rounded() -> some View { - self - .textFieldStyle(RoundedBorderTextFieldStyle()) - } -} - -// MARK: Toggle -struct SymbolToggleStyle: ToggleStyle { - var systemImage: String = "checkmark" - var activeColor: Color = .green - - func makeBody(configuration: Configuration) -> some View { - HStack { - configuration.label - - Spacer() - - RoundedRectangle(cornerRadius: 25) - .fill(configuration.isOn ? activeColor : Color(.lightGray)) - .overlay { - Circle() - .fill(.white) - .padding(3) - .overlay { - Image(systemName: systemImage) - .foregroundColor(configuration.isOn ? activeColor : Color(.lightGray)) - } - .offset(x: configuration.isOn ? 10 : -10) - - } - .frame(width: 50, height: 25) - .onTapGesture { - withAnimation(.spring()) { - configuration.isOn.toggle() - } - } - } - } -}