From 2d770b4523c7b844765b40457d6d362ab8c3a9ba Mon Sep 17 00:00:00 2001 From: Oleg Date: Mon, 26 Feb 2024 20:07:31 +0700 Subject: [PATCH 1/3] MOB-1829 - Sunset UD Blue (#393) --- .../Entities/PreviewNetworkService.swift | 3 +-- .../Extensions/Extension-String+Preview.swift | 3 --- .../Extensions/UIImage.swift | 1 - .../DomainProfileTopInfoCell.swift | 2 -- .../DomainProfileTopInfoCell.xib | 15 ++------------- .../Entities/DomainProfileTopInfoData.swift | 2 -- ...mainProfileViewControllerItemsEntities.swift | 1 - .../Public profile view/PublicProfileView.swift | 5 ----- .../PublicProfileViewModel.swift | 8 ++------ .../Sections/DomainProfileTopInfoSection.swift | 2 -- .../Services/FeatureFlags/UDFeatureFlag.swift | 3 +-- .../NetworkService+ProfilesEntities.swift | 11 +---------- .../udBlueGrayIcon.imageset/Contents.json | 15 --------------- .../udBlueGrayIcon.imageset/udBlueBlueIcon.png | Bin 10941 -> 0 bytes .../SwiftUI/Extensions/Image.swift | 1 - 15 files changed, 7 insertions(+), 65 deletions(-) delete mode 100644 unstoppable-ios-app/domains-manager-ios/SupportingFiles/Assets.xcassets/DomainProfile/udBlueGrayIcon.imageset/Contents.json delete mode 100644 unstoppable-ios-app/domains-manager-ios/SupportingFiles/Assets.xcassets/DomainProfile/udBlueGrayIcon.imageset/udBlueBlueIcon.png diff --git a/unstoppable-ios-app/domains-manager-ios-preview/Entities/PreviewNetworkService.swift b/unstoppable-ios-app/domains-manager-ios-preview/Entities/PreviewNetworkService.swift index 0cd8fb565..88a4a5b32 100644 --- a/unstoppable-ios-app/domains-manager-ios-preview/Entities/PreviewNetworkService.swift +++ b/unstoppable-ios-app/domains-manager-ios-preview/Entities/PreviewNetworkService.swift @@ -177,8 +177,7 @@ extension NetworkService { imageType: nil, coverPath: nil, phoneNumber: nil, - domainPurchased: nil, - udBlue: nil), + domainPurchased: nil), socialAccounts: nil, referralCode: nil, social: nil, diff --git a/unstoppable-ios-app/domains-manager-ios/Extensions/Extension-String+Preview.swift b/unstoppable-ios-app/domains-manager-ios/Extensions/Extension-String+Preview.swift index b89f95988..596fa6d60 100644 --- a/unstoppable-ios-app/domains-manager-ios/Extensions/Extension-String+Preview.swift +++ b/unstoppable-ios-app/domains-manager-ios/Extensions/Extension-String+Preview.swift @@ -28,7 +28,6 @@ extension String { case unableToCreateAccountTutorial case referralTutorial case referralLink(code: String) - case udBlue case communitiesInfo case setupApplePayInstruction case unstoppableDomainSearch(searchKey: String) @@ -92,8 +91,6 @@ extension String { return "https://unstoppabledomains.com/refer-a-friend" case .referralLink(let code): return "\(NetworkConfig.migratedBaseUrl)/?ref=\(code)" - case .udBlue: - return "https://unstoppabledomains.com/products/blue" case .communitiesInfo: return "https://support.unstoppabledomains.com/support/solutions/articles/48001215751-badges" case .setupApplePayInstruction: diff --git a/unstoppable-ios-app/domains-manager-ios/Extensions/UIImage.swift b/unstoppable-ios-app/domains-manager-ios/Extensions/UIImage.swift index bc831762b..d03b65bd8 100644 --- a/unstoppable-ios-app/domains-manager-ios/Extensions/UIImage.swift +++ b/unstoppable-ios-app/domains-manager-ios/Extensions/UIImage.swift @@ -145,7 +145,6 @@ extension UIImage { static let cellChevron = UIImage(named: "cellChevron")! static let udCartLogoRaster = UIImage(named: "udCartLogoRaster")! static let chooseRRDomainIllustration = UIImage(named: "chooseRRDomainIllustration")! - static let udBlueGrayIcon = UIImage(named: "udBlueGrayIcon")! static let check = UIImage(named: "check")! static let statsIcon = UIImage(named: "statsIcon")! static let sparkleIcon = UIImage(named: "sparkleIcon")! diff --git a/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Cells/TopInfoCell/DomainProfileTopInfoCell/DomainProfileTopInfoCell.swift b/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Cells/TopInfoCell/DomainProfileTopInfoCell/DomainProfileTopInfoCell.swift index 7ce86c9e3..2fb8d1931 100644 --- a/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Cells/TopInfoCell/DomainProfileTopInfoCell/DomainProfileTopInfoCell.swift +++ b/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Cells/TopInfoCell/DomainProfileTopInfoCell/DomainProfileTopInfoCell.swift @@ -19,7 +19,6 @@ final class DomainProfileTopInfoCell: BaseDomainProfileTopInfoCell { @IBOutlet private weak var domainNameLabel: UILabel! @IBOutlet private weak var qrCodeButton: SmallRaisedTertiaryWhiteButton! @IBOutlet private weak var followersButton: SmallRaisedTertiaryWhiteButton! - @IBOutlet private weak var udBlueImageView: UIImageView! private let dropItemIdentifier = UTType.image.identifier @@ -50,7 +49,6 @@ final class DomainProfileTopInfoCell: BaseDomainProfileTopInfoCell { lineBreakMode: .byTruncatingTail) followersButton.isHidden = false - udBlueImageView.isHidden = !data.isUDBlue let social = data.social let havingFollowers = social.followerCount > 0 let havingFollowings = social.followingCount > 0 diff --git a/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Cells/TopInfoCell/DomainProfileTopInfoCell/DomainProfileTopInfoCell.xib b/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Cells/TopInfoCell/DomainProfileTopInfoCell/DomainProfileTopInfoCell.xib index 724c74f73..dc770980b 100644 --- a/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Cells/TopInfoCell/DomainProfileTopInfoCell/DomainProfileTopInfoCell.xib +++ b/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Cells/TopInfoCell/DomainProfileTopInfoCell/DomainProfileTopInfoCell.xib @@ -1,9 +1,9 @@ - + - + @@ -72,21 +72,12 @@ - - - - - - - - - @@ -188,13 +179,11 @@ - - diff --git a/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Entities/DomainProfileTopInfoData.swift b/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Entities/DomainProfileTopInfoData.swift index 68b8d4ffd..3eaa1b67a 100644 --- a/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Entities/DomainProfileTopInfoData.swift +++ b/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Entities/DomainProfileTopInfoData.swift @@ -13,12 +13,10 @@ struct DomainProfileTopInfoData { var imagePathPublic: Bool var coverPathPublic: Bool let social: DomainProfileSocialInfo - let isUDBlue: Bool init(profile: SerializedUserDomainProfile) { imagePathPublic = profile.profile.imagePathPublic coverPathPublic = profile.profile.coverPathPublic - isUDBlue = profile.profile.udBlue ?? false social = profile.social if let avatarPath = profile.profile.imagePath, diff --git a/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Entities/DomainProfileViewControllerItemsEntities.swift b/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Entities/DomainProfileViewControllerItemsEntities.swift index 2bd053a5e..969e23b57 100644 --- a/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Entities/DomainProfileViewControllerItemsEntities.swift +++ b/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Entities/DomainProfileViewControllerItemsEntities.swift @@ -29,7 +29,6 @@ extension DomainProfileViewController { let id: UUID let domain: DomainDisplayInfo let social: DomainProfileSocialInfo - let isUDBlue: Bool let isEnabled: Bool let avatarImageState: DomainProfileTopInfoData.ImageState let bannerImageState: DomainProfileTopInfoData.ImageState diff --git a/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Public Profile/Public profile view/PublicProfileView.swift b/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Public Profile/Public profile view/PublicProfileView.swift index b1c11bf7d..b7dd5553c 100644 --- a/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Public Profile/Public profile view/PublicProfileView.swift +++ b/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Public Profile/Public profile view/PublicProfileView.swift @@ -189,11 +189,6 @@ private extension PublicProfileView { height: avatarSize) .squareFrame(avatarSize) .clipForAvatarStyle(avatarStyle) - if viewModel.isUDBlue { - Image.udBlueGrayIcon - .resizable() - .squareFrame(24) - } } } diff --git a/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Public Profile/Public profile view/PublicProfileViewModel.swift b/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Public Profile/Public profile view/PublicProfileViewModel.swift index ffeda705c..785259765 100644 --- a/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Public Profile/Public profile view/PublicProfileViewModel.swift +++ b/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Public Profile/Public profile view/PublicProfileViewModel.swift @@ -42,7 +42,6 @@ extension PublicProfileView { @Published var socialAccounts: SocialAccounts? @Published var error: Error? @Published private(set) var isLoading = false - @Published private(set) var isUDBlue = false @Published private(set) var isUserDomainSelected = true @Published private(set) var profile: SerializedPublicDomainProfile? @Published private(set) var badgesDisplayInfo: [DomainProfileBadgeDisplayInfo]? @@ -165,7 +164,6 @@ extension PublicProfileView { records = await convertRecordsFrom(recordsDict: profile.records ?? [:]) socialInfo = profile.social socialAccounts = profile.socialAccounts - isUDBlue = profile.profile.udBlue ?? false isLoading = false loadImages() } @@ -300,8 +298,7 @@ extension PublicDomainProfileAttributes { imageType: nil, coverPath: nil, phoneNumber: nil, - domainPurchased: nil, - udBlue: false) + domainPurchased: nil) static let filled = PublicDomainProfileAttributes(displayName: "Oleg Kuplin", description: "Unstoppable iOS developer", @@ -311,8 +308,7 @@ extension PublicDomainProfileAttributes { imageType: .onChain, coverPath: "nil", phoneNumber: nil, - domainPurchased: nil, - udBlue: false) + domainPurchased: nil) } func loadImageFrom(url: URL) async -> UIImage? { diff --git a/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Sections/DomainProfileTopInfoSection.swift b/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Sections/DomainProfileTopInfoSection.swift index 4aff02e44..41183c5a0 100644 --- a/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Sections/DomainProfileTopInfoSection.swift +++ b/unstoppable-ios-app/domains-manager-ios/Modules/DomainProfile/Sections/DomainProfileTopInfoSection.swift @@ -34,7 +34,6 @@ extension DomainProfileTopInfoSection: DomainProfileSection { func fill(snapshot: inout DomainProfileSnapshot, withGeneralData generalData: DomainProfileGeneralData) { let domain = generalData.domain let social = topInfoData.social - let isUDBlue = topInfoData.isUDBlue let isEnabled = state == .default || state == .updatingRecords snapshot.appendSections([.topInfo]) @@ -42,7 +41,6 @@ extension DomainProfileTopInfoSection: DomainProfileSection { let itemData = DomainProfileViewController.ItemTopInfoData(id: id, domain: domain, social: social, - isUDBlue: isUDBlue, isEnabled: isEnabled, avatarImageState: editingTopInfoData.avatarImageState, bannerImageState: editingTopInfoData.bannerImageState, diff --git a/unstoppable-ios-app/domains-manager-ios/Services/FeatureFlags/UDFeatureFlag.swift b/unstoppable-ios-app/domains-manager-ios/Services/FeatureFlags/UDFeatureFlag.swift index 2babb5dc0..1e81d037b 100644 --- a/unstoppable-ios-app/domains-manager-ios/Services/FeatureFlags/UDFeatureFlag.swift +++ b/unstoppable-ios-app/domains-manager-ios/Services/FeatureFlags/UDFeatureFlag.swift @@ -9,11 +9,10 @@ import Foundation enum UDFeatureFlag: String, CaseIterable { case communityMediaEnabled = "ecommerce-service-users-enable-chat-community-media" - case udBlueRequiredForCommunities = "ecommerce-service-users-enable-chat-community-udBlue" var defaultValue: Bool { switch self { - case .communityMediaEnabled, .udBlueRequiredForCommunities: + case .communityMediaEnabled: return false } } diff --git a/unstoppable-ios-app/domains-manager-ios/Services/Networking/NetworkService+ProfilesEntities.swift b/unstoppable-ios-app/domains-manager-ios/Services/Networking/NetworkService+ProfilesEntities.swift index 6f811da3b..b179dc6f9 100644 --- a/unstoppable-ios-app/domains-manager-ios/Services/Networking/NetworkService+ProfilesEntities.swift +++ b/unstoppable-ios-app/domains-manager-ios/Services/Networking/NetworkService+ProfilesEntities.swift @@ -94,7 +94,6 @@ struct PublicDomainProfileAttributes: Decodable { let coverPath: String? let phoneNumber: String? let domainPurchased: Bool? - let udBlue: Bool? enum CodingKeys: CodingKey { case displayName @@ -106,7 +105,6 @@ struct PublicDomainProfileAttributes: Decodable { case coverPath case phoneNumber case domainPurchased - case udBlue } } @@ -128,7 +126,6 @@ extension PublicDomainProfileAttributes { self.imageType = nil } self.domainPurchased = try? container.decode(Bool.self, forKey: .domainPurchased) - self.udBlue = try? container.decode(Bool.self, forKey: .udBlue) } } @@ -157,7 +154,6 @@ struct UserDomainProfileAttributes: Codable { let imagePathPublic: Bool let coverPathPublic: Bool let phoneNumberPublic: Bool - let udBlue: Bool? enum CodingKeys: CodingKey { case id @@ -179,7 +175,6 @@ struct UserDomainProfileAttributes: Codable { case coverPathPublic case web2UrlPublic case phoneNumberPublic - case udBlue } internal init(id: UInt = 0, @@ -200,8 +195,7 @@ struct UserDomainProfileAttributes: Codable { imagePathPublic: Bool = false, coverPathPublic: Bool = false, web2UrlPublic: Bool = false, - phoneNumberPublic: Bool = false, - udBlue: Bool = false) { + phoneNumberPublic: Bool = false) { self.id = id self.domainId = domainId self.privateEmail = privateEmail @@ -221,7 +215,6 @@ struct UserDomainProfileAttributes: Codable { self.coverPathPublic = coverPathPublic self.web2UrlPublic = web2UrlPublic self.phoneNumberPublic = phoneNumberPublic - self.udBlue = udBlue } init(from decoder: Decoder) throws { @@ -250,7 +243,6 @@ struct UserDomainProfileAttributes: Codable { self.coverPathPublic = try container.decode(Bool.self, forKey: UserDomainProfileAttributes.CodingKeys.coverPathPublic) self.web2UrlPublic = try container.decode(Bool.self, forKey: UserDomainProfileAttributes.CodingKeys.web2UrlPublic) self.phoneNumberPublic = try container.decode(Bool.self, forKey: UserDomainProfileAttributes.CodingKeys.phoneNumberPublic) - self.udBlue = try? container.decode(Bool.self, forKey: UserDomainProfileAttributes.CodingKeys.udBlue) } func encode(to encoder: Encoder) throws { @@ -275,7 +267,6 @@ struct UserDomainProfileAttributes: Codable { try container.encode(coverPathPublic, forKey: .coverPathPublic) try container.encode(web2UrlPublic, forKey: .web2UrlPublic) try container.encode(phoneNumberPublic, forKey: .phoneNumberPublic) - try container.encode(udBlue, forKey: .udBlue) } } diff --git a/unstoppable-ios-app/domains-manager-ios/SupportingFiles/Assets.xcassets/DomainProfile/udBlueGrayIcon.imageset/Contents.json b/unstoppable-ios-app/domains-manager-ios/SupportingFiles/Assets.xcassets/DomainProfile/udBlueGrayIcon.imageset/Contents.json deleted file mode 100644 index 19c80e07d..000000000 --- a/unstoppable-ios-app/domains-manager-ios/SupportingFiles/Assets.xcassets/DomainProfile/udBlueGrayIcon.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "filename" : "udBlueBlueIcon.png", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - }, - "properties" : { - "template-rendering-intent" : "original" - } -} diff --git a/unstoppable-ios-app/domains-manager-ios/SupportingFiles/Assets.xcassets/DomainProfile/udBlueGrayIcon.imageset/udBlueBlueIcon.png b/unstoppable-ios-app/domains-manager-ios/SupportingFiles/Assets.xcassets/DomainProfile/udBlueGrayIcon.imageset/udBlueBlueIcon.png deleted file mode 100644 index 973b1450c65bb468cf299adbc07deeea57ef5480..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10941 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�`JmczYlA z_7CP^_yzd7n?e5d4Zz@qV4$HgtAg6Vz_>>TR^$Rm__G#TCP5?$th%W1MtKWiu z2+YWY5?OKMC2wts?1@!$LPzS}@({_)Y?&sCzhZXM)bZHxZxTU#u&x!c9CAXa8U=U5 zez-ccH$BS+!ZDLZ1%~X^@LxSao{KOI*#i*o%Ums4u!(2nw=KAcf1U%CbRmE{-u~cA zsg1Kf)}0<+nSI)17#FewQ@i78Ub_-Lu9vLcursU-?nv3!s0}16F5XUnUWJ7T?g=Ep zLF$uG)h`Ik)f)!>Lkj=infBvnP6Z70+j+p%5Ai9k$d4TaXrZ>gN!vfASNv` zaBz$Ov9dZZa~e?q4n&wJ$0Vue7-e@)7!A6uHSvKSJP;#d84)v58P%MR=_i_XT6ApJ zC}<0vllQlUcxfT366Yw*A`?KK?eGi~au7JchauX=+>*$}GeLlrNSy)H?>U)AM78ur zjr!oz8$Krm1x8@~S_+)PrBQ8&#~(Anu|28R`l{Jj4DV4!%#55Sspdm|+9nMoZp1n+ zEOEx)bRvCuftZ-mmewWL=Xaimf=>h|J%@N`XcA^rEY+2NSGu5=D z&~{c)vqr{G(vnj>Q;r%J_nbkwiv$+?0B^W5a?OBfu0FLgw7%E|iPSNwNk?~$7L4@y z0G^iq;z0Vp@-yf3faqG`+&Bi3HyM1ZJn+vc23>Ra;~)ZW(7|aCcd4~_ARs!IcSVvj zO?;sJ1IasU)48K2b;kW>-j@%hTKv#AE?N!;DI)^#db#?ppFa@BGS3T7PgtJavb`6m z6frc@qfh$q)w&6SOcdU8Rc?BK+=iu5d~oF(K+pKHdDT?)nuvToZdE9wKay398iZdN z;d4APdE)5suaoC1@gA*tXvr52>GcdPX@(T+ZNE8;X0>T8QrEclkgspo0R#Ko!%YU% zwKVBhwI%~@)fxbOuWmlpH!yL%7{!};V~7&?Ak~c`mH+_I{Fwmudf)&T80(Xw(_X3b&gF#*^2@r^ndbWC?AP8!$2cV;{cH}y~(p8wFIkugF@aKwr- zBxp#M&up*<1}oUGWiRyi*M5OUX2s^rMa;%9p?Hz9Fb$!a)MrgWWip!#zEotH0Sds@ z41jSBhUUy--LM3W(~cg;J3L&P2U}-EEJu_Xu_T666c`e6SOofjW&EM`cY=n*tvLb& z=K7KnLW|P~0%tPVE5%wq$y&11x11|18`W@Nh&g0!B6V4_i_9sSj`lV>?&z`nRF`RI zxOqJ^;gVJv5z7&0Ml8yZ_Vd%F3ly*5v z+t!`?VcX6=BKLZ35!oTnLWt^Qi$?at?pll6@DdGFtg{oyGkzceD7(?l(D`_7D5u3YkyS#31uO%i0Ep_Y7Q_;AqAh#t(M=hArJr?pq^MY~eVQsGl2e0|7JOB9; za0JT-!i-pg*_uAs*1Rpub{_HC1v>Iaro78cDeSdsjIN-$7ZDg^3Q*Rn!<~b|jW#A^ z;EtOHLL?258Ky$0@k}&Jg9FX^58rio_%K}gz?dQBD}TCTUI_ee3y0HH!VxsKh(BDu zb!RW_+|yT#t$gX0$7=W0Yk}NX?&t$qcc?ES#ixiShXAfK?}ODElJ|=7Lx}zt|J9N& z+zszj`M{YGO9c1e;NBE^zYWUKD5gZF1T6_n*^m1ND(Cvv%#O&qn5Bv=cTPjikQ_%Y z1@9E&a}r}a+tc%PF9We*k*-4^lXn<`bnodO;oS z@m~`rj_-hG1B1=4y2>p>ZUX`&h6E-Ie&9?1?f)ZKBBl&Nb#Wlmjp6Gojmia63b?Ss zxsqWs!E%3Xw@At-g)>Wcx9z|C{lr!Gs(VM~`k1Nm-WdmS zx-Ew@#L+W)unE-@AC?vjS3dI0@a4;kel#Z#`RZ^uC(!sLcB9I4M=b@OqxG~=ZhNTv zY+&lr@7+FkC42JQrt9jyF+-OAZb=)%Oa00000NkvXXu0mjfi5tfD diff --git a/unstoppable-ios-app/domains-manager-ios/SwiftUI/Extensions/Image.swift b/unstoppable-ios-app/domains-manager-ios/SwiftUI/Extensions/Image.swift index 761321fce..b0d61a75b 100644 --- a/unstoppable-ios-app/domains-manager-ios/SwiftUI/Extensions/Image.swift +++ b/unstoppable-ios-app/domains-manager-ios/SwiftUI/Extensions/Image.swift @@ -23,7 +23,6 @@ extension Image { static let chevronDown = Image(uiImage: .chevronDown) static let checkCircle = Image(uiImage: .checkCircle) static let udCartLogoRaster = Image(uiImage: .udCartLogoRaster) - static let udBlueGrayIcon = Image(uiImage: .udBlueGrayIcon) static let crossWhite = Image(uiImage: .crossWhite) static let chevronRight = Image(uiImage: .chevronRight) static let check = Image(uiImage: .check) From df5031e9fb2c82f775e5ff2f8459638da406f66d Mon Sep 17 00:00:00 2001 From: Oleg Date: Mon, 26 Feb 2024 20:08:13 +0700 Subject: [PATCH 2/3] Increased tappable area of chat nav title profile selector (#394) --- .../ChatListViews/ChatListNavTitleView.swift | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/ChatsList/ChatListViews/ChatListNavTitleView.swift b/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/ChatsList/ChatListViews/ChatListNavTitleView.swift index fcd73fbe1..a0c89985c 100644 --- a/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/ChatsList/ChatListViews/ChatListNavTitleView.swift +++ b/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/ChatsList/ChatListViews/ChatListNavTitleView.swift @@ -20,13 +20,20 @@ struct ChatListNavTitleView: View { UDVibration.buttonTap.vibrate() tabRouter.isSelectProfilePresented = true } label: { - HStack { - content() - if selectable { - Image.chevronDown - .resizable() - .squareFrame(20) - .foregroundStyle(Color.foregroundDefault) + ZStack { + Rectangle() + .frame(width: 200, + height: 30) + .opacity(0.001) + .layoutPriority(-1) + HStack { + content() + if selectable { + Image.chevronDown + .resizable() + .squareFrame(20) + .foregroundStyle(Color.foregroundDefault) + } } } } @@ -49,6 +56,7 @@ private extension ChatListNavTitleView { var selectable: Bool { appContext.userProfileService.profiles.count > 1 } + @ViewBuilder func content() -> some View { switch profile { @@ -122,3 +130,7 @@ private extension ChatListNavTitleView { extension ChatListNavTitleView { } + +#Preview { + ChatListNavTitleView(profile: appContext.userProfileService.selectedProfile!) +} From c12cec032dea3ae85e7de900b747c117b7f396d6 Mon Sep 17 00:00:00 2001 From: Oleg Date: Mon, 26 Feb 2024 20:09:39 +0700 Subject: [PATCH 3/3] MOB-1771 - Fixed send image functionality in private and group chats (#395) * Added API to upload remote attachments for domain. Removed all approach to upload attachments. * Updated upload request details * Send images as media embed in group chats * Adjusted chat input field UI * Check if user able to send attachments. * Chat row view refactoring * Show number of members in community --- .../project.pbxproj | 2 +- .../xcshareddata/swiftpm/Package.resolved | 2 +- .../Messaging/Chat/ChatView/ChatView.swift | 4 +- .../Chat/ChatView/ChatViewModel.swift | 12 ++-- .../InputView/ExpandableTextEditor.swift | 2 +- .../ChatView/InputView/MessageInputView.swift | 63 ++++++++++++------ .../ChatListRows/ChatListChatRowView.swift | 18 +++++- .../ChatsList/SelectableChatRowView.swift | 1 + .../ApiRequestBuilder.swift | 19 ++++++ .../AnalyticsServiceEnvironment.swift | 1 + .../MessagingAPIServiceHelper.swift | 11 ++++ .../PushMessagingAPIService.swift | 27 +++++--- .../XMTPMessagingAPIService.swift | 64 ++----------------- .../NetworkService+ProfilesApi.swift | 15 +++++ .../NetworkService+ProfilesEntities.swift | 24 ++++++- .../Services/Networking/NetworkService.swift | 8 +-- 16 files changed, 168 insertions(+), 105 deletions(-) diff --git a/unstoppable-ios-app/domains-manager-ios.xcodeproj/project.pbxproj b/unstoppable-ios-app/domains-manager-ios.xcodeproj/project.pbxproj index 7bab4e2e4..9345014b8 100644 --- a/unstoppable-ios-app/domains-manager-ios.xcodeproj/project.pbxproj +++ b/unstoppable-ios-app/domains-manager-ios.xcodeproj/project.pbxproj @@ -10999,7 +10999,7 @@ repositoryURL = "https://github.com/Oleg-Pecheneg/push-swift-sdk"; requirement = { kind = revision; - revision = ff3151a6834db9ca841ee0564979298f4b0df053; + revision = 7aa3a1aeea89acd91dcbefcb0473a2a993a66334; }; }; C66811F02B47B0F500BDABB0 /* XCRemoteSwiftPackageReference "xmtp-ios" */ = { diff --git a/unstoppable-ios-app/domains-manager-ios.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/unstoppable-ios-app/domains-manager-ios.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index db3970c4a..3a8a9428f 100644 --- a/unstoppable-ios-app/domains-manager-ios.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/unstoppable-ios-app/domains-manager-ios.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -131,7 +131,7 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/Oleg-Pecheneg/push-swift-sdk", "state" : { - "revision" : "ff3151a6834db9ca841ee0564979298f4b0df053" + "revision" : "7aa3a1aeea89acd91dcbefcb0473a2a993a66334" } }, { diff --git a/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/Chat/ChatView/ChatView.swift b/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/Chat/ChatView/ChatView.swift index 165327514..d9d131a87 100644 --- a/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/Chat/ChatView/ChatView.swift +++ b/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/Chat/ChatView/ChatView.swift @@ -28,7 +28,6 @@ struct ChatView: View, ViewAnalyticsLogger { ProgressView() } } - .environmentObject(viewModel) .displayError($viewModel.error) .background(Color.backgroundMuted2) .onChange(of: viewModel.keyboardFocused) { keyboardFocused in @@ -50,6 +49,9 @@ struct ChatView: View, ViewAnalyticsLogger { .background(.regularMaterial) } } + .environmentObject(viewModel) + .environment(\.analyticsViewName, analyticsName) + .environment(\.analyticsAdditionalProperties, additionalAppearAnalyticParameters) .onAppear(perform: onAppear) } } diff --git a/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/Chat/ChatView/ChatViewModel.swift b/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/Chat/ChatView/ChatViewModel.swift index 7099dcc95..b09dc44a9 100644 --- a/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/Chat/ChatView/ChatViewModel.swift +++ b/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/Chat/ChatView/ChatViewModel.swift @@ -63,7 +63,7 @@ final class ChatViewModel: ObservableObject, ViewAnalyticsLogger { chatState = .loading setupTitle() setupPlaceholder() - setupFunctionality() + setIfUserCanSendAttachments() loadAndShowData() } @@ -258,9 +258,13 @@ private extension ChatViewModel { } } - func setupFunctionality() { + func setIfUserCanSendAttachments() { + let isProfileHasDomain = appContext.walletsDataService.wallets.findWithAddress(profile.wallet)?.rrDomain != nil if isCommunityChat() { - canSendAttachments = featureFlagsService.valueFor(flag: .communityMediaEnabled) + let isCommunityMediaEnabled = featureFlagsService.valueFor(flag: .communityMediaEnabled) + canSendAttachments = isCommunityMediaEnabled && isProfileHasDomain + } else { + canSendAttachments = isProfileHasDomain } } @@ -899,7 +903,7 @@ extension ChatViewModel: UDFeatureFlagsListener { switch flag { case .communityMediaEnabled: if isCommunityChat() { - canSendAttachments = newValue + setIfUserCanSendAttachments() reloadCachedMessages() } default: diff --git a/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/Chat/ChatView/InputView/ExpandableTextEditor.swift b/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/Chat/ChatView/InputView/ExpandableTextEditor.swift index 5498ad172..8393e8840 100644 --- a/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/Chat/ChatView/InputView/ExpandableTextEditor.swift +++ b/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/Chat/ChatView/InputView/ExpandableTextEditor.swift @@ -33,7 +33,7 @@ struct ExpandableTextEditor: View { .foregroundStyle(Color.foregroundDefault) .frame(height: max(40, textEditorHeight)) .scrollContentBackground(.hidden) - .padding(EdgeInsets(top: 0, leading: 8, + .padding(EdgeInsets(top: 4, leading: 8, bottom: 0, trailing: 8)) .background(focused ? Color.backgroundMuted : Color.backgroundSubtle) .tint(Color.foregroundAccent) diff --git a/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/Chat/ChatView/InputView/MessageInputView.swift b/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/Chat/ChatView/InputView/MessageInputView.swift index 4b2807c48..c63d659bf 100644 --- a/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/Chat/ChatView/InputView/MessageInputView.swift +++ b/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/Chat/ChatView/InputView/MessageInputView.swift @@ -7,8 +7,12 @@ import SwiftUI -struct MessageInputView: View { +struct MessageInputView: View, ViewAnalyticsLogger { + @Environment(\.analyticsViewName) var analyticsName + @Environment(\.analyticsAdditionalProperties) var additionalAppearAnalyticParameters + @EnvironmentObject var viewModel: ChatViewModel + let input: Binding let placeholder: String @FocusState.Binding var focused: Bool @@ -17,30 +21,13 @@ struct MessageInputView: View { var body: some View { HStack(alignment: .bottom, spacing: 16) { - Menu { - ForEach(AdditionalAction.allCases.filter { $0.isAvailable }, id: \.self) { action in - Button { - UDVibration.buttonTap.vibrate() - additionalActionCallback(action) - } label: { - Label(action.title, systemImage: action.icon) - } - } - } label: { - Image.plusIcon18 - .resizable() - .squareFrame(20) - .padding(EdgeInsets(10)) - .foregroundStyle(Color.foregroundSecondary) - } - .onButtonTap { -// logButtonPressedAnalyticEvents(button: action.analyticButton) + if viewModel.canSendAttachments { + additionalActionsView() } - textFieldView() - if !input.wrappedValue.isEmpty { Button { + UDVibration.buttonTap.vibrate() sendCallback() } label: { Image.arrowUp24 @@ -88,11 +75,45 @@ struct MessageInputView: View { return UnstoppableImagePicker.isCameraAvailable } } + + var analyticButton: Analytics.Button { + switch self { + case .takePhoto: + return .takePhoto + case .choosePhoto: + return .choosePhoto + } + } } } // MARK: - Private methods private extension MessageInputView { + @MainActor + @ViewBuilder + func additionalActionsView() -> some View { + Menu { + ForEach(AdditionalAction.allCases.filter { $0.isAvailable }, id: \.self) { action in + Button { + UDVibration.buttonTap.vibrate() + logButtonPressedAnalyticEvents(button: action.analyticButton) + additionalActionCallback(action) + } label: { + Label(action.title, systemImage: action.icon) + } + } + } label: { + Image.plusIcon18 + .resizable() + .squareFrame(20) + .padding(EdgeInsets(10)) + .foregroundStyle(Color.foregroundSecondary) + } + .onButtonTap { + logButtonPressedAnalyticEvents(button: .chatInputActions) + } + } + @ViewBuilder func textFieldView() -> some View { ExpandableTextEditor(text: input, diff --git a/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/ChatsList/ChatListRows/ChatListChatRowView.swift b/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/ChatsList/ChatListRows/ChatListChatRowView.swift index 6053a2b4e..b7be171ad 100644 --- a/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/ChatsList/ChatListRows/ChatListChatRowView.swift +++ b/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/ChatsList/ChatListRows/ChatListChatRowView.swift @@ -119,14 +119,28 @@ private extension ChatListChatRowView { @ViewBuilder func subtitleView() -> some View { - if let lastMessage = chat.lastMessage { - Text(lastMessageTextFrom(message: lastMessage)) + if let subtitle = getSubtitleText() { + Text(subtitle) .lineLimit(2) .foregroundStyle(Color.foregroundSecondary) .font(.currentFont(size: 14)) } } + func getSubtitleText() -> String? { + if let lastMessage = chat.lastMessage { + return lastMessageTextFrom(message: lastMessage) + } else if case .community(let details) = chat.type { + switch details.type { + case .badge(let badgeDetailedInfo): + let holders = badgeDetailedInfo.usage.holders + let holdersKsString = holders.asFormattedKsString + return String.Constants.pluralNHolders.localized(holdersKsString, holders) + } + } + return nil + } + func lastMessageTextFrom(message: MessagingChatMessageDisplayInfo) -> String { switch message.type { case .text(let description): diff --git a/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/ChatsList/SelectableChatRowView.swift b/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/ChatsList/SelectableChatRowView.swift index d09fb6118..0c1b52a95 100644 --- a/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/ChatsList/SelectableChatRowView.swift +++ b/unstoppable-ios-app/domains-manager-ios/Modules/Messaging/ChatsList/SelectableChatRowView.swift @@ -26,6 +26,7 @@ struct SelectableChatRowView: View, ViewAnalyticsLogger { ChatListChatRowView(chat: chat, joinCommunityCallback: { joinCommunityCallback?(chat) }) + .padding(.init(horizontal: 12)) } } } diff --git a/unstoppable-ios-app/domains-manager-ios/NetworkEnvironment/ApiRequestBuilder.swift b/unstoppable-ios-app/domains-manager-ios/NetworkEnvironment/ApiRequestBuilder.swift index 7b3dee4d6..385445673 100644 --- a/unstoppable-ios-app/domains-manager-ios/NetworkEnvironment/ApiRequestBuilder.swift +++ b/unstoppable-ios-app/domains-manager-ios/NetworkEnvironment/ApiRequestBuilder.swift @@ -836,6 +836,25 @@ extension Endpoint { ) } + static func uploadRemoteAttachment(for domain: DomainItem, + with timedSignature: PersistedTimedSignature, + body: String) throws -> Endpoint { + // https://profile.ud-staging.com/api/user/aaron.x/attachment + let expires = "\(timedSignature.expires)" + let signature = timedSignature.sign + let headers = [ + SignatureComponentHeaders.CodingKeys.domain.rawValue: domain.name, + SignatureComponentHeaders.CodingKeys.expires.rawValue: expires, + SignatureComponentHeaders.CodingKeys.signature.rawValue: signature + ] + return Endpoint( + host: NetworkConfig.baseProfileHost, + path: "/profile/user/\(domain.name)/attachment", + queryItems: [], + body: body, + headers: headers + ) + } } // MARK: - Open methods diff --git a/unstoppable-ios-app/domains-manager-ios/Services/AnalyticsService/AnalyticsServiceEnvironment.swift b/unstoppable-ios-app/domains-manager-ios/Services/AnalyticsService/AnalyticsServiceEnvironment.swift index 6b7086bbb..baadb9098 100644 --- a/unstoppable-ios-app/domains-manager-ios/Services/AnalyticsService/AnalyticsServiceEnvironment.swift +++ b/unstoppable-ios-app/domains-manager-ios/Services/AnalyticsService/AnalyticsServiceEnvironment.swift @@ -345,6 +345,7 @@ extension Analytics { case copyChatMessageToClipboard case saveChatImage case blockUserInGroupChat + case chatInputActions, takePhoto, choosePhoto // Public profile case follow, unfollow diff --git a/unstoppable-ios-app/domains-manager-ios/Services/MessagingService/SubServices/MessagingAPI/MessagingAPIServiceHelper.swift b/unstoppable-ios-app/domains-manager-ios/Services/MessagingService/SubServices/MessagingAPI/MessagingAPIServiceHelper.swift index 2c8bff03c..376abfaed 100644 --- a/unstoppable-ios-app/domains-manager-ios/Services/MessagingService/SubServices/MessagingAPI/MessagingAPIServiceHelper.swift +++ b/unstoppable-ios-app/domains-manager-ios/Services/MessagingService/SubServices/MessagingAPI/MessagingAPIServiceHelper.swift @@ -44,6 +44,17 @@ struct MessagingAPIServiceHelper { return serviceMetadata } + static func uploadDataToWeb3Storage(_ data: Data, + ofType type: String, + by wallet: HexAddress) async throws -> URL { + let domain = try await MessagingAPIServiceHelper.getAnyDomainItem(for: wallet) + let response = try await NetworkService().uploadRemoteAttachment(for: domain, + base64: data.base64EncodedString(), + type: type) + return response.url + } + + enum MessagingHelperError: String, LocalizedError { case noDomainForWallet case failedToDecodeServiceData diff --git a/unstoppable-ios-app/domains-manager-ios/Services/MessagingService/SubServices/MessagingAPI/PushMessagingAPIService.swift b/unstoppable-ios-app/domains-manager-ios/Services/MessagingService/SubServices/MessagingAPI/PushMessagingAPIService.swift index f844bbc83..a67242fb5 100644 --- a/unstoppable-ios-app/domains-manager-ios/Services/MessagingService/SubServices/MessagingAPI/PushMessagingAPIService.swift +++ b/unstoppable-ios-app/domains-manager-ios/Services/MessagingService/SubServices/MessagingAPI/PushMessagingAPIService.swift @@ -645,7 +645,8 @@ private extension PushMessagingAPIService { receiver: String, by user: MessagingChatUserProfile) async throws -> Push.PushChat.SendOptions { let env = getCurrentPushEnvironment() - let pushMessageContent = try getPushMessageContentFrom(displayType: messageType) + let pushMessageContent = try await getPushMessageContentFrom(displayType: messageType, + by: user) let pushMessageType = try getPushMessageTypeFrom(displayType: messageType) let pgpPrivateKey = try await getPGPPrivateKeyFor(user: user) let reference = getPushMessageReferenceFrom(displayType: messageType) @@ -668,19 +669,16 @@ private extension PushMessagingAPIService { try MessagingAPIServiceHelper.decodeServiceMetadata(from: data) } - func getPushMessageContentFrom(displayType: MessagingChatMessageDisplayType) throws -> String { + func getPushMessageContentFrom(displayType: MessagingChatMessageDisplayType, + by user: MessagingChatUserProfile) async throws -> String { switch displayType { case .text(let details): return details.text case .imageBase64(let details): - let entity = PushEnvironment.PushMessageContentResponse(content: details.base64) - guard let jsonString = entity.jsonString() else { throw PushMessagingAPIServiceError.failedToPrepareMessageContent } - return jsonString + guard let data = Data(base64Encoded: details.base64) else { throw PushMessagingAPIServiceError.failedToPrepareMessageContent } + return try await getImagePushMessageContentFrom(data: data, by: user) case .imageData(let details): - guard let base64 = details.image?.base64String else { throw PushMessagingAPIServiceError.unsupportedType } - let preparedBase64 = Base64DataTransformer.addingImageIdentifier(to: base64) - let imageBase64TypeDetails = MessagingChatMessageImageBase64TypeDisplayInfo(base64: preparedBase64) - return try getPushMessageContentFrom(displayType: .imageBase64(imageBase64TypeDetails)) + return try await getImagePushMessageContentFrom(data: details.data, by: user) case .reaction(let details): return details.content case .unknown, .remoteContent: @@ -688,6 +686,15 @@ private extension PushMessagingAPIService { } } + func getImagePushMessageContentFrom(data: Data, + by user: MessagingChatUserProfile) async throws -> String { + let wallet = user.wallet + let url = try await MessagingAPIServiceHelper.uploadDataToWeb3Storage(data, + ofType: "image/png", + by: wallet) + return url.absoluteString + } + func getPushMessageReferenceFrom(displayType: MessagingChatMessageDisplayType) -> String? { switch displayType { case .reaction(let details): @@ -704,7 +711,7 @@ private extension PushMessagingAPIService { case .reaction: return .reaction case .imageBase64, .imageData: - return .image + return .mediaEmbed case .unknown, .remoteContent: throw PushMessagingAPIServiceError.unsupportedType } diff --git a/unstoppable-ios-app/domains-manager-ios/Services/MessagingService/SubServices/MessagingAPI/XMTPMessagingAPIService.swift b/unstoppable-ios-app/domains-manager-ios/Services/MessagingService/SubServices/MessagingAPI/XMTPMessagingAPIService.swift index 5fd770588..ebd8ad48a 100644 --- a/unstoppable-ios-app/domains-manager-ios/Services/MessagingService/SubServices/MessagingAPI/XMTPMessagingAPIService.swift +++ b/unstoppable-ios-app/domains-manager-ios/Services/MessagingService/SubServices/MessagingAPI/XMTPMessagingAPIService.swift @@ -22,7 +22,6 @@ final class XMTPMessagingAPIService { private let blockedUsersStorage = XMTPBlockedUsersStorage.shared private let approvedUsersStorage = XMTPApprovedTopicsStorage.shared - private let cachedDataHolder = CachedDataHolder() let capabilities = MessagingServiceCapabilities(canContactWithoutProfile: false, canBlockUsers: true, isSupportChatsListPagination: false, @@ -530,70 +529,19 @@ private extension XMTPMessagingAPIService { let encryptedAttachment = try RemoteAttachment.encodeEncrypted(content: attachment, codec: AttachmentCodec(), with: client) - let url = try await uploadDataToWeb3Storage(encryptedAttachment.payload, by: wallet) - let remoteAttachment = try RemoteAttachment(url: url, + let url = try await MessagingAPIServiceHelper.uploadDataToWeb3Storage(encryptedAttachment.payload, + ofType: mimeType, + by: wallet) + let urlString = url.absoluteString + let remoteAttachment = try RemoteAttachment(url: urlString, encryptedEncodedContent: encryptedAttachment) return try await conversation.send(content: remoteAttachment, options: .init(contentType: ContentTypeRemoteAttachment)) } - - func uploadDataToWeb3Storage(_ data: Data, - by wallet: HexAddress) async throws -> String { - struct Web3StorageResponse: Codable { - let carCid: String - let cid: String - } - - let token = await getWeb3StorageKey(for: wallet) - let url = URL(string: "https://api.web3.storage/upload")! - var request = URLRequest(url: url) - request.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization") - request.addValue("XMTP", forHTTPHeaderField: "X-NAME") - request.httpMethod = "POST" - - let responseData = try await URLSession.shared.upload(for: request, from: data).0 - let response = try Web3StorageResponse.objectFromDataThrowing(responseData) - - return "https://\(response.cid).ipfs.w3s.link" - } - + func getXMTPConversationTopicFromChat(_ chat: MessagingChat) -> String { chat.displayInfo.id // XMTP Chat's topic = chat's id } - - func getWeb3StorageKey(for wallet: HexAddress) async -> String { - if let cachedKey = await cachedDataHolder.getKeyFor(wallet: wallet) { - return cachedKey - } else if let domain = try? await MessagingAPIServiceHelper.getAnyDomainItem(for: wallet), - let profile = try? await NetworkService().fetchUserDomainProfile(for: domain, fields: [.profile]), - let storage = profile.storage, - storage.type == .web3 { - let key = storage.apiKey - await cachedDataHolder.setKey(key, for: wallet) - return key - } - - if User.instance.getSettings().isTestnetUsed { - return Web3Storage.StagingAPIKey - } else { - return Web3Storage.ProductionAPIKey - } - } -} - -// MARK: - Private methods -private extension XMTPMessagingAPIService { - actor CachedDataHolder { - var walletsToStorageKeys: [HexAddress : String] = [:] - - func getKeyFor(wallet: HexAddress) -> String? { - walletsToStorageKeys[wallet] - } - - func setKey(_ key: String, for wallet: HexAddress) { - walletsToStorageKeys[wallet] = key - } - } } // MARK: - Open methods diff --git a/unstoppable-ios-app/domains-manager-ios/Services/Networking/NetworkService+ProfilesApi.swift b/unstoppable-ios-app/domains-manager-ios/Services/Networking/NetworkService+ProfilesApi.swift index f5f28cd08..1b8a852a2 100644 --- a/unstoppable-ios-app/domains-manager-ios/Services/Networking/NetworkService+ProfilesApi.swift +++ b/unstoppable-ios-app/domains-manager-ios/Services/Networking/NetworkService+ProfilesApi.swift @@ -145,6 +145,21 @@ extension NetworkService { return try await updateUserDomainProfile(for: domain, body: body) } + @discardableResult + public func uploadRemoteAttachment(for domain: DomainItem, + base64: String, + type: String) async throws -> ProfileUploadRemoteAttachmentResponse { + let request = ProfileUploadRemoteAttachmentRequest(base64: base64, type: type) + let body = try prepareRequestBodyFrom(entity: request) + let persistedSignature = try await getOrCreateAndStorePersistedProfileSignature(for: domain) + let endpoint = try Endpoint.uploadRemoteAttachment(for: domain, + with: persistedSignature, + body: body) + let data = try await fetchDataHandlingThrottleFor(endpoint: endpoint, method: .post) + let info = try ProfileUploadRemoteAttachmentResponse.objectFromDataThrowing(data) + return info + } + public func updatePendingDomainProfiles(with requests: [UpdateProfilePendingChangesRequest]) async throws { try await withThrowingTaskGroup(of: Void.self) { group in for request in requests { diff --git a/unstoppable-ios-app/domains-manager-ios/Services/Networking/NetworkService+ProfilesEntities.swift b/unstoppable-ios-app/domains-manager-ios/Services/Networking/NetworkService+ProfilesEntities.swift index b179dc6f9..c1b81e42b 100644 --- a/unstoppable-ios-app/domains-manager-ios/Services/Networking/NetworkService+ProfilesEntities.swift +++ b/unstoppable-ios-app/domains-manager-ios/Services/Networking/NetworkService+ProfilesEntities.swift @@ -401,8 +401,8 @@ struct UserDomainNotificationsPreferences: Codable { } struct UserDomainStorageDetails: Codable { - let apiKey: String - let type: StorageType + let apiKey: String? + let type: StorageType? enum StorageType: String, Codable { case web3 = "web3.storage" @@ -692,3 +692,23 @@ struct WalletTokenPortfolio: Codable, Hashable { let value: WalletTokenPortfolio.Value? } } + +// MARK: Profile Update Request Structures +struct ProfileUploadRemoteAttachmentRequest: Codable { + let attachment: Attachment + + init(base64: String, + type: String) { + self.attachment = .init(base64: base64, type: type) + } + + struct Attachment: Codable { + let base64: String + let type: String + } +} + +// MARK: Profile Update Request Structures +struct ProfileUploadRemoteAttachmentResponse: Codable { + let url: URL +} diff --git a/unstoppable-ios-app/domains-manager-ios/Services/Networking/NetworkService.swift b/unstoppable-ios-app/domains-manager-ios/Services/Networking/NetworkService.swift index 25297cc4d..40ef31dc6 100644 --- a/unstoppable-ios-app/domains-manager-ios/Services/Networking/NetworkService.swift +++ b/unstoppable-ios-app/domains-manager-ios/Services/Networking/NetworkService.swift @@ -119,16 +119,16 @@ struct NetworkService { @discardableResult func fetchDataHandlingThrottleFor(endpoint: Endpoint, - method: HttpRequestMethod) async throws -> Data { + method: HttpRequestMethod) async throws -> Data { guard let url = endpoint.url else { throw NetworkLayerError.creatingURLFailed } let data = try await fetchDataHandlingThrottle(for: url, body: endpoint.body, method: method, extraHeaders: endpoint.headers) return data } func fetchDataHandlingThrottle(for url: URL, - body: String = "", - method: HttpRequestMethod = .post, - extraHeaders: [String: String] = [:]) async throws -> Data { + body: String = "", + method: HttpRequestMethod = .post, + extraHeaders: [String: String] = [:]) async throws -> Data { let data: Data do { data = try await fetchData(for: url, body: body, method: method, extraHeaders: extraHeaders)