Skip to content

Commit

Permalink
fix: fix login performance (#2450)
Browse files Browse the repository at this point in the history
* update stores only once on loadNFTs

* persist client across a session

---------

Co-authored-by: Nicole O'Brien <[email protected]>
  • Loading branch information
MarkNerdi and nicole-obrien authored May 7, 2024
1 parent ae3f659 commit d6bfdd3
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 48 deletions.
59 changes: 36 additions & 23 deletions packages/shared/src/lib/core/nfts/actions/addNftsToDownloadQueue.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { get } from 'svelte/store'
import { Nft } from '../interfaces'
import { addNftToDownloadQueue, nftDownloadQueue, updateNftForAllAccounts, updatePersistedNft } from '../stores'
import { nftDownloadQueue, updateNftsForAllAccounts, updatePersistedNfts } from '../stores'
import { checkIfNftShouldBeDownloaded } from '../utils/checkIfNftShouldBeDownloaded'
import { NftDownloadOptions } from '../types'

Expand All @@ -10,37 +10,50 @@ export async function addNftsToDownloadQueue(nfts: Nft[], options?: Partial<NftD
}

const fullOptions: NftDownloadOptions = { skipDownloadSettingsCheck: false, skipSizeCheck: false, ...options }
const nftsToAdd: Nft[] = []
const checkedNfts = await validateNftAndCheckIfShouldBeDownloaded(nfts, fullOptions)

updatePersistedNfts(checkedNfts.map(({ nft }) => ({ id: nft.id, downloadMetadata: nft.downloadMetadata })))
updateNftsForAllAccounts(
checkedNfts.map(({ nft }) => ({ id: nft.id, downloadMetadata: nft.downloadMetadata, isLoaded: nft.isLoaded }))
)

addNftsToDownloadQueueIfShouldBeDownloaded(checkedNfts, fullOptions)
}

async function validateNftAndCheckIfShouldBeDownloaded(
nfts: Nft[],
options: NftDownloadOptions
): Promise<{ nft: Nft; shouldDownload: boolean }[]> {
const checkedNfts: { nft: Nft; shouldDownload: boolean }[] = []
for (const nft of nfts) {
const isNftInDownloadQueue = get(nftDownloadQueue).some((queueItem) => queueItem.nft.id === nft.id)
if (isNftInDownloadQueue || nft.isLoaded) {
continue
}
try {
const { shouldDownload, downloadMetadata, isLoaded } = await checkIfNftShouldBeDownloaded(
nft,
options.skipDownloadSettingsCheck
)

const nftToAdd = await validateNft(nft, fullOptions.skipDownloadSettingsCheck)
if (nftToAdd) {
nftsToAdd.push(nftToAdd)
checkedNfts.push({ nft: { ...nft, downloadMetadata, isLoaded }, shouldDownload })
} catch (error) {
console.error(error)
}
}

for (const nft of nftsToAdd) {
addNftToDownloadQueue(nft, fullOptions)
}
return checkedNfts
}

async function validateNft(nft: Nft, skipDownloadSettingsCheck: boolean): Promise<Nft | undefined> {
try {
const { shouldDownload, downloadMetadata, isLoaded } = await checkIfNftShouldBeDownloaded(
nft,
skipDownloadSettingsCheck
)
updatePersistedNft(nft.id, { downloadMetadata })
updateNftForAllAccounts({ id: nft.id, downloadMetadata, isLoaded })

if (shouldDownload) {
return nft
function addNftsToDownloadQueueIfShouldBeDownloaded(
nftsToAdd: { nft: Nft; shouldDownload: boolean }[],
options: NftDownloadOptions
): void {
nftDownloadQueue.update((state) => {
for (const nft of nftsToAdd) {
if (!nft.shouldDownload) {
state.push({ nft: nft.nft, options })
}
}
} catch (error) {
console.error(error)
}
return state
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,12 @@ export function updateNftForAccount(accountIndex: number, partialNft: PartialWit
}

export function updateNftForAllAccounts(partialNft: PartialWithId<Nft>): void {
updateNftsForAllAccounts([partialNft])
}

export function updateNftsForAllAccounts(partialNfts: PartialWithId<Nft>[]): void {
for (const accountIndex of Object.keys(get(activeProfileNftsPerAccount)) as unknown as number[]) {
updateNftForAccount(accountIndex, partialNft)
updateNftsForAccount(accountIndex, partialNfts)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,6 @@ import { NftDownloadOptions } from '../types'

export const nftDownloadQueue = writable<{ nft: Nft; options: NftDownloadOptions }[]>([])

export function addNftToDownloadQueue(nft: Nft, options: NftDownloadOptions): void {
const isNftInDownloadQueue = get(nftDownloadQueue).some((nftInQueue) => nftInQueue.nft.id === nft.id)
if (isNftInDownloadQueue) {
return
}

nftDownloadQueue.update((state) => {
return [...state, { nft, options }]
})
}

export function removeNftFromDownloadQueue(nftId: string): void {
const isNftInDownloadQueue = get(nftDownloadQueue).some((nftInQueue) => nftInQueue.nft.id === nftId)
if (!isNftInDownloadQueue) {
Expand Down
19 changes: 13 additions & 6 deletions packages/shared/src/lib/core/nfts/stores/persisted-nfts.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { persistent } from '@core/utils/store'

import { IPersistedNfts } from '../interfaces'
import { PersistedNft } from '../types'
import { PartialWithId } from '@core/utils/types'

export const persistedNfts = persistent<IPersistedNfts>('persistedNfts', {})

Expand All @@ -24,21 +25,27 @@ export function addPersistedNft(nftId: string, newPersistedNft: PersistedNft): v
})
}

export function updatePersistedNft(nftId: string, payload: Partial<PersistedNft>): void {
export function updatePersistedNfts(nftsToUpdate: PartialWithId<PersistedNft>[]): void {
const profileId = getActiveProfileId()
persistedNfts.update((state) => {
if (!state[profileId]) {
state[profileId] = {}
}
const nftState = state[profileId][nftId]
state[profileId][nftId] = {
...nftState,
...payload,
} as PersistedNft
for (const partialNft of nftsToUpdate) {
const nftState = state[profileId][partialNft.id]
state[profileId][partialNft.id] = {
...nftState,
...partialNft,
} as PersistedNft
}
return state
})
}

export function updatePersistedNft(nftId: string, payload: Partial<PersistedNft>): void {
updatePersistedNfts([{ id: nftId, ...payload }])
}

export function removePersistedNftsForProfile(profileId: string): void {
persistedNfts.update((state) => {
delete state[profileId]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Nft } from '../interfaces'
import { Collections } from '../types'
import { getCollectionFromNft } from '../utils'
import { ownedNfts, selectedAccountNfts } from './selected-account-nfts.store'
import { isFeatureEnabled } from '@lib/features/utils'

export const collectionsStore: Writable<Collections> = writable({})

Expand Down Expand Up @@ -50,7 +51,9 @@ async function updateCollections(nfts: Nft[]): Promise<void> {
}

selectedAccountNfts.subscribe((nfts) => {
void updateCollections(nfts.filter((nft) => nft.isSpendable))
if (isFeatureEnabled('collectibles.collections')) {
void updateCollections(nfts.filter((nft) => nft.isSpendable))
}
})

export const selectedAccountCollections: Readable<Collections> = derived(
Expand Down
23 changes: 17 additions & 6 deletions packages/shared/src/lib/core/profile-manager/api/getClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,22 @@ import { api } from './api'
import { get } from 'svelte/store'
import { profileManager } from '../stores'

export function getClient(): Promise<Client> {
const manager = get(profileManager)
if (!manager) {
return Promise.reject('No profile manager')
let client: Client | undefined

export async function getClient(): Promise<Client> {
if (!client) {
const manager = get(profileManager)
if (!manager) {
return Promise.reject('No profile manager')
}
client = await api.getClient(manager.id)
}
return client
}

export async function resetClient(): Promise<void> {
if (client) {
await client.destroy()
}
const { id } = manager
return api.getClient(id)
client = undefined
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { clearLayer2Balance } from '@core/layer-2/stores'
import { clearActiveProfileNftsPerAccount } from '@core/nfts/stores'
import { clearAccountActivities } from '@core/activity/stores'
import { destroyNetworks } from '@core/network/stores'
import { resetClient } from '@core/profile-manager/api'

/**
* Logout from active profile
Expand Down Expand Up @@ -81,6 +82,7 @@ function cleanupProfileState(clearActiveProfile: boolean): void {

async function destroyWalletRsObjects(manager?: IProfileManager): Promise<void> {
isDestroyingManager.set(true)
await resetClient()
await manager?.stopBackgroundSync()
await unsubscribeFromWalletApiEvents()
await destroyProfileManager()
Expand Down

0 comments on commit d6bfdd3

Please sign in to comment.