@onekeyfe/react-native-native-list 3.0.105 → 3.0.106
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/com/onekey/nativelist/NativeListAdapter.kt +16 -3
- package/android/src/main/java/com/onekey/nativelist/NativeListModels.kt +6 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListRowView.kt +671 -52
- package/android/src/main/java/com/onekey/nativelist/NativeListView.kt +282 -54
- package/ios/HybridNativeList.swift +8 -2
- package/ios/NativeListCell.swift +630 -31
- package/ios/NativeListDesignAssets.swift +24 -1
- package/ios/RNCNativeListView.swift +216 -42
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_account_error_custom.imageset/Contents.json +15 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_account_error_custom.imageset/icon.svg +14 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_all_networks_solid.imageset/Contents.json +15 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_all_networks_solid.imageset/icon.svg +12 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_apple_brand.imageset/Contents.json +15 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_apple_brand.imageset/icon.svg +6 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_bot_illus.imageset/Contents.json +15 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_bot_illus.imageset/icon.svg +15 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_crossed_small_solid.imageset/Contents.json +15 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_crossed_small_solid.imageset/icon.svg +3 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_globus_outline.imageset/Contents.json +15 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_globus_outline.imageset/icon.svg +7 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_google_illus.imageset/Contents.json +15 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_google_illus.imageset/icon.svg +18 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_lock_solid.imageset/Contents.json +15 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_lock_solid.imageset/icon.svg +7 -0
- package/lib/module/NativeList.js +102 -8
- package/lib/module/NativeList.web.js +20 -2
- package/lib/module/avatarPrefetch.js +174 -0
- package/lib/module/validation.js +45 -2
- package/lib/module/web/NativeListAvatarWorker.js +542 -0
- package/lib/module/web/NativeListWebAvatarCache.js +267 -0
- package/lib/module/web/NativeListWebEngine.js +958 -47
- package/lib/typescript/src/NativeList.web.d.ts +2 -2
- package/lib/typescript/src/avatarPrefetch.d.ts +28 -0
- package/lib/typescript/src/models.d.ts +72 -4
- package/lib/typescript/src/web/NativeListWebAvatarCache.d.ts +6 -0
- package/lib/typescript/src/web/NativeListWebEngine.d.ts +10 -1
- package/package.json +2 -2
- package/src/NativeList.tsx +149 -13
- package/src/NativeList.web.tsx +30 -3
- package/src/avatarPrefetch.ts +236 -0
- package/src/models.ts +98 -7
- package/src/validation.ts +131 -2
- package/src/web/NativeListAvatarWorker.js +567 -0
- package/src/web/NativeListWebAvatarCache.ts +314 -0
- package/src/web/NativeListWebEngine.ts +1409 -60
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// OneKey patch: avatar bytes stay in a worker and IndexedDB, outside list snapshots.
|
|
4
|
+
const AVATAR_PREFIX = 'onekey-avatar://blockie/v1/';
|
|
5
|
+
const MAX_RETAINED_AVATARS = 128;
|
|
6
|
+
export function canonicalNativeListAvatarUri(uri) {
|
|
7
|
+
if (!uri.startsWith(AVATAR_PREFIX)) return undefined;
|
|
8
|
+
try {
|
|
9
|
+
const seed = decodeURIComponent(uri.slice(AVATAR_PREFIX.length));
|
|
10
|
+
return seed ? AVATAR_PREFIX + encodeURIComponent(seed.toLowerCase()) : undefined;
|
|
11
|
+
} catch {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
class NativeListWebAvatarCache {
|
|
16
|
+
entries = new Map();
|
|
17
|
+
requests = new Map();
|
|
18
|
+
nextId = 0;
|
|
19
|
+
// OneKey patch: one cancellable startup serves every pending avatar lease.
|
|
20
|
+
workerGeneration = 0;
|
|
21
|
+
acquire(uri, resolve, reject, priority = 2) {
|
|
22
|
+
let entry = this.entries.get(uri);
|
|
23
|
+
const isNew = !entry;
|
|
24
|
+
if (!entry) {
|
|
25
|
+
entry = {
|
|
26
|
+
id: ++this.nextId,
|
|
27
|
+
uri,
|
|
28
|
+
references: 0,
|
|
29
|
+
listeners: new Set()
|
|
30
|
+
};
|
|
31
|
+
this.entries.set(uri, entry);
|
|
32
|
+
this.requests.set(entry.id, entry);
|
|
33
|
+
}
|
|
34
|
+
const current = entry;
|
|
35
|
+
this.entries.delete(uri);
|
|
36
|
+
this.entries.set(uri, current);
|
|
37
|
+
current.references += 1;
|
|
38
|
+
const listener = {
|
|
39
|
+
resolve,
|
|
40
|
+
reject,
|
|
41
|
+
priority
|
|
42
|
+
};
|
|
43
|
+
if (current.url) resolve(current.url);
|
|
44
|
+
// OneKey patch: keep lease priority after resolution as well as while queued.
|
|
45
|
+
// else current.listeners.add(listener);
|
|
46
|
+
current.listeners.add(listener);
|
|
47
|
+
if (isNew) {
|
|
48
|
+
// OneKey patch: file workers need async asset loading; keep pending requests in this cache.
|
|
49
|
+
// try {
|
|
50
|
+
// if (!this.worker) {
|
|
51
|
+
// // Deliberately avoid *.worker.js and its inline Blob-worker loader.
|
|
52
|
+
// this.worker = new Worker(new URL('./NativeListAvatarWorker.js', import.meta.url), {
|
|
53
|
+
// name: 'onekey-native-list-avatar',
|
|
54
|
+
// });
|
|
55
|
+
// this.worker.addEventListener('message', this.handleMessage);
|
|
56
|
+
// this.worker.addEventListener('error', this.handleFailure);
|
|
57
|
+
// this.worker.addEventListener('messageerror', this.handleFailure);
|
|
58
|
+
// }
|
|
59
|
+
// this.worker.postMessage({ type: 'acquire', id: current.id, uri, priority });
|
|
60
|
+
// } catch {
|
|
61
|
+
// queueMicrotask(this.handleFailure);
|
|
62
|
+
// }
|
|
63
|
+
if (this.worker) {
|
|
64
|
+
this.sendAcquire(current);
|
|
65
|
+
} else {
|
|
66
|
+
this.startWorker();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const updatePriority = () => {
|
|
70
|
+
if (current.url) return;
|
|
71
|
+
const priorities = [...current.listeners].map(value => value.priority);
|
|
72
|
+
this.worker?.postMessage({
|
|
73
|
+
type: 'priority',
|
|
74
|
+
id: current.id,
|
|
75
|
+
priority: Math.min(2, ...priorities)
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
updatePriority();
|
|
79
|
+
this.trim();
|
|
80
|
+
let disposed = false;
|
|
81
|
+
const release = () => {
|
|
82
|
+
if (disposed) return;
|
|
83
|
+
disposed = true;
|
|
84
|
+
current.listeners.delete(listener);
|
|
85
|
+
current.references = Math.max(0, current.references - 1);
|
|
86
|
+
if (current.references === 0 && !current.url && this.entries.get(uri) === current) {
|
|
87
|
+
this.entries.delete(uri);
|
|
88
|
+
this.requests.delete(current.id);
|
|
89
|
+
this.worker?.postMessage({
|
|
90
|
+
type: 'release',
|
|
91
|
+
id: current.id
|
|
92
|
+
});
|
|
93
|
+
if (this.requests.size === 0 && this.startingWorker) {
|
|
94
|
+
const starting = this.startingWorker;
|
|
95
|
+
this.startingWorker = undefined;
|
|
96
|
+
this.workerGeneration += 1;
|
|
97
|
+
starting.controller?.abort();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
updatePriority();
|
|
101
|
+
this.trim();
|
|
102
|
+
};
|
|
103
|
+
return Object.assign(release, {
|
|
104
|
+
setPriority: next => {
|
|
105
|
+
if (disposed || listener.priority === next) return;
|
|
106
|
+
listener.priority = next;
|
|
107
|
+
updatePriority();
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// OneKey patch: HTTP/extension keeps the bundler's original Worker entry. Electron's
|
|
113
|
+
// file interceptor can serve the same self-contained source as an asset for a Blob worker.
|
|
114
|
+
startWorker() {
|
|
115
|
+
if (this.worker || this.startingWorker) return;
|
|
116
|
+
const starting = {
|
|
117
|
+
generation: ++this.workerGeneration
|
|
118
|
+
};
|
|
119
|
+
this.startingWorker = starting;
|
|
120
|
+
const assetURL = new URL('./NativeListAvatarWorker.js', import.meta.url);
|
|
121
|
+
if (assetURL.protocol === 'file:') {
|
|
122
|
+
starting.controller = new AbortController();
|
|
123
|
+
void (async () => {
|
|
124
|
+
const response = await fetch(assetURL, {
|
|
125
|
+
signal: starting.controller?.signal
|
|
126
|
+
});
|
|
127
|
+
if (!response.ok) throw new Error('NativeList avatar worker asset failed to load');
|
|
128
|
+
const source = await response.blob();
|
|
129
|
+
if (this.startingWorker !== starting) return;
|
|
130
|
+
const sourceURL = URL.createObjectURL(source);
|
|
131
|
+
try {
|
|
132
|
+
this.activateWorker(new Worker(sourceURL, {
|
|
133
|
+
name: 'onekey-native-list-avatar'
|
|
134
|
+
}), starting);
|
|
135
|
+
} finally {
|
|
136
|
+
// Worker construction captures the script URL; the document must not retain its bytes.
|
|
137
|
+
URL.revokeObjectURL(sourceURL);
|
|
138
|
+
}
|
|
139
|
+
})().catch(() => {
|
|
140
|
+
if (this.startingWorker === starting || this.workerGeneration === starting.generation) {
|
|
141
|
+
this.handleFailure();
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
try {
|
|
147
|
+
this.activateWorker(new Worker(new URL('./NativeListAvatarWorker.js', import.meta.url), {
|
|
148
|
+
name: 'onekey-native-list-avatar'
|
|
149
|
+
}), starting);
|
|
150
|
+
} catch {
|
|
151
|
+
queueMicrotask(() => {
|
|
152
|
+
if (this.workerGeneration === starting.generation) this.handleFailure();
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
activateWorker(worker, starting) {
|
|
157
|
+
if (this.startingWorker !== starting) {
|
|
158
|
+
worker.terminate();
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
this.startingWorker = undefined;
|
|
162
|
+
this.worker = worker;
|
|
163
|
+
// OneKey patch: queued events from a failed instance cannot affect its replacement.
|
|
164
|
+
worker.addEventListener('message', event => {
|
|
165
|
+
if (this.worker === worker) this.handleMessage(event);
|
|
166
|
+
});
|
|
167
|
+
const failed = () => {
|
|
168
|
+
if (this.worker === worker) this.handleFailure();
|
|
169
|
+
};
|
|
170
|
+
worker.addEventListener('error', failed);
|
|
171
|
+
worker.addEventListener('messageerror', failed);
|
|
172
|
+
this.requests.forEach(entry => {
|
|
173
|
+
if (entry.references > 0 && !entry.url) this.sendAcquire(entry);
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
sendAcquire(entry) {
|
|
177
|
+
const worker = this.worker;
|
|
178
|
+
try {
|
|
179
|
+
worker?.postMessage({
|
|
180
|
+
type: 'acquire',
|
|
181
|
+
id: entry.id,
|
|
182
|
+
uri: entry.uri,
|
|
183
|
+
priority: Math.min(2, ...[...entry.listeners].map(listener => listener.priority))
|
|
184
|
+
});
|
|
185
|
+
} catch {
|
|
186
|
+
queueMicrotask(() => {
|
|
187
|
+
if (this.worker === worker) this.handleFailure();
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
handleMessage = event => {
|
|
192
|
+
const response = event.data;
|
|
193
|
+
if (!response || !Number.isSafeInteger(response.id)) return;
|
|
194
|
+
const entry = this.requests.get(response.id);
|
|
195
|
+
if (!entry) {
|
|
196
|
+
this.worker?.postMessage({
|
|
197
|
+
type: 'release',
|
|
198
|
+
id: response.id
|
|
199
|
+
});
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
if (response.type === 'resolved' && typeof response.url === 'string' && response.url.startsWith('blob:')) {
|
|
203
|
+
entry.url = response.url;
|
|
204
|
+
entry.listeners.forEach(listener => listener.resolve(response.url));
|
|
205
|
+
} else {
|
|
206
|
+
this.entries.delete(entry.uri);
|
|
207
|
+
this.requests.delete(entry.id);
|
|
208
|
+
this.worker?.postMessage({
|
|
209
|
+
type: 'release',
|
|
210
|
+
id: entry.id
|
|
211
|
+
});
|
|
212
|
+
entry.listeners.forEach(listener => listener.reject());
|
|
213
|
+
}
|
|
214
|
+
// OneKey patch: retain resolved lease priorities until their explicit release.
|
|
215
|
+
// entry.listeners.clear();
|
|
216
|
+
if (!entry.url) entry.listeners.clear();
|
|
217
|
+
this.trim();
|
|
218
|
+
};
|
|
219
|
+
handleFailure = () => {
|
|
220
|
+
// OneKey patch: detach the failed generation before callbacks can acquire a replacement.
|
|
221
|
+
// this.worker?.terminate();
|
|
222
|
+
// this.worker = undefined;
|
|
223
|
+
// this.requests.forEach((entry) => {
|
|
224
|
+
// if (!entry.url) entry.listeners.forEach((listener) => listener.reject());
|
|
225
|
+
// entry.listeners.clear();
|
|
226
|
+
// });
|
|
227
|
+
// this.requests.clear();
|
|
228
|
+
// this.entries.clear();
|
|
229
|
+
const failedEntries = [...this.requests.values()];
|
|
230
|
+
const starting = this.startingWorker;
|
|
231
|
+
this.startingWorker = undefined;
|
|
232
|
+
this.workerGeneration += 1;
|
|
233
|
+
starting?.controller?.abort();
|
|
234
|
+
this.worker?.terminate();
|
|
235
|
+
this.worker = undefined;
|
|
236
|
+
this.requests.clear();
|
|
237
|
+
this.entries.clear();
|
|
238
|
+
failedEntries.forEach(entry => {
|
|
239
|
+
const listeners = [...entry.listeners];
|
|
240
|
+
entry.listeners.clear();
|
|
241
|
+
if (!entry.url) listeners.forEach(listener => listener.reject());
|
|
242
|
+
});
|
|
243
|
+
};
|
|
244
|
+
trim() {
|
|
245
|
+
for (const [uri, entry] of this.entries) {
|
|
246
|
+
if (this.entries.size <= MAX_RETAINED_AVATARS) break;
|
|
247
|
+
if (entry.references === 0) {
|
|
248
|
+
this.entries.delete(uri);
|
|
249
|
+
this.requests.delete(entry.id);
|
|
250
|
+
this.worker?.postMessage({
|
|
251
|
+
type: 'release',
|
|
252
|
+
id: entry.id
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
const documentCaches = new WeakMap();
|
|
259
|
+
export function acquireNativeListAvatar(document, uri, resolve, reject, priority = 2) {
|
|
260
|
+
let cache = documentCaches.get(document);
|
|
261
|
+
if (!cache) {
|
|
262
|
+
cache = new NativeListWebAvatarCache();
|
|
263
|
+
documentCaches.set(document, cache);
|
|
264
|
+
}
|
|
265
|
+
return cache.acquire(uri, resolve, reject, priority);
|
|
266
|
+
}
|
|
267
|
+
//# sourceMappingURL=NativeListWebAvatarCache.js.map
|