@buoy-gg/assets 7.0.38 → 7.0.39
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/lib/commonjs/capture/expo.js +46 -1
- package/lib/commonjs/capture/expo.js.map +1 -0
- package/lib/commonjs/capture/install.js +91 -1
- package/lib/commonjs/capture/install.js.map +1 -0
- package/lib/commonjs/capture/isBuoyAsset.js +23 -1
- package/lib/commonjs/capture/isBuoyAsset.js.map +1 -0
- package/lib/commonjs/capture/measure.js +186 -1
- package/lib/commonjs/capture/measure.js.map +1 -0
- package/lib/commonjs/capture/metroGraph.js +175 -1
- package/lib/commonjs/capture/metroGraph.js.map +1 -0
- package/lib/commonjs/capture/registry.js +127 -1
- package/lib/commonjs/capture/registry.js.map +1 -0
- package/lib/commonjs/components/AssetDetail.js +211 -1
- package/lib/commonjs/components/AssetDetail.js.map +1 -0
- package/lib/commonjs/components/AssetImage.js +66 -1
- package/lib/commonjs/components/AssetImage.js.map +1 -0
- package/lib/commonjs/components/AssetRow.js +232 -1
- package/lib/commonjs/components/AssetRow.js.map +1 -0
- package/lib/commonjs/components/AssetsFilterBar.js +105 -1
- package/lib/commonjs/components/AssetsFilterBar.js.map +1 -0
- package/lib/commonjs/components/AssetsHeader.js +73 -1
- package/lib/commonjs/components/AssetsHeader.js.map +1 -0
- package/lib/commonjs/components/AssetsIcon.js +19 -1
- package/lib/commonjs/components/AssetsIcon.js.map +1 -0
- package/lib/commonjs/components/AssetsListControls.js +81 -1
- package/lib/commonjs/components/AssetsListControls.js.map +1 -0
- package/lib/commonjs/components/AssetsModal.js +378 -1
- package/lib/commonjs/components/AssetsModal.js.map +1 -0
- package/lib/commonjs/components/ScanNotice.js +85 -1
- package/lib/commonjs/components/ScanNotice.js.map +1 -0
- package/lib/commonjs/components/optionalExpoImage.js +16 -1
- package/lib/commonjs/components/optionalExpoImage.js.map +1 -0
- package/lib/commonjs/components/optionalExpoImage.web.js +11 -1
- package/lib/commonjs/components/optionalExpoImage.web.js.map +1 -0
- package/lib/commonjs/export.js +62 -1
- package/lib/commonjs/export.js.map +1 -0
- package/lib/commonjs/format.js +59 -1
- package/lib/commonjs/format.js.map +1 -0
- package/lib/commonjs/hooks/useAssetRecords.js +22 -1
- package/lib/commonjs/hooks/useAssetRecords.js.map +1 -0
- package/lib/commonjs/hooks/useAssetScanStatus.js +28 -1
- package/lib/commonjs/hooks/useAssetScanStatus.js.map +1 -0
- package/lib/commonjs/index.js +313 -1
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/preset.js +39 -1
- package/lib/commonjs/preset.js.map +1 -0
- package/lib/commonjs/remote.js +68 -1
- package/lib/commonjs/remote.js.map +1 -0
- package/lib/commonjs/state.js +51 -1
- package/lib/commonjs/state.js.map +1 -0
- package/lib/commonjs/store/assetStore.js +256 -1
- package/lib/commonjs/store/assetStore.js.map +1 -0
- package/lib/commonjs/store/baseline.js +175 -1
- package/lib/commonjs/store/baseline.js.map +1 -0
- package/lib/commonjs/store/insights.js +120 -1
- package/lib/commonjs/store/insights.js.map +1 -0
- package/lib/commonjs/sync/assetsSyncAdapter.js +157 -1
- package/lib/commonjs/sync/assetsSyncAdapter.js.map +1 -0
- package/lib/commonjs/types.js +2 -1
- package/lib/commonjs/types.js.map +1 -0
- package/lib/commonjs/utils/deviceScale.js +50 -1
- package/lib/commonjs/utils/deviceScale.js.map +1 -0
- package/lib/commonjs/utils/testIDs.js +110 -1
- package/lib/commonjs/utils/testIDs.js.map +1 -0
- package/lib/module/capture/expo.js +41 -1
- package/lib/module/capture/expo.js.map +1 -0
- package/lib/module/capture/install.js +85 -1
- package/lib/module/capture/install.js.map +1 -0
- package/lib/module/capture/isBuoyAsset.js +18 -1
- package/lib/module/capture/isBuoyAsset.js.map +1 -0
- package/lib/module/capture/measure.js +179 -1
- package/lib/module/capture/measure.js.map +1 -0
- package/lib/module/capture/metroGraph.js +168 -1
- package/lib/module/capture/metroGraph.js.map +1 -0
- package/lib/module/capture/registry.js +120 -1
- package/lib/module/capture/registry.js.map +1 -0
- package/lib/module/components/AssetDetail.js +207 -1
- package/lib/module/components/AssetDetail.js.map +1 -0
- package/lib/module/components/AssetImage.js +62 -1
- package/lib/module/components/AssetImage.js.map +1 -0
- package/lib/module/components/AssetRow.js +228 -1
- package/lib/module/components/AssetRow.js.map +1 -0
- package/lib/module/components/AssetsFilterBar.js +101 -1
- package/lib/module/components/AssetsFilterBar.js.map +1 -0
- package/lib/module/components/AssetsHeader.js +69 -1
- package/lib/module/components/AssetsHeader.js.map +1 -0
- package/lib/module/components/AssetsIcon.js +12 -1
- package/lib/module/components/AssetsIcon.js.map +1 -0
- package/lib/module/components/AssetsListControls.js +77 -1
- package/lib/module/components/AssetsListControls.js.map +1 -0
- package/lib/module/components/AssetsModal.js +373 -1
- package/lib/module/components/AssetsModal.js.map +1 -0
- package/lib/module/components/ScanNotice.js +81 -1
- package/lib/module/components/ScanNotice.js.map +1 -0
- package/lib/module/components/optionalExpoImage.js +12 -1
- package/lib/module/components/optionalExpoImage.js.map +1 -0
- package/lib/module/components/optionalExpoImage.web.js +7 -1
- package/lib/module/components/optionalExpoImage.web.js.map +1 -0
- package/lib/module/export.js +57 -1
- package/lib/module/export.js.map +1 -0
- package/lib/module/format.js +51 -1
- package/lib/module/format.js.map +1 -0
- package/lib/module/hooks/useAssetRecords.js +18 -1
- package/lib/module/hooks/useAssetRecords.js.map +1 -0
- package/lib/module/hooks/useAssetScanStatus.js +23 -1
- package/lib/module/hooks/useAssetScanStatus.js.map +1 -0
- package/lib/module/index.js +63 -1
- package/lib/module/index.js.map +1 -0
- package/lib/module/preset.js +35 -1
- package/lib/module/preset.js.map +1 -0
- package/lib/module/remote.js +61 -1
- package/lib/module/remote.js.map +1 -0
- package/lib/module/state.js +47 -1
- package/lib/module/state.js.map +1 -0
- package/lib/module/store/assetStore.js +240 -1
- package/lib/module/store/assetStore.js.map +1 -0
- package/lib/module/store/baseline.js +167 -1
- package/lib/module/store/baseline.js.map +1 -0
- package/lib/module/store/insights.js +116 -1
- package/lib/module/store/insights.js.map +1 -0
- package/lib/module/sync/assetsSyncAdapter.js +153 -1
- package/lib/module/sync/assetsSyncAdapter.js.map +1 -0
- package/lib/module/types.js +2 -1
- package/lib/module/types.js.map +1 -0
- package/lib/module/utils/deviceScale.js +46 -1
- package/lib/module/utils/deviceScale.js.map +1 -0
- package/lib/module/utils/testIDs.js +99 -1
- package/lib/module/utils/testIDs.js.map +1 -0
- package/lib/typescript/capture/expo.d.ts.map +1 -0
- package/lib/typescript/capture/install.d.ts.map +1 -0
- package/lib/typescript/capture/isBuoyAsset.d.ts.map +1 -0
- package/lib/typescript/capture/measure.d.ts.map +1 -0
- package/lib/typescript/capture/metroGraph.d.ts.map +1 -0
- package/lib/typescript/capture/registry.d.ts.map +1 -0
- package/lib/typescript/components/AssetDetail.d.ts.map +1 -0
- package/lib/typescript/components/AssetImage.d.ts.map +1 -0
- package/lib/typescript/components/AssetRow.d.ts.map +1 -0
- package/lib/typescript/components/AssetsFilterBar.d.ts.map +1 -0
- package/lib/typescript/components/AssetsHeader.d.ts.map +1 -0
- package/lib/typescript/components/AssetsIcon.d.ts.map +1 -0
- package/lib/typescript/components/AssetsListControls.d.ts.map +1 -0
- package/lib/typescript/components/AssetsModal.d.ts.map +1 -0
- package/lib/typescript/components/ScanNotice.d.ts.map +1 -0
- package/lib/typescript/components/optionalExpoImage.d.ts.map +1 -0
- package/lib/typescript/components/optionalExpoImage.web.d.ts.map +1 -0
- package/lib/typescript/export.d.ts.map +1 -0
- package/lib/typescript/format.d.ts.map +1 -0
- package/lib/typescript/hooks/useAssetRecords.d.ts.map +1 -0
- package/lib/typescript/hooks/useAssetScanStatus.d.ts.map +1 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/preset.d.ts.map +1 -0
- package/lib/typescript/remote.d.ts.map +1 -0
- package/lib/typescript/state.d.ts.map +1 -0
- package/lib/typescript/store/assetStore.d.ts.map +1 -0
- package/lib/typescript/store/baseline.d.ts.map +1 -0
- package/lib/typescript/store/insights.d.ts.map +1 -0
- package/lib/typescript/sync/assetsSyncAdapter.d.ts.map +1 -0
- package/lib/typescript/types.d.ts.map +1 -0
- package/lib/typescript/utils/deviceScale.d.ts.map +1 -0
- package/lib/typescript/utils/testIDs.d.ts.map +1 -0
- package/package.json +2 -2
|
@@ -1 +1,240 @@
|
|
|
1
|
-
"use strict";
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* assetStore
|
|
5
|
+
*
|
|
6
|
+
* Bounded store of AssetRecords keyed by their stable asset key
|
|
7
|
+
* (`location/name.type`). Follows the images tool's store shape — Set of
|
|
8
|
+
* listeners, frame-coalesced emit, all mutable state on the globalThis
|
|
9
|
+
* singleton (../state.ts) so dual module instances share one store.
|
|
10
|
+
*
|
|
11
|
+
* Unlike the images tool this is an INVENTORY, not an event log: upserts
|
|
12
|
+
* merge into the existing record for a key instead of appending, and there
|
|
13
|
+
* is no ring-buffer cap (a bundle has a bounded asset count by construction).
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { assetsState } from "../state";
|
|
17
|
+
import { isBuoyAsset } from "../capture/isBuoyAsset";
|
|
18
|
+
import { effectivePixelRatio, pickScale } from "../utils/deviceScale";
|
|
19
|
+
function emit() {
|
|
20
|
+
const s = assetsState();
|
|
21
|
+
if (s.emitScheduled) return;
|
|
22
|
+
s.emitScheduled = true;
|
|
23
|
+
requestAnimationFrame(() => {
|
|
24
|
+
s.emitScheduled = false;
|
|
25
|
+
for (const listener of s.listeners) listener();
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Snapshot identity only changes on emit, so useSyncExternalStore stays cheap. */
|
|
30
|
+
export function invalidate() {
|
|
31
|
+
const s = assetsState();
|
|
32
|
+
s.snapshot = [...s.records];
|
|
33
|
+
emit();
|
|
34
|
+
}
|
|
35
|
+
const KIND_BY_EXT = {
|
|
36
|
+
png: "image",
|
|
37
|
+
jpg: "image",
|
|
38
|
+
jpeg: "image",
|
|
39
|
+
gif: "image",
|
|
40
|
+
webp: "image",
|
|
41
|
+
bmp: "image",
|
|
42
|
+
psd: "image",
|
|
43
|
+
svg: "image",
|
|
44
|
+
tiff: "image",
|
|
45
|
+
ktx: "image",
|
|
46
|
+
heic: "image",
|
|
47
|
+
heif: "image",
|
|
48
|
+
avif: "image",
|
|
49
|
+
ttf: "font",
|
|
50
|
+
otf: "font",
|
|
51
|
+
woff: "font",
|
|
52
|
+
woff2: "font",
|
|
53
|
+
ttc: "font",
|
|
54
|
+
mp4: "video",
|
|
55
|
+
m4v: "video",
|
|
56
|
+
mov: "video",
|
|
57
|
+
mpeg: "video",
|
|
58
|
+
mpg: "video",
|
|
59
|
+
webm: "video",
|
|
60
|
+
avi: "video",
|
|
61
|
+
mp3: "audio",
|
|
62
|
+
wav: "audio",
|
|
63
|
+
aac: "audio",
|
|
64
|
+
aiff: "audio",
|
|
65
|
+
caf: "audio",
|
|
66
|
+
m4a: "audio",
|
|
67
|
+
ogg: "audio",
|
|
68
|
+
json: "data",
|
|
69
|
+
db: "data",
|
|
70
|
+
yaml: "data",
|
|
71
|
+
yml: "data",
|
|
72
|
+
xml: "data",
|
|
73
|
+
html: "data",
|
|
74
|
+
pdf: "data",
|
|
75
|
+
zip: "data"
|
|
76
|
+
};
|
|
77
|
+
export function kindForType(type) {
|
|
78
|
+
return KIND_BY_EXT[type.toLowerCase()] ?? "other";
|
|
79
|
+
}
|
|
80
|
+
export function assetKey(httpServerLocation, name, type) {
|
|
81
|
+
// The runtime registry percent-encodes ?unstable_path= locations while the
|
|
82
|
+
// Metro graph endpoint returns them decoded — normalize or every asset
|
|
83
|
+
// splits into a registry record + a graph record.
|
|
84
|
+
let location = httpServerLocation ?? "";
|
|
85
|
+
try {
|
|
86
|
+
location = decodeURIComponent(location);
|
|
87
|
+
} catch {
|
|
88
|
+
// malformed escapes: keep the raw string
|
|
89
|
+
}
|
|
90
|
+
return `${location}/${name}.${type}`;
|
|
91
|
+
}
|
|
92
|
+
/** Merge an asset sighting into the store; creates the record on first sight. */
|
|
93
|
+
export function upsertRecord(input) {
|
|
94
|
+
if (isBuoyAsset(input)) return undefined;
|
|
95
|
+
const s = assetsState();
|
|
96
|
+
let record = s.byKey.get(input.key);
|
|
97
|
+
if (!record) {
|
|
98
|
+
record = {
|
|
99
|
+
id: s.nextId++,
|
|
100
|
+
key: input.key,
|
|
101
|
+
name: input.name,
|
|
102
|
+
type: input.type,
|
|
103
|
+
kind: kindForType(input.type),
|
|
104
|
+
scales: input.scales ?? [],
|
|
105
|
+
loaded: input.loaded ?? false,
|
|
106
|
+
origin: input.origin,
|
|
107
|
+
firstSeenAt: Date.now()
|
|
108
|
+
};
|
|
109
|
+
s.records.push(record);
|
|
110
|
+
s.byKey.set(record.key, record);
|
|
111
|
+
s.byId.set(record.id, record);
|
|
112
|
+
}
|
|
113
|
+
if (input.registryId != null) record.registryId = input.registryId;
|
|
114
|
+
if (input.hash != null) record.hash = input.hash;
|
|
115
|
+
if (input.httpServerLocation != null) record.httpServerLocation = input.httpServerLocation;
|
|
116
|
+
if (input.width != null) record.width = input.width;
|
|
117
|
+
if (input.height != null) record.height = input.height;
|
|
118
|
+
if (input.scales && input.scales.length) {
|
|
119
|
+
// Dedupe: foo.png + foo@1x.png both existing yields [1, 1, …] from Metro.
|
|
120
|
+
record.scales = [...new Set(input.scales)].sort((a, b) => a - b);
|
|
121
|
+
}
|
|
122
|
+
if (input.resolvedUri != null) record.resolvedUri = input.resolvedUri;
|
|
123
|
+
if (input.resolvedScale != null) record.resolvedScale = input.resolvedScale;
|
|
124
|
+
if (input.loaded) record.loaded = true;
|
|
125
|
+
if (input.fileSystemLocation != null) record.fileSystemLocation = input.fileSystemLocation;
|
|
126
|
+
if (input.files) record.files = input.files;
|
|
127
|
+
if (input.fileHashes) record.fileHashes = input.fileHashes;
|
|
128
|
+
invalidate();
|
|
129
|
+
return record;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** Mutate a record in place (records are owned by the store) and notify. */
|
|
133
|
+
export function updateRecord(id, patch) {
|
|
134
|
+
const s = assetsState();
|
|
135
|
+
const record = s.byId.get(id);
|
|
136
|
+
if (!record) return undefined;
|
|
137
|
+
Object.assign(record, patch);
|
|
138
|
+
invalidate();
|
|
139
|
+
return record;
|
|
140
|
+
}
|
|
141
|
+
export function getRecord(id) {
|
|
142
|
+
return assetsState().byId.get(id);
|
|
143
|
+
}
|
|
144
|
+
export function getRecordByKey(key) {
|
|
145
|
+
return assetsState().byKey.get(key);
|
|
146
|
+
}
|
|
147
|
+
export function getSnapshot() {
|
|
148
|
+
return assetsState().snapshot;
|
|
149
|
+
}
|
|
150
|
+
export function subscribe(listener) {
|
|
151
|
+
const s = assetsState();
|
|
152
|
+
s.listeners.add(listener);
|
|
153
|
+
return () => assetsState().listeners.delete(listener);
|
|
154
|
+
}
|
|
155
|
+
export function clearRecords() {
|
|
156
|
+
const s = assetsState();
|
|
157
|
+
s.records = [];
|
|
158
|
+
s.byKey = new Map();
|
|
159
|
+
s.byId = new Map();
|
|
160
|
+
s.measuredCount = 0;
|
|
161
|
+
s.graphCount = null;
|
|
162
|
+
invalidate();
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/** Remove records captured before the exclusion was installed through Fast Refresh. */
|
|
166
|
+
export function removeBuoyRecords() {
|
|
167
|
+
const s = assetsState();
|
|
168
|
+
const remaining = s.records.filter(record => !isBuoyAsset(record));
|
|
169
|
+
if (remaining.length === s.records.length) return;
|
|
170
|
+
s.records = remaining;
|
|
171
|
+
s.byKey = new Map(remaining.map(record => [record.key, record]));
|
|
172
|
+
s.byId = new Map(remaining.map(record => [record.id, record]));
|
|
173
|
+
s.measuredCount = remaining.filter(record => record.sizeSource === "measured").length;
|
|
174
|
+
invalidate();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Estimated decoded-bitmap memory (RGBA8888) at the scale this device would
|
|
179
|
+
* pick — the size fallback when bytes can't be measured (release builds).
|
|
180
|
+
*
|
|
181
|
+
* `resolvedScale` is React Native's own answer and is authoritative, but it
|
|
182
|
+
* only exists once the asset has been REGISTERED. For everything still known
|
|
183
|
+
* only from the Metro graph — the never-loaded set, which is most of what this
|
|
184
|
+
* tool is for — the scale has to be predicted the same way AssetSourceResolver
|
|
185
|
+
* would, not taken as the largest variant shipped.
|
|
186
|
+
*/
|
|
187
|
+
export function estDecodedBytes(record) {
|
|
188
|
+
if (record.kind !== "image" || !record.width || !record.height) return 0;
|
|
189
|
+
const scale = record.resolvedScale ?? pickScale(record.scales, effectivePixelRatio());
|
|
190
|
+
return Math.round(record.width * scale * record.height * scale * 4);
|
|
191
|
+
}
|
|
192
|
+
export function computeStats(list) {
|
|
193
|
+
const s = assetsState();
|
|
194
|
+
const byKind = {
|
|
195
|
+
image: {
|
|
196
|
+
count: 0,
|
|
197
|
+
bytes: 0
|
|
198
|
+
},
|
|
199
|
+
font: {
|
|
200
|
+
count: 0,
|
|
201
|
+
bytes: 0
|
|
202
|
+
},
|
|
203
|
+
video: {
|
|
204
|
+
count: 0,
|
|
205
|
+
bytes: 0
|
|
206
|
+
},
|
|
207
|
+
audio: {
|
|
208
|
+
count: 0,
|
|
209
|
+
bytes: 0
|
|
210
|
+
},
|
|
211
|
+
data: {
|
|
212
|
+
count: 0,
|
|
213
|
+
bytes: 0
|
|
214
|
+
},
|
|
215
|
+
other: {
|
|
216
|
+
count: 0,
|
|
217
|
+
bytes: 0
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
const stats = {
|
|
221
|
+
total: list.length,
|
|
222
|
+
loaded: 0,
|
|
223
|
+
neverLoaded: 0,
|
|
224
|
+
byKind,
|
|
225
|
+
totalBytes: 0,
|
|
226
|
+
measuredCount: 0,
|
|
227
|
+
fontFamilies: s.fontFamilies.length
|
|
228
|
+
};
|
|
229
|
+
for (const r of list) {
|
|
230
|
+
if (r.loaded) stats.loaded++;else stats.neverLoaded++;
|
|
231
|
+
byKind[r.kind].count++;
|
|
232
|
+
if (r.sizeBytes != null && r.sizeSource === "measured") {
|
|
233
|
+
byKind[r.kind].bytes += r.sizeBytes;
|
|
234
|
+
stats.totalBytes += r.sizeBytes;
|
|
235
|
+
stats.measuredCount++;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return stats;
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=assetStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["assetsState","isBuoyAsset","effectivePixelRatio","pickScale","emit","s","emitScheduled","requestAnimationFrame","listener","listeners","invalidate","snapshot","records","KIND_BY_EXT","png","jpg","jpeg","gif","webp","bmp","psd","svg","tiff","ktx","heic","heif","avif","ttf","otf","woff","woff2","ttc","mp4","m4v","mov","mpeg","mpg","webm","avi","mp3","wav","aac","aiff","caf","m4a","ogg","json","db","yaml","yml","xml","html","pdf","zip","kindForType","type","toLowerCase","assetKey","httpServerLocation","name","location","decodeURIComponent","upsertRecord","input","undefined","record","byKey","get","key","id","nextId","kind","scales","loaded","origin","firstSeenAt","Date","now","push","set","byId","registryId","hash","width","height","length","Set","sort","a","b","resolvedUri","resolvedScale","fileSystemLocation","files","fileHashes","updateRecord","patch","Object","assign","getRecord","getRecordByKey","getSnapshot","subscribe","add","delete","clearRecords","Map","measuredCount","graphCount","removeBuoyRecords","remaining","filter","map","sizeSource","estDecodedBytes","scale","Math","round","computeStats","list","byKind","image","count","bytes","font","video","audio","data","other","stats","total","neverLoaded","totalBytes","fontFamilies","r","sizeBytes"],"sourceRoot":"../../../src","sources":["store/assetStore.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1,167 @@
|
|
|
1
|
-
"use strict";
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Baseline diff — the regression-prevention half of the tool.
|
|
5
|
+
*
|
|
6
|
+
* "Save baseline" persists a slim {hash, size} snapshot of the inventory via
|
|
7
|
+
* shared-ui's persistentStorage (FileSystem → AsyncStorage → memory), and
|
|
8
|
+
* every later scan diffs against it: new assets, removed assets, grown
|
|
9
|
+
* assets, net bytes. Run it before and after a branch and you get "this
|
|
10
|
+
* branch added 2.3 MB" without any CI tooling.
|
|
11
|
+
*
|
|
12
|
+
* On dashboard mirrors the actions forward to the device (the baseline
|
|
13
|
+
* belongs to the app being inspected, not the dashboard) and the computed
|
|
14
|
+
* diff arrives back inside the synced snapshot.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { persistentStorage } from "@buoy-gg/shared-ui";
|
|
18
|
+
import { remoteAssetsDispatch } from "../remote";
|
|
19
|
+
import { assetsState } from "../state";
|
|
20
|
+
import { getSnapshot, invalidate } from "./assetStore";
|
|
21
|
+
import { isBuoyAssetPath } from "../capture/isBuoyAsset";
|
|
22
|
+
const STORAGE_KEY = "@react_buoy/assets/baseline";
|
|
23
|
+
|
|
24
|
+
/** ≥1 KB counts as growth; below that is codec/metadata noise. */
|
|
25
|
+
const GROWN_THRESHOLD_BYTES = 1024;
|
|
26
|
+
|
|
27
|
+
/** Load the persisted baseline into state once; safe to call repeatedly. */
|
|
28
|
+
export async function loadBaseline() {
|
|
29
|
+
const s = assetsState();
|
|
30
|
+
if (s.baselineLoaded) return s.baseline;
|
|
31
|
+
s.baselineLoaded = true;
|
|
32
|
+
try {
|
|
33
|
+
const raw = await persistentStorage.getItem(STORAGE_KEY);
|
|
34
|
+
if (raw) {
|
|
35
|
+
const parsed = JSON.parse(raw);
|
|
36
|
+
if (parsed && typeof parsed.savedAt === "number" && parsed.entries) {
|
|
37
|
+
s.baseline = parsed;
|
|
38
|
+
invalidate();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
} catch {
|
|
42
|
+
// unreadable baseline = no baseline
|
|
43
|
+
}
|
|
44
|
+
return s.baseline;
|
|
45
|
+
}
|
|
46
|
+
export async function saveBaseline() {
|
|
47
|
+
const remote = remoteAssetsDispatch();
|
|
48
|
+
if (remote) {
|
|
49
|
+
await remote("saveBaseline");
|
|
50
|
+
return assetsState().baseline ?? {
|
|
51
|
+
savedAt: Date.now(),
|
|
52
|
+
entries: {}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const s = assetsState();
|
|
56
|
+
const entries = {};
|
|
57
|
+
for (const r of getSnapshot()) {
|
|
58
|
+
entries[r.key] = {
|
|
59
|
+
hash: r.hash ?? null,
|
|
60
|
+
sizeBytes: r.sizeSource === "measured" ? r.sizeBytes ?? null : null,
|
|
61
|
+
name: r.name,
|
|
62
|
+
type: r.type
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
const baseline = {
|
|
66
|
+
savedAt: Date.now(),
|
|
67
|
+
entries
|
|
68
|
+
};
|
|
69
|
+
s.baseline = baseline;
|
|
70
|
+
s.baselineLoaded = true;
|
|
71
|
+
invalidate();
|
|
72
|
+
try {
|
|
73
|
+
await persistentStorage.setItem(STORAGE_KEY, JSON.stringify(baseline));
|
|
74
|
+
} catch {
|
|
75
|
+
// in-memory baseline still works for this session
|
|
76
|
+
}
|
|
77
|
+
return baseline;
|
|
78
|
+
}
|
|
79
|
+
export async function clearBaseline() {
|
|
80
|
+
const remote = remoteAssetsDispatch();
|
|
81
|
+
if (remote) {
|
|
82
|
+
await remote("clearBaseline");
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const s = assetsState();
|
|
86
|
+
s.baseline = null;
|
|
87
|
+
s.baselineLoaded = true;
|
|
88
|
+
invalidate();
|
|
89
|
+
try {
|
|
90
|
+
await persistentStorage.removeItem(STORAGE_KEY);
|
|
91
|
+
} catch {
|
|
92
|
+
// nothing to clean up
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
export function computeDiff(records, baseline) {
|
|
96
|
+
const added = [];
|
|
97
|
+
const grown = [];
|
|
98
|
+
const seen = new Set();
|
|
99
|
+
let currentBytes = 0;
|
|
100
|
+
let baselineBytes = 0;
|
|
101
|
+
let comparable = false;
|
|
102
|
+
for (const r of records) {
|
|
103
|
+
seen.add(r.key);
|
|
104
|
+
const then = baseline.entries[r.key];
|
|
105
|
+
if (!then) {
|
|
106
|
+
added.push(r.id);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
const now = r.sizeSource === "measured" ? r.sizeBytes ?? null : null;
|
|
110
|
+
if (now != null && then.sizeBytes != null) {
|
|
111
|
+
comparable = true;
|
|
112
|
+
currentBytes += now;
|
|
113
|
+
baselineBytes += then.sizeBytes;
|
|
114
|
+
if (now - then.sizeBytes >= GROWN_THRESHOLD_BYTES) {
|
|
115
|
+
grown.push({
|
|
116
|
+
id: r.id,
|
|
117
|
+
deltaBytes: now - then.sizeBytes
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const removed = [];
|
|
123
|
+
for (const [key, entry] of Object.entries(baseline.entries)) {
|
|
124
|
+
if (isBuoyAssetPath(key)) continue;
|
|
125
|
+
if (!seen.has(key)) {
|
|
126
|
+
removed.push({
|
|
127
|
+
key,
|
|
128
|
+
name: entry.name,
|
|
129
|
+
type: entry.type
|
|
130
|
+
});
|
|
131
|
+
if (entry.sizeBytes != null) {
|
|
132
|
+
// A removal is as comparable as a survivor: its bytes were measured
|
|
133
|
+
// then and are definitionally zero now. Counting them toward the
|
|
134
|
+
// baseline total without marking the diff comparable meant a branch
|
|
135
|
+
// that only DELETED assets reported "12 removed" and no size at all —
|
|
136
|
+
// the one number anyone reads that bar for.
|
|
137
|
+
comparable = true;
|
|
138
|
+
baselineBytes += entry.sizeBytes;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// Added assets' measured bytes count toward the net even without a
|
|
143
|
+
// baseline counterpart — that's exactly the growth being reported.
|
|
144
|
+
for (const id of added) {
|
|
145
|
+
const r = records.find(rec => rec.id === id);
|
|
146
|
+
if (r?.sizeSource === "measured" && r.sizeBytes != null) {
|
|
147
|
+
comparable = true;
|
|
148
|
+
currentBytes += r.sizeBytes;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
baselineSavedAt: baseline.savedAt,
|
|
153
|
+
added,
|
|
154
|
+
removed,
|
|
155
|
+
grown: grown.sort((a, b) => b.deltaBytes - a.deltaBytes),
|
|
156
|
+
netBytes: comparable ? currentBytes - baselineBytes : null
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** Current diff: the synced device's on mirrors, computed locally on device. */
|
|
161
|
+
export function getDiff() {
|
|
162
|
+
const s = assetsState();
|
|
163
|
+
if (s.mirrorDiff) return s.mirrorDiff;
|
|
164
|
+
if (!s.baseline) return null;
|
|
165
|
+
return computeDiff(getSnapshot(), s.baseline);
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=baseline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["persistentStorage","remoteAssetsDispatch","assetsState","getSnapshot","invalidate","isBuoyAssetPath","STORAGE_KEY","GROWN_THRESHOLD_BYTES","loadBaseline","s","baselineLoaded","baseline","raw","getItem","parsed","JSON","parse","savedAt","entries","saveBaseline","remote","Date","now","r","key","hash","sizeBytes","sizeSource","name","type","setItem","stringify","clearBaseline","removeItem","computeDiff","records","added","grown","seen","Set","currentBytes","baselineBytes","comparable","add","then","push","id","deltaBytes","removed","entry","Object","has","find","rec","baselineSavedAt","sort","a","b","netBytes","getDiff","mirrorDiff"],"sourceRoot":"../../../src","sources":["store/baseline.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,iBAAiB,QAAQ,oBAAoB;AACtD,SAASC,oBAAoB,QAAQ,WAAW;AAChD,SAASC,WAAW,QAAQ,UAAU;AACtC,SAASC,WAAW,EAAEC,UAAU,QAAQ,cAAc;AACtD,SAASC,eAAe,QAAQ,wBAAwB;AAGxD,MAAMC,WAAW,GAAG,6BAA6B;;AAEjD;AACA,MAAMC,qBAAqB,GAAG,IAAI;;AAElC;AACA,OAAO,eAAeC,YAAYA,CAAA,EAAmC;EACnE,MAAMC,CAAC,GAAGP,WAAW,CAAC,CAAC;EACvB,IAAIO,CAAC,CAACC,cAAc,EAAE,OAAOD,CAAC,CAACE,QAAQ;EACvCF,CAAC,CAACC,cAAc,GAAG,IAAI;EACvB,IAAI;IACF,MAAME,GAAG,GAAG,MAAMZ,iBAAiB,CAACa,OAAO,CAACP,WAAW,CAAC;IACxD,IAAIM,GAAG,EAAE;MACP,MAAME,MAAM,GAAGC,IAAI,CAACC,KAAK,CAACJ,GAAG,CAAmB;MAChD,IAAIE,MAAM,IAAI,OAAOA,MAAM,CAACG,OAAO,KAAK,QAAQ,IAAIH,MAAM,CAACI,OAAO,EAAE;QAClET,CAAC,CAACE,QAAQ,GAAGG,MAAM;QACnBV,UAAU,CAAC,CAAC;MACd;IACF;EACF,CAAC,CAAC,MAAM;IACN;EAAA;EAEF,OAAOK,CAAC,CAACE,QAAQ;AACnB;AAEA,OAAO,eAAeQ,YAAYA,CAAA,EAA4B;EAC5D,MAAMC,MAAM,GAAGnB,oBAAoB,CAAC,CAAC;EACrC,IAAImB,MAAM,EAAE;IACV,MAAMA,MAAM,CAAC,cAAc,CAAC;IAC5B,OAAOlB,WAAW,CAAC,CAAC,CAACS,QAAQ,IAAI;MAAEM,OAAO,EAAEI,IAAI,CAACC,GAAG,CAAC,CAAC;MAAEJ,OAAO,EAAE,CAAC;IAAE,CAAC;EACvE;EACA,MAAMT,CAAC,GAAGP,WAAW,CAAC,CAAC;EACvB,MAAMgB,OAAkC,GAAG,CAAC,CAAC;EAC7C,KAAK,MAAMK,CAAC,IAAIpB,WAAW,CAAC,CAAC,EAAE;IAC7Be,OAAO,CAACK,CAAC,CAACC,GAAG,CAAC,GAAG;MACfC,IAAI,EAAEF,CAAC,CAACE,IAAI,IAAI,IAAI;MACpBC,SAAS,EAAEH,CAAC,CAACI,UAAU,KAAK,UAAU,GAAIJ,CAAC,CAACG,SAAS,IAAI,IAAI,GAAI,IAAI;MACrEE,IAAI,EAAEL,CAAC,CAACK,IAAI;MACZC,IAAI,EAAEN,CAAC,CAACM;IACV,CAAC;EACH;EACA,MAAMlB,QAAwB,GAAG;IAAEM,OAAO,EAAEI,IAAI,CAACC,GAAG,CAAC,CAAC;IAAEJ;EAAQ,CAAC;EACjET,CAAC,CAACE,QAAQ,GAAGA,QAAQ;EACrBF,CAAC,CAACC,cAAc,GAAG,IAAI;EACvBN,UAAU,CAAC,CAAC;EACZ,IAAI;IACF,MAAMJ,iBAAiB,CAAC8B,OAAO,CAACxB,WAAW,EAAES,IAAI,CAACgB,SAAS,CAACpB,QAAQ,CAAC,CAAC;EACxE,CAAC,CAAC,MAAM;IACN;EAAA;EAEF,OAAOA,QAAQ;AACjB;AAEA,OAAO,eAAeqB,aAAaA,CAAA,EAAkB;EACnD,MAAMZ,MAAM,GAAGnB,oBAAoB,CAAC,CAAC;EACrC,IAAImB,MAAM,EAAE;IACV,MAAMA,MAAM,CAAC,eAAe,CAAC;IAC7B;EACF;EACA,MAAMX,CAAC,GAAGP,WAAW,CAAC,CAAC;EACvBO,CAAC,CAACE,QAAQ,GAAG,IAAI;EACjBF,CAAC,CAACC,cAAc,GAAG,IAAI;EACvBN,UAAU,CAAC,CAAC;EACZ,IAAI;IACF,MAAMJ,iBAAiB,CAACiC,UAAU,CAAC3B,WAAW,CAAC;EACjD,CAAC,CAAC,MAAM;IACN;EAAA;AAEJ;AAEA,OAAO,SAAS4B,WAAWA,CACzBC,OAAsB,EACtBxB,QAAwB,EACZ;EACZ,MAAMyB,KAAe,GAAG,EAAE;EAC1B,MAAMC,KAAgD,GAAG,EAAE;EAC3D,MAAMC,IAAI,GAAG,IAAIC,GAAG,CAAS,CAAC;EAC9B,IAAIC,YAAY,GAAG,CAAC;EACpB,IAAIC,aAAa,GAAG,CAAC;EACrB,IAAIC,UAAU,GAAG,KAAK;EAEtB,KAAK,MAAMnB,CAAC,IAAIY,OAAO,EAAE;IACvBG,IAAI,CAACK,GAAG,CAACpB,CAAC,CAACC,GAAG,CAAC;IACf,MAAMoB,IAAI,GAAGjC,QAAQ,CAACO,OAAO,CAACK,CAAC,CAACC,GAAG,CAAC;IACpC,IAAI,CAACoB,IAAI,EAAE;MACTR,KAAK,CAACS,IAAI,CAACtB,CAAC,CAACuB,EAAE,CAAC;MAChB;IACF;IACA,MAAMxB,GAAG,GAAGC,CAAC,CAACI,UAAU,KAAK,UAAU,GAAIJ,CAAC,CAACG,SAAS,IAAI,IAAI,GAAI,IAAI;IACtE,IAAIJ,GAAG,IAAI,IAAI,IAAIsB,IAAI,CAAClB,SAAS,IAAI,IAAI,EAAE;MACzCgB,UAAU,GAAG,IAAI;MACjBF,YAAY,IAAIlB,GAAG;MACnBmB,aAAa,IAAIG,IAAI,CAAClB,SAAS;MAC/B,IAAIJ,GAAG,GAAGsB,IAAI,CAAClB,SAAS,IAAInB,qBAAqB,EAAE;QACjD8B,KAAK,CAACQ,IAAI,CAAC;UAAEC,EAAE,EAAEvB,CAAC,CAACuB,EAAE;UAAEC,UAAU,EAAEzB,GAAG,GAAGsB,IAAI,CAAClB;QAAU,CAAC,CAAC;MAC5D;IACF;EACF;EAEA,MAAMsB,OAA8B,GAAG,EAAE;EACzC,KAAK,MAAM,CAACxB,GAAG,EAAEyB,KAAK,CAAC,IAAIC,MAAM,CAAChC,OAAO,CAACP,QAAQ,CAACO,OAAO,CAAC,EAAE;IAC3D,IAAIb,eAAe,CAACmB,GAAG,CAAC,EAAE;IAC1B,IAAI,CAACc,IAAI,CAACa,GAAG,CAAC3B,GAAG,CAAC,EAAE;MAClBwB,OAAO,CAACH,IAAI,CAAC;QAAErB,GAAG;QAAEI,IAAI,EAAEqB,KAAK,CAACrB,IAAI;QAAEC,IAAI,EAAEoB,KAAK,CAACpB;MAAK,CAAC,CAAC;MACzD,IAAIoB,KAAK,CAACvB,SAAS,IAAI,IAAI,EAAE;QAC3B;QACA;QACA;QACA;QACA;QACAgB,UAAU,GAAG,IAAI;QACjBD,aAAa,IAAIQ,KAAK,CAACvB,SAAS;MAClC;IACF;EACF;EACA;EACA;EACA,KAAK,MAAMoB,EAAE,IAAIV,KAAK,EAAE;IACtB,MAAMb,CAAC,GAAGY,OAAO,CAACiB,IAAI,CAAEC,GAAG,IAAKA,GAAG,CAACP,EAAE,KAAKA,EAAE,CAAC;IAC9C,IAAIvB,CAAC,EAAEI,UAAU,KAAK,UAAU,IAAIJ,CAAC,CAACG,SAAS,IAAI,IAAI,EAAE;MACvDgB,UAAU,GAAG,IAAI;MACjBF,YAAY,IAAIjB,CAAC,CAACG,SAAS;IAC7B;EACF;EAEA,OAAO;IACL4B,eAAe,EAAE3C,QAAQ,CAACM,OAAO;IACjCmB,KAAK;IACLY,OAAO;IACPX,KAAK,EAAEA,KAAK,CAACkB,IAAI,CAAC,CAACC,CAAC,EAAEC,CAAC,KAAKA,CAAC,CAACV,UAAU,GAAGS,CAAC,CAACT,UAAU,CAAC;IACxDW,QAAQ,EAAEhB,UAAU,GAAGF,YAAY,GAAGC,aAAa,GAAG;EACxD,CAAC;AACH;;AAEA;AACA,OAAO,SAASkB,OAAOA,CAAA,EAAsB;EAC3C,MAAMlD,CAAC,GAAGP,WAAW,CAAC,CAAC;EACvB,IAAIO,CAAC,CAACmD,UAAU,EAAE,OAAOnD,CAAC,CAACmD,UAAU;EACrC,IAAI,CAACnD,CAAC,CAACE,QAAQ,EAAE,OAAO,IAAI;EAC5B,OAAOuB,WAAW,CAAC/B,WAAW,CAAC,CAAC,EAAEM,CAAC,CAACE,QAAQ,CAAC;AAC/C","ignoreList":[]}
|
|
@@ -1 +1,116 @@
|
|
|
1
|
-
"use strict";
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Derived insights over the asset inventory — the Lighthouse/Emerge-style
|
|
5
|
+
* audit findings, each pointing at concrete record ids.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { estDecodedBytes } from "./assetStore";
|
|
9
|
+
import { effectivePixelRatio } from "../utils/deviceScale";
|
|
10
|
+
/** png/jpeg at or above this measured size are flagged as WebP candidates. */
|
|
11
|
+
const WEBP_CANDIDATE_BYTES = 50 * 1024;
|
|
12
|
+
/** GIFs at or above this measured size decode into serious frame memory. */
|
|
13
|
+
const HEAVY_GIF_BYTES = 100 * 1024;
|
|
14
|
+
/** Fonts at or above this are usually unsubset icon fonts. */
|
|
15
|
+
const HEAVY_FONT_BYTES = 150 * 1024;
|
|
16
|
+
/** Flag images decoding to more pixels than this many screenfuls. */
|
|
17
|
+
const OVER_DECODE_SCREENS = 2;
|
|
18
|
+
/** A higher scale variant this much smaller than a lower one = bad export. */
|
|
19
|
+
const SCALE_ANOMALY_RATIO = 0.9;
|
|
20
|
+
/**
|
|
21
|
+
* Anomaly checks only apply when the smaller variant is at least this big —
|
|
22
|
+
* for tiny icons PNG overhead dominates and byte ordering is pure noise.
|
|
23
|
+
*/
|
|
24
|
+
const SCALE_ANOMALY_MIN_BYTES = 4 * 1024;
|
|
25
|
+
|
|
26
|
+
/** Physical pixels of the entire screen (fallback ≈ a 6.1" phone). */
|
|
27
|
+
function screenPixels() {
|
|
28
|
+
try {
|
|
29
|
+
const {
|
|
30
|
+
Dimensions,
|
|
31
|
+
PixelRatio
|
|
32
|
+
} = require("react-native");
|
|
33
|
+
const screen = Dimensions.get("screen");
|
|
34
|
+
const ratio = PixelRatio.get();
|
|
35
|
+
return screen.width * ratio * screen.height * ratio;
|
|
36
|
+
} catch {
|
|
37
|
+
return 1170 * 2532;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** True when the measured per-scale sizes contradict the scales (bad export). */
|
|
42
|
+
function hasScaleAnomaly(record) {
|
|
43
|
+
const sizes = record.sizesByScale;
|
|
44
|
+
if (!sizes) return false;
|
|
45
|
+
const ordered = Object.entries(sizes).map(([scale, bytes]) => ({
|
|
46
|
+
scale: Number(scale),
|
|
47
|
+
bytes
|
|
48
|
+
})).filter(e => Number.isFinite(e.scale) && e.bytes > 0).sort((a, b) => a.scale - b.scale);
|
|
49
|
+
for (let i = 1; i < ordered.length; i++) {
|
|
50
|
+
if (ordered[i - 1].bytes >= SCALE_ANOMALY_MIN_BYTES && ordered[i].bytes < ordered[i - 1].bytes * SCALE_ANOMALY_RATIO) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
export function computeInsights(list) {
|
|
57
|
+
const deviceScale = effectivePixelRatio();
|
|
58
|
+
const byHash = new Map();
|
|
59
|
+
for (const r of list) {
|
|
60
|
+
if (!r.hash) continue;
|
|
61
|
+
const group = byHash.get(r.hash);
|
|
62
|
+
if (group) group.push(r);else byHash.set(r.hash, [r]);
|
|
63
|
+
}
|
|
64
|
+
const duplicates = [];
|
|
65
|
+
for (const [hash, group] of byHash) {
|
|
66
|
+
if (group.length < 2) continue;
|
|
67
|
+
const measured = group.find(r => r.sizeBytes != null);
|
|
68
|
+
duplicates.push({
|
|
69
|
+
hash,
|
|
70
|
+
ids: group.map(r => r.id),
|
|
71
|
+
wastedBytes: measured?.sizeBytes != null ? measured.sizeBytes * (group.length - 1) : null
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
const screenPx = screenPixels();
|
|
75
|
+
const scaleGaps = [];
|
|
76
|
+
const webpCandidates = [];
|
|
77
|
+
const neverLoaded = [];
|
|
78
|
+
const overDecode = [];
|
|
79
|
+
const heavyGifs = [];
|
|
80
|
+
const heavyFonts = [];
|
|
81
|
+
const scaleAnomalies = [];
|
|
82
|
+
for (const r of list) {
|
|
83
|
+
if (!r.loaded) neverLoaded.push(r.id);
|
|
84
|
+
// Only multi-scale assets missing the device scale are flagged — the
|
|
85
|
+
// author clearly manages variants and missed one. Single-@1x images are
|
|
86
|
+
// the overwhelmingly common case and flagging them all is pure noise.
|
|
87
|
+
if (r.kind === "image" && r.scales.length > 1 && !r.scales.some(s => s >= deviceScale)) {
|
|
88
|
+
scaleGaps.push(r.id);
|
|
89
|
+
}
|
|
90
|
+
if ((r.type === "png" || r.type === "jpg" || r.type === "jpeg") && r.sizeBytes != null && r.sizeBytes >= WEBP_CANDIDATE_BYTES) {
|
|
91
|
+
webpCandidates.push(r.id);
|
|
92
|
+
}
|
|
93
|
+
// estDecodedBytes = pixels × 4, so pixels = bytes / 4.
|
|
94
|
+
if (r.kind === "image" && estDecodedBytes(r) / 4 > screenPx * OVER_DECODE_SCREENS) {
|
|
95
|
+
overDecode.push(r.id);
|
|
96
|
+
}
|
|
97
|
+
if (r.type === "gif" && (r.sizeBytes ?? 0) >= HEAVY_GIF_BYTES) {
|
|
98
|
+
heavyGifs.push(r.id);
|
|
99
|
+
}
|
|
100
|
+
if (r.kind === "font" && (r.sizeBytes ?? 0) >= HEAVY_FONT_BYTES) {
|
|
101
|
+
heavyFonts.push(r.id);
|
|
102
|
+
}
|
|
103
|
+
if (hasScaleAnomaly(r)) scaleAnomalies.push(r.id);
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
duplicates,
|
|
107
|
+
scaleGaps,
|
|
108
|
+
webpCandidates,
|
|
109
|
+
neverLoaded,
|
|
110
|
+
overDecode,
|
|
111
|
+
heavyGifs,
|
|
112
|
+
heavyFonts,
|
|
113
|
+
scaleAnomalies
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=insights.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["estDecodedBytes","effectivePixelRatio","WEBP_CANDIDATE_BYTES","HEAVY_GIF_BYTES","HEAVY_FONT_BYTES","OVER_DECODE_SCREENS","SCALE_ANOMALY_RATIO","SCALE_ANOMALY_MIN_BYTES","screenPixels","Dimensions","PixelRatio","require","screen","get","ratio","width","height","hasScaleAnomaly","record","sizes","sizesByScale","ordered","Object","entries","map","scale","bytes","Number","filter","e","isFinite","sort","a","b","i","length","computeInsights","list","deviceScale","byHash","Map","r","hash","group","push","set","duplicates","measured","find","sizeBytes","ids","id","wastedBytes","screenPx","scaleGaps","webpCandidates","neverLoaded","overDecode","heavyGifs","heavyFonts","scaleAnomalies","loaded","kind","scales","some","s","type"],"sourceRoot":"../../../src","sources":["store/insights.ts"],"mappings":"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","ignoreList":[]}
|