diff --git a/app.json b/app.json index 98b5e42c9..f37b1ed25 100644 --- a/app.json +++ b/app.json @@ -3,10 +3,10 @@ "newArchEnabled": false, "version": "2.1.0", "ios": { - "buildNumber": "69" + "buildNumber": "70" }, "android": { - "versionCode": 270 + "versionCode": 271 } } } diff --git a/components/AccountSettingsButton.tsx b/components/AccountSettingsButton.tsx index 7c1577825..4210ec60f 100644 --- a/components/AccountSettingsButton.tsx +++ b/components/AccountSettingsButton.tsx @@ -60,7 +60,7 @@ export default function AccountSettingsButton({ account }: Props) { const methods = { [translate("your_profile_page")]: async () => { if (account) { - invalidateProfileSocialsQuery(account, account); + invalidateProfileSocialsQuery(account); setCurrentAccount(account, false); router.navigate("Chats"); navigate("Profile", { diff --git a/components/StateHandlers/HydrationStateHandler.tsx b/components/StateHandlers/HydrationStateHandler.tsx index bc3728d0a..77328640d 100644 --- a/components/StateHandlers/HydrationStateHandler.tsx +++ b/components/StateHandlers/HydrationStateHandler.tsx @@ -13,8 +13,12 @@ export default function HydrationStateHandler() { const startTime = new Date().getTime(); const accounts = getAccountsList(); if (accounts.length === 0) { - // Awaiting before showing onboarding - await getInstalledWallets(false); + try { + // Awaiting before showing onboarding + await getInstalledWallets(false); + } catch (e) { + logger.error("[Hydration] Error getting installed wallets", e); + } } else { // note(lustig) I don't think this does anything? getInstalledWallets(false); @@ -26,26 +30,27 @@ export default function HydrationStateHandler() { logger.debug( "[Hydration] Fetching persisted conversation list for all accounts" ); - await Promise.allSettled( - accounts.map(async (account) => { - const accountStartTime = new Date().getTime(); - logger.debug( - `[Hydration] Fetching persisted conversation list for ${account}` - ); - - prefetchInboxIdQuery({ account }); - prefetchConversationsQuery({ account }); - - const accountEndTime = new Date().getTime(); - logger.debug( - `[Hydration] Done fetching persisted conversation list for ${account} in ${ - (accountEndTime - accountStartTime) / 1000 - } seconds` - ); - }) - ); - logger.debug("[Hydration] Done fetching persisted conversation list"); + accounts.map((account) => { + const accountStartTime = new Date().getTime(); + logger.debug( + `[Hydration] Fetching persisted conversation list for ${account}` + ); + + prefetchInboxIdQuery({ account }); + prefetchConversationsQuery({ account }); + + const accountEndTime = new Date().getTime(); + logger.debug( + `[Hydration] Done fetching persisted conversation list for ${account} in ${ + (accountEndTime - accountStartTime) / 1000 + } seconds` + ); + }); + + logger.debug( + "[Hydration] Done prefetching all accounts conversation lists" + ); useAppStore.getState().setHydrationDone(true); logger.debug( diff --git a/components/StateHandlers/MainIdentityStateHandler.tsx b/components/StateHandlers/MainIdentityStateHandler.tsx index d2b14a8a5..4cd52532e 100644 --- a/components/StateHandlers/MainIdentityStateHandler.tsx +++ b/components/StateHandlers/MainIdentityStateHandler.tsx @@ -15,7 +15,7 @@ export default function MainIdentityStateHandler() { useEffect(() => { if (userAddress) { saveUser(userAddress, privyAccountId[userAddress] as string); - invalidateProfileSocialsQuery(userAddress, userAddress); + invalidateProfileSocialsQuery(userAddress); } }, [privyAccountId, userAddress]); diff --git a/features/groups/invite-to-group/invite-users-to-exisiting-group.screen.tsx b/features/groups/invite-to-group/invite-users-to-exisiting-group.screen.tsx index 92e4fd497..7351ba9fd 100644 --- a/features/groups/invite-to-group/invite-users-to-exisiting-group.screen.tsx +++ b/features/groups/invite-to-group/invite-users-to-exisiting-group.screen.tsx @@ -196,7 +196,7 @@ export function InviteUsersToExistingGroupScreen({ if (!isEmptyObject(profiles)) { // Let's save the profiles for future use - setProfileRecordSocialsQueryData(currentAccount(), profiles); + setProfileRecordSocialsQueryData(profiles); setStatus({ loading: false, error: "", @@ -233,7 +233,7 @@ export function InviteUsersToExistingGroupScreen({ if (!isEmptyObject(profiles)) { // Let's save the profiles for future use - setProfileRecordSocialsQueryData(currentAccount(), profiles); + setProfileRecordSocialsQueryData(profiles); setStatus({ loading: false, error: "", diff --git a/hooks/useProfileSocials.ts b/hooks/useProfileSocials.ts index b0cf560e8..cea6430a8 100644 --- a/hooks/useProfileSocials.ts +++ b/hooks/useProfileSocials.ts @@ -1,7 +1,5 @@ -import { useCurrentAccount } from "@data/store/accountsStore"; import { useProfileSocialsQuery } from "@queries/useProfileSocialsQuery"; export const useProfileSocials = (peerAddress: string) => { - const currentAccount = useCurrentAccount(); - return useProfileSocialsQuery(currentAccount!, peerAddress); + return useProfileSocialsQuery(peerAddress); }; diff --git a/hooks/useProfilesSocials.ts b/hooks/useProfilesSocials.ts index ea41c7b37..1fe98e5ed 100644 --- a/hooks/useProfilesSocials.ts +++ b/hooks/useProfilesSocials.ts @@ -7,6 +7,5 @@ import { useProfileSocialsQueries } from "@queries/useProfileSocialsQuery"; * @returns */ export const useProfilesSocials = (peerAddresses: string[]) => { - const currentAccount = useCurrentAccount(); - return useProfileSocialsQueries(currentAccount!, peerAddresses); + return useProfileSocialsQueries(peerAddresses); }; diff --git a/ios/ConverseNotificationExtension/MMKV.swift b/ios/ConverseNotificationExtension/MMKV.swift index 7368ede0f..8d7a83d8d 100644 --- a/ios/ConverseNotificationExtension/MMKV.swift +++ b/ios/ConverseNotificationExtension/MMKV.swift @@ -56,9 +56,9 @@ func getAccountsState() -> Accounts? { } } -func getProfilesStore(account: String, address: String) -> ProfileSocials? { +func getProfilesStore(address: String) -> ProfileSocials? { let mmkv = getMmkv() - let key = "profileSocials-\(account.lowercased())-\(address.lowercased())" + let key = "profileSocials-\(address.lowercased())" let profilesString = mmkv?.string(forKey: key) if (profilesString == nil) { return nil @@ -72,9 +72,9 @@ func getProfilesStore(account: String, address: String) -> ProfileSocials? { } } -func getInboxIdProfilesStore(account: String, inboxId: String) -> ProfileSocials? { +func getInboxIdProfilesStore(inboxId: String) -> ProfileSocials? { let mmkv = getMmkv() - let key = "inboxProfileSocials-\(account.lowercased())-\(inboxId.lowercased())" + let key = "inboxProfileSocials-\(inboxId.lowercased())" let profilesString = mmkv?.string(forKey: key) if (profilesString == nil) { return nil @@ -88,21 +88,21 @@ func getInboxIdProfilesStore(account: String, inboxId: String) -> ProfileSocials } } -func saveProfileSocials(account: String, address: String, socials: ProfileSocials) { +func saveProfileSocials(address: String, socials: ProfileSocials) { let updatedAt = Int(Date().timeIntervalSince1970) let newProfile = Profile(updatedAt: updatedAt, socials: socials) let mmkv = getMmkv() if let jsonData = try? JSONEncoder().encode(newProfile), let jsonString = String(data: jsonData, encoding: .utf8) { - mmkv?.set(jsonString, forKey: "profileSocials-\(account.lowercased())-\(address.lowercased())") + mmkv?.set(jsonString, forKey: "profileSocials-\(address.lowercased())") } } -func saveInboxIdProfileSocials(account: String, inboxId: String, socials: ProfileSocials) { +func saveInboxIdProfileSocials(inboxId: String, socials: ProfileSocials) { let updatedAt = Int(Date().timeIntervalSince1970) let newProfile = Profile(updatedAt: updatedAt, socials: socials) let mmkv = getMmkv() if let jsonData = try? JSONEncoder().encode(newProfile), let jsonString = String(data: jsonData, encoding: .utf8) { - mmkv?.set(jsonString, forKey: "inboxProfileSocials-\(account.lowercased())-\(inboxId.lowercased())") + mmkv?.set(jsonString, forKey: "inboxProfileSocials-\(inboxId.lowercased())") } } diff --git a/ios/ConverseNotificationExtension/Profile.swift b/ios/ConverseNotificationExtension/Profile.swift index 78e95916c..d383e660f 100644 --- a/ios/ConverseNotificationExtension/Profile.swift +++ b/ios/ConverseNotificationExtension/Profile.swift @@ -8,40 +8,40 @@ import Foundation import Alamofire -func getProfile(account: String, address: String) async -> ProfileSocials? { - var profileFromStore = getProfilesStore(account: account, address: address) +func getProfile(address: String) async -> ProfileSocials? { + var profileFromStore = getProfilesStore(address: address) let formattedAddress = address.lowercased() if let profile = profileFromStore { return profile } // If profile is nil, let's refresh it - try? await refreshProfileFromBackend(account: account, address: formattedAddress) + try? await refreshProfileFromBackend(address: formattedAddress) - profileFromStore = getProfilesStore(account: account, address: address) + profileFromStore = getProfilesStore(address: address) if let profile = profileFromStore { return profile } return nil } -func getInboxIdProfile(account: String, inboxId: String) async -> ProfileSocials? { - var profileFromStore = getInboxIdProfilesStore(account: account, inboxId: inboxId) +func getInboxIdProfile(inboxId: String) async -> ProfileSocials? { + var profileFromStore = getInboxIdProfilesStore(inboxId: inboxId) if let profile = profileFromStore { return profile } // If profile is nil, let's refresh it - try? await refreshInboxProfileFromBackend(account: account, inboxId: inboxId) + try? await refreshInboxProfileFromBackend(inboxId: inboxId) - profileFromStore = getInboxIdProfilesStore(account: account, inboxId: inboxId) + profileFromStore = getInboxIdProfilesStore(inboxId: inboxId) if let profile = profileFromStore { return profile } return nil } -func refreshProfileFromBackend(account: String, address: String) async throws { +func refreshProfileFromBackend(address: String) async throws { let apiURI = getApiURI() if (apiURI != nil && !apiURI!.isEmpty) { let profileURI = "\(apiURI ?? "")/api/profile" @@ -63,7 +63,7 @@ func refreshProfileFromBackend(account: String, address: String) async throws { let decoder = JSONDecoder() if let socials = try? decoder.decode(ProfileSocials.self, from: response) { - saveProfileSocials(account: account, address: address, socials: socials) + saveProfileSocials(address: address, socials: socials) } @@ -71,7 +71,7 @@ func refreshProfileFromBackend(account: String, address: String) async throws { } -func refreshInboxProfileFromBackend(account: String, inboxId: String) async throws { +func refreshInboxProfileFromBackend(inboxId: String) async throws { let apiURI = getApiURI() if (apiURI != nil && !apiURI!.isEmpty) { let profileURI = "\(apiURI ?? "")/api/inbox" @@ -93,7 +93,7 @@ func refreshInboxProfileFromBackend(account: String, inboxId: String) async thro let decoder = JSONDecoder() if let socials = try? decoder.decode(ProfileSocials.self, from: response) { - saveInboxIdProfileSocials(account: account, inboxId: inboxId, socials: socials) + saveInboxIdProfileSocials(inboxId: inboxId, socials: socials) } } diff --git a/ios/ConverseNotificationExtension/Xmtp/Messages.swift b/ios/ConverseNotificationExtension/Xmtp/Messages.swift index 0064b22d0..89e0505a8 100644 --- a/ios/ConverseNotificationExtension/Xmtp/Messages.swift +++ b/ios/ConverseNotificationExtension/Xmtp/Messages.swift @@ -78,7 +78,7 @@ func handleV3Message(xmtpClient: XMTP.Client, envelope: XMTP.Xmtp_MessageApi_V1_ } // We replaced decodedMessage.senderAddress from inboxId to actual address // so it appears well in the app until inboxId is a first class citizen - if let senderProfileSocials = await getInboxIdProfile(account: xmtpClient.address, inboxId: decodedMessage.senderInboxId) { + if let senderProfileSocials = await getInboxIdProfile(inboxId: decodedMessage.senderInboxId) { bestAttemptContent.subtitle = getPreferredName(address: decodedMessage.senderInboxId, socials: senderProfileSocials) } @@ -89,7 +89,7 @@ func handleV3Message(xmtpClient: XMTP.Client, envelope: XMTP.Xmtp_MessageApi_V1_ messageIntent = getIncomingGroupMessageIntent(group: group, content: bestAttemptContent.body, senderId: decodedMessage.senderInboxId, senderName: bestAttemptContent.subtitle) } else if case .dm(let dm) = conversation { var senderAvatar: String? = nil - if let senderProfileSocials = await getInboxIdProfile(account: xmtpClient.address, inboxId: decodedMessage.senderInboxId) { + if let senderProfileSocials = await getInboxIdProfile(inboxId: decodedMessage.senderInboxId) { let name = getPreferredName(address: decodedMessage.senderInboxId, socials: senderProfileSocials) bestAttemptContent.title = getPreferredName(address: decodedMessage.senderInboxId, socials: senderProfileSocials) senderAvatar = getPreferredAvatar(socials: senderProfileSocials) diff --git a/queries/useProfileSocialsQuery.ts b/queries/useProfileSocialsQuery.ts index fe03575e5..9ab50ee0f 100644 --- a/queries/useProfileSocialsQuery.ts +++ b/queries/useProfileSocialsQuery.ts @@ -12,20 +12,14 @@ import mmkv from "@/utils/mmkv"; type ProfileSocialsData = IProfileSocials | null | undefined; -const profileSocialsQueryKey = ( - account: string, - peerAddress: string -): QueryKey => [ +const profileSocialsQueryKey = (peerAddress: string): QueryKey => [ "profileSocials", - account?.toLowerCase(), // Typesafe because there's a lot of account! usage peerAddress?.toLowerCase(), ]; -export const profileSocialsQueryStorageKey = ( - account: string, - peerAddress: string -) => profileSocialsQueryKey(account, peerAddress).join("-"); +export const profileSocialsQueryStorageKey = (peerAddress: string) => + profileSocialsQueryKey(peerAddress).join("-"); const profileSocials = create({ fetcher: async (addresses: string[]) => { @@ -39,10 +33,10 @@ const profileSocials = create({ }), }); -const fetchProfileSocials = async (account: string, peerAddress: string) => { +const fetchProfileSocials = async (peerAddress: string) => { const data = await profileSocials.fetch(peerAddress); - const key = profileSocialsQueryStorageKey(account, peerAddress); + const key = profileSocialsQueryStorageKey(peerAddress); mmkv.delete(key); @@ -53,10 +47,9 @@ const fetchProfileSocials = async (account: string, peerAddress: string) => { return data; }; -const profileSocialsQueryConfig = (account: string, peerAddress: string) => ({ - queryKey: profileSocialsQueryKey(account, peerAddress), - queryFn: () => fetchProfileSocials(account, peerAddress), - enabled: !!account, +const profileSocialsQueryConfig = (peerAddress: string) => ({ + queryKey: profileSocialsQueryKey(peerAddress), + queryFn: () => fetchProfileSocials(peerAddress), // Store for 30 days gcTime: 1000 * 60 * 60 * 24 * 30, refetchIntervalInBackground: false, @@ -66,9 +59,9 @@ const profileSocialsQueryConfig = (account: string, peerAddress: string) => ({ refetchOnMount: false, staleTime: 1000 * 60 * 60 * 24, initialData: (): ProfileSocialsData => { - if (mmkv.contains(profileSocialsQueryStorageKey(account, peerAddress))) { + if (mmkv.contains(profileSocialsQueryStorageKey(peerAddress))) { const data = JSON.parse( - mmkv.getString(profileSocialsQueryStorageKey(account, peerAddress))! + mmkv.getString(profileSocialsQueryStorageKey(peerAddress))! ) as ProfileSocialsData; return data; } @@ -77,20 +70,14 @@ const profileSocialsQueryConfig = (account: string, peerAddress: string) => ({ // persister: reactQueryPersister, }); -export const useProfileSocialsQuery = ( - account: string, - peerAddress: string -) => { - return useQuery(profileSocialsQueryConfig(account, peerAddress)); +export const useProfileSocialsQuery = (peerAddress: string) => { + return useQuery(profileSocialsQueryConfig(peerAddress)); }; -export const useProfileSocialsQueries = ( - account: string, - peerAddresses: string[] -) => { +export const useProfileSocialsQueries = (peerAddresses: string[]) => { return useQueries({ queries: peerAddresses.map((peerAddress) => - profileSocialsQueryConfig(account, peerAddress) + profileSocialsQueryConfig(peerAddress) ), }); }; @@ -99,9 +86,7 @@ export const prefetchProfileSocialsQuery = ( account: string, peerAddress: string ) => { - return queryClient.prefetchQuery( - profileSocialsQueryConfig(account, peerAddress) - ); + return queryClient.prefetchQuery(profileSocialsQueryConfig(peerAddress)); }; export const fetchProfileSocialsQuery = ( @@ -109,18 +94,17 @@ export const fetchProfileSocialsQuery = ( peerAddress: string ) => { return queryClient.fetchQuery( - profileSocialsQueryConfig(account, peerAddress) + profileSocialsQueryConfig(peerAddress) ); }; export const setProfileSocialsQueryData = ( - account: string, peerAddress: string, data: IProfileSocials, updatedAt?: number ) => { return queryClient.setQueryData( - profileSocialsQueryKey(account, peerAddress), + profileSocialsQueryKey(peerAddress), data, { updatedAt, @@ -129,11 +113,10 @@ export const setProfileSocialsQueryData = ( }; export const setProfileRecordSocialsQueryData = ( - account: string, record: Record ) => { Object.keys(record).forEach((peerAddress) => { - setProfileSocialsQueryData(account, peerAddress, record[peerAddress]); + setProfileSocialsQueryData(peerAddress, record[peerAddress]); }); }; @@ -142,15 +125,12 @@ export const getProfileSocialsQueryData = ( peerAddress: string ) => { return queryClient.getQueryData( - profileSocialsQueryConfig(account, peerAddress).queryKey + profileSocialsQueryConfig(peerAddress).queryKey ); }; -export const invalidateProfileSocialsQuery = ( - account: string, - address: string -) => { +export const invalidateProfileSocialsQuery = (address: string) => { queryClient.invalidateQueries({ - queryKey: profileSocialsQueryKey(account, address), + queryKey: profileSocialsQueryKey(address), }); }; diff --git a/screens/NewConversation/NewConversation.tsx b/screens/NewConversation/NewConversation.tsx index 810bef228..80b6c9ce8 100644 --- a/screens/NewConversation/NewConversation.tsx +++ b/screens/NewConversation/NewConversation.tsx @@ -274,7 +274,7 @@ export default function NewConversation({ profileCount: Object.keys(profiles).length, }); // Let's save the profiles for future use - setProfileRecordSocialsQueryData(currentAccount(), profiles); + setProfileRecordSocialsQueryData(profiles); // delete pending chat memebers from search results pendingChatMembers.members.forEach((member) => { delete profiles[member.address]; @@ -335,7 +335,7 @@ export default function NewConversation({ profileCount: Object.keys(profiles).length, }); // Let's save the profiles for future use - setProfileRecordSocialsQueryData(currentAccount(), profiles); + setProfileRecordSocialsQueryData(profiles); setStatus({ loading: false, error: "", diff --git a/screens/Onboarding/OnboardingUserProfileScreen.tsx b/screens/Onboarding/OnboardingUserProfileScreen.tsx index dca8fbddc..87d9c2454 100644 --- a/screens/Onboarding/OnboardingUserProfileScreen.tsx +++ b/screens/Onboarding/OnboardingUserProfileScreen.tsx @@ -387,7 +387,7 @@ export function useCreateOrUpdateProfileInfo() { account: address, profile: { ...profile, avatar: publicAvatar }, }); - await invalidateProfileSocialsQuery(address, address); + await invalidateProfileSocialsQuery(address); return { success: true }; } catch (e: any) { logger.error(e, { context: "UserProfile: claiming and refreshing" }); diff --git a/utils/profile/getProfile.ts b/utils/profile/getProfile.ts index dae8823a7..301a6fe22 100644 --- a/utils/profile/getProfile.ts +++ b/utils/profile/getProfile.ts @@ -16,10 +16,7 @@ export const getProfile = async ( address: string | undefined ): Promise => { if (address) { - const addressStorageKey = profileSocialsQueryStorageKey( - currentAccount, - address - ); + const addressStorageKey = profileSocialsQueryStorageKey(address); const mmkvString = mmkv.getString(addressStorageKey); if (mmkvString) { return JSON.parse(mmkvString) as IProfileSocials;