From 1f615524e1d6d29da2cee15952f220f41df557f3 Mon Sep 17 00:00:00 2001 From: tisfeng Date: Wed, 6 Nov 2024 10:29:22 +0800 Subject: [PATCH 01/11] feat: load default acknow list when init AcknowListSwiftUIView --- .../project.pbxproj | 6 +- .../AcknowExampleSPM/ViewController.swift | 7 +- Package.swift | 4 +- Sources/AcknowList/AcknowListSwiftUI.swift | 100 ++++++++++-------- .../Resources/Package.resolved | 61 +++++++++++ 5 files changed, 126 insertions(+), 52 deletions(-) create mode 100644 Tests/AcknowListTests/Resources/Package.resolved diff --git a/Examples/AcknowExampleSPM/AcknowExampleSPM.xcodeproj/project.pbxproj b/Examples/AcknowExampleSPM/AcknowExampleSPM.xcodeproj/project.pbxproj index 87ff7a3..1a66711 100644 --- a/Examples/AcknowExampleSPM/AcknowExampleSPM.xcodeproj/project.pbxproj +++ b/Examples/AcknowExampleSPM/AcknowExampleSPM.xcodeproj/project.pbxproj @@ -3,10 +3,11 @@ archiveVersion = 1; classes = { }; - objectVersion = 52; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ + 031D428A2CDA828C00C803B8 /* Package.resolved in Resources */ = {isa = PBXBuildFile; fileRef = 031D42892CDA828C00C803B8 /* Package.resolved */; }; BB29000228230B37002FF5C4 /* Package-version-1.resolved in Resources */ = {isa = PBXBuildFile; fileRef = BB29000128230B37002FF5C4 /* Package-version-1.resolved */; }; D7527E2125CADE4E00378FB8 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7527E2025CADE4E00378FB8 /* AppDelegate.swift */; }; D7527E2325CADE4E00378FB8 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7527E2225CADE4E00378FB8 /* SceneDelegate.swift */; }; @@ -18,6 +19,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 031D42892CDA828C00C803B8 /* Package.resolved */ = {isa = PBXFileReference; lastKnownFileType = text; name = Package.resolved; path = /Users/tisfeng/Documents/Code/Github/AcknowList/Tests/AcknowListTests/Resources/Package.resolved; sourceTree = ""; }; BB29000128230B37002FF5C4 /* Package-version-1.resolved */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "Package-version-1.resolved"; path = "../../../Tests/AcknowListTests/Resources/Package-version-1.resolved"; sourceTree = ""; }; D7527E1D25CADE4E00378FB8 /* AcknowExampleSPM.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AcknowExampleSPM.app; sourceTree = BUILT_PRODUCTS_DIR; }; D7527E2025CADE4E00378FB8 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -73,6 +75,7 @@ D7527E2B25CADE5000378FB8 /* LaunchScreen.storyboard */, D7527E2E25CADE5000378FB8 /* Info.plist */, BB29000128230B37002FF5C4 /* Package-version-1.resolved */, + 031D42892CDA828C00C803B8 /* Package.resolved */, ); path = AcknowExampleSPM; sourceTree = ""; @@ -146,6 +149,7 @@ buildActionMask = 2147483647; files = ( D7527E2D25CADE5000378FB8 /* LaunchScreen.storyboard in Resources */, + 031D428A2CDA828C00C803B8 /* Package.resolved in Resources */, BB29000228230B37002FF5C4 /* Package-version-1.resolved in Resources */, D7527E2A25CADE5000378FB8 /* Assets.xcassets in Resources */, D7527E2825CADE4E00378FB8 /* Main.storyboard in Resources */, diff --git a/Examples/AcknowExampleSPM/AcknowExampleSPM/ViewController.swift b/Examples/AcknowExampleSPM/AcknowExampleSPM/ViewController.swift index cbc19e0..89d80b4 100644 --- a/Examples/AcknowExampleSPM/AcknowExampleSPM/ViewController.swift +++ b/Examples/AcknowExampleSPM/AcknowExampleSPM/ViewController.swift @@ -34,11 +34,8 @@ class ViewController: UIViewController { } @IBAction func presentAcknowledgementsSwiftUI(_ sender: AnyObject) { - let listViewController = AcknowListSwiftUIView(acknowledgements: [ - Acknow(title: "Test", text: "Bla bla"), - Acknow(title: "Test URL", repository: URL(string: "https://developer.apple.com")), - Acknow(title: "Test GitHub", repository: URL(string: "https://github.com/vtourraine/AcknowList.git")) - ]) + // Load default acknowledgements from CocoaPods and Swift Package Manager + let listViewController = AcknowListSwiftUIView() let viewController = UIHostingController(rootView: listViewController) let navigationController = UINavigationController(rootViewController: viewController) present(navigationController, animated: true, completion: nil) diff --git a/Package.swift b/Package.swift index 8175288..f9768d8 100644 --- a/Package.swift +++ b/Package.swift @@ -31,7 +31,9 @@ let package = Package( .copy("Resources/RegexTesting-GroundTruth-TPKeyboardAvoiding.txt"), .copy("Resources/RegexTesting-GroundTruth-pop.txt"), .copy("Resources/Package-version-1.resolved"), - .copy("Resources/Package-version-2.resolved")] + .copy("Resources/Package-version-2.resolved"), + .copy("Resources/Package.resolved"), + ] ), ], swiftLanguageVersions: [.v5] diff --git a/Sources/AcknowList/AcknowListSwiftUI.swift b/Sources/AcknowList/AcknowListSwiftUI.swift index d082d65..2e06aed 100644 --- a/Sources/AcknowList/AcknowListSwiftUI.swift +++ b/Sources/AcknowList/AcknowListSwiftUI.swift @@ -25,9 +25,7 @@ import SwiftUI extension Acknow: Identifiable { public var id: String { - get { - title - } + title } } @@ -44,10 +42,10 @@ public struct AcknowListSwiftUIView: View { /// Footer text to be displayed below the list of the acknowledgements. public var footerText: String? - public init(acknowList: AcknowList) { - acknowledgements = acknowList.acknowledgements - headerText = acknowList.headerText - footerText = acknowList.footerText + public init(acknowList: AcknowList? = AcknowParser.defaultAcknowList()) { + acknowledgements = acknowList?.acknowledgements ?? [] + headerText = acknowList?.headerText + footerText = acknowList?.footerText } public init(acknowledgements: [Acknow], headerText: String? = nil, footerText: String? = nil) { @@ -58,7 +56,8 @@ public struct AcknowListSwiftUIView: View { public init(plistFileURL: URL) { guard let data = try? Data(contentsOf: plistFileURL), - let acknowList = try? AcknowPodDecoder().decode(from: data) else { + let acknowList = try? AcknowPodDecoder().decode(from: data) + else { self.init(acknowledgements: [], headerText: nil, footerText: nil) return } @@ -66,12 +65,13 @@ public struct AcknowListSwiftUIView: View { let header: String? if acknowList.headerText != AcknowPodDecoder.K.DefaultHeaderText { header = acknowList.headerText - } - else { + } else { header = nil } - self.init(acknowledgements: acknowList.acknowledgements, headerText: header, footerText: acknowList.footerText) + self.init( + acknowledgements: acknowList.acknowledgements, headerText: header, + footerText: acknowList.footerText) } struct HeaderFooter: View { @@ -80,33 +80,36 @@ public struct AcknowListSwiftUIView: View { var body: some View { if let text = text { Text(text) - } - else { + } else { EmptyView() } } } public var body: some View { - #if os(iOS) || os(tvOS) +#if os(iOS) || os(tvOS) List { - Section(header: HeaderFooter(text: headerText), footer: HeaderFooter(text: footerText)) { - ForEach (acknowledgements) { acknowledgement in + Section( + header: HeaderFooter(text: headerText), footer: HeaderFooter(text: footerText) + ) { + ForEach(acknowledgements) { acknowledgement in AcknowListRowSwiftUIView(acknowledgement: acknowledgement) } } } .listStyle(GroupedListStyle()) .navigationBarTitle(Text(AcknowLocalization.localizedTitle())) - #else +#else List { - Section(header: HeaderFooter(text: headerText), footer: HeaderFooter(text: footerText)) { - ForEach (acknowledgements) { acknowledgement in + Section( + header: HeaderFooter(text: headerText), footer: HeaderFooter(text: footerText) + ) { + ForEach(acknowledgements) { acknowledgement in AcknowListRowSwiftUIView(acknowledgement: acknowledgement) } } } - #endif +#endif } } @@ -121,21 +124,22 @@ public struct AcknowListRowSwiftUIView: View { public var canFetchLicenseFromGitHub = true public var body: some View { - if acknowledgement.text != nil || canFetchLicenseFromGitHubAndIsGitHubRepository(acknowledgement) { + if acknowledgement.text != nil + || canFetchLicenseFromGitHubAndIsGitHubRepository(acknowledgement) + { NavigationLink(destination: AcknowSwiftUIView(acknowledgement: acknowledgement)) { Text(acknowledgement.title) } - } - else if let repository = acknowledgement.repository, - canOpenRepository(for: repository) { + } else if let repository = acknowledgement.repository, + canOpenRepository(for: repository) + { Button(action: { repository.openWithDefaultBrowser() }) { Text(acknowledgement.title) .foregroundColor(.primary) } - } - else { + } else { Text(acknowledgement.title) } } @@ -150,10 +154,10 @@ public struct AcknowListRowSwiftUIView: View { private func canFetchLicenseFromGitHubAndIsGitHubRepository(_ acknowledgement: Acknow) -> Bool { if canFetchLicenseFromGitHub, - let repository = acknowledgement.repository { + let repository = acknowledgement.repository + { return GitHubAPI.isGitHubRepository(repository) - } - else { + } else { return false } } @@ -162,17 +166,19 @@ public struct AcknowListRowSwiftUIView: View { @available(iOS 13.0.0, macOS 10.15.0, watchOS 7.0.0, tvOS 13.0.0, visionOS 1.0.0, *) struct AcknowListSwiftUI_Previews: PreviewProvider { static let license = """ - Copyright (c) 2015-2024 Vincent Tourraine (https://www.vtourraine.net) - - Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - """ - static let acks = [Acknow(title: "Title 1", text: license), - Acknow(title: "Title 2", text: license), - Acknow(title: "Title 3", text: license)] + Copyright (c) 2015-2024 Vincent Tourraine (https://www.vtourraine.net) + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + """ + static let acks = [ + Acknow(title: "Title 1", text: license), + Acknow(title: "Title 2", text: license), + Acknow(title: "Title 3", text: license), + ] static var previews: some View { NavigationView { @@ -181,22 +187,26 @@ struct AcknowListSwiftUI_Previews: PreviewProvider { .previewDevice(PreviewDevice(rawValue: "iPhone 12")) NavigationView { - AcknowListSwiftUIView(acknowledgements: acks, headerText: "Test Header", footerText: "Test Footer") + AcknowListSwiftUIView( + acknowledgements: acks, headerText: "Test Header", footerText: "Test Footer") } .previewDevice(PreviewDevice(rawValue: "iPhone 12")) - + NavigationView { - AcknowListSwiftUIView(acknowledgements: acks, headerText: "Test Header", footerText: "Test Footer") + AcknowListSwiftUIView( + acknowledgements: acks, headerText: "Test Header", footerText: "Test Footer") } .previewDevice(PreviewDevice(rawValue: "Apple TV 4K")) NavigationView { - AcknowListSwiftUIView(acknowledgements: acks, headerText: "Test Header", footerText: "Test Footer") + AcknowListSwiftUIView( + acknowledgements: acks, headerText: "Test Header", footerText: "Test Footer") } .previewDevice(PreviewDevice(rawValue: "Apple Watch Series 6 - 44mm")) NavigationView { - AcknowListSwiftUIView(acknowledgements: acks, headerText: "Test Header", footerText: "Test Footer") + AcknowListSwiftUIView( + acknowledgements: acks, headerText: "Test Header", footerText: "Test Footer") } .previewDevice(PreviewDevice(rawValue: "Mac")) } diff --git a/Tests/AcknowListTests/Resources/Package.resolved b/Tests/AcknowListTests/Resources/Package.resolved new file mode 100644 index 0000000..15a062b --- /dev/null +++ b/Tests/AcknowListTests/Resources/Package.resolved @@ -0,0 +1,61 @@ +{ + "object": { + "pins": [ + { + "package": "AcknowList", + "repositoryURL": "https://github.com/vtourraine/AcknowList.git", + "state": { + "branch": null, + "revision": "e66b9541c1902ced4979b3c214a5def2cf96f015", + "version": "2.1.0" + } + }, + { + "package": "AMGAppButton", + "repositoryURL": "https://github.com/studioamanga/AMGAppButton.git", + "state": { + "branch": null, + "revision": "6044b277a3a4281afb1fdf6f651fa4829109d7d9", + "version": "1.1.0" + } + }, + { + "package": "SVProgressHUD", + "repositoryURL": "https://github.com/epitonium/SVProgressHUD.git", + "state": { + "branch": null, + "revision": "3580cb55f351d83f861f52362aa38305f663f88d", + "version": "1.0.0" + } + }, + { + "package": "TrackupCore", + "repositoryURL": "https://github.com/vtourraine/Trackup.git", + "state": { + "branch": null, + "revision": "513e0bf40b6d005354c844446e8e2334c450a863", + "version": "0.1.0" + } + }, + { + "package": "TrackupVersionHistory", + "repositoryURL": "https://github.com/vtourraine/TrackupVersionHistory.git", + "state": { + "branch": null, + "revision": "7916b78a3cd5392b5807220277f3aa1d561c1658", + "version": "0.2.0" + } + }, + { + "package": "VTAppButton", + "repositoryURL": "https://github.com/vtourraine/VTAppButton.git", + "state": { + "branch": null, + "revision": "3eeb59199d563d7e0ac35ebb0bf967defa878391", + "version": "1.1.0" + } + } + ] + }, + "version": 1 +} From a515297790fd4a4c42873a43a9e09de37c83629c Mon Sep 17 00:00:00 2001 From: tisfeng Date: Wed, 6 Nov 2024 21:09:58 +0800 Subject: [PATCH 02/11] fix: remove pods footer if have both pods and package libraries --- Sources/AcknowList/AcknowList.swift | 2 +- Sources/AcknowList/AcknowParser.swift | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Sources/AcknowList/AcknowList.swift b/Sources/AcknowList/AcknowList.swift index 26e2322..4493fe6 100644 --- a/Sources/AcknowList/AcknowList.swift +++ b/Sources/AcknowList/AcknowList.swift @@ -36,7 +36,7 @@ public struct AcknowList { /** Footer text to be displayed below the list of the acknowledgements. */ - public let footerText: String? + public var footerText: String? } extension AcknowList { diff --git a/Sources/AcknowList/AcknowParser.swift b/Sources/AcknowList/AcknowParser.swift index d61e28d..edf24ee 100644 --- a/Sources/AcknowList/AcknowParser.swift +++ b/Sources/AcknowList/AcknowParser.swift @@ -60,7 +60,10 @@ open class AcknowParser { let pods = defaultPods() let packages = defaultPackages() if let pods = pods, let packages = packages { - return pods + packages + var acknowList = pods + packages + // If have both pods and packages libraries, remove the footer text from the pods. + acknowList.footerText = nil + return acknowList } else { return pods ?? packages From f0cef79ad0cf3f4f7026d1a71901f958d08f3779 Mon Sep 17 00:00:00 2001 From: tisfeng Date: Thu, 7 Nov 2024 13:12:23 +0800 Subject: [PATCH 03/11] fix: call designated init --- Sources/AcknowList/AcknowListSwiftUI.swift | 68 ++++++++++++---------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/Sources/AcknowList/AcknowListSwiftUI.swift b/Sources/AcknowList/AcknowListSwiftUI.swift index 2e06aed..4cec580 100644 --- a/Sources/AcknowList/AcknowListSwiftUI.swift +++ b/Sources/AcknowList/AcknowListSwiftUI.swift @@ -43,12 +43,15 @@ public struct AcknowListSwiftUIView: View { public var footerText: String? public init(acknowList: AcknowList? = AcknowParser.defaultAcknowList()) { - acknowledgements = acknowList?.acknowledgements ?? [] - headerText = acknowList?.headerText - footerText = acknowList?.footerText + self.init( + acknowledgements: acknowList?.acknowledgements ?? [], + headerText: acknowList?.headerText, + footerText: acknowList?.footerText) } - public init(acknowledgements: [Acknow], headerText: String? = nil, footerText: String? = nil) { + public init(acknowledgements: [Acknow], + headerText: String? = nil, + footerText: String? = nil) { self.acknowledgements = acknowledgements self.headerText = headerText self.footerText = footerText @@ -56,9 +59,11 @@ public struct AcknowListSwiftUIView: View { public init(plistFileURL: URL) { guard let data = try? Data(contentsOf: plistFileURL), - let acknowList = try? AcknowPodDecoder().decode(from: data) + let acknowList = try? AcknowPodDecoder().decode(from: data) else { - self.init(acknowledgements: [], headerText: nil, footerText: nil) + self.init(acknowledgements: [], + headerText: nil, + footerText: nil) return } @@ -70,7 +75,8 @@ public struct AcknowListSwiftUIView: View { } self.init( - acknowledgements: acknowList.acknowledgements, headerText: header, + acknowledgements: acknowList.acknowledgements, + headerText: header, footerText: acknowList.footerText) } @@ -87,29 +93,29 @@ public struct AcknowListSwiftUIView: View { } public var body: some View { -#if os(iOS) || os(tvOS) - List { - Section( - header: HeaderFooter(text: headerText), footer: HeaderFooter(text: footerText) - ) { - ForEach(acknowledgements) { acknowledgement in - AcknowListRowSwiftUIView(acknowledgement: acknowledgement) + #if os(iOS) || os(tvOS) + List { + Section( + header: HeaderFooter(text: headerText), footer: HeaderFooter(text: footerText) + ) { + ForEach(acknowledgements) { acknowledgement in + AcknowListRowSwiftUIView(acknowledgement: acknowledgement) + } } } - } - .listStyle(GroupedListStyle()) - .navigationBarTitle(Text(AcknowLocalization.localizedTitle())) -#else - List { - Section( - header: HeaderFooter(text: headerText), footer: HeaderFooter(text: footerText) - ) { - ForEach(acknowledgements) { acknowledgement in - AcknowListRowSwiftUIView(acknowledgement: acknowledgement) + .listStyle(GroupedListStyle()) + .navigationBarTitle(Text(AcknowLocalization.localizedTitle())) + #else + List { + Section( + header: HeaderFooter(text: headerText), footer: HeaderFooter(text: footerText) + ) { + ForEach(acknowledgements) { acknowledgement in + AcknowListRowSwiftUIView(acknowledgement: acknowledgement) + } } } - } -#endif + #endif } } @@ -131,7 +137,7 @@ public struct AcknowListRowSwiftUIView: View { Text(acknowledgement.title) } } else if let repository = acknowledgement.repository, - canOpenRepository(for: repository) + canOpenRepository(for: repository) { Button(action: { repository.openWithDefaultBrowser() @@ -154,7 +160,7 @@ public struct AcknowListRowSwiftUIView: View { private func canFetchLicenseFromGitHubAndIsGitHubRepository(_ acknowledgement: Acknow) -> Bool { if canFetchLicenseFromGitHub, - let repository = acknowledgement.repository + let repository = acknowledgement.repository { return GitHubAPI.isGitHubRepository(repository) } else { @@ -167,11 +173,11 @@ public struct AcknowListRowSwiftUIView: View { struct AcknowListSwiftUI_Previews: PreviewProvider { static let license = """ Copyright (c) 2015-2024 Vincent Tourraine (https://www.vtourraine.net) - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ static let acks = [ From 00798cfaf3e46c161d247eb7367add19744c717b Mon Sep 17 00:00:00 2001 From: tisfeng Date: Thu, 7 Nov 2024 13:18:09 +0800 Subject: [PATCH 04/11] style: format code --- Sources/AcknowList/AcknowListSwiftUI.swift | 64 +++++++++++----------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/Sources/AcknowList/AcknowListSwiftUI.swift b/Sources/AcknowList/AcknowListSwiftUI.swift index 4cec580..af76e1b 100644 --- a/Sources/AcknowList/AcknowListSwiftUI.swift +++ b/Sources/AcknowList/AcknowListSwiftUI.swift @@ -42,13 +42,6 @@ public struct AcknowListSwiftUIView: View { /// Footer text to be displayed below the list of the acknowledgements. public var footerText: String? - public init(acknowList: AcknowList? = AcknowParser.defaultAcknowList()) { - self.init( - acknowledgements: acknowList?.acknowledgements ?? [], - headerText: acknowList?.headerText, - footerText: acknowList?.footerText) - } - public init(acknowledgements: [Acknow], headerText: String? = nil, footerText: String? = nil) { @@ -57,9 +50,16 @@ public struct AcknowListSwiftUIView: View { self.footerText = footerText } + public init(acknowList: AcknowList? = AcknowParser.defaultAcknowList()) { + self.init( + acknowledgements: acknowList?.acknowledgements ?? [], + headerText: acknowList?.headerText, + footerText: acknowList?.footerText) + } + public init(plistFileURL: URL) { guard let data = try? Data(contentsOf: plistFileURL), - let acknowList = try? AcknowPodDecoder().decode(from: data) + let acknowList = try? AcknowPodDecoder().decode(from: data) else { self.init(acknowledgements: [], headerText: nil, @@ -93,29 +93,29 @@ public struct AcknowListSwiftUIView: View { } public var body: some View { - #if os(iOS) || os(tvOS) - List { - Section( - header: HeaderFooter(text: headerText), footer: HeaderFooter(text: footerText) - ) { - ForEach(acknowledgements) { acknowledgement in - AcknowListRowSwiftUIView(acknowledgement: acknowledgement) - } +#if os(iOS) || os(tvOS) + List { + Section( + header: HeaderFooter(text: headerText), footer: HeaderFooter(text: footerText) + ) { + ForEach(acknowledgements) { acknowledgement in + AcknowListRowSwiftUIView(acknowledgement: acknowledgement) } } - .listStyle(GroupedListStyle()) - .navigationBarTitle(Text(AcknowLocalization.localizedTitle())) - #else - List { - Section( - header: HeaderFooter(text: headerText), footer: HeaderFooter(text: footerText) - ) { - ForEach(acknowledgements) { acknowledgement in - AcknowListRowSwiftUIView(acknowledgement: acknowledgement) - } + } + .listStyle(GroupedListStyle()) + .navigationBarTitle(Text(AcknowLocalization.localizedTitle())) +#else + List { + Section( + header: HeaderFooter(text: headerText), footer: HeaderFooter(text: footerText) + ) { + ForEach(acknowledgements) { acknowledgement in + AcknowListRowSwiftUIView(acknowledgement: acknowledgement) } } - #endif + } +#endif } } @@ -137,7 +137,7 @@ public struct AcknowListRowSwiftUIView: View { Text(acknowledgement.title) } } else if let repository = acknowledgement.repository, - canOpenRepository(for: repository) + canOpenRepository(for: repository) { Button(action: { repository.openWithDefaultBrowser() @@ -160,7 +160,7 @@ public struct AcknowListRowSwiftUIView: View { private func canFetchLicenseFromGitHubAndIsGitHubRepository(_ acknowledgement: Acknow) -> Bool { if canFetchLicenseFromGitHub, - let repository = acknowledgement.repository + let repository = acknowledgement.repository { return GitHubAPI.isGitHubRepository(repository) } else { @@ -173,11 +173,11 @@ public struct AcknowListRowSwiftUIView: View { struct AcknowListSwiftUI_Previews: PreviewProvider { static let license = """ Copyright (c) 2015-2024 Vincent Tourraine (https://www.vtourraine.net) - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ static let acks = [ From 0de4f94053dac7e345d392e6264d9974e474b753 Mon Sep 17 00:00:00 2001 From: Vincent Tourraine Date: Mon, 6 Jan 2025 22:16:37 +0100 Subject: [PATCH 05/11] Fix Package.resolved file path for SPM Example project --- .../AcknowExampleSPM/AcknowExampleSPM.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Examples/AcknowExampleSPM/AcknowExampleSPM.xcodeproj/project.pbxproj b/Examples/AcknowExampleSPM/AcknowExampleSPM.xcodeproj/project.pbxproj index 1a66711..b5d7ff8 100644 --- a/Examples/AcknowExampleSPM/AcknowExampleSPM.xcodeproj/project.pbxproj +++ b/Examples/AcknowExampleSPM/AcknowExampleSPM.xcodeproj/project.pbxproj @@ -19,7 +19,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 031D42892CDA828C00C803B8 /* Package.resolved */ = {isa = PBXFileReference; lastKnownFileType = text; name = Package.resolved; path = /Users/tisfeng/Documents/Code/Github/AcknowList/Tests/AcknowListTests/Resources/Package.resolved; sourceTree = ""; }; + 031D42892CDA828C00C803B8 /* Package.resolved */ = {isa = PBXFileReference; lastKnownFileType = text; name = Package.resolved; path = "../../../Tests/AcknowListTests/Resources/Package.resolved"; sourceTree = ""; }; BB29000128230B37002FF5C4 /* Package-version-1.resolved */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "Package-version-1.resolved"; path = "../../../Tests/AcknowListTests/Resources/Package-version-1.resolved"; sourceTree = ""; }; D7527E1D25CADE4E00378FB8 /* AcknowExampleSPM.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AcknowExampleSPM.app; sourceTree = BUILT_PRODUCTS_DIR; }; D7527E2025CADE4E00378FB8 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; From 0eff33c433ab49b6d9f6b2026ced519cd5254b93 Mon Sep 17 00:00:00 2001 From: Vincent Tourraine Date: Mon, 6 Jan 2025 22:31:22 +0100 Subject: [PATCH 06/11] Revert footer merging proposed implementation --- Sources/AcknowList/AcknowList.swift | 2 +- Sources/AcknowList/AcknowParser.swift | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Sources/AcknowList/AcknowList.swift b/Sources/AcknowList/AcknowList.swift index 4493fe6..26e2322 100644 --- a/Sources/AcknowList/AcknowList.swift +++ b/Sources/AcknowList/AcknowList.swift @@ -36,7 +36,7 @@ public struct AcknowList { /** Footer text to be displayed below the list of the acknowledgements. */ - public var footerText: String? + public let footerText: String? } extension AcknowList { diff --git a/Sources/AcknowList/AcknowParser.swift b/Sources/AcknowList/AcknowParser.swift index edf24ee..d61e28d 100644 --- a/Sources/AcknowList/AcknowParser.swift +++ b/Sources/AcknowList/AcknowParser.swift @@ -60,10 +60,7 @@ open class AcknowParser { let pods = defaultPods() let packages = defaultPackages() if let pods = pods, let packages = packages { - var acknowList = pods + packages - // If have both pods and packages libraries, remove the footer text from the pods. - acknowList.footerText = nil - return acknowList + return pods + packages } else { return pods ?? packages From cdb213ab3a3952de80317ac28a58633140d52767 Mon Sep 17 00:00:00 2001 From: Vincent Tourraine Date: Mon, 6 Jan 2025 22:34:40 +0100 Subject: [PATCH 07/11] Revert format changes --- Sources/AcknowList/AcknowListSwiftUI.swift | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/Sources/AcknowList/AcknowListSwiftUI.swift b/Sources/AcknowList/AcknowListSwiftUI.swift index af76e1b..d7dbd83 100644 --- a/Sources/AcknowList/AcknowListSwiftUI.swift +++ b/Sources/AcknowList/AcknowListSwiftUI.swift @@ -193,26 +193,22 @@ struct AcknowListSwiftUI_Previews: PreviewProvider { .previewDevice(PreviewDevice(rawValue: "iPhone 12")) NavigationView { - AcknowListSwiftUIView( - acknowledgements: acks, headerText: "Test Header", footerText: "Test Footer") + AcknowListSwiftUIView(acknowledgements: acks, headerText: "Test Header", footerText: "Test Footer") } .previewDevice(PreviewDevice(rawValue: "iPhone 12")) NavigationView { - AcknowListSwiftUIView( - acknowledgements: acks, headerText: "Test Header", footerText: "Test Footer") + AcknowListSwiftUIView(acknowledgements: acks, headerText: "Test Header", footerText: "Test Footer") } .previewDevice(PreviewDevice(rawValue: "Apple TV 4K")) NavigationView { - AcknowListSwiftUIView( - acknowledgements: acks, headerText: "Test Header", footerText: "Test Footer") + AcknowListSwiftUIView(acknowledgements: acks, headerText: "Test Header", footerText: "Test Footer") } .previewDevice(PreviewDevice(rawValue: "Apple Watch Series 6 - 44mm")) NavigationView { - AcknowListSwiftUIView( - acknowledgements: acks, headerText: "Test Header", footerText: "Test Footer") + AcknowListSwiftUIView(acknowledgements: acks, headerText: "Test Header", footerText: "Test Footer") } .previewDevice(PreviewDevice(rawValue: "Mac")) } From e1f81d71ba21388042978922b6b67194808d6521 Mon Sep 17 00:00:00 2001 From: Vincent Tourraine Date: Mon, 6 Jan 2025 22:38:45 +0100 Subject: [PATCH 08/11] Revert format changes --- Sources/AcknowList/AcknowListSwiftUI.swift | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Sources/AcknowList/AcknowListSwiftUI.swift b/Sources/AcknowList/AcknowListSwiftUI.swift index d7dbd83..f6f5b10 100644 --- a/Sources/AcknowList/AcknowListSwiftUI.swift +++ b/Sources/AcknowList/AcknowListSwiftUI.swift @@ -172,14 +172,14 @@ public struct AcknowListRowSwiftUIView: View { @available(iOS 13.0.0, macOS 10.15.0, watchOS 7.0.0, tvOS 13.0.0, visionOS 1.0.0, *) struct AcknowListSwiftUI_Previews: PreviewProvider { static let license = """ - Copyright (c) 2015-2024 Vincent Tourraine (https://www.vtourraine.net) - - Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - """ + Copyright (c) 2015-2024 Vincent Tourraine (https://www.vtourraine.net) + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + """ static let acks = [ Acknow(title: "Title 1", text: license), Acknow(title: "Title 2", text: license), From c66039b6dfb69b62089d780f90ad9c16e4bb8e82 Mon Sep 17 00:00:00 2001 From: Vincent Tourraine Date: Mon, 6 Jan 2025 22:44:18 +0100 Subject: [PATCH 09/11] Revert format changes --- Sources/AcknowList/AcknowListSwiftUI.swift | 59 +++++++++------------- 1 file changed, 24 insertions(+), 35 deletions(-) diff --git a/Sources/AcknowList/AcknowListSwiftUI.swift b/Sources/AcknowList/AcknowListSwiftUI.swift index f6f5b10..15ad02f 100644 --- a/Sources/AcknowList/AcknowListSwiftUI.swift +++ b/Sources/AcknowList/AcknowListSwiftUI.swift @@ -42,14 +42,6 @@ public struct AcknowListSwiftUIView: View { /// Footer text to be displayed below the list of the acknowledgements. public var footerText: String? - public init(acknowledgements: [Acknow], - headerText: String? = nil, - footerText: String? = nil) { - self.acknowledgements = acknowledgements - self.headerText = headerText - self.footerText = footerText - } - public init(acknowList: AcknowList? = AcknowParser.defaultAcknowList()) { self.init( acknowledgements: acknowList?.acknowledgements ?? [], @@ -57,27 +49,28 @@ public struct AcknowListSwiftUIView: View { footerText: acknowList?.footerText) } + public init(acknowledgements: [Acknow], headerText: String? = nil, footerText: String? = nil) { + self.acknowledgements = acknowledgements + self.headerText = headerText + self.footerText = footerText + } + public init(plistFileURL: URL) { guard let data = try? Data(contentsOf: plistFileURL), - let acknowList = try? AcknowPodDecoder().decode(from: data) - else { - self.init(acknowledgements: [], - headerText: nil, - footerText: nil) + let acknowList = try? AcknowPodDecoder().decode(from: data) else { + self.init(acknowledgements: [], headerText: nil, footerText: nil) return } let header: String? if acknowList.headerText != AcknowPodDecoder.K.DefaultHeaderText { header = acknowList.headerText - } else { + } + else { header = nil } - self.init( - acknowledgements: acknowList.acknowledgements, - headerText: header, - footerText: acknowList.footerText) + self.init(acknowledgements: acknowList.acknowledgements, headerText: header, footerText: acknowList.footerText) } struct HeaderFooter: View { @@ -86,7 +79,8 @@ public struct AcknowListSwiftUIView: View { var body: some View { if let text = text { Text(text) - } else { + } + else { EmptyView() } } @@ -95,9 +89,7 @@ public struct AcknowListSwiftUIView: View { public var body: some View { #if os(iOS) || os(tvOS) List { - Section( - header: HeaderFooter(text: headerText), footer: HeaderFooter(text: footerText) - ) { + Section(header: HeaderFooter(text: headerText), footer: HeaderFooter(text: footerText)) { ForEach(acknowledgements) { acknowledgement in AcknowListRowSwiftUIView(acknowledgement: acknowledgement) } @@ -107,9 +99,7 @@ public struct AcknowListSwiftUIView: View { .navigationBarTitle(Text(AcknowLocalization.localizedTitle())) #else List { - Section( - header: HeaderFooter(text: headerText), footer: HeaderFooter(text: footerText) - ) { + Section(header: HeaderFooter(text: headerText), footer: HeaderFooter(text: footerText)) { ForEach(acknowledgements) { acknowledgement in AcknowListRowSwiftUIView(acknowledgement: acknowledgement) } @@ -130,22 +120,21 @@ public struct AcknowListRowSwiftUIView: View { public var canFetchLicenseFromGitHub = true public var body: some View { - if acknowledgement.text != nil - || canFetchLicenseFromGitHubAndIsGitHubRepository(acknowledgement) - { + if acknowledgement.text != nil || canFetchLicenseFromGitHubAndIsGitHubRepository(acknowledgement) { NavigationLink(destination: AcknowSwiftUIView(acknowledgement: acknowledgement)) { Text(acknowledgement.title) } - } else if let repository = acknowledgement.repository, - canOpenRepository(for: repository) - { + } + else if let repository = acknowledgement.repository, + canOpenRepository(for: repository) { Button(action: { repository.openWithDefaultBrowser() }) { Text(acknowledgement.title) .foregroundColor(.primary) } - } else { + } + else { Text(acknowledgement.title) } } @@ -160,10 +149,10 @@ public struct AcknowListRowSwiftUIView: View { private func canFetchLicenseFromGitHubAndIsGitHubRepository(_ acknowledgement: Acknow) -> Bool { if canFetchLicenseFromGitHub, - let repository = acknowledgement.repository - { + let repository = acknowledgement.repository { return GitHubAPI.isGitHubRepository(repository) - } else { + } + else { return false } } From 26a8d24ac452690a43cfd00b27a46c60025e08fc Mon Sep 17 00:00:00 2001 From: Vincent Tourraine Date: Mon, 6 Jan 2025 22:53:14 +0100 Subject: [PATCH 10/11] Add AcknowListSwiftUI initializer to load default acknow list --- Sources/AcknowList/AcknowListSwiftUI.swift | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/Sources/AcknowList/AcknowListSwiftUI.swift b/Sources/AcknowList/AcknowListSwiftUI.swift index 15ad02f..d6af879 100644 --- a/Sources/AcknowList/AcknowListSwiftUI.swift +++ b/Sources/AcknowList/AcknowListSwiftUI.swift @@ -42,11 +42,23 @@ public struct AcknowListSwiftUIView: View { /// Footer text to be displayed below the list of the acknowledgements. public var footerText: String? - public init(acknowList: AcknowList? = AcknowParser.defaultAcknowList()) { - self.init( - acknowledgements: acknowList?.acknowledgements ?? [], - headerText: acknowList?.headerText, - footerText: acknowList?.footerText) + public init() { + if let acknowList = AcknowParser.defaultAcknowList() { + self.init(acknowList: acknowList) + } + else { + print( + "** AcknowList Warning **\n" + + "No acknowledgements found.\n" + + "Please take a look at https://github.com/vtourraine/AcknowList for instructions.", terminator: "\n") + self.init(acknowledgements: []) + } + } + + public init(acknowList: AcknowList) { + acknowledgements = acknowList.acknowledgements + headerText = acknowList.headerText + footerText = acknowList.footerText } public init(acknowledgements: [Acknow], headerText: String? = nil, footerText: String? = nil) { From 920cf5ff9c8159def03fe94e6f752428298f8435 Mon Sep 17 00:00:00 2001 From: Vincent Tourraine Date: Mon, 6 Jan 2025 22:55:55 +0100 Subject: [PATCH 11/11] Update changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fe9326..b293d35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 3.3.0 (work in progress) + +- Add initializer to `AcknowListSwiftUI` to load default acknow list, by Tisfeng (@tisfeng) + + ## 3.2.0 (11 June 2024) - Add visionOS support