Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various fixes in messages module #398

Merged
merged 10 commits into from
Feb 28, 2024
10 changes: 10 additions & 0 deletions unstoppable-ios-app/domains-manager-ios.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1280,6 +1280,9 @@
C6BA74722AD4FEE600628DC6 /* PullUpViewService+ExternalWallets.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6BA74712AD4FEE600628DC6 /* PullUpViewService+ExternalWallets.swift */; };
C6BA74742AD5013500628DC6 /* PullUpViewService+DomainProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6BA74732AD5013500628DC6 /* PullUpViewService+DomainProfile.swift */; };
C6BEEF3029C30C89000489B9 /* FirebaseNetworkConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6BEEF2F29C30C89000489B9 /* FirebaseNetworkConfig.swift */; };
C6BF0C5B2B8EDEB4009CB50F /* CheckPendingEventsOnAppearViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6BF0C5A2B8EDEB4009CB50F /* CheckPendingEventsOnAppearViewModifier.swift */; };
C6BF0C5C2B8EDEB4009CB50F /* CheckPendingEventsOnAppearViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6BF0C5A2B8EDEB4009CB50F /* CheckPendingEventsOnAppearViewModifier.swift */; };
C6BF6BDA2B8EE724006CC2BD /* PassViewAnalyticsDetailsViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6BF6BD92B8EE724006CC2BD /* PassViewAnalyticsDetailsViewModifier.swift */; };
C6C1E9342B74C33B00030447 /* AnalyticAppearanceTrackerModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6C1E9332B74C33B00030447 /* AnalyticAppearanceTrackerModifier.swift */; };
C6C1E9352B74C33B00030447 /* AnalyticAppearanceTrackerModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6C1E9332B74C33B00030447 /* AnalyticAppearanceTrackerModifier.swift */; };
C6C1EC5A2A3AD2F3005EB37D /* UIMenuDomainAvatarLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6C1EC592A3AD2F3005EB37D /* UIMenuDomainAvatarLoader.swift */; };
Expand Down Expand Up @@ -3336,6 +3339,8 @@
C6BA74712AD4FEE600628DC6 /* PullUpViewService+ExternalWallets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PullUpViewService+ExternalWallets.swift"; sourceTree = "<group>"; };
C6BA74732AD5013500628DC6 /* PullUpViewService+DomainProfile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PullUpViewService+DomainProfile.swift"; sourceTree = "<group>"; };
C6BEEF2F29C30C89000489B9 /* FirebaseNetworkConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirebaseNetworkConfig.swift; sourceTree = "<group>"; };
C6BF0C5A2B8EDEB4009CB50F /* CheckPendingEventsOnAppearViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckPendingEventsOnAppearViewModifier.swift; sourceTree = "<group>"; };
C6BF6BD92B8EE724006CC2BD /* PassViewAnalyticsDetailsViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PassViewAnalyticsDetailsViewModifier.swift; sourceTree = "<group>"; };
C6C1E9332B74C33B00030447 /* AnalyticAppearanceTrackerModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticAppearanceTrackerModifier.swift; sourceTree = "<group>"; };
C6C1EC592A3AD2F3005EB37D /* UIMenuDomainAvatarLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIMenuDomainAvatarLoader.swift; sourceTree = "<group>"; };
C6C1EC5E2A3AD483005EB37D /* UIAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIAction.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -6517,6 +6522,7 @@
C69F991A2A9F1264004B1958 /* AdaptiveSheet.swift */,
C6C1E9332B74C33B00030447 /* AnalyticAppearanceTrackerModifier.swift */,
C69F99192A9F1264004B1958 /* AvatarStyleClipped.swift */,
C6BF0C5A2B8EDEB4009CB50F /* CheckPendingEventsOnAppearViewModifier.swift */,
C69F99162A9F1264004B1958 /* ClearListBackground.swift */,
C6DA0B742B7C5F68009920B5 /* SectionSpacingModifier.swift */,
C6DF46262AA18F8900D124E7 /* DisplayError.swift */,
Expand All @@ -6525,6 +6531,7 @@
C685803A2B357EF400907568 /* NavBarVisibleModifier.swift */,
C6C837A02B5FF307000A6AF5 /* TabBarVisibleModifier.swift */,
C663A4D82B7F2FAC0099BCE8 /* PresentationStyleCheckerModifier.swift */,
C6BF6BD92B8EE724006CC2BD /* PassViewAnalyticsDetailsViewModifier.swift */,
C631DFA02B7B1ED500040221 /* InfiniteRotationModifier.swift */,
C6493A012B63A8B700457363 /* TrackingPressingStateModifier.swift */,
C6D645792B1D7C2F00D724AC /* PullUpError.swift */,
Expand Down Expand Up @@ -8372,6 +8379,7 @@
C6A89C4F2B315B8D008AB043 /* HotFeatureSuggestionsService.swift in Sources */,
C6D3B9C42A6EBF370091B279 /* XMTPMessagingAPIService.swift in Sources */,
C6B65F772B550FC2006D1812 /* WalletNFTsService.swift in Sources */,
C6BF0C5B2B8EDEB4009CB50F /* CheckPendingEventsOnAppearViewModifier.swift in Sources */,
C685A96F2840A59B00E54044 /* TextBlackButton.swift in Sources */,
C692C31F282E485C00C31393 /* SecuritySettingsViewController.swift in Sources */,
C6D6463A2B1DC50400D724AC /* AppReviewActionEvent.swift in Sources */,
Expand Down Expand Up @@ -9117,6 +9125,7 @@
C6B65F502B54DA84006D1812 /* HomeWalletViewModel.swift in Sources */,
C685A97B2840BF6200E54044 /* InfoScreen.swift in Sources */,
C630BC7B2B183E5700E29318 /* PurchaseDomainsHappyEndViewPresenter.swift in Sources */,
C6BF6BDA2B8EE724006CC2BD /* PassViewAnalyticsDetailsViewModifier.swift in Sources */,
C630E4B32B7F5835008F3269 /* ExpandableTextEditor.swift in Sources */,
C63095EF2B0DA66400205054 /* FirebaseAuthenticationService.swift in Sources */,
C666E0C829CC0B5D0003DECB /* FirebaseDomainsStorage.swift in Sources */,
Expand Down Expand Up @@ -9859,6 +9868,7 @@
C61807F62B19A7BC0032E543 /* CryptoRecord.swift in Sources */,
C6C8F9302B2183C700A9834D /* DomainsCollectionMintingInProgressCell.swift in Sources */,
C6C8F8782B21827700A9834D /* LoginWithEmailInAppViewPresenter.swift in Sources */,
C6BF0C5C2B8EDEB4009CB50F /* CheckPendingEventsOnAppearViewModifier.swift in Sources */,
C607A5CA2B327A600088ECF3 /* PreviewHappyEndViewController.swift in Sources */,
C6C8F8D02B21833D00A9834D /* UDBTSearchView.swift in Sources */,
C6D6460C2B1DC07200D724AC /* FirebaseDomainDisplayInfo.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public struct Debugger {
case WalletConnect = "WC"
case WalletConnectV2 = "WC_V2"
case UI = "=UI="
case Analytics = "Analtyics"
case Analytics = "Analytics"
case LocalNotification = "LN"
case Images = "IMG"
case DataAggregation = "AGGR"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,12 @@ extension HomeTabRouter {
func showDomainProfile(_ domain: DomainDisplayInfo,
wallet: WalletEntity,
preRequestedAction: PreRequestedProfileAction?,
shouldResetNavigation: Bool = true,
dismissCallback: EmptyCallback?) async {
await popToRootAndWait()
tabViewSelection = .wallets
if shouldResetNavigation {
await popToRootAndWait()
tabViewSelection = .wallets
}
await askToFinishSetupPurchasedProfileIfNeeded(domains: wallet.domains)
guard let topVC = appContext.coreAppCoordinator.topVC else { return }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ struct HomeView: View, ViewAnalyticsLogger {
.ignoresSafeArea()
}
.trackAppearanceAnalytics(analyticsLogger: self)
.environment(\.analyticsViewName, analyticsName)
.environment(\.analyticsAdditionalProperties, additionalAppearAnalyticParameters)
.passViewAnalyticsDetails(logger: self)
.checkPendingEventsOnAppear()

}, navigationStateProvider: { state in
self.navigationState = state
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ struct ChannelView: View, ViewAnalyticsLogger {
ProgressView()
}
}
.environment(\.analyticsViewName, analyticsName)
.environment(\.analyticsAdditionalProperties, additionalAppearAnalyticParameters)
.displayError($viewModel.error)
.background(Color.backgroundMuted2)
.toolbar {
Expand All @@ -45,6 +43,7 @@ struct ChannelView: View, ViewAnalyticsLogger {
.background(.regularMaterial)
}
}
.passViewAnalyticsDetails(logger: self)
.onAppear(perform: onAppear)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ extension Chat {
case copyText(String)
case sendReaction(content: String, toMessage: MessagingChatMessageDisplayInfo)
case saveImage(UIImage)
case showImage(UIImage)
case blockUserInGroup(MessagingChatUserDisplayInfo)
case reply(MessagingChatMessageDisplayInfo)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@

import SwiftUI

struct ChatMentionSuggestionsView: View {
struct ChatMentionSuggestionsView: View, ViewAnalyticsLogger {

@Environment(\.analyticsViewName) var analyticsName
@Environment(\.analyticsAdditionalProperties) var additionalAppearAnalyticParameters

let suggestingUsers: [MessagingChatUserDisplayInfo]
let selectionCallback: (MessagingChatUserDisplayInfo)->()
Expand Down Expand Up @@ -36,6 +39,7 @@ private extension ChatMentionSuggestionsView {
@ViewBuilder
func selectableRowViewFor(user: MessagingChatUserDisplayInfo) -> some View {
Button {
logButtonPressedAnalyticEvents(button: .messagingMentionSuggestion)
UDVibration.buttonTap.vibrate()
selectionCallback(user)
} label: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ struct ChatNavTitleView: View {
.foregroundStyle(Color.foregroundDefault)
.font(.currentFont(size: 16, weight: .semibold))
}
.task {
await loadIcon()
}
.onChange(of: titleType, perform: { newValue in
loadIconNonBlocking()
})
.onAppear(perform: loadIconNonBlocking)
}

private var title: String {
Expand All @@ -44,6 +45,12 @@ struct ChatNavTitleView: View {
}
}

private func loadIconNonBlocking() {
Task {
await loadIcon()
}
}

private func loadIcon() async {
switch titleType {
case .domainName(let domainName):
Expand All @@ -64,7 +71,7 @@ struct ChatNavTitleView: View {
}
}

enum TitleType {
enum TitleType: Hashable {
case domainName(DomainName)
case walletAddress(HexAddress)
case channel(MessagingNewsChannel)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@

import SwiftUI

struct ChatReplyInfoView: View {
struct ChatReplyInfoView: View, ViewAnalyticsLogger {

@EnvironmentObject var viewModel: ChatViewModel

@Environment(\.analyticsViewName) var analyticsName
@Environment(\.analyticsAdditionalProperties) var additionalAppearAnalyticParameters

let messageToReply: MessagingChatMessageDisplayInfo

var body: some View {
Expand Down Expand Up @@ -48,6 +50,7 @@ private extension ChatReplyInfoView {
func clickableMessageDescriptionView() -> some View {
Button {
UDVibration.buttonTap.vibrate()
logButtonPressedAnalyticEvents(button: .jumpToMessageToReply)
withAnimation {
viewModel.didTapJumpToReplyButton()
}
Expand Down Expand Up @@ -85,6 +88,7 @@ private extension ChatReplyInfoView {
@ViewBuilder
func removeReplyView() -> some View {
Button {
logButtonPressedAnalyticEvents(button: .cancelReply)
UDVibration.buttonTap.vibrate()
withAnimation {
viewModel.didTapRemoveReplyButton()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ struct ChatView: View, ViewAnalyticsLogger {
@FocusState var focused: Bool

var analyticsName: Analytics.ViewName { .chatDialog }
var additionalAppearAnalyticParameters: Analytics.EventParameters { [:] }

var body: some View {
ZStack {
Expand Down Expand Up @@ -55,8 +54,7 @@ struct ChatView: View, ViewAnalyticsLogger {
}
}
.environmentObject(viewModel)
.environment(\.analyticsViewName, analyticsName)
.environment(\.analyticsAdditionalProperties, additionalAppearAnalyticParameters)
.passViewAnalyticsDetails(logger: self)
.onAppear(perform: onAppear)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ final class ChatViewModel: ObservableObject, ViewAnalyticsLogger {
private let messagingService: MessagingServiceProtocol
private let featureFlagsService: UDFeatureFlagsServiceProtocol
private(set) var conversationState: MessagingChatConversationState
private let fetchLimit: Int = 20
private let fetchLimit: Int = 30
@Published private(set) var isLoadingMessages = false
@Published private(set) var blockStatus: MessagingPrivateChatBlockingStatus = .unblocked
@Published private(set) var isChannelEncrypted: Bool = true
Expand Down Expand Up @@ -167,6 +167,9 @@ extension ChatViewModel {
logButtonPressedAnalyticEvents(button: .saveChatImage)
let saver = PhotoLibraryImageSaver()
saver.saveImage(image)
case .showImage(let image):
logButtonPressedAnalyticEvents(button: .viewMessagePhoto)
showMessageImageViewWith(image: image, mode: .view)
case .blockUserInGroup(let user):
logButtonPressedAnalyticEvents(button: .blockUserInGroupChat,
parameters: [.chatId : chat.id,
Expand All @@ -175,8 +178,10 @@ extension ChatViewModel {
try? await setUser(user, in: chat, blocked: true)
}
case .sendReaction(let content, let toMessage):
logButtonPressedAnalyticEvents(button: .sendReaction, parameters: [.value: content])
sendReactionMessage(content, toMessage: toMessage)
case .reply(let message):
logButtonPressedAnalyticEvents(button: .replyToMessage)
messageToReply = message
keyboardFocused = true
}
Expand Down Expand Up @@ -266,8 +271,10 @@ private extension ChatViewModel {

func verifyAndHandleExternalLink(_ url: URL, by sender: MessagingChatSender) {
if let domainName = parseMentionDomainNameFrom(url: url) {
logButtonPressedAnalyticEvents(button: .mentionWithinMessage, parameters: [.value: domainName])
handleMentionPressedTo(domainName: domainName)
} else {
logButtonPressedAnalyticEvents(button: .linkWithinMessage)
handleOtherLinkPressed(url, by: sender)
}
}
Expand All @@ -283,10 +290,7 @@ private extension ChatViewModel {

func parseMentionDomainNameFrom(url: URL) -> String? {
let string = url.absoluteString
if string.first == "@" {
return String(string.dropFirst())
}
return nil
return MessageMentionString(string: string)?.mentionWithoutPrefix
}

func handleOtherLinkPressed(_ url: URL, by sender: MessagingChatSender) {
Expand Down Expand Up @@ -974,6 +978,7 @@ private extension ChatViewModel {
await router.showDomainProfile(domain,
wallet: wallet,
preRequestedAction: action,
shouldResetNavigation: false,
dismissCallback: nil)
case .showPublicDomainProfile(let publicDomainDisplayInfo, let wallet, let action):
router.showPublicDomainProfile(of: publicDomainDisplayInfo,
Expand All @@ -987,11 +992,14 @@ private extension ChatViewModel {
private extension ChatViewModel {
func didPickImageToSend(_ image: UIImage) {
let resizedImage = image.resized(to: Constants.maxImageResolution) ?? image

let confirmationVC = MessagingImageView.instantiate(mode: .confirmSending(callback: { [weak self] in
showMessageImageViewWith(image: resizedImage, mode: .confirmSending(callback: { [weak self] in
self?.sendImageMessage(resizedImage)
}), image: resizedImage)
appContext.coreAppCoordinator.topVC?.present(confirmationVC, animated: true)
}))
}

func showMessageImageViewWith(image: UIImage, mode: MessagingImageView.Mode) {
let messagingImageVC = MessagingImageView.instantiate(mode: mode, image: image)
appContext.coreAppCoordinator.topVC?.present(messagingImageVC, animated: true)
}
}

Expand Down Expand Up @@ -1089,20 +1097,9 @@ extension ChatViewModel: MessagingServiceListener {
case .chats:
return
case .messagesAdded(let messages, let chatId, let userId):
if userId == self.profile.id,
case .existingChat(let chat) = conversationState,
chatId == chat.id,
!messages.isEmpty {
await self.addMessages(messages, scrollToBottom: true)
}
await addMessagesFromUpdatedData(messages, chatId: chatId, userId: userId)
case .messageUpdated(let updatedMessage, var newMessage):
if case .existingChat(let chat) = conversationState,
updatedMessage.chatId == chat.id,
let i = self.messages.firstIndex(where: { $0.id == updatedMessage.id }) {
await newMessage.prepareToDisplay()
self.messages[i] = newMessage
messagesCache.insert(newMessage)
}
await updateMessageFromUpdatedData(updatedMessage, with: newMessage)
case .messagesRemoved(let messages, let chatId):
if case .existingChat(let chat) = conversationState,
chatId == chat.id {
Expand All @@ -1117,6 +1114,27 @@ extension ChatViewModel: MessagingServiceListener {
}
}
}

private func addMessagesFromUpdatedData(_ messages: [MessagingChatMessageDisplayInfo], chatId: String, userId: String) async {
if userId == self.profile.id,
case .existingChat(let chat) = conversationState,
chatId == chat.id,
!messages.isEmpty {
let messages = messages.filter { !$0.isReactionMessage }
await self.addMessages(messages, scrollToBottom: true)
}
}

private func updateMessageFromUpdatedData(_ updatedMessage: MessagingChatMessageDisplayInfo, with newMessage: MessagingChatMessageDisplayInfo) async {
if case .existingChat(let chat) = conversationState,
updatedMessage.chatId == chat.id,
let i = self.messages.firstIndex(where: { $0.id == updatedMessage.id }) {
var newMessage = newMessage
await newMessage.prepareToDisplay()
self.messages[i] = newMessage
messagesCache.insert(newMessage)
}
}
}

// MARK: - UDFeatureFlagsListener
Expand All @@ -1128,8 +1146,6 @@ extension ChatViewModel: UDFeatureFlagsListener {
setIfUserCanSendAttachments()
reloadCachedMessages()
}
default:
return
}
}
}
Expand Down
Loading