diff --git a/ios/Packages/PolkadotIdenticon/Sources/PolkadotIdenticon/Public/PolkadotIdenticonView.swift b/ios/Packages/PolkadotIdenticon/Sources/PolkadotIdenticon/Public/PolkadotIdenticonView.swift new file mode 100644 index 0000000000..0c132a2d4c --- /dev/null +++ b/ios/Packages/PolkadotIdenticon/Sources/PolkadotIdenticon/Public/PolkadotIdenticonView.swift @@ -0,0 +1,59 @@ +// +// PolkadotIdenticonView.swift +// +// +// Created by Krzysztof Rodak on 02/08/2023. +// + +import SwiftUI + +/// `PolkadotIdenticonView` is a SwiftUI view that renders a Polkadot Identicon. +/// +/// An Identicon is a visual representation of a public key value, typically used to represent user identities in the +/// context of cryptographic applications. +/// This struct uses `PolkadotIdenticonGenerator` to generate a unique image, based on a provided public key input, +/// which can then be rendered within the SwiftUI view hierarchy. +public struct PolkadotIdenticonView: View { + private let identiconGenerator: PolkadotIdenticonGenerator = PolkadotIdenticonGenerator() + + /// The public key input based on which the Identicon is generated. + /// The public key can be in one of three formats: raw binary data (`Data`), a hexadecimal string, or a base58 + /// string. + let publicKey: PublicKey + + /// The size of the Identicon image to be generated. + let size: CGFloat + + /// Initializes a new instance of `PolkadotIdenticonView`. + /// + /// - Parameters: + /// - publicKey: The public key input based on which the Identicon is generated. This could be any unique public + /// key. + /// - size: The size of the Identicon image to be generated. + public init(publicKey: PublicKey, size: CGFloat) { + self.publicKey = publicKey + self.size = size + } + + /// Defines the content and behavior of this view. + /// + /// The body property returns an `Image` view if an Identicon image can be generated from the public key, + /// or an `EmptyView` if not. + public var body: some View { + if let identiconImage = createIdenticonImage() { + Image(uiImage: identiconImage) + .resizable() + .frame(width: size, height: size) + .aspectRatio(contentMode: .fit) + } else { + EmptyView() + } + } + + /// Helper function to generate an Identicon image. + /// + /// - Returns: A `UIImage` instance representing the generated Identicon, or nil if the image couldn't be generated. + private func createIdenticonImage() -> UIImage? { + identiconGenerator.generateIdenticonImage(from: publicKey, size: size) + } +} diff --git a/ios/PolkadotVault.xcodeproj/project.pbxproj b/ios/PolkadotVault.xcodeproj/project.pbxproj index 46809fc27f..c6bec95874 100644 --- a/ios/PolkadotVault.xcodeproj/project.pbxproj +++ b/ios/PolkadotVault.xcodeproj/project.pbxproj @@ -52,6 +52,7 @@ 6D0677AC29BB0C6000D76D90 /* AppLaunchMediator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D0677AB29BB0C6000D76D90 /* AppLaunchMediator.swift */; }; 6D0677AE29BB0D0000D76D90 /* WarningStateMediator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D0677AD29BB0D0000D76D90 /* WarningStateMediator.swift */; }; 6D07D370292B40D2001A0B79 /* TransactionSummaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D07D36F292B40D2001A0B79 /* TransactionSummaryView.swift */; }; + 6D09912A2A7AA10800DF75EC /* BlockiesIdenticonViewPreviews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D0991292A7AA10800DF75EC /* BlockiesIdenticonViewPreviews.swift */; }; 6D0BF95229F2BBF500F5B569 /* NetworkIconCapsuleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D0BF95129F2BBF500F5B569 /* NetworkIconCapsuleView.swift */; }; 6D0E188B291B82D000B59875 /* ProgressSnackbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D0E188A291B82D000B59875 /* ProgressSnackbar.swift */; }; 6D0FA73B2907010E00E45BA6 /* ExportMultipleKeysModal+ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D0FA73A2907010E00E45BA6 /* ExportMultipleKeysModal+ViewModel.swift */; }; @@ -147,8 +148,9 @@ 6D71290E294C2A380048558C /* VerticalActionsBottomModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D71290D294C2A380048558C /* VerticalActionsBottomModal.swift */; }; 6D7129222952B7800048558C /* NetworkSettingsDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D7129212952B7800048558C /* NetworkSettingsDetails.swift */; }; 6D7129252952C3D50048558C /* VerticalRoundedBackgroundContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D7129242952C3D50048558C /* VerticalRoundedBackgroundContainer.swift */; }; - 6D749C5A2A6871530064D7E5 /* BlockiesIdenticonViewPreviews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D749C592A6871530064D7E5 /* BlockiesIdenticonViewPreviews.swift */; }; 6D749C5C2A6871BA0064D7E5 /* Blockies in Frameworks */ = {isa = PBXBuildFile; productRef = 6D749C5B2A6871BA0064D7E5 /* Blockies */; }; + 6D749C602A69C6020064D7E5 /* PolkadotIdenticonViewPreviews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D749C5F2A69C6020064D7E5 /* PolkadotIdenticonViewPreviews.swift */; }; + 6D749C622A69CE2C0064D7E5 /* PolkadotIdenticon in Frameworks */ = {isa = PBXBuildFile; productRef = 6D749C612A69CE2C0064D7E5 /* PolkadotIdenticon */; }; 6D77F31F296D0C5600044C7C /* CreateKeyNetworkSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D77F31E296D0C5600044C7C /* CreateKeyNetworkSelectionView.swift */; }; 6D77F321296D0D4600044C7C /* GetAllNetworksService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D77F320296D0D4600044C7C /* GetAllNetworksService.swift */; }; 6D77F323296D4D8900044C7C /* CreateDerivedKeyService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D77F322296D4D8900044C7C /* CreateDerivedKeyService.swift */; }; @@ -401,6 +403,7 @@ 6D0677AB29BB0C6000D76D90 /* AppLaunchMediator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppLaunchMediator.swift; sourceTree = ""; }; 6D0677AD29BB0D0000D76D90 /* WarningStateMediator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WarningStateMediator.swift; sourceTree = ""; }; 6D07D36F292B40D2001A0B79 /* TransactionSummaryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionSummaryView.swift; sourceTree = ""; }; + 6D0991292A7AA10800DF75EC /* BlockiesIdenticonViewPreviews.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BlockiesIdenticonViewPreviews.swift; sourceTree = ""; }; 6D0AE5572A6129100042282A /* Blockies */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = Blockies; sourceTree = ""; }; 6D0BF95129F2BBF500F5B569 /* NetworkIconCapsuleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkIconCapsuleView.swift; sourceTree = ""; }; 6D0E188A291B82D000B59875 /* ProgressSnackbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressSnackbar.swift; sourceTree = ""; }; @@ -497,7 +500,8 @@ 6D71290D294C2A380048558C /* VerticalActionsBottomModal.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VerticalActionsBottomModal.swift; sourceTree = ""; }; 6D7129212952B7800048558C /* NetworkSettingsDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkSettingsDetails.swift; sourceTree = ""; }; 6D7129242952C3D50048558C /* VerticalRoundedBackgroundContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerticalRoundedBackgroundContainer.swift; sourceTree = ""; }; - 6D749C592A6871530064D7E5 /* BlockiesIdenticonViewPreviews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockiesIdenticonViewPreviews.swift; sourceTree = ""; }; + 6D749C5D2A699F5D0064D7E5 /* PolkadotIdenticon */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = PolkadotIdenticon; sourceTree = ""; }; + 6D749C5F2A69C6020064D7E5 /* PolkadotIdenticonViewPreviews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PolkadotIdenticonViewPreviews.swift; sourceTree = ""; }; 6D77F31E296D0C5600044C7C /* CreateKeyNetworkSelectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateKeyNetworkSelectionView.swift; sourceTree = ""; }; 6D77F320296D0D4600044C7C /* GetAllNetworksService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetAllNetworksService.swift; sourceTree = ""; }; 6D77F322296D4D8900044C7C /* CreateDerivedKeyService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateDerivedKeyService.swift; sourceTree = ""; }; @@ -680,6 +684,7 @@ 6D971ABC2941B1C600121A36 /* SVGView in Frameworks */, 6DEEA87E28AFBF5D00371ECA /* libsigner.a in Frameworks */, 6D971ACA2942E79100121A36 /* QRCode in Frameworks */, + 6D749C622A69CE2C0064D7E5 /* PolkadotIdenticon in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -754,6 +759,7 @@ 2D7A7BC826BA97AE0053C1E0 /* Components */ = { isa = PBXGroup; children = ( + 6D749C5E2A69C5F00064D7E5 /* Identicons */, 6DEB18ED2A0BAFA60013995E /* Progress */, 6D10EACC297114550063FB71 /* DerivationPathComponents.swift */, 6DEB18EC2A0BAEE10013995E /* TextFields */, @@ -773,7 +779,6 @@ 6DDEF13D28AE7C4B004CA2FD /* Buttons */, 6DDEF11928AE2DD3004CA2FD /* TabBar */, 6D2779C728B3D33100570055 /* NavigationBarView.swift */, - 6D749C592A6871530064D7E5 /* BlockiesIdenticonViewPreviews.swift */, ); path = Components; sourceTree = ""; @@ -937,6 +942,7 @@ 6D0AE5532A6128F00042282A /* Packages */ = { isa = PBXGroup; children = ( + 6D749C5D2A699F5D0064D7E5 /* PolkadotIdenticon */, 6D0AE5572A6129100042282A /* Blockies */, ); path = Packages; @@ -1344,6 +1350,15 @@ path = Backgrounds; sourceTree = ""; }; + 6D749C5E2A69C5F00064D7E5 /* Identicons */ = { + isa = PBXGroup; + children = ( + 6D0991292A7AA10800DF75EC /* BlockiesIdenticonViewPreviews.swift */, + 6D749C5F2A69C6020064D7E5 /* PolkadotIdenticonViewPreviews.swift */, + ); + path = Identicons; + sourceTree = ""; + }; 6D77F31D296D0C4000044C7C /* DerivedKey */ = { isa = PBXGroup; children = ( @@ -1956,6 +1971,7 @@ 6D971ABB2941B1C600121A36 /* SVGView */, 6D971AC92942E79100121A36 /* QRCode */, 6D749C5B2A6871BA0064D7E5 /* Blockies */, + 6D749C612A69CE2C0064D7E5 /* PolkadotIdenticon */, ); productName = PolkadotVault; productReference = 2DE72BBE26A588C7002BB752 /* PolkadotVault.app */; @@ -2222,7 +2238,6 @@ 6DA2ACAC2939E87600AAEADC /* Event+Value.swift in Sources */, 6D25E6B32A02323A00376AB9 /* FullscreenModal.swift in Sources */, 6DDF439C29879D3900881AFF /* SecondaryFont.swift in Sources */, - 6D749C5A2A6871530064D7E5 /* BlockiesIdenticonViewPreviews.swift in Sources */, 6D6430F628CB460A00342E37 /* ServiceLocator.swift in Sources */, 6DC5642E28B652DE003D540B /* AddKeySetModal.swift in Sources */, 6DF91F4329C06BB4000A6BB2 /* TextResources.swift in Sources */, @@ -2234,6 +2249,7 @@ 6DEA1B1528D4587200D170B7 /* SeedPhraseView.swift in Sources */, 6D8973AB2A08EE1E0046A2F3 /* SignSpecService.swift in Sources */, 6D6430EF28CB30A000342E37 /* BottoEdgeOverlay.swift in Sources */, + 6D749C602A69C6020064D7E5 /* PolkadotIdenticonViewPreviews.swift in Sources */, 6D88CFF828C634CA001FB0A1 /* KeyDetailsActionsModal.swift in Sources */, 6DE67D05298AA4270042415A /* BackupSelectKeyView.swift in Sources */, 6D45065E296E94FC0065B4D4 /* DerivationMethodsInfoView.swift in Sources */, @@ -2435,6 +2451,7 @@ 6D042AF22901B3FB00B3F4F7 /* QRCodeImageGenerator.swift in Sources */, 6D95E97528B500EE00E28A11 /* Heights.swift in Sources */, 6D8045DE28D087D400237F8C /* QRCodeRootFooterView.swift in Sources */, + 6D09912A2A7AA10800DF75EC /* BlockiesIdenticonViewPreviews.swift in Sources */, 6DA317C1299E3DDF005DD060 /* OnboardingAirgapView.swift in Sources */, 6DFE588D297A72B1002BFDBF /* JailbreakDetectionPublisher.swift in Sources */, 6D42793728DB147800C141DC /* PrivateKeyQRCodeService.swift in Sources */, @@ -2784,6 +2801,10 @@ isa = XCSwiftPackageProductDependency; productName = Blockies; }; + 6D749C612A69CE2C0064D7E5 /* PolkadotIdenticon */ = { + isa = XCSwiftPackageProductDependency; + productName = PolkadotIdenticon; + }; 6D971ABB2941B1C600121A36 /* SVGView */ = { isa = XCSwiftPackageProductDependency; package = 6D971ABA2941B1C600121A36 /* XCRemoteSwiftPackageReference "SVGView" */; diff --git a/ios/PolkadotVault/Components/Identicons/PolkadotIdenticonViewPreviews.swift b/ios/PolkadotVault/Components/Identicons/PolkadotIdenticonViewPreviews.swift new file mode 100644 index 0000000000..95fdc2d98e --- /dev/null +++ b/ios/PolkadotVault/Components/Identicons/PolkadotIdenticonViewPreviews.swift @@ -0,0 +1,31 @@ +// +// PolkadotIdenticonViewPreviews.swift +// PolkadotVault +// +// Created by Krzysztof Rodak on 02/08/2023. +// + +import PolkadotIdenticon +import SwiftUI + +struct PolkadotIdenticonView_Previews: PreviewProvider { + static var previews: some View { + VStack { + PolkadotIdenticonView( + publicKey: .hex("d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"), + size: 100 + ) + PolkadotIdenticonView( + publicKey: .base58("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"), + size: 100 + ) + PolkadotIdenticonView( + publicKey: .data(Data([ + 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, + 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125 + ])), + size: 100 + ) + } + } +}