diff --git a/SnowballSwiftExample/SnowballSwiftExample.xcodeproj/xcshareddata/xcschemes/SnowballSwiftExample.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/SnowballSwiftExample.xcscheme similarity index 84% rename from SnowballSwiftExample/SnowballSwiftExample.xcodeproj/xcshareddata/xcschemes/SnowballSwiftExample.xcscheme rename to .swiftpm/xcode/xcshareddata/xcschemes/SnowballSwiftExample.xcscheme index 6cb61294..46081efd 100644 --- a/SnowballSwiftExample/SnowballSwiftExample.xcodeproj/xcshareddata/xcschemes/SnowballSwiftExample.xcscheme +++ b/.swiftpm/xcode/xcshareddata/xcschemes/SnowballSwiftExample.xcscheme @@ -17,7 +17,21 @@ BlueprintIdentifier = "0877BF8F2A1C18D500A236AB" BuildableName = "SnowballSwiftExample.app" BlueprintName = "SnowballSwiftExample" - ReferencedContainer = "container:SnowballSwiftExample.xcodeproj"> + ReferencedContainer = "container:SnowballSwiftExample/SnowballSwiftExample.xcodeproj"> + + + + @@ -37,7 +51,7 @@ BlueprintIdentifier = "0877BF9F2A1C18D600A236AB" BuildableName = "SnowballSwiftExampleTests.xctest" BlueprintName = "SnowballSwiftExampleTests" - ReferencedContainer = "container:SnowballSwiftExample.xcodeproj"> + ReferencedContainer = "container:SnowballSwiftExample/SnowballSwiftExample.xcodeproj"> + ReferencedContainer = "container:SnowballSwiftExample/SnowballSwiftExample.xcodeproj"> @@ -70,7 +84,7 @@ BlueprintIdentifier = "0877BF8F2A1C18D500A236AB" BuildableName = "SnowballSwiftExample.app" BlueprintName = "SnowballSwiftExample" - ReferencedContainer = "container:SnowballSwiftExample.xcodeproj"> + ReferencedContainer = "container:SnowballSwiftExample/SnowballSwiftExample.xcodeproj"> @@ -87,7 +101,7 @@ BlueprintIdentifier = "0877BF8F2A1C18D500A236AB" BuildableName = "SnowballSwiftExample.app" BlueprintName = "SnowballSwiftExample" - ReferencedContainer = "container:SnowballSwiftExample.xcodeproj"> + ReferencedContainer = "container:SnowballSwiftExample/SnowballSwiftExample.xcodeproj"> diff --git a/README.md b/README.md index e546492d..b9711247 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,23 @@ # SnowballSwiftKit -Lots to do!! SwiftUI Component Kit supporting iOS 15.0+ +Lots to do!! SwiftUI Component Kit supporting iOS 15.0+. ## Getting Started -- Easiest way to open [both the SnowballSwiftKit Package and SnowballSwiftKit Example App] is via the bash script `start` or open `SnowballSwiftKit/SnowballSwiftExample/SnowballSwiftExample.xcodeproj` +- Easiest way to open -- both the `SnowballSwiftKit` Package and `SnowballSwiftExample` App -- is via the bash script `start` or open `SnowballSwiftExample/SnowballSwiftExample.xcodeproj` - [swiftlint](https://github.com/realm/SwiftLint) - [apple package manager plugins](https://github.com/apple/swift-package-manager/blob/main/Documentation/Plugins.md) -Soon: (send me a tg @ vivianphung if u want anything sooner) -- [Custom SF Symbols Collection](https://www.david-smith.org/blog/2023/01/23/design-notes-18/) -- Snowball Component Kit documentation site -- SnowballKotlinKit (for [Jetpack](https://developer.android.com/jetpack)) +### `Config.xcconfig` + +For now, until an app wide `SnowballSettings` is arch, edit `Config.xcconfig` with API Keys to test out some of the custom views such as `SnowballNFTGridView` and `SnowballNFTListView`. +Read more on [Config / Dev Mode](https://nshipster.com/xcconfig/) +## Soon +(send me a telegram @vivianphung if u want anything sooner) +- 'SnowballSettings' for app wide configs +- Login with wallet / email flow +- [Custom SF Symbols Collection](https://www.david-smith.org/blog/2023/01/23/design-notes-18/) +- Snowball Kit documentation site +- 'SnowballKotlinKit' (for [Jetpack](https://developer.android.com/jetpack)) diff --git a/SnowballSwiftExample/Config.xcconfig b/SnowballSwiftExample/Config.xcconfig new file mode 100644 index 00000000..ad8c5a97 --- /dev/null +++ b/SnowballSwiftExample/Config.xcconfig @@ -0,0 +1,11 @@ +// +// Config.xcconfig +// SnowballSwiftExample +// +// Created by Vivian Phung on 5/22/23. +// + +// Configuration settings file format documentation can be found at: +// https://help.apple.com/xcode/#/dev745c5c974 + +ALCHEMY_NFT_KEY = PasteNFTKeyHere diff --git a/SnowballSwiftExample/SnowballSwiftExample.xcodeproj/project.pbxproj b/SnowballSwiftExample/SnowballSwiftExample.xcodeproj/project.pbxproj index 747ac189..0db7d4cb 100644 --- a/SnowballSwiftExample/SnowballSwiftExample.xcodeproj/project.pbxproj +++ b/SnowballSwiftExample/SnowballSwiftExample.xcodeproj/project.pbxproj @@ -17,6 +17,8 @@ 0877BFAF2A1C18D600A236AB /* SnowballSwiftExampleUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0877BFAE2A1C18D600A236AB /* SnowballSwiftExampleUITests.swift */; }; 0877BFB12A1C18D600A236AB /* SnowballSwiftExampleUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0877BFB02A1C18D600A236AB /* SnowballSwiftExampleUITestsLaunchTests.swift */; }; 0877BFC02A1C195F00A236AB /* SnowballSwiftKit in Frameworks */ = {isa = PBXBuildFile; productRef = 0877BFBF2A1C195F00A236AB /* SnowballSwiftKit */; }; + 08801CBD2A1C438500C98ADF /* Config.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 08801CBC2A1C438500C98ADF /* Config.xcconfig */; }; + 08801CBF2A1C484C00C98ADF /* SnowballSwiftExampleNFTView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08801CBE2A1C484C00C98ADF /* SnowballSwiftExampleNFTView.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -50,6 +52,9 @@ 0877BFAE2A1C18D600A236AB /* SnowballSwiftExampleUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnowballSwiftExampleUITests.swift; sourceTree = ""; }; 0877BFB02A1C18D600A236AB /* SnowballSwiftExampleUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnowballSwiftExampleUITestsLaunchTests.swift; sourceTree = ""; }; 0877BFBD2A1C192600A236AB /* SnowballSwiftKit */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = SnowballSwiftKit; path = ..; sourceTree = ""; }; + 08801CBC2A1C438500C98ADF /* Config.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = SOURCE_ROOT; }; + 08801CBE2A1C484C00C98ADF /* SnowballSwiftExampleNFTView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SnowballSwiftExampleNFTView.swift; sourceTree = ""; }; + 08F1AAB32A1C405500BD4CC7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -81,6 +86,7 @@ 084672F22A1C372600C7FB93 /* Example Views */ = { isa = PBXGroup; children = ( + 08801CBE2A1C484C00C98ADF /* SnowballSwiftExampleNFTView.swift */, 084672EE2A1C2B8B00C7FB93 /* SnowballSwiftExampleText.swift */, 084672F02A1C2FFF00C7FB93 /* SnowballSwiftExampleButtonsView.swift */, ); @@ -115,6 +121,8 @@ 0877BF952A1C18D500A236AB /* SnowballSwiftKitHomeView.swift */, 084672F22A1C372600C7FB93 /* Example Views */, 0877BF972A1C18D600A236AB /* Assets.xcassets */, + 08801CBC2A1C438500C98ADF /* Config.xcconfig */, + 08F1AAB32A1C405500BD4CC7 /* Info.plist */, 0877BF992A1C18D600A236AB /* Preview Content */, ); path = SnowballSwiftExample; @@ -253,6 +261,7 @@ buildActionMask = 2147483647; files = ( 0877BF9B2A1C18D600A236AB /* Preview Assets.xcassets in Resources */, + 08801CBD2A1C438500C98ADF /* Config.xcconfig in Resources */, 0877BF982A1C18D600A236AB /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -280,6 +289,7 @@ files = ( 0877BF962A1C18D500A236AB /* SnowballSwiftKitHomeView.swift in Sources */, 084672F12A1C2FFF00C7FB93 /* SnowballSwiftExampleButtonsView.swift in Sources */, + 08801CBF2A1C484C00C98ADF /* SnowballSwiftExampleNFTView.swift in Sources */, 0877BF942A1C18D500A236AB /* SnowballSwiftExampleApp.swift in Sources */, 084672EF2A1C2B8B00C7FB93 /* SnowballSwiftExampleText.swift in Sources */, ); @@ -320,6 +330,7 @@ /* Begin XCBuildConfiguration section */ 0877BFB22A1C18D600A236AB /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 08801CBC2A1C438500C98ADF /* Config.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -434,6 +445,7 @@ }; 0877BFB52A1C18D600A236AB /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 08801CBC2A1C438500C98ADF /* Config.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; @@ -443,6 +455,7 @@ DEVELOPMENT_TEAM = 9SAQ42S589; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = SnowballSwiftExample/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "Snowball Swift Example App"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools"; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; @@ -474,6 +487,7 @@ DEVELOPMENT_TEAM = 9SAQ42S589; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = SnowballSwiftExample/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "Snowball Swift Example App"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools"; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; @@ -496,6 +510,7 @@ }; 0877BFB82A1C18D600A236AB /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 08801CBC2A1C438500C98ADF /* Config.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; @@ -536,6 +551,7 @@ }; 0877BFBB2A1C18D600A236AB /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 08801CBC2A1C438500C98ADF /* Config.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; diff --git a/SnowballSwiftExample/SnowballSwiftExample/Example Views/SnowballSwiftExampleButtonsView.swift b/SnowballSwiftExample/SnowballSwiftExample/Example Views/SnowballSwiftExampleButtonsView.swift index f3d66ed9..bb0a93a0 100644 --- a/SnowballSwiftExample/SnowballSwiftExample/Example Views/SnowballSwiftExampleButtonsView.swift +++ b/SnowballSwiftExample/SnowballSwiftExample/Example Views/SnowballSwiftExampleButtonsView.swift @@ -10,29 +10,29 @@ import SnowballSwiftKit struct SnowballSwiftExampleButtonsView: View { @State var tappedButtonString: String = "" - + var body: some View { VStack(spacing: 15) { Text("SnowballButton is just a convenient view! You can use buttons ButtonStyle (.danger, .plain, etc) on it to style") - + Text("Tapped Button: \(tappedButtonString)") - + SnowballButton(leftSystemIcon: "clipboard") { self.tappedButtonString = "clipboard icon only" } - + SnowballButton(leftSystemIcon: "clipboard", text: "clipboard") { self.tappedButtonString = "clipboard with *left* icon and text" } - + SnowballButton(text: "clipboard", rightSystemIcon: "clipboard") { self.tappedButtonString = "clipboard with *right* icon and text" } - + SnowballButton(text: "clipboard") { self.tappedButtonString = "clipboard text only" } - + Spacer() VStack(alignment: .leading) { Text("ex. ButtonStyle") @@ -41,21 +41,21 @@ struct SnowballSwiftExampleButtonsView: View { self.tappedButtonString = "danger" }) .buttonStyle(.danger) - + Button("plain", action: { self.tappedButtonString = "plain" }) .buttonStyle(.plain) - + Button("bordered", action: { self.tappedButtonString = "bordered" }) .buttonStyle(.bordered) } } - + Spacer() - + VStack(alignment: .leading) { Text("SwiftUI understands context") HStack { @@ -63,7 +63,7 @@ struct SnowballSwiftExampleButtonsView: View { self.tappedButtonString = "styled button" }) .buttonStyle(.danger) - + SnowballButton(text: "styled 'SnowballButton'") { self.tappedButtonString = "styled snowball 'button'" } diff --git a/SnowballSwiftExample/SnowballSwiftExample/Example Views/SnowballSwiftExampleNFTView.swift b/SnowballSwiftExample/SnowballSwiftExample/Example Views/SnowballSwiftExampleNFTView.swift new file mode 100644 index 00000000..bcd14b27 --- /dev/null +++ b/SnowballSwiftExample/SnowballSwiftExample/Example Views/SnowballSwiftExampleNFTView.swift @@ -0,0 +1,29 @@ +// +// SnowballSwiftExampleNFTGridView.swift +// SnowballSwiftExample +// +// Created by Vivian Phung on 5/22/23. +// + +import SwiftUI +import SnowballSwiftKit + +struct SnowballSwiftExampleNFTView: View { + // todo: Snowball Settings for app wide settings + var alchemyKey: String + var type: NFTViewType = .grid + + var body: some View { + switch type { + case .grid: + SnowballNFTGridView(ethAddress: "vivianphung.eth", alchemyKey: alchemyKey) + case .list: + SnowballNFTListView(ethAddress: "vivianphung.eth", alchemyKey: alchemyKey) + } + } +} + +enum NFTViewType: String { + case grid = "grid" + case list = "list" +} diff --git a/SnowballSwiftExample/SnowballSwiftExample/Example Views/SnowballSwiftExampleText.swift b/SnowballSwiftExample/SnowballSwiftExample/Example Views/SnowballSwiftExampleText.swift index 6122b9f4..94267bba 100644 --- a/SnowballSwiftExample/SnowballSwiftExample/Example Views/SnowballSwiftExampleText.swift +++ b/SnowballSwiftExample/SnowballSwiftExample/Example Views/SnowballSwiftExampleText.swift @@ -35,4 +35,3 @@ extension Font.TextStyle { "Caption": .caption ] } - diff --git a/SnowballSwiftExample/SnowballSwiftExample/Info.plist b/SnowballSwiftExample/SnowballSwiftExample/Info.plist new file mode 100644 index 00000000..3377438f --- /dev/null +++ b/SnowballSwiftExample/SnowballSwiftExample/Info.plist @@ -0,0 +1,8 @@ + + + + + ALCHEMY_NFT_KEY + $(ALCHEMY_NFT_KEY) + + diff --git a/SnowballSwiftExample/SnowballSwiftExample/SnowballSwiftKitHomeView.swift b/SnowballSwiftExample/SnowballSwiftExample/SnowballSwiftKitHomeView.swift index 1b6ac6b0..760fe832 100644 --- a/SnowballSwiftExample/SnowballSwiftExample/SnowballSwiftKitHomeView.swift +++ b/SnowballSwiftExample/SnowballSwiftExample/SnowballSwiftKitHomeView.swift @@ -9,6 +9,9 @@ import SwiftUI import SnowballSwiftKit struct SnowballSwiftKitHomeView: View { + // todo: Snowball Settings for app wide settings + let alchemyKey: String = Bundle.main.infoDictionary?["ALCHEMY_NFT_KEY"] as? String ?? "" + var body: some View { NavigationView { List { @@ -16,11 +19,23 @@ struct SnowballSwiftKitHomeView: View { SnowballSwiftExampleText() .navigationTitle("Text") } - + NavigationLink("Buttons") { SnowballSwiftExampleButtonsView() .navigationTitle("Buttons") } + + NavigationLink("NFT Grid View") { + SnowballSwiftExampleNFTView(alchemyKey: alchemyKey) + .navigationTitle("NFT Grid View") + } + .disabled(alchemyKey == "" || alchemyKey == "PasteNFTKeyHere") + + NavigationLink("NFT List View") { + SnowballSwiftExampleNFTView(alchemyKey: alchemyKey, type: .list) + .navigationTitle("NFT List View") + } + .disabled(alchemyKey == "" || alchemyKey == "PasteNFTKeyHere") } .listStyle(.plain) .navigationTitle("Snowball Example") diff --git a/Sources/SnowballSwiftKit/Views/SnowballNFTGridView.swift b/Sources/SnowballSwiftKit/Views/SnowballNFTGridView.swift index 71acf078..5cb98a11 100644 --- a/Sources/SnowballSwiftKit/Views/SnowballNFTGridView.swift +++ b/Sources/SnowballSwiftKit/Views/SnowballNFTGridView.swift @@ -13,13 +13,17 @@ public struct SnowballNFTGridView: View { @StateObject private var viewModel = AlchemyNFTViewModel() @State var ethAddress: String + // todo: snowball settings with api key + var alchemyKey: String + private var gridLayout: [GridItem] = [ GridItem(.flexible(), spacing: 10), GridItem(.flexible(), spacing: 10) ] - public init(ethAddress: String) { + public init(ethAddress: String, alchemyKey: String) { self.ethAddress = ethAddress + self.alchemyKey = alchemyKey } public var body: some View { @@ -43,16 +47,8 @@ public struct SnowballNFTGridView: View { .padding(10) } .onAppear { - viewModel.fetchNFTs(forAddress: self.ethAddress, key: "") + viewModel.fetchNFTs(forAddress: self.ethAddress, key: alchemyKey) } } } } - -struct NFTGridView_Previews: PreviewProvider { - static var previews: some View { - Group { - SnowballNFTGridView(ethAddress: "vivianphung.eth") - } - } -} diff --git a/Sources/SnowballSwiftKit/Views/SnowballNFTListView.swift b/Sources/SnowballSwiftKit/Views/SnowballNFTListView.swift index 0baa70e4..45a71734 100644 --- a/Sources/SnowballSwiftKit/Views/SnowballNFTListView.swift +++ b/Sources/SnowballSwiftKit/Views/SnowballNFTListView.swift @@ -12,6 +12,14 @@ public struct SnowballNFTListView: View { @StateObject private var viewModel = AlchemyNFTViewModel() let ethAddress: String + // todo: snowball settings with api key + var alchemyKey: String + + public init(ethAddress: String, alchemyKey: String) { + self.ethAddress = ethAddress + self.alchemyKey = alchemyKey + } + public var body: some View { List(viewModel.nfts) { nft in HStack { @@ -25,15 +33,7 @@ public struct SnowballNFTListView: View { } .onAppear { - viewModel.fetchNFTs(forAddress: ethAddress, key: "") - } - } -} - -struct NFTListView_Previews: PreviewProvider { - static var previews: some View { - Group { - SnowballNFTListView(ethAddress: "vivianphung.eth") + viewModel.fetchNFTs(forAddress: ethAddress, key: alchemyKey) } } }