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

MOB-2142 - Show loading state if ULW messaging profile activation is in progress #661

Merged
merged 1 commit into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ final class MessagingService: MessagingServiceProtocol {
return .init(id: "1", wallet: wallet.address, serviceIdentifier: .xmtp)
}

func isCreatingProfileInProgressFor(wallet: WalletEntity) async -> Bool { true }

func isCommunitiesEnabled(for messagingProfile: MessagingChatUserProfileDisplayInfo) async -> Bool {
false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ extension ChannelViewModel: MessagingServiceListener {
if channelId == channel.id {
addFeed([feed])
}
case .chats, .messagesAdded, .messageUpdated, .messagesRemoved, .refreshOfUserProfile, .messageReadStatusUpdated, .totalUnreadMessagesCountUpdated, .userInfoRefreshed:
case .chats, .messagesAdded, .messageUpdated, .messagesRemoved, .refreshOfUserProfile, .messageReadStatusUpdated, .totalUnreadMessagesCountUpdated, .userInfoRefreshed, .profileCreated:
return
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1116,7 +1116,7 @@ extension ChatViewModel: MessagingServiceListener {
if let i = listOfGroupParticipants.firstIndex(where: { $0.wallet == user.wallet }) {
listOfGroupParticipants[i] = user
}
case .channels, .channelFeedAdded, .refreshOfUserProfile, .messageReadStatusUpdated, .totalUnreadMessagesCountUpdated:
case .channels, .channelFeedAdded, .refreshOfUserProfile, .messageReadStatusUpdated, .totalUnreadMessagesCountUpdated, .profileCreated:
return
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,8 @@ extension ChatListViewModel: MessagingServiceListener {
prepareData()
}
}
case .profileCreated(let profile):
loadAndShowData()
case .messageUpdated, .messagesRemoved, .messagesAdded, .channelFeedAdded, .totalUnreadMessagesCountUpdated, .refreshOfUserProfile, .userInfoRefreshed:
return
}
Expand Down Expand Up @@ -539,9 +541,14 @@ private extension ChatListViewModel {
parameters: [.state : state.rawValue,
.wallet: chatProfile.wallet.address])
await awaitForUIReady()
chatState = .createProfile
prepareData()
return
if await messagingService.isCreatingProfileInProgressFor(wallet: chatProfile.wallet) {
runLoadingState()
return
} else {
chatState = .createProfile
prepareData()
return
}
}

logAnalytic(event: .willShowMessagingProfile, parameters: [.state : MessagingProfileStateAnalytics.created.rawValue,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ extension ChatRequestsListViewModel: MessagingServiceListener {
case .channelsSpam:
return
}
case .messageUpdated, .messagesRemoved, .messagesAdded, .channelFeedAdded, .refreshOfUserProfile, .totalUnreadMessagesCountUpdated, .userInfoRefreshed:
case .messageUpdated, .messagesRemoved, .messagesAdded, .channelFeedAdded, .refreshOfUserProfile, .totalUnreadMessagesCountUpdated, .userInfoRefreshed, .profileCreated:
return
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,35 @@ import Foundation

extension MessagingService {
func createUserProfile(for wallet: WalletEntity, serviceIdentifier: MessagingServiceIdentifier) async throws -> MessagingChatUserProfileDisplayInfo {
let apiService = try getAPIServiceWith(identifier: serviceIdentifier)

if let existingUser = try? await getUserProfile(for: wallet, serviceIdentifier: serviceIdentifier) {
return existingUser
if let task = await stateHolder.getOngoingCreateProfileTask(for: wallet, serviceIdentifier: serviceIdentifier) {
return try await task.value
}
let newUser = try await apiService.createUser(for: wallet)
if let domain = wallet.rrDomain {
Task.detached {
try? await apiService.updateUserProfile(newUser, name: domain.name, avatar: domain.pfpSource.value)

let task = CreateProfileTask {
let apiService = try getAPIServiceWith(identifier: serviceIdentifier)

if let existingUser = try? await getUserProfile(for: wallet, serviceIdentifier: serviceIdentifier) {
return existingUser
}
let newUser = try await apiService.createUser(for: wallet)
if let domain = wallet.rrDomain {
Task.detached {
try? await apiService.updateUserProfile(newUser, name: domain.name, avatar: domain.pfpSource.value)
}
}
await storageService.saveUserProfile(newUser)
return newUser.displayInfo
}
await storageService.saveUserProfile(newUser)
return newUser.displayInfo

await stateHolder.setOngoingCreateProfileTask(task,
for: wallet,
serviceIdentifier: serviceIdentifier)
let profile = try await task.value
await stateHolder.setOngoingCreateProfileTask(nil,
for: wallet,
serviceIdentifier: serviceIdentifier)
notifyListenersChangedDataType(.profileCreated(profile))
return profile
}

func getUserProfile(for wallet: WalletEntity, serviceIdentifier: MessagingServiceIdentifier) async throws -> MessagingChatUserProfileDisplayInfo {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ extension MessagingService: MessagingServiceProtocol {
// Capabilities
func canContactWithoutProfileIn(newConversation newConversationDescription: MessagingChatNewConversationDescription) -> Bool {
guard let apiService = try? getAPIServiceWith(identifier: newConversationDescription.messagingService) else { return false }

return apiService.capabilities.canContactWithoutProfile
}

Expand All @@ -80,7 +80,7 @@ extension MessagingService: MessagingServiceProtocol {
let serviceIdentifier = newConversationDescription.messagingService
let address = newConversationDescription.userInfo.wallet
let profile = try await getUserProfileWith(wallet: user.wallet, serviceIdentifier: serviceIdentifier)

let apiService = try getAPIServiceWith(identifier: serviceIdentifier)
return try await apiService.isAbleToContactAddress(address, by: profile)
}
Expand Down Expand Up @@ -116,7 +116,7 @@ extension MessagingService: MessagingServiceProtocol {
func getUserMessagingProfile(for wallet: WalletEntity) async throws -> MessagingChatUserProfileDisplayInfo {
try await getUserProfile(for: wallet, serviceIdentifier: defaultServiceIdentifier)
}

func createUserMessagingProfile(for wallet: WalletEntity) async throws -> MessagingChatUserProfileDisplayInfo {
let profile = try await createUserProfile(for: wallet, serviceIdentifier: defaultServiceIdentifier)
if wallet.udWallet.type != .mpc,
Expand All @@ -126,6 +126,10 @@ extension MessagingService: MessagingServiceProtocol {
return profile
}

func isCreatingProfileInProgressFor(wallet: WalletEntity) async -> Bool {
await stateHolder.getOngoingCreateProfileTask(for: wallet, serviceIdentifier: defaultServiceIdentifier) != nil
}

func isCommunitiesEnabled(for messagingProfile: MessagingChatUserProfileDisplayInfo) async -> Bool {
if Constants.isCommunitiesEnabled {
let communitiesProfile = try? await getUserCommunitiesProfile(for: messagingProfile)
Expand Down Expand Up @@ -749,9 +753,11 @@ extension MessagingService {

// MARK: - StateHolder
extension MessagingService {
typealias CreateProfileTask = Task<MessagingChatUserProfileDisplayInfo, Error>
actor StateHolder {

private var sendingMessagesCounter: Int = 0
private var creatingProfilesProcess = [MessagingProfileDetails : CreateProfileTask]()

var isSendingMessage: Bool { sendingMessagesCounter > 0 }

Expand All @@ -768,5 +774,22 @@ extension MessagingService {
}
}

func getOngoingCreateProfileTask(for wallet: WalletEntity,
serviceIdentifier: MessagingServiceIdentifier) -> CreateProfileTask? {
let details = MessagingProfileDetails(walletAddress: wallet.address, serviceIdentifier: serviceIdentifier)
return creatingProfilesProcess[details]
}

func setOngoingCreateProfileTask(_ task: CreateProfileTask?,
for wallet: WalletEntity,
serviceIdentifier: MessagingServiceIdentifier) {
let details = MessagingProfileDetails(walletAddress: wallet.address, serviceIdentifier: serviceIdentifier)
creatingProfilesProcess[details] = task
}

private struct MessagingProfileDetails: Hashable {
let walletAddress: String
let serviceIdentifier: MessagingServiceIdentifier
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ protocol MessagingServiceProtocol {
// User
func getUserMessagingProfile(for wallet: WalletEntity) async throws -> MessagingChatUserProfileDisplayInfo
func createUserMessagingProfile(for wallet: WalletEntity) async throws -> MessagingChatUserProfileDisplayInfo
func isCreatingProfileInProgressFor(wallet: WalletEntity) async -> Bool
func isCommunitiesEnabled(for messagingProfile: MessagingChatUserProfileDisplayInfo) async -> Bool
func createCommunityProfile(for messagingProfile: MessagingChatUserProfileDisplayInfo) async throws
func setCurrentUser(_ userProfile: MessagingChatUserProfileDisplayInfo?)
Expand Down Expand Up @@ -125,6 +126,7 @@ enum MessagingDataType {
case refreshOfUserProfile(_ userProfile: MessagingChatUserProfileDisplayInfo, isInProgress: Bool)
case totalUnreadMessagesCountUpdated(_ havingUnreadMessages: Bool)
case userInfoRefreshed(_ userInfo: MessagingChatUserDisplayInfo)
case profileCreated(_ userProfile: MessagingChatUserProfileDisplayInfo)

var debugDescription: String {
switch self {
Expand All @@ -148,6 +150,8 @@ enum MessagingDataType {
return "TotalUnreadMessagesCountUpdated to havingUnreadMessages: \(havingUnreadMessages)"
case .userInfoRefreshed(let user):
return "User Info Refreshed to \(user)"
case .profileCreated(let profile):
return "Profile \(profile.id) has been created"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ extension MockMessagingService: MessagingServiceProtocol {

func getUserMessagingProfile(for wallet: WalletEntity) async throws -> MessagingChatUserProfileDisplayInfo { throw NSError() }
func createUserMessagingProfile(for wallet: WalletEntity) async throws -> MessagingChatUserProfileDisplayInfo { throw NSError() }
func isCreatingProfileInProgressFor(wallet: WalletEntity) async -> Bool { false }
func isCommunitiesEnabled(for messagingProfile: MessagingChatUserProfileDisplayInfo) async -> Bool { true }
func createCommunityProfile(for messagingProfile: MessagingChatUserProfileDisplayInfo) async throws { throw NSError() }
func setCurrentUser(_ userProfile: MessagingChatUserProfileDisplayInfo?) { }
Expand Down