react-native-tapline 1.4.0 → 1.6.0
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/TaplineNative.podspec +3 -1
- package/dist/actions.d.ts +75 -2
- package/dist/actions.js +333 -25
- package/dist/actions.js.map +1 -1
- package/dist/alerts.d.ts +2 -0
- package/dist/alerts.js +5 -0
- package/dist/alerts.js.map +1 -1
- package/dist/anim.d.ts +25 -0
- package/dist/anim.js +311 -0
- package/dist/anim.js.map +1 -0
- package/dist/appinfo.d.ts +12 -0
- package/dist/appinfo.js +78 -0
- package/dist/appinfo.js.map +1 -0
- package/dist/checks.d.ts +43 -1
- package/dist/checks.js +17 -5
- package/dist/checks.js.map +1 -1
- package/dist/client.d.ts +2 -0
- package/dist/client.js +28 -2
- package/dist/client.js.map +1 -1
- package/dist/commands.js +28 -0
- package/dist/commands.js.map +1 -1
- package/dist/glass.d.ts +3 -0
- package/dist/glass.js +81 -0
- package/dist/glass.js.map +1 -0
- package/dist/glassclip.d.ts +18 -0
- package/dist/glassclip.js +69 -0
- package/dist/glassclip.js.map +1 -0
- package/dist/guard.d.ts +17 -0
- package/dist/guard.js +44 -0
- package/dist/guard.js.map +1 -0
- package/dist/idle.d.ts +43 -0
- package/dist/idle.js +379 -0
- package/dist/idle.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/inspect.d.ts +18 -1
- package/dist/inspect.js +48 -8
- package/dist/inspect.js.map +1 -1
- package/dist/loading.d.ts +17 -0
- package/dist/loading.js +96 -0
- package/dist/loading.js.map +1 -0
- package/dist/locale.js +1 -1
- package/dist/locale.js.map +1 -1
- package/dist/media.d.ts +71 -0
- package/dist/media.js +516 -0
- package/dist/media.js.map +1 -0
- package/dist/methods.js +14 -1
- package/dist/methods.js.map +1 -1
- package/dist/move.d.ts +40 -0
- package/dist/move.js +125 -0
- package/dist/move.js.map +1 -0
- package/dist/native.d.ts +5 -0
- package/dist/native.js.map +1 -1
- package/dist/network.d.ts +4 -0
- package/dist/network.js +49 -1
- package/dist/network.js.map +1 -1
- package/dist/place.d.ts +23 -0
- package/dist/place.js +66 -0
- package/dist/place.js.map +1 -0
- package/dist/placekey.d.ts +29 -0
- package/dist/placekey.js +134 -0
- package/dist/placekey.js.map +1 -0
- package/dist/routetree.d.ts +27 -0
- package/dist/routetree.js +216 -0
- package/dist/routetree.js.map +1 -0
- package/dist/types.d.ts +28 -2
- package/dist/types.js +5 -1
- package/dist/types.js.map +1 -1
- package/dist/uxcheck.d.ts +57 -0
- package/dist/uxcheck.js +222 -0
- package/dist/uxcheck.js.map +1 -0
- package/dist/wait.d.ts +5 -0
- package/dist/wait.js +34 -3
- package/dist/wait.js.map +1 -1
- package/ios/TaplineNativeModule.swift +61 -0
- package/package.json +1 -1
package/dist/uxcheck.js
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BASIS_WAY_BACK = exports.BASIS_DEAD_END = exports.BASIS_NAMING = exports.BASIS_ICON = exports.BASIS_THUMB = exports.BASIS_MAIN = exports.BASIS_CHOICES = exports.NEAR = exports.CLEAR_MARGIN = exports.TALL_SCREEN = exports.MAX_CHOICES = void 0;
|
|
4
|
+
exports.sameActionDifferentName = sameActionDifferentName;
|
|
5
|
+
exports.looksLikeMessage = looksLikeMessage;
|
|
6
|
+
exports.uxScreen = uxScreen;
|
|
7
|
+
const checks_1 = require("./checks");
|
|
8
|
+
const fiber_1 = require("./fiber");
|
|
9
|
+
const glassclip_1 = require("./glassclip");
|
|
10
|
+
const inspect_1 = require("./inspect");
|
|
11
|
+
/** More competing choices than this on one screen is flagged (Hick's law). */
|
|
12
|
+
exports.MAX_CHOICES = 7;
|
|
13
|
+
/** A phone at least this tall (points) has a top third out of the thumb's reach. */
|
|
14
|
+
exports.TALL_SCREEN = 700;
|
|
15
|
+
/** The top-ranked action must be this many times as prominent as the next to count as clear. */
|
|
16
|
+
exports.CLEAR_MARGIN = 1.5;
|
|
17
|
+
/** A filled button counts this many times its area. */
|
|
18
|
+
const FILL_WEIGHT = 2;
|
|
19
|
+
/** A fill needs this contrast against what is behind it to count as filled. */
|
|
20
|
+
const FILL_CONTRAST = 1.5;
|
|
21
|
+
/** An action this far (points) from a message counts as near it. */
|
|
22
|
+
exports.NEAR = 160;
|
|
23
|
+
/** A primary-looking button is a filled one at least this share of the screen width wide. */
|
|
24
|
+
const PRIMARY_WIDTH = 0.4;
|
|
25
|
+
exports.BASIS_CHOICES = `best practice: Hick's law, more than ${exports.MAX_CHOICES} choices`;
|
|
26
|
+
exports.BASIS_MAIN = 'best practice: one clear main action per screen';
|
|
27
|
+
exports.BASIS_THUMB = 'best practice: thumb zone, main actions belong in the lower part of a tall screen';
|
|
28
|
+
exports.BASIS_ICON = 'best practice: an icon-only button needs an accessibility label';
|
|
29
|
+
exports.BASIS_NAMING = 'best practice: name the same action the same way on every screen';
|
|
30
|
+
exports.BASIS_DEAD_END = 'best practice: an error or empty state says what to do next';
|
|
31
|
+
exports.BASIS_WAY_BACK = 'house rule: every screen has a way back';
|
|
32
|
+
/* -------------------------------------------------------------------------- */
|
|
33
|
+
/* Pure measurements */
|
|
34
|
+
/* -------------------------------------------------------------------------- */
|
|
35
|
+
const SYNONYMS = [
|
|
36
|
+
['save', 'done', 'submit', 'confirm', 'apply', 'ok'],
|
|
37
|
+
['cancel', 'dismiss', 'close', 'back'],
|
|
38
|
+
['delete', 'remove', 'trash', 'discard'],
|
|
39
|
+
['add', 'new', 'create'],
|
|
40
|
+
['edit', 'change', 'modify', 'update'],
|
|
41
|
+
['log in', 'login', 'sign in'],
|
|
42
|
+
['sign up', 'register', 'create account', 'join'],
|
|
43
|
+
['next', 'continue'],
|
|
44
|
+
['search', 'find'],
|
|
45
|
+
];
|
|
46
|
+
function normalise(label) {
|
|
47
|
+
return label.trim().toLowerCase().replace(/\s+/g, ' ');
|
|
48
|
+
}
|
|
49
|
+
function groupOf(label) {
|
|
50
|
+
return SYNONYMS.findIndex((group) => group.includes(label));
|
|
51
|
+
}
|
|
52
|
+
/** Names that are two names for one action: the same group of synonyms, but not the same words. */
|
|
53
|
+
function sameActionDifferentName(a, b) {
|
|
54
|
+
const x = normalise(a);
|
|
55
|
+
const y = normalise(b);
|
|
56
|
+
if (x === y || x === '' || y === '')
|
|
57
|
+
return false;
|
|
58
|
+
const group = groupOf(x);
|
|
59
|
+
return group >= 0 && group === groupOf(y);
|
|
60
|
+
}
|
|
61
|
+
const MESSAGE = /\b(error|errors|failed|failure|couldn['’]t|could not|can['’]t|cannot|something went wrong|nothing|empty)\b|^\s*no\s+\S/i;
|
|
62
|
+
/** Text that reads like an error or an empty-state message. */
|
|
63
|
+
function looksLikeMessage(text) {
|
|
64
|
+
return MESSAGE.test(text);
|
|
65
|
+
}
|
|
66
|
+
const BACK_NAME = /^(go back|back|close|cancel|dismiss|×|✕|✖|‹|<|x)$|^(back|close)\b/i;
|
|
67
|
+
const BACK_ID = /(^|[-_.])(back|close|dismiss)([-_.]|$)/i;
|
|
68
|
+
function nameOf(entry) {
|
|
69
|
+
const { label, text } = entry.info;
|
|
70
|
+
return (label !== null && label !== '' ? label : text).trim();
|
|
71
|
+
}
|
|
72
|
+
function isBackControl(entry) {
|
|
73
|
+
if (entry.navBack === true || entry.tab !== undefined)
|
|
74
|
+
return true;
|
|
75
|
+
if (!(0, checks_1.isTapTarget)(entry))
|
|
76
|
+
return false;
|
|
77
|
+
const id = entry.info.testID;
|
|
78
|
+
return BACK_NAME.test(nameOf(entry)) || (id !== null && BACK_ID.test(id));
|
|
79
|
+
}
|
|
80
|
+
/** The opaque fill of a button: its own background, else its parent's, if it stands out from what is behind. */
|
|
81
|
+
function fillOf(nodes, node) {
|
|
82
|
+
let current = node;
|
|
83
|
+
for (let level = 0; current && level < 2; level++) {
|
|
84
|
+
const raw = (0, checks_1.flatStyle)((0, fiber_1.propsOf)(current.fiber).style).backgroundColor;
|
|
85
|
+
const color = raw !== undefined && raw !== null ? (0, checks_1.parseColor)(raw) : null;
|
|
86
|
+
if (color !== null && color.a >= 1) {
|
|
87
|
+
const above = current.parent >= 0 ? nodes[current.parent] : undefined;
|
|
88
|
+
const behind = above !== undefined ? (0, checks_1.backgroundBehind)(nodes, above) : { found: false };
|
|
89
|
+
const reference = behind.found ? behind.color : { r: 255, g: 255, b: 255, a: 1 };
|
|
90
|
+
return (0, checks_1.contrastRatio)(color, reference) >= FILL_CONTRAST;
|
|
91
|
+
}
|
|
92
|
+
current = current.parent >= 0 ? nodes[current.parent] : undefined;
|
|
93
|
+
}
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
/* -------------------------------------------------------------------------- */
|
|
97
|
+
/* The check */
|
|
98
|
+
/* -------------------------------------------------------------------------- */
|
|
99
|
+
async function uxScreen(options = {}) {
|
|
100
|
+
const snapshot = (0, inspect_1.takeSnapshot)();
|
|
101
|
+
const { screen, nodes } = snapshot;
|
|
102
|
+
const candidates = snapshot.entries.filter((entry) => entry.info.interesting && !entry.tab);
|
|
103
|
+
const frames = await Promise.all(candidates.map((entry) => (0, inspect_1.measureFiber)(entry.node.fiber)));
|
|
104
|
+
const scrollers = options.glass === true ? await (0, glassclip_1.measureScrollers)(snapshot) : null;
|
|
105
|
+
const measured = [];
|
|
106
|
+
candidates.forEach((entry, i) => {
|
|
107
|
+
const frame = frames[i] ?? null;
|
|
108
|
+
if (frame === null || !(0, inspect_1.isOnScreen)(frame, screen))
|
|
109
|
+
return;
|
|
110
|
+
// In a user's eyes, what a scroll view clips or the keyboard covers isn't there for the check either.
|
|
111
|
+
if (scrollers !== null && (0, glassclip_1.visiblePartOnGlass)(snapshot, entry, frame, scrollers) === null)
|
|
112
|
+
return;
|
|
113
|
+
measured.push({ entry, frame });
|
|
114
|
+
});
|
|
115
|
+
const findings = [];
|
|
116
|
+
const add = (kind, item, problem, basis) => {
|
|
117
|
+
findings.push({ kind, entry: item?.entry ?? null, frame: item?.frame ?? null, problem, basis });
|
|
118
|
+
};
|
|
119
|
+
const checked = ['choices', 'main_action', 'thumb_reach', 'icon_only', 'cut_off_text', 'contrast', 'target_size', 'dead_end'];
|
|
120
|
+
// 1. Competing choices.
|
|
121
|
+
const taps = measured.filter((item) => (0, checks_1.isTapTarget)(item.entry));
|
|
122
|
+
if (taps.length > exports.MAX_CHOICES) {
|
|
123
|
+
add('choices', null, `${taps.length} choices compete for attention on this screen (more than ${exports.MAX_CHOICES})`, exports.BASIS_CHOICES);
|
|
124
|
+
}
|
|
125
|
+
// 2. One clear main action.
|
|
126
|
+
const buttons = taps
|
|
127
|
+
.filter((item) => item.entry.info.actions.includes('press') && !item.entry.info.actions.includes('toggle') && nameOf(item.entry) !== '')
|
|
128
|
+
.map((item) => {
|
|
129
|
+
const filled = fillOf(nodes, item.entry.node);
|
|
130
|
+
return { item, filled, score: item.frame.width * item.frame.height * (filled ? FILL_WEIGHT : 1) };
|
|
131
|
+
})
|
|
132
|
+
.sort((a, b) => b.score - a.score);
|
|
133
|
+
const [first, second] = buttons;
|
|
134
|
+
if (first !== undefined && second !== undefined && first.score < second.score * exports.CLEAR_MARGIN) {
|
|
135
|
+
const a = nameOf(first.item.entry);
|
|
136
|
+
const b = nameOf(second.item.entry);
|
|
137
|
+
if (first.filled && second.filled) {
|
|
138
|
+
add('main_action', first.item, `two actions look equally important: ${JSON.stringify(a)} and ${JSON.stringify(b)}`, exports.BASIS_MAIN);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
add('main_action', null, `no action stands out as the main one (largest: ${JSON.stringify(a)} and ${JSON.stringify(b)} are alike in size and look)`, exports.BASIS_MAIN);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// 3. Primary-looking buttons in the top third of a tall screen.
|
|
145
|
+
if (screen.height >= exports.TALL_SCREEN) {
|
|
146
|
+
for (const candidate of buttons) {
|
|
147
|
+
const { frame } = candidate.item;
|
|
148
|
+
if (!candidate.filled || frame.width < screen.width * PRIMARY_WIDTH)
|
|
149
|
+
continue;
|
|
150
|
+
if (frame.y + frame.height / 2 < screen.height / 3) {
|
|
151
|
+
add('thumb_reach', candidate.item, `a main-looking button sits in the top third of a ${(0, checks_1.num)(screen.height)} pt tall screen, out of easy thumb reach`, exports.BASIS_THUMB);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// 4. Icon-only buttons with no label; then cut-off text, contrast and target size (as audit).
|
|
156
|
+
for (const item of measured)
|
|
157
|
+
if ((0, checks_1.noName)(item) !== null)
|
|
158
|
+
add('icon_only', item, 'icon-only button with no accessibility label', exports.BASIS_ICON);
|
|
159
|
+
for (const item of measured) {
|
|
160
|
+
const truncated = (0, checks_1.maybeTruncated)(item, nodes);
|
|
161
|
+
if (truncated !== null)
|
|
162
|
+
add('cut_off_text', item, truncated, 'measured');
|
|
163
|
+
const cut = (0, checks_1.cutOff)(item, screen.width);
|
|
164
|
+
if (cut !== null)
|
|
165
|
+
add('cut_off_text', item, `it ${cut}`, 'measured');
|
|
166
|
+
const contrast = (0, checks_1.contrastOf)(item, nodes);
|
|
167
|
+
if (contrast !== null) {
|
|
168
|
+
add('contrast', item, `contrast ${(0, checks_1.num)(contrast.ratio)}:1 is below ${(0, checks_1.num)(contrast.required)}:1 (${contrast.foreground} on ${contrast.background})`, 'measured');
|
|
169
|
+
}
|
|
170
|
+
const systemSwitch = item.entry.info.type === 'Switch' && item.frame.width >= checks_1.MIN_TARGET && item.frame.height >= 24;
|
|
171
|
+
if ((0, checks_1.smallTarget)(item) !== null && !systemSwitch) {
|
|
172
|
+
add('target_size', item, `tap area ${(0, checks_1.num)(item.frame.width)}x${(0, checks_1.num)(item.frame.height)} pt is smaller than ${checks_1.MIN_TARGET}x${checks_1.MIN_TARGET}`, 'measured');
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
// 5. The same action named differently on screens seen in this journey.
|
|
176
|
+
const actions = taps.flatMap((item) => {
|
|
177
|
+
const label = nameOf(item.entry);
|
|
178
|
+
const id = item.entry.info.testID;
|
|
179
|
+
return label === '' ? [] : [{ label, ...(id !== null && id !== '' ? { id } : {}) }];
|
|
180
|
+
});
|
|
181
|
+
if (options.earlier !== undefined) {
|
|
182
|
+
checked.push('naming');
|
|
183
|
+
const told = new Set();
|
|
184
|
+
for (const item of taps) {
|
|
185
|
+
const label = nameOf(item.entry);
|
|
186
|
+
if (label === '')
|
|
187
|
+
continue;
|
|
188
|
+
const id = item.entry.info.testID;
|
|
189
|
+
const before = options.earlier.find((e) => normalise(e.label) !== normalise(label) && ((id !== null && id !== '' && e.id === id) || sameActionDifferentName(e.label, label)));
|
|
190
|
+
if (before === undefined)
|
|
191
|
+
continue;
|
|
192
|
+
const key = `${normalise(before.label)}|${normalise(label)}`;
|
|
193
|
+
if (told.has(key))
|
|
194
|
+
continue;
|
|
195
|
+
told.add(key);
|
|
196
|
+
add('naming', item, `the same action is ${JSON.stringify(label)} here and ${JSON.stringify(before.label)} on an earlier screen`, exports.BASIS_NAMING);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// 6. An error or empty state that doesn't say what to do next.
|
|
200
|
+
for (const item of measured) {
|
|
201
|
+
const { node, info } = item.entry;
|
|
202
|
+
if (!node.isText || info.text === '' || !looksLikeMessage(info.text))
|
|
203
|
+
continue;
|
|
204
|
+
if (taps.some((tap) => tap === item || (0, checks_1.isAncestor)(nodes, tap.entry.node, node)))
|
|
205
|
+
continue;
|
|
206
|
+
const near = taps.some((tap) => {
|
|
207
|
+
const gap = Math.max(tap.frame.y - (item.frame.y + item.frame.height), item.frame.y - (tap.frame.y + tap.frame.height), 0);
|
|
208
|
+
return gap <= exports.NEAR;
|
|
209
|
+
});
|
|
210
|
+
if (!near)
|
|
211
|
+
add('dead_end', item, 'it reports a problem or an empty state, and nothing near it says what to do next', exports.BASIS_DEAD_END);
|
|
212
|
+
}
|
|
213
|
+
// 7. House rule: a way back.
|
|
214
|
+
if (options.wayBack === true) {
|
|
215
|
+
checked.push('way_back');
|
|
216
|
+
const reachable = snapshot.entries.some((entry) => isBackControl(entry) && (entry.tab !== undefined || entry.navBack === true || measured.some((m) => m.entry === entry)));
|
|
217
|
+
if (!reachable)
|
|
218
|
+
add('way_back', null, 'no back button, close control or tab bar is visible', exports.BASIS_WAY_BACK);
|
|
219
|
+
}
|
|
220
|
+
return { findings, checked, choices: taps.length, actions };
|
|
221
|
+
}
|
|
222
|
+
//# sourceMappingURL=uxcheck.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uxcheck.js","sourceRoot":"","sources":["../src/uxcheck.ts"],"names":[],"mappings":"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"}
|
package/dist/wait.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
type IdleProvider = () => boolean;
|
|
2
2
|
/** Where "the network is quiet" comes from (the network tracker; tests). Null restores "always quiet". */
|
|
3
3
|
export declare function setNetworkIdleProvider(provider: IdleProvider | null): void;
|
|
4
|
+
export declare function waitFor(raw: {
|
|
5
|
+
once: true;
|
|
6
|
+
} & Record<string, unknown>): Promise<{
|
|
7
|
+
found: boolean;
|
|
8
|
+
}>;
|
|
4
9
|
export declare function waitFor(raw: unknown): Promise<{
|
|
5
10
|
met: true;
|
|
6
11
|
waitedMs: number;
|
package/dist/wait.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.setNetworkIdleProvider = setNetworkIdleProvider;
|
|
4
4
|
exports.waitFor = waitFor;
|
|
5
|
+
const glassclip_1 = require("./glassclip");
|
|
5
6
|
const inspect_1 = require("./inspect");
|
|
6
7
|
const types_1 = require("./types");
|
|
7
8
|
/**
|
|
@@ -35,10 +36,12 @@ function parse(raw) {
|
|
|
35
36
|
throw new types_1.TaplineError('bad_params', `timeout is in seconds, above 0 and at most ${MAX_TIMEOUT_S}`);
|
|
36
37
|
}
|
|
37
38
|
return {
|
|
39
|
+
once: raw.once === true,
|
|
38
40
|
...(text !== undefined ? { text } : {}),
|
|
39
41
|
...(testID !== undefined ? { testID } : {}),
|
|
40
42
|
...(label !== undefined ? { label } : {}),
|
|
41
43
|
gone: raw.gone === true,
|
|
44
|
+
glass: raw.glass === true,
|
|
42
45
|
networkIdle: wantsNetwork,
|
|
43
46
|
timeoutMs: timeout * 1000,
|
|
44
47
|
};
|
|
@@ -54,9 +57,34 @@ function matches(entry, condition) {
|
|
|
54
57
|
return false;
|
|
55
58
|
return true;
|
|
56
59
|
}
|
|
57
|
-
|
|
60
|
+
/** Whether an element matching the condition is there now (and, with `glass`, shows on the glass). */
|
|
61
|
+
async function presentNow(condition) {
|
|
62
|
+
const snapshot = (0, inspect_1.takeSnapshot)();
|
|
63
|
+
const found = snapshot.entries.filter((entry) => entry.info.interesting && matches(entry, condition));
|
|
64
|
+
if (!condition.glass)
|
|
65
|
+
return found.length > 0;
|
|
66
|
+
// A container's text holds everything inside it, clipped or not: only the innermost matches say what shows.
|
|
67
|
+
const innermost = found.filter((entry) => !found.some((other) => {
|
|
68
|
+
if (other === entry)
|
|
69
|
+
return false;
|
|
70
|
+
for (let p = other.node.parent; p >= 0; p = snapshot.nodes[p]?.parent ?? -1)
|
|
71
|
+
if (p === entry.node.index)
|
|
72
|
+
return true;
|
|
73
|
+
return false;
|
|
74
|
+
}));
|
|
75
|
+
// The scroll views are measured once for this poll, not once per candidate.
|
|
76
|
+
const scrollers = innermost.length > 0 ? await (0, glassclip_1.measureScrollers)(snapshot) : new Map();
|
|
77
|
+
for (const entry of innermost) {
|
|
78
|
+
// A native tab has no frame to measure: it is on the glass.
|
|
79
|
+
const frame = entry.tab ? null : await (0, inspect_1.measureFiber)(entry.node.fiber);
|
|
80
|
+
if ((0, glassclip_1.visiblePartOnGlass)(snapshot, entry, frame, scrollers) !== null)
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
async function satisfied(condition) {
|
|
58
86
|
if (condition.text !== undefined || condition.testID !== undefined || condition.label !== undefined) {
|
|
59
|
-
const present =
|
|
87
|
+
const present = await presentNow(condition);
|
|
60
88
|
if (present === condition.gone)
|
|
61
89
|
return false;
|
|
62
90
|
}
|
|
@@ -85,9 +113,12 @@ function describe(condition) {
|
|
|
85
113
|
}
|
|
86
114
|
async function waitFor(raw) {
|
|
87
115
|
const condition = parse(raw);
|
|
116
|
+
// Same matching as the polling path below, so the two never disagree about one screen.
|
|
117
|
+
if (condition.once)
|
|
118
|
+
return { found: await satisfied(condition) };
|
|
88
119
|
const started = Date.now();
|
|
89
120
|
for (;;) {
|
|
90
|
-
if (satisfied(condition))
|
|
121
|
+
if (await satisfied(condition))
|
|
91
122
|
return { met: true, waitedMs: Date.now() - started };
|
|
92
123
|
const waited = Date.now() - started;
|
|
93
124
|
if (waited >= condition.timeoutMs) {
|
package/dist/wait.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wait.js","sourceRoot":"","sources":["../src/wait.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"wait.js","sourceRoot":"","sources":["../src/wait.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,6 +9,7 @@ import UIKit
|
|
|
9
9
|
/// - `cover`: what UIKit presents over the app that React Native doesn't draw: an alert or action
|
|
10
10
|
/// sheet (`UIAlertController`, also the one `Alert.alert` shows) and the share sheet
|
|
11
11
|
/// (`UIActivityViewController`), with what an agent needs to name it.
|
|
12
|
+
/// - `setAnimationSpeed`: the speed of every window's layer, for fast-forwarded animations (1 is normal).
|
|
12
13
|
private enum TaplineWindows {
|
|
13
14
|
static func keyWindow() -> UIWindow? {
|
|
14
15
|
let scenes = UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }
|
|
@@ -17,6 +18,52 @@ private enum TaplineWindows {
|
|
|
17
18
|
return windows.first { $0.isKeyWindow } ?? windows.first
|
|
18
19
|
}
|
|
19
20
|
|
|
21
|
+
/// Every window of the app's scenes (the key window and any other the app or UIKit opened).
|
|
22
|
+
static func allWindows() -> [UIWindow] {
|
|
23
|
+
UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }.flatMap { $0.windows }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/// The speed the app's windows should have now (1 is normal); new windows get it too (see `setSpeed`).
|
|
27
|
+
private static var wanted: Float = 1
|
|
28
|
+
private static var visibleObserver: NSObjectProtocol?
|
|
29
|
+
|
|
30
|
+
/// Gives one window's layer `speed` without a jump or a freeze (Apple's QA1673 pattern for changing a layer's
|
|
31
|
+
/// timing). Changing `speed` alone moves the layer's local time, which stops repeating animations (an
|
|
32
|
+
/// ActivityIndicator) after a few flips. So the local time now is read first and kept: it becomes the time offset,
|
|
33
|
+
/// counted from now.
|
|
34
|
+
private static func apply(_ speed: Float, to window: UIWindow) {
|
|
35
|
+
let layer = window.layer
|
|
36
|
+
guard layer.speed != speed else { return }
|
|
37
|
+
let now = CACurrentMediaTime()
|
|
38
|
+
let local = layer.convertTime(now, from: nil)
|
|
39
|
+
CATransaction.begin()
|
|
40
|
+
CATransaction.setDisableActions(true)
|
|
41
|
+
layer.speed = speed
|
|
42
|
+
layer.timeOffset = local
|
|
43
|
+
layer.beginTime = now
|
|
44
|
+
CATransaction.commit()
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/// Sets every window's layer speed (1 is normal) from any thread. While the speed is not 1, a window that
|
|
48
|
+
/// becomes visible later (React Native's alert window, a scene's window) gets it too; at 1 the observer goes.
|
|
49
|
+
static func setSpeed(_ speed: Float) {
|
|
50
|
+
let run = {
|
|
51
|
+
wanted = speed
|
|
52
|
+
for window in allWindows() { apply(speed, to: window) }
|
|
53
|
+
if speed != 1 {
|
|
54
|
+
if visibleObserver == nil {
|
|
55
|
+
visibleObserver = NotificationCenter.default.addObserver(forName: UIWindow.didBecomeVisibleNotification, object: nil, queue: .main) { note in
|
|
56
|
+
if let window = note.object as? UIWindow { apply(wanted, to: window) }
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
} else if let observer = visibleObserver {
|
|
60
|
+
NotificationCenter.default.removeObserver(observer)
|
|
61
|
+
visibleObserver = nil
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if Thread.isMainThread { run() } else { DispatchQueue.main.async(execute: run) }
|
|
65
|
+
}
|
|
66
|
+
|
|
20
67
|
/// The view controllers presented over the root, front last.
|
|
21
68
|
static func presented(from root: UIViewController?) -> [UIViewController] {
|
|
22
69
|
var chain: [UIViewController] = []
|
|
@@ -56,6 +103,20 @@ public final class TaplineNativeModule: Module {
|
|
|
56
103
|
}
|
|
57
104
|
}.runOnQueue(.main)
|
|
58
105
|
|
|
106
|
+
/// Sets the speed of the app's windows' layers (PLAN-1.6 F4; the trick EarlGrey and KIF use). 1 is normal; a
|
|
107
|
+
/// larger number makes every UIKit and Core Animation animation in those windows (native-stack pushes, sheets,
|
|
108
|
+
/// alerts) finish that many times sooner. Windows that open while the speed is not 1 get it as they appear.
|
|
109
|
+
/// Timers and JavaScript are not touched. The JavaScript side puts 1 back on `normal`, on a disconnect and when
|
|
110
|
+
/// the session ends.
|
|
111
|
+
AsyncFunction("setAnimationSpeed") { (speed: Double) in
|
|
112
|
+
let safe = speed.isFinite ? min(max(speed, 1), 1000) : 1
|
|
113
|
+
TaplineWindows.setSpeed(Float(safe))
|
|
114
|
+
}.runOnQueue(.main)
|
|
115
|
+
|
|
116
|
+
// A JavaScript reload (or a new runtime) makes a new module: the windows are never left fast-forwarded.
|
|
117
|
+
OnCreate { TaplineWindows.setSpeed(1) }
|
|
118
|
+
OnDestroy { TaplineWindows.setSpeed(1) }
|
|
119
|
+
|
|
59
120
|
/// What UIKit shows in front of the app: `kind` is "alert", "actionSheet", "share" or "" (nothing).
|
|
60
121
|
AsyncFunction("cover") { () -> [String: Any] in
|
|
61
122
|
let chain = TaplineWindows.presented(from: TaplineWindows.keyWindow()?.rootViewController)
|
package/package.json
CHANGED