Skip to content

Commit e37fd56

Browse files
committed
move search history to a separate storage item
1 parent 74941d4 commit e37fd56

File tree

6 files changed

+117
-48
lines changed

6 files changed

+117
-48
lines changed

src/background/Wallet/Wallet.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ import type { Credentials, SessionCredentials } from '../account/Credentials';
121121
import { isSessionCredentials } from '../account/Credentials';
122122
import { lastUsedAddressStore } from '../user-activity';
123123
import { transactionService } from '../transactions/TransactionService';
124+
import { searchStore } from '../search/SearchStore';
124125
import { toEthersWallet } from './helpers/toEthersWallet';
125126
import { maskWallet, maskWalletGroup, maskWalletGroups } from './helpers/mask';
126127
import type { PendingWallet, WalletRecord } from './model/types';
@@ -855,6 +856,33 @@ export class Wallet {
855856
return Model.getPreferences(this.record);
856857
}
857858

859+
async getSearchHistory({ context }: WalletMethodParams): Promise<string[]> {
860+
this.verifyInternalOrigin(context);
861+
await searchStore.ready();
862+
return searchStore.getSearchHistory();
863+
}
864+
865+
async addRecentSearch({
866+
context,
867+
params: { fungibleId },
868+
}: WalletMethodParams<{ fungibleId: string }>) {
869+
this.verifyInternalOrigin(context);
870+
searchStore.addRecentSearch(fungibleId);
871+
}
872+
873+
async clearSearchHistory({ context }: WalletMethodParams) {
874+
this.verifyInternalOrigin(context);
875+
searchStore.clearSearchHistory();
876+
}
877+
878+
async removeRecentSearch({
879+
context,
880+
params: { fungibleId },
881+
}: WalletMethodParams<{ fungibleId: string }>) {
882+
this.verifyInternalOrigin(context);
883+
searchStore.removeRecentSearch(fungibleId);
884+
}
885+
858886
/** bound to instance */
859887
private async notifyChainConfigStore() {
860888
const preferences = await this.getPreferences({

src/background/Wallet/WalletRecord.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,6 @@ export class WalletRecordModel {
848848
configurableNonce: false,
849849
invitationBannerDismissed: false,
850850
recentAddresses: [],
851-
recentSearch: [],
852851
mintDnaBannerDismissed: false,
853852
upgradeDnaBannerDismissed: false,
854853
inviteFriendsBannerDismissed: false,

src/background/Wallet/model/types.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ interface PublicPreferences {
4545
configurableNonce?: boolean;
4646
invitationBannerDismissed?: boolean;
4747
recentAddresses?: string[];
48-
recentSearch?: string[];
4948
mintDnaBannerDismissed?: boolean;
5049
upgradeDnaBannerDismissed?: boolean;
5150
inviteFriendsBannerDismissed?: boolean;
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { PersistentStore } from 'src/modules/persistent-store';
2+
3+
type SearchStoreState = {
4+
version: 1;
5+
searchHistory: string[];
6+
};
7+
8+
const MAX_RECENT_SEARCH_SIZE = 10;
9+
10+
function updateSearchHistory(
11+
fungibleId: string,
12+
recentSearch: string[]
13+
): string[] {
14+
const searchIndex = recentSearch.findIndex((item) => item === fungibleId);
15+
if (searchIndex >= 0) {
16+
return [
17+
fungibleId,
18+
...recentSearch.slice(0, searchIndex),
19+
...recentSearch.slice(searchIndex + 1, MAX_RECENT_SEARCH_SIZE),
20+
];
21+
}
22+
return [fungibleId, ...recentSearch.slice(0, MAX_RECENT_SEARCH_SIZE - 1)];
23+
}
24+
25+
class SearchStore extends PersistentStore<SearchStoreState> {
26+
static initialState: SearchStoreState = {
27+
version: 1,
28+
searchHistory: [],
29+
};
30+
31+
addRecentSearch(fungibleId: string) {
32+
this.setState((state) => ({
33+
...state,
34+
searchHistory: updateSearchHistory(fungibleId, state.searchHistory),
35+
}));
36+
}
37+
38+
removeRecentSearch(fungibleId: string) {
39+
this.setState((state) => ({
40+
...state,
41+
searchHistory: state.searchHistory.filter((id) => id !== fungibleId),
42+
}));
43+
}
44+
45+
clearSearchHistory() {
46+
this.setState((state) => ({
47+
...state,
48+
searchHistory: [],
49+
}));
50+
}
51+
52+
getSearchHistory() {
53+
return this.getState().searchHistory;
54+
}
55+
}
56+
57+
export const searchStore = new SearchStore(
58+
SearchStore.initialState,
59+
'search-store'
60+
);

src/ui/pages/Search/Search.tsx

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@ import { Media } from 'src/ui/ui-kit/Media';
2323
import VerifiedIcon from 'jsx:src/ui/assets/verified.svg';
2424
import { HStack } from 'src/ui/ui-kit/HStack/HStack';
2525
import { walletPort } from 'src/ui/shared/channels';
26-
import { usePreferences } from 'src/ui/features/preferences';
2726
import { UnstyledButton } from 'src/ui/ui-kit/UnstyledButton';
2827
import CloseIcon from 'jsx:src/ui/assets/close.svg';
2928
import { useAssetFullInfo } from 'src/modules/zerion-api/hooks/useAssetFullInfo';
3029
import { useHttpClientSource } from 'src/modules/zerion-api/hooks/useHttpClientSource';
3130
import { invariant } from 'src/shared/invariant';
3231
import { Button } from 'src/ui/ui-kit/Button';
3332
import { useEvent } from 'src/ui/shared/useEvent';
34-
import { updateRecentSearch } from './updateRecentSearch';
33+
import { useMutation, useQuery } from '@tanstack/react-query';
34+
import { queryClient } from 'src/ui/shared/requests/queryClient';
3535
import { useSearchQuery } from './useSearchQuery';
3636

3737
const FungibleView = React.forwardRef<
@@ -125,7 +125,6 @@ const RecentItem = React.forwardRef<
125125
}
126126
>(({ fungibleId, index, highlighted, onClick }, ref) => {
127127
const { currency } = useCurrency();
128-
const { preferences, setPreferences } = usePreferences();
129128

130129
const { data, isLoading } = useAssetFullInfo(
131130
{ fungibleId, currency },
@@ -134,15 +133,12 @@ const RecentItem = React.forwardRef<
134133

135134
const fungible = data?.data.fungible;
136135

137-
const handleRemoveItemClick = useCallback(() => {
138-
if (preferences) {
139-
setPreferences({
140-
recentSearch: preferences.recentSearch.filter(
141-
(id) => id !== fungibleId
142-
),
143-
});
144-
}
145-
}, [fungibleId, preferences, setPreferences]);
136+
const removeRecentSearchMutation = useMutation({
137+
mutationFn: () => walletPort.request('removeRecentSearch', { fungibleId }),
138+
onSuccess: () => {
139+
queryClient.refetchQueries(['wallet/getSearchHistory']);
140+
},
141+
});
146142

147143
if (!isLoading && !fungible) {
148144
return null;
@@ -173,7 +169,8 @@ const RecentItem = React.forwardRef<
173169
style={{ display: 'flex' }}
174170
size={28}
175171
aria-label="Remove item from recent"
176-
onClick={handleRemoveItemClick}
172+
onClick={() => removeRecentSearchMutation.mutate()}
173+
disabled={removeRecentSearchMutation.isLoading}
177174
>
178175
<CloseIcon
179176
style={{ width: 20, height: 20, color: 'var(--neutral-500)' }}
@@ -202,21 +199,26 @@ export function Search() {
202199
500
203200
);
204201
const normalizedQuery = urlQuery.trim();
202+
const { data: searchHistory } = useQuery({
203+
queryKey: ['wallet/getSearchHistory'],
204+
queryFn: () => walletPort.request('getSearchHistory'),
205+
suspense: false,
206+
keepPreviousData: true,
207+
});
205208

206-
const { preferences, setPreferences } = usePreferences();
207209
const { data: searchResults, isLoading } = useSearchQuery({
208210
query: normalizedQuery,
209211
currency,
210212
});
211213

212214
const recentItems = useMemo<SearchPageItem[]>(() => {
213215
return (
214-
preferences?.recentSearch.map((id) => ({
216+
searchHistory?.map((id) => ({
215217
kind: 'recent',
216218
fungibleId: id,
217219
})) || []
218220
);
219-
}, [preferences]);
221+
}, [searchHistory]);
220222

221223
const searchItems = useMemo<SearchPageItem[]>(() => {
222224
return (
@@ -238,21 +240,14 @@ export function Search() {
238240
*/
239241
const handleFungibleClick = useCallback(
240242
(fungibleId: string) => {
241-
if (preferences) {
242-
setPreferences({
243-
recentSearch: updateRecentSearch(
244-
fungibleId,
245-
preferences.recentSearch
246-
),
247-
});
248-
}
243+
walletPort.request('addRecentSearch', { fungibleId });
249244
walletPort.request('assetClicked', {
250245
assetId: fungibleId,
251246
pathname,
252247
section: 'Search',
253248
});
254249
},
255-
[pathname, preferences, setPreferences]
250+
[pathname]
256251
);
257252

258253
const { getItemProps, getInputProps, getMenuProps, highlightedIndex } =
@@ -331,9 +326,12 @@ export function Search() {
331326
});
332327
}, [items, getItemProps, highlightedIndex, handleFungibleClick]);
333328

334-
const handleClearRecentClick = useCallback(() => {
335-
setPreferences({ recentSearch: [] });
336-
}, [setPreferences]);
329+
const clearSearchHistoryMutation = useMutation({
330+
mutationFn: () => walletPort.request('clearSearchHistory'),
331+
onSuccess: () => {
332+
queryClient.refetchQueries(['wallet/getSearchHistory']);
333+
},
334+
});
337335

338336
return (
339337
<>
@@ -362,7 +360,7 @@ export function Search() {
362360
<UIText kind="body/accent" style={{ paddingInline: 8 }}>
363361
Results
364362
</UIText>
365-
) : preferences?.recentSearch.length ? (
363+
) : searchHistory?.length ? (
366364
<HStack gap={4} justifyContent="space-between" alignItems="center">
367365
<UIText kind="body/accent" style={{ paddingInline: 8 }}>
368366
Recent
@@ -371,7 +369,8 @@ export function Search() {
371369
<UnstyledButton
372370
className="hover:underline"
373371
aria-label="Clear recent search"
374-
onClick={handleClearRecentClick}
372+
onClick={() => clearSearchHistoryMutation.mutate()}
373+
disabled={clearSearchHistoryMutation.isLoading}
375374
>
376375
Clear
377376
</UnstyledButton>

src/ui/pages/Search/updateRecentSearch.ts

Lines changed: 0 additions & 16 deletions
This file was deleted.

0 commit comments

Comments
 (0)