Skip to content

Commit 23965cb

Browse files
author
Sterling Long
committed
Updated explorer to be faster when swapping recents
1 parent 9749e41 commit 23965cb

10 files changed

Lines changed: 179 additions & 109 deletions

File tree

lib/services/explorer/explorer_service.dart

Lines changed: 112 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ class ExplorerService implements IExplorerService {
3333
Set<String>? excludedWalletIds;
3434

3535
List<Listing> _listings = [];
36-
List<GridListItemModel<WalletData>> _walletList = [];
36+
List<GridListItemModel<WalletData>> _walletListUnsorted = [];
37+
List<GridListItemModel<WalletData>> _walletListSorted = [];
3738
@override
3839
ValueNotifier<List<GridListItemModel<WalletData>>> itemList =
3940
ValueNotifier([]);
@@ -45,6 +46,8 @@ class ExplorerService implements IExplorerService {
4546

4647
final String referer;
4748

49+
String? previousRecentWallet;
50+
4851
ExplorerService({
4952
required this.projectId,
5053
required this.referer,
@@ -56,69 +59,68 @@ class ExplorerService implements IExplorerService {
5659
}) : client = client ?? http.Client();
5760

5861
@override
59-
Future<void> init({bool refetch = false}) async {
60-
if (!initialized.value || refetch) {
61-
String? platform;
62-
switch (platformUtils.instance.getPlatformType()) {
63-
case PlatformType.desktop:
64-
platform = 'Desktop';
65-
break;
66-
case PlatformType.mobile:
67-
if (Platform.isIOS) {
68-
platform = 'iOS';
69-
} else if (Platform.isAndroid) {
70-
platform = 'Android';
71-
} else {
72-
platform = 'Mobile';
73-
}
74-
break;
75-
case PlatformType.web:
76-
platform = 'Injected';
77-
break;
78-
default:
79-
platform = null;
80-
}
81-
82-
LoggerUtil.logger.i('Fetching wallet listings. Platform: $platform');
83-
_listings = await fetchListings(
84-
endpoint: '/w3m/v1/get${platform}Listings',
85-
referer: referer,
86-
// params: params,
87-
);
62+
Future<void> init() async {
63+
if (initialized.value) {
64+
return;
65+
}
8866

89-
if (excludedWalletState == ExcludedWalletState.list) {
90-
// If we are excluding all wallets, take out the excluded listings, if they exist
91-
if (excludedWalletIds != null) {
92-
_listings = filterExcludedListings(
93-
listings: _listings,
94-
);
67+
String? platform;
68+
switch (platformUtils.instance.getPlatformType()) {
69+
case PlatformType.desktop:
70+
platform = 'Desktop';
71+
break;
72+
case PlatformType.mobile:
73+
if (Platform.isIOS) {
74+
platform = 'iOS';
75+
} else if (Platform.isAndroid) {
76+
platform = 'Android';
77+
} else {
78+
platform = 'Mobile';
9579
}
96-
} else if (excludedWalletState == ExcludedWalletState.all &&
97-
recommendedWalletIds != null) {
98-
// Filter down to only the included
99-
_listings = _listings
100-
.where(
101-
(listing) => recommendedWalletIds!.contains(
102-
listing.id,
103-
),
104-
)
105-
.toList();
106-
} else {
107-
// If we are excluding all wallets and have no recommended wallets,
108-
// return an empty list
109-
_walletList = [];
110-
itemList.value = [];
111-
return;
112-
}
80+
break;
81+
case PlatformType.web:
82+
platform = 'Injected';
83+
break;
84+
default:
85+
platform = null;
11386
}
11487

115-
_walletList.clear();
88+
LoggerUtil.logger.i('Fetching wallet listings. Platform: $platform');
89+
_listings = await fetchListings(
90+
endpoint: '/w3m/v1/get${platform}Listings',
91+
referer: referer,
92+
// params: params,
93+
);
11694

117-
final List<GridListItemModel<WalletData>> newList = [];
95+
if (excludedWalletState == ExcludedWalletState.list) {
96+
// If we are excluding all wallets, take out the excluded listings, if they exist
97+
if (excludedWalletIds != null) {
98+
_listings = filterExcludedListings(
99+
listings: _listings,
100+
);
101+
}
102+
} else if (excludedWalletState == ExcludedWalletState.all &&
103+
recommendedWalletIds != null) {
104+
// Filter down to only the included
105+
_listings = _listings
106+
.where(
107+
(listing) => recommendedWalletIds!.contains(
108+
listing.id,
109+
),
110+
)
111+
.toList();
112+
} else {
113+
// If we are excluding all wallets and have no recommended wallets,
114+
// return an empty list
115+
_walletListUnsorted = [];
116+
itemList.value = [];
117+
return;
118+
}
118119

119120
// Get the recent wallet
120121
final String? recentWallet =
121122
storageService.instance.getString(StringConstants.recentWallet);
123+
previousRecentWallet = recentWallet;
122124

123125
for (Listing item in _listings) {
124126
String? uri = item.mobile.native;
@@ -131,7 +133,7 @@ class ExplorerService implements IExplorerService {
131133
if (installed) {
132134
LoggerUtil.logger.v('Wallet ${item.name} installed: $installed');
133135
}
134-
newList.add(
136+
_walletListUnsorted.add(
135137
GridListItemModel<WalletData>(
136138
title: item.name,
137139
id: item.id,
@@ -152,37 +154,8 @@ class ExplorerService implements IExplorerService {
152154
);
153155
}
154156

155-
// Sort the installed wallets to the top
156-
int insertAt = 0;
157-
if (recommendedWalletIds != null) {
158-
for (int i = 0; i < newList.length; i++) {
159-
if (newList[i].data.recent == true) {
160-
_walletList.insert(0, newList[i]);
161-
insertAt++;
162-
} else if (newList[i].data.installed) {
163-
_walletList.insert(insertAt, newList[i]);
164-
insertAt++;
165-
} else if (recommendedWalletIds!.contains(newList[i].id)) {
166-
_walletList.insert(insertAt, newList[i]);
167-
} else {
168-
_walletList.add(newList[i]);
169-
}
170-
}
171-
} else {
172-
for (int i = 0; i < newList.length; i++) {
173-
if (newList[i].data.recent == true) {
174-
_walletList.insert(0, newList[i]);
175-
insertAt++;
176-
} else if (newList[i].data.installed) {
177-
_walletList.insert(insertAt, newList[i]);
178-
insertAt++;
179-
} else {
180-
_walletList.add(newList[i]);
181-
}
182-
}
183-
}
157+
await updateSort();
184158

185-
itemList.value = _walletList;
186159
initialized.value = true;
187160
}
188161

@@ -191,11 +164,11 @@ class ExplorerService implements IExplorerService {
191164
String? query,
192165
}) {
193166
if (query == null || query.isEmpty) {
194-
itemList.value = _walletList;
167+
itemList.value = _walletListSorted;
195168
return;
196169
}
197170

198-
final List<GridListItemModel<WalletData>> filtered = _walletList
171+
final List<GridListItemModel<WalletData>> filtered = _walletListSorted
199172
.where(
200173
(wallet) => wallet.title.toLowerCase().contains(
201174
query.toLowerCase(),
@@ -205,6 +178,57 @@ class ExplorerService implements IExplorerService {
205178
itemList.value = filtered;
206179
}
207180

181+
@override
182+
Future<void> updateSort() async {
183+
final List<GridListItemModel<WalletData>> newList = [];
184+
185+
final String? recentWallet =
186+
storageService.instance.getString(StringConstants.recentWallet);
187+
188+
// Sort the installed wallets to the top
189+
int insertAt = 0;
190+
for (int i = 0; i < _walletListUnsorted.length; i++) {
191+
// If the recent wallet doesn't match the id, then set it to not recent
192+
if (_walletListUnsorted[i].data.recent == true &&
193+
recentWallet != previousRecentWallet) {
194+
_walletListUnsorted[i] = _walletListUnsorted[i].copyWith(
195+
description:
196+
_walletListUnsorted[i].data.installed ? 'Installed' : null,
197+
data: _walletListUnsorted[i].data.copyWith(
198+
recent: false,
199+
),
200+
);
201+
}
202+
// If the recent wallet matches the id, then set it to recent
203+
else if (_walletListUnsorted[i].id == recentWallet) {
204+
_walletListUnsorted[i] = _walletListUnsorted[i].copyWith(
205+
description: 'Recent',
206+
data: _walletListUnsorted[i].data.copyWith(
207+
recent: true,
208+
),
209+
);
210+
}
211+
212+
// Handle sorting
213+
if (_walletListUnsorted[i].data.recent == true) {
214+
newList.insert(0, _walletListUnsorted[i]);
215+
insertAt++;
216+
} else if (_walletListUnsorted[i].data.installed) {
217+
newList.insert(insertAt, _walletListUnsorted[i]);
218+
insertAt++;
219+
} else if (recommendedWalletIds != null &&
220+
recommendedWalletIds!.contains(_walletListUnsorted[i].id)) {
221+
newList.insert(insertAt, _walletListUnsorted[i]);
222+
} else {
223+
newList.add(_walletListUnsorted[i]);
224+
}
225+
}
226+
227+
previousRecentWallet = recentWallet;
228+
_walletListSorted = newList;
229+
itemList.value = newList;
230+
}
231+
208232
@override
209233
String getWalletImageUrl({
210234
required String imageId,

lib/services/explorer/i_explorer_service.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ abstract class IExplorerService implements GridListProvider<WalletData> {
2525
/// The wallets that will be excluded from the modal.
2626
Set<String>? excludedWalletIds;
2727

28-
Future<void> init({bool refetch = false});
28+
Future<void> init();
2929

3030
String getWalletImageUrl({
3131
required String imageId,

lib/services/walletconnect_modal/walletconnect_modal_service.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ class WalletConnectModalService extends ChangeNotifier
373373
walletData.listing.id,
374374
);
375375
// Update explorer service with new recent
376-
await explorerService.instance!.init();
376+
await explorerService.instance!.updateSort();
377377

378378
try {
379379
await rebuildConnectionUri();

lib/widgets/grid_list/grid_list.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@ class GridList<T> extends StatelessWidget {
2525
required this.provider,
2626
this.viewLongList,
2727
required this.onSelect,
28+
this.visibleRowCount,
2829
});
2930

3031
final GridListState state;
3132
final GridListProvider<T> provider;
3233
final void Function()? viewLongList;
3334
final void Function(T) onSelect;
35+
final int? visibleRowCount;
3436

3537
@override
3638
Widget build(BuildContext context) {
@@ -89,6 +91,10 @@ class GridList<T> extends StatelessWidget {
8991
break;
9092
}
9193

94+
if (visibleRowCount != null) {
95+
height = 120.0 * visibleRowCount!;
96+
}
97+
9298
if (value.isEmpty) {
9399
return KeyboardVisibilityBuilder(
94100
builder: (context, isKeyboardVisible) {

lib/widgets/grid_list/grid_list_item_model.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,20 @@ class GridListItemModel<T> {
1212
this.description,
1313
required this.data,
1414
});
15+
16+
GridListItemModel<T> copyWith({
17+
String? image,
18+
String? id,
19+
String? title,
20+
String? description,
21+
T? data,
22+
}) {
23+
return GridListItemModel<T>(
24+
image: image ?? this.image,
25+
id: id ?? this.id,
26+
title: title ?? this.title,
27+
description: description ?? this.description,
28+
data: data ?? this.data,
29+
);
30+
}
1531
}

lib/widgets/grid_list/grid_list_provider.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@ abstract class GridListProvider<T> {
88
void filterList({
99
String? query,
1010
});
11+
12+
Future<void> updateSort();
1113
}

test/get_a_wallet/get_a_wallet_test.dart

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
22
import 'package:flutter_test/flutter_test.dart';
33
import 'package:mockito/mockito.dart';
44
import 'package:network_image_mock/network_image_mock.dart';
5+
import 'package:url_launcher/url_launcher.dart';
56
import 'package:walletconnect_modal_flutter/models/listings.dart';
67
import 'package:walletconnect_modal_flutter/pages/get_wallet_page.dart';
78
import 'package:walletconnect_modal_flutter/services/explorer/explorer_service_singleton.dart';
@@ -35,7 +36,10 @@ void main() {
3536
when(mockPlatformUtils.isMobileWidth(any)).thenReturn(true);
3637
platformUtils.instance = mockPlatformUtils;
3738

38-
when(mockUrlUtils.launchUrl(any)).thenAnswer(
39+
when(mockUrlUtils.launchUrl(
40+
any,
41+
mode: anyNamed("mode"),
42+
)).thenAnswer(
3943
(_) => Future.value(true),
4044
);
4145
urlUtils.instance = mockUrlUtils;
@@ -73,11 +77,13 @@ void main() {
7377

7478
verify(mockUrlUtils.launchUrl(
7579
Uri.parse(StringConstants.getAWalletExploreWalletsUrl),
80+
mode: LaunchMode.externalApplication,
7681
)).called(1);
7782
});
7883
});
7984

80-
testWidgets('should load in wallets and their buttons',
85+
testWidgets(
86+
'should load in wallets, their buttons, and their buttons should launch the correct URL',
8187
(WidgetTester tester) async {
8288
// FlutterError.onError = ignoreOverflowErrors;
8389

@@ -119,6 +125,15 @@ void main() {
119125
find.byType(WalletItem, skipOffstage: false),
120126
findsNWidgets(2),
121127
);
128+
129+
await tester.tap(
130+
find.byType(WalletConnectModalButton).first,
131+
);
132+
133+
verify(mockUrlUtils.launchUrl(
134+
Uri.parse(testListings1[0].homepage),
135+
mode: LaunchMode.externalApplication,
136+
)).called(1);
122137
});
123138
});
124139
});

0 commit comments

Comments
 (0)