yaver-feedback-react-native 0.9.7 → 0.9.8
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/README.md +39 -7
- package/android/src/main/java/io/yaver/feedback/YaverDogfoodGestureModule.java +241 -0
- package/android/src/main/java/io/yaver/feedback/YaverHotReloadPackage.java +1 -0
- package/app.plugin.js +12 -2
- package/dist/AuthOverlay.js +13 -2
- package/dist/DogfoodQuickControls.d.ts +8 -0
- package/dist/DogfoodQuickControls.js +394 -0
- package/dist/DogfoodSessionUi.d.ts +50 -0
- package/dist/DogfoodSessionUi.js +135 -0
- package/dist/FeedbackModal.js +50 -22
- package/dist/YaverFeedback.d.ts +35 -1
- package/dist/YaverFeedback.js +302 -12
- package/dist/__tests__/NativeDogfoodShortcut.test.js +14 -0
- package/dist/__tests__/YaverFeedback.test.js +148 -0
- package/dist/auth.d.ts +15 -0
- package/dist/auth.js +41 -2
- package/dist/dogfoodPolicy.d.ts +22 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +8 -2
- package/dist/preferences.d.ts +13 -0
- package/dist/preferences.js +84 -0
- package/ios/YaverDogfoodGesture.m +14 -0
- package/ios/YaverDogfoodGesture.swift +175 -0
- package/package.json +1 -1
- package/src/AuthOverlay.tsx +20 -3
- package/src/DogfoodQuickControls.tsx +454 -0
- package/src/DogfoodSessionUi.tsx +213 -0
- package/src/FeedbackModal.tsx +62 -34
- package/src/YaverFeedback.ts +333 -12
- package/src/__tests__/NativeDogfoodShortcut.test.ts +15 -0
- package/src/__tests__/YaverFeedback.test.ts +155 -0
- package/src/auth.ts +53 -2
- package/src/dogfoodPolicy.ts +22 -1
- package/src/index.ts +13 -1
- package/src/preferences.ts +89 -0
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const react_native_1 = require("react-native");
|
|
4
4
|
const YaverFeedback_1 = require("../YaverFeedback");
|
|
5
|
+
const auth_1 = require("../auth");
|
|
5
6
|
// Mock react-native: DeviceEventEmitter for event dispatch + Platform so
|
|
6
7
|
// ShakeDetector.start() can branch on iOS without hitting a real RN runtime.
|
|
7
8
|
jest.mock('react-native', () => ({
|
|
@@ -15,6 +16,10 @@ jest.mock('react-native', () => ({
|
|
|
15
16
|
setDogfoodShortcut: jest.fn(async () => true),
|
|
16
17
|
consumeDogfoodShortcut: jest.fn(async () => false),
|
|
17
18
|
},
|
|
19
|
+
YaverDogfoodGesture: {
|
|
20
|
+
getCapability: jest.fn(async () => ({ supported: true, enabled: false, reason: 'supported', platform: 'ios' })),
|
|
21
|
+
setEnabled: jest.fn(async (next) => ({ supported: true, enabled: next, reason: 'supported', platform: 'ios' })),
|
|
22
|
+
},
|
|
18
23
|
},
|
|
19
24
|
AppState: { addEventListener: jest.fn(() => ({ remove: jest.fn() })) },
|
|
20
25
|
}));
|
|
@@ -32,8 +37,10 @@ jest.mock('../auth', () => ({
|
|
|
32
37
|
getDogfoodAccountAccess: jest.fn(async (_appId, token) => ({
|
|
33
38
|
authenticated: token === 'owner-token',
|
|
34
39
|
ownerAuthorized: token === 'owner-token',
|
|
40
|
+
accountAuthorized: token === 'owner-token',
|
|
35
41
|
installationAuthorized: token === 'owner-token',
|
|
36
42
|
})),
|
|
43
|
+
setDogfoodControlPreference: jest.fn(async () => true),
|
|
37
44
|
saveSelectedDeviceId: jest.fn(async () => { }),
|
|
38
45
|
clearToken: jest.fn(async () => { }),
|
|
39
46
|
clearSelectedDeviceId: jest.fn(async () => { }),
|
|
@@ -96,6 +103,17 @@ describe('YaverFeedback', () => {
|
|
|
96
103
|
unsubscribe();
|
|
97
104
|
expect(states[states.length - 1]).toBe('auth-required');
|
|
98
105
|
});
|
|
106
|
+
it('returns a visible structured error when access verification fails', async () => {
|
|
107
|
+
YaverFeedback_1.YaverFeedback.init({ enabled: true, authToken: 'owner-token' });
|
|
108
|
+
auth_1.getDogfoodAccountAccess.mockRejectedValueOnce(new Error('Access service unavailable'));
|
|
109
|
+
const state = await YaverFeedback_1.YaverFeedback.beginDogfoodOnboarding({ appId: 'io.example.app' });
|
|
110
|
+
expect(state).toEqual({
|
|
111
|
+
phase: 'error',
|
|
112
|
+
appId: 'io.example.app',
|
|
113
|
+
error: 'Access service unavailable',
|
|
114
|
+
});
|
|
115
|
+
expect(react_native_1.DeviceEventEmitter.emit).not.toHaveBeenCalledWith('yaverFeedback:startReport');
|
|
116
|
+
});
|
|
99
117
|
it('lets a host ACL hide its affordance without opening auth UI', async () => {
|
|
100
118
|
YaverFeedback_1.YaverFeedback.init({
|
|
101
119
|
enabled: true,
|
|
@@ -113,6 +131,7 @@ describe('YaverFeedback', () => {
|
|
|
113
131
|
appId: 'io.example.app',
|
|
114
132
|
yaverAuthenticated: true,
|
|
115
133
|
ownerAuthorized: false,
|
|
134
|
+
accountAuthorized: true,
|
|
116
135
|
installationId: 'phone-1',
|
|
117
136
|
deviceState: 'active',
|
|
118
137
|
authorized: true,
|
|
@@ -128,6 +147,7 @@ describe('YaverFeedback', () => {
|
|
|
128
147
|
appId: 'io.example.app',
|
|
129
148
|
yaverAuthenticated: false,
|
|
130
149
|
ownerAuthorized: false,
|
|
150
|
+
accountAuthorized: true,
|
|
131
151
|
installationId: 'phone-1',
|
|
132
152
|
deviceState: 'active',
|
|
133
153
|
authorized: false,
|
|
@@ -145,6 +165,7 @@ describe('YaverFeedback', () => {
|
|
|
145
165
|
appId: 'io.example.app',
|
|
146
166
|
yaverAuthenticated: true,
|
|
147
167
|
ownerAuthorized: false,
|
|
168
|
+
accountAuthorized: true,
|
|
148
169
|
installationId: 'phone-1',
|
|
149
170
|
deviceState: 'active',
|
|
150
171
|
authorized: true,
|
|
@@ -153,6 +174,133 @@ describe('YaverFeedback', () => {
|
|
|
153
174
|
expect(react_native_1.NativeModules.YaverHotReload.setDogfoodShortcut)
|
|
154
175
|
.toHaveBeenCalledWith(false, 'Dogfood');
|
|
155
176
|
});
|
|
177
|
+
it('keeps the Y visible until the authorized phone has completed onboarding', async () => {
|
|
178
|
+
YaverFeedback_1.YaverFeedback.init({ bundleId: 'io.example.app', dogfood: {} });
|
|
179
|
+
YaverFeedback_1.YaverFeedback.getConfig().dogfood.controlGesture = true;
|
|
180
|
+
jest.spyOn(YaverFeedback_1.YaverFeedback, 'getDogfoodAccess').mockResolvedValueOnce({
|
|
181
|
+
appId: 'io.example.app',
|
|
182
|
+
yaverAuthenticated: true,
|
|
183
|
+
ownerAuthorized: false,
|
|
184
|
+
accountAuthorized: true,
|
|
185
|
+
installationId: 'phone-1',
|
|
186
|
+
deviceState: 'active',
|
|
187
|
+
authorized: true,
|
|
188
|
+
});
|
|
189
|
+
const state = await YaverFeedback_1.YaverFeedback.syncDogfoodControlGesture();
|
|
190
|
+
expect(state).toMatchObject({
|
|
191
|
+
onboardingSeen: false,
|
|
192
|
+
presentation: 'minimized-y',
|
|
193
|
+
gestureSupported: true,
|
|
194
|
+
gestureEnabled: false,
|
|
195
|
+
fallbackVisible: true,
|
|
196
|
+
});
|
|
197
|
+
expect(react_native_1.NativeModules.YaverDogfoodGesture.setEnabled).toHaveBeenCalledWith(false, 900);
|
|
198
|
+
});
|
|
199
|
+
it('uses the invisible three-finger hold only after onboarding selects it', async () => {
|
|
200
|
+
YaverFeedback_1.YaverFeedback.init({ bundleId: 'io.example.app', dogfood: {} });
|
|
201
|
+
YaverFeedback_1.YaverFeedback.getConfig().dogfood.controlGesture = true;
|
|
202
|
+
jest.spyOn(YaverFeedback_1.YaverFeedback, 'getDogfoodAccess').mockResolvedValueOnce({
|
|
203
|
+
appId: 'io.example.app',
|
|
204
|
+
yaverAuthenticated: true,
|
|
205
|
+
ownerAuthorized: false,
|
|
206
|
+
accountAuthorized: true,
|
|
207
|
+
installationId: 'phone-1',
|
|
208
|
+
deviceState: 'active',
|
|
209
|
+
authorized: true,
|
|
210
|
+
controlPresentation: 'auto',
|
|
211
|
+
controlOnboardingSeen: true,
|
|
212
|
+
});
|
|
213
|
+
const state = await YaverFeedback_1.YaverFeedback.syncDogfoodControlGesture();
|
|
214
|
+
expect(state).toMatchObject({
|
|
215
|
+
onboardingSeen: true,
|
|
216
|
+
presentation: 'auto',
|
|
217
|
+
gestureSupported: true,
|
|
218
|
+
gestureEnabled: true,
|
|
219
|
+
fallbackVisible: false,
|
|
220
|
+
});
|
|
221
|
+
expect(react_native_1.NativeModules.YaverDogfoodGesture.setEnabled).toHaveBeenCalledWith(true, 900);
|
|
222
|
+
});
|
|
223
|
+
it('keeps the Y when native capability reports support but enabling the gesture fails', async () => {
|
|
224
|
+
YaverFeedback_1.YaverFeedback.init({ bundleId: 'io.example.app', dogfood: {} });
|
|
225
|
+
YaverFeedback_1.YaverFeedback.getConfig().dogfood.controlGesture = true;
|
|
226
|
+
jest.spyOn(YaverFeedback_1.YaverFeedback, 'getDogfoodAccess').mockResolvedValueOnce({
|
|
227
|
+
appId: 'io.example.app',
|
|
228
|
+
yaverAuthenticated: true,
|
|
229
|
+
ownerAuthorized: false,
|
|
230
|
+
accountAuthorized: true,
|
|
231
|
+
installationId: 'phone-1',
|
|
232
|
+
deviceState: 'active',
|
|
233
|
+
authorized: true,
|
|
234
|
+
controlPresentation: 'auto',
|
|
235
|
+
controlOnboardingSeen: true,
|
|
236
|
+
});
|
|
237
|
+
react_native_1.NativeModules.YaverDogfoodGesture.setEnabled.mockResolvedValueOnce({
|
|
238
|
+
supported: true,
|
|
239
|
+
enabled: false,
|
|
240
|
+
reason: 'supported',
|
|
241
|
+
platform: 'ios',
|
|
242
|
+
});
|
|
243
|
+
const state = await YaverFeedback_1.YaverFeedback.syncDogfoodControlGesture();
|
|
244
|
+
expect(state).toMatchObject({
|
|
245
|
+
gestureSupported: true,
|
|
246
|
+
gestureEnabled: false,
|
|
247
|
+
fallbackVisible: true,
|
|
248
|
+
reason: 'gesture-enable-failed',
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
it('persists first-run completion for the exact account app installation', async () => {
|
|
252
|
+
YaverFeedback_1.YaverFeedback.init({ authToken: 'owner-token', bundleId: 'io.example.app', dogfood: {} });
|
|
253
|
+
YaverFeedback_1.YaverFeedback.getConfig().dogfood.controlGesture = true;
|
|
254
|
+
jest.spyOn(YaverFeedback_1.YaverFeedback, 'getDogfoodAccess').mockResolvedValueOnce({
|
|
255
|
+
appId: 'io.example.app',
|
|
256
|
+
yaverAuthenticated: true,
|
|
257
|
+
ownerAuthorized: true,
|
|
258
|
+
accountAuthorized: true,
|
|
259
|
+
installationId: 'phone-1',
|
|
260
|
+
deviceState: 'active',
|
|
261
|
+
authorized: true,
|
|
262
|
+
controlOnboardingSeen: false,
|
|
263
|
+
});
|
|
264
|
+
const state = await YaverFeedback_1.YaverFeedback.setDogfoodControlPresentation('minimized-y');
|
|
265
|
+
expect(state).toMatchObject({ onboardingSeen: true, presentation: 'minimized-y', fallbackVisible: true });
|
|
266
|
+
expect(auth_1.setDogfoodControlPreference).toHaveBeenCalledWith(expect.objectContaining({
|
|
267
|
+
appId: 'io.example.app',
|
|
268
|
+
installationId: 'phone-1',
|
|
269
|
+
token: 'owner-token',
|
|
270
|
+
presentation: 'minimized-y',
|
|
271
|
+
controlOnboardingSeen: true,
|
|
272
|
+
}));
|
|
273
|
+
});
|
|
274
|
+
it('falls back to the minimized Y when accessibility owns multi-touch', async () => {
|
|
275
|
+
YaverFeedback_1.YaverFeedback.init({ bundleId: 'io.example.app', dogfood: {} });
|
|
276
|
+
YaverFeedback_1.YaverFeedback.getConfig().dogfood.controlGesture = { durationMs: 1200 };
|
|
277
|
+
jest.spyOn(YaverFeedback_1.YaverFeedback, 'getDogfoodAccess').mockResolvedValueOnce({
|
|
278
|
+
appId: 'io.example.app',
|
|
279
|
+
yaverAuthenticated: true,
|
|
280
|
+
ownerAuthorized: false,
|
|
281
|
+
accountAuthorized: true,
|
|
282
|
+
installationId: 'phone-1',
|
|
283
|
+
deviceState: 'active',
|
|
284
|
+
authorized: true,
|
|
285
|
+
});
|
|
286
|
+
react_native_1.NativeModules.YaverDogfoodGesture.getCapability.mockResolvedValueOnce({
|
|
287
|
+
supported: false,
|
|
288
|
+
enabled: false,
|
|
289
|
+
reason: 'accessibility-touch-exploration',
|
|
290
|
+
platform: 'ios',
|
|
291
|
+
});
|
|
292
|
+
const state = await YaverFeedback_1.YaverFeedback.syncDogfoodControlGesture();
|
|
293
|
+
expect(state).toMatchObject({ gestureSupported: false, gestureEnabled: false, fallbackVisible: true });
|
|
294
|
+
expect(react_native_1.NativeModules.YaverDogfoodGesture.setEnabled).toHaveBeenCalledWith(false, 1200);
|
|
295
|
+
});
|
|
296
|
+
it('suppresses guest controls inside the Yaver split-view container', async () => {
|
|
297
|
+
YaverFeedback_1.YaverFeedback.init({ bundleId: 'io.example.app', dogfood: {} });
|
|
298
|
+
YaverFeedback_1.YaverFeedback.getConfig().dogfood.controlGesture = true;
|
|
299
|
+
react_native_1.NativeModules.YaverInfo = { isYaver: true };
|
|
300
|
+
const state = await YaverFeedback_1.YaverFeedback.syncDogfoodControlGesture();
|
|
301
|
+
delete react_native_1.NativeModules.YaverInfo;
|
|
302
|
+
expect(state).toMatchObject({ gestureEnabled: false, fallbackVisible: false, reason: 'yaver-host-owns-controls' });
|
|
303
|
+
});
|
|
156
304
|
});
|
|
157
305
|
describe('init()', () => {
|
|
158
306
|
it('sets config correctly with defaults', () => {
|
package/dist/auth.d.ts
CHANGED
|
@@ -52,8 +52,23 @@ export declare function clearSelectedDeviceId(): Promise<void>;
|
|
|
52
52
|
export declare function getDogfoodAccountAccess(appId: string, token: string, installationId?: string): Promise<{
|
|
53
53
|
authenticated: boolean;
|
|
54
54
|
ownerAuthorized: boolean;
|
|
55
|
+
accountAuthorized: boolean;
|
|
55
56
|
installationAuthorized: boolean;
|
|
57
|
+
controlPresentation?: 'auto' | 'minimized-y';
|
|
58
|
+
gestureSupported?: boolean;
|
|
59
|
+
gestureCapabilityReason?: string;
|
|
60
|
+
controlOnboardingSeen?: boolean;
|
|
56
61
|
}>;
|
|
62
|
+
export declare function setDogfoodControlPreference(input: {
|
|
63
|
+
appId: string;
|
|
64
|
+
installationId: string;
|
|
65
|
+
token: string;
|
|
66
|
+
presentation: 'auto' | 'minimized-y';
|
|
67
|
+
gestureSupported: boolean;
|
|
68
|
+
gestureCapabilityReason: string;
|
|
69
|
+
gesturePlatform: string;
|
|
70
|
+
controlOnboardingSeen?: boolean;
|
|
71
|
+
}): Promise<boolean>;
|
|
57
72
|
export declare function validateToken(token: string): Promise<User | null>;
|
|
58
73
|
/**
|
|
59
74
|
* Sign in with Apple using the native ASAuthorization flow. Requires
|
package/dist/auth.js
CHANGED
|
@@ -32,6 +32,7 @@ exports.getSelectedDeviceId = getSelectedDeviceId;
|
|
|
32
32
|
exports.saveSelectedDeviceId = saveSelectedDeviceId;
|
|
33
33
|
exports.clearSelectedDeviceId = clearSelectedDeviceId;
|
|
34
34
|
exports.getDogfoodAccountAccess = getDogfoodAccountAccess;
|
|
35
|
+
exports.setDogfoodControlPreference = setDogfoodControlPreference;
|
|
35
36
|
exports.validateToken = validateToken;
|
|
36
37
|
exports.signInWithApple = signInWithApple;
|
|
37
38
|
exports.signInWithOAuth = signInWithOAuth;
|
|
@@ -202,16 +203,54 @@ async function getDogfoodAccountAccess(appId, token, installationId) {
|
|
|
202
203
|
});
|
|
203
204
|
clearTimeout(timeout);
|
|
204
205
|
if (!response.ok)
|
|
205
|
-
return { authenticated: false, ownerAuthorized: false, installationAuthorized: false };
|
|
206
|
+
return { authenticated: false, ownerAuthorized: false, accountAuthorized: false, installationAuthorized: false };
|
|
206
207
|
const result = await response.json();
|
|
207
208
|
return {
|
|
208
209
|
authenticated: result?.authenticated === true,
|
|
209
210
|
ownerAuthorized: result?.ownerAuthorized === true,
|
|
211
|
+
accountAuthorized: result?.accountAuthorized === true,
|
|
210
212
|
installationAuthorized: result?.installationAuthorized === true,
|
|
213
|
+
controlPresentation: result?.controlPresentation === 'minimized-y' ? 'minimized-y'
|
|
214
|
+
: result?.controlPresentation === 'auto' ? 'auto' : undefined,
|
|
215
|
+
gestureSupported: typeof result?.gestureSupported === 'boolean' ? result.gestureSupported : undefined,
|
|
216
|
+
gestureCapabilityReason: typeof result?.gestureCapabilityReason === 'string'
|
|
217
|
+
? result.gestureCapabilityReason
|
|
218
|
+
: undefined,
|
|
219
|
+
controlOnboardingSeen: result?.controlOnboardingSeen === true,
|
|
211
220
|
};
|
|
212
221
|
}
|
|
213
222
|
catch {
|
|
214
|
-
return { authenticated: false, ownerAuthorized: false, installationAuthorized: false };
|
|
223
|
+
return { authenticated: false, ownerAuthorized: false, accountAuthorized: false, installationAuthorized: false };
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
async function setDogfoodControlPreference(input) {
|
|
227
|
+
const controller = new AbortController();
|
|
228
|
+
const timeout = setTimeout(() => controller.abort(), 5000);
|
|
229
|
+
try {
|
|
230
|
+
const response = await fetch(`${convexSiteUrl}/dogfood/control-preference`, {
|
|
231
|
+
method: 'POST',
|
|
232
|
+
headers: {
|
|
233
|
+
Authorization: `Bearer ${input.token}`,
|
|
234
|
+
'Content-Type': 'application/json',
|
|
235
|
+
},
|
|
236
|
+
body: JSON.stringify({
|
|
237
|
+
appId: input.appId,
|
|
238
|
+
installationId: input.installationId,
|
|
239
|
+
presentation: input.presentation,
|
|
240
|
+
gestureSupported: input.gestureSupported,
|
|
241
|
+
gestureCapabilityReason: input.gestureCapabilityReason,
|
|
242
|
+
gesturePlatform: input.gesturePlatform,
|
|
243
|
+
controlOnboardingSeen: input.controlOnboardingSeen === true,
|
|
244
|
+
}),
|
|
245
|
+
signal: controller.signal,
|
|
246
|
+
});
|
|
247
|
+
return response.ok;
|
|
248
|
+
}
|
|
249
|
+
catch {
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
finally {
|
|
253
|
+
clearTimeout(timeout);
|
|
215
254
|
}
|
|
216
255
|
}
|
|
217
256
|
// ─── Token validation ──────────────────────────────────────────────────
|
package/dist/dogfoodPolicy.d.ts
CHANGED
|
@@ -4,10 +4,18 @@ export interface DogfoodAccessSnapshot {
|
|
|
4
4
|
yaverAuthenticated: boolean;
|
|
5
5
|
/** Backend-confirmed owner/maintainer of this exact appId. */
|
|
6
6
|
ownerAuthorized: boolean;
|
|
7
|
+
/** Backend-confirmed app assignment for this Yaver account. App owners are
|
|
8
|
+
* assigned implicitly; other accounts require an active owner grant. */
|
|
9
|
+
accountAuthorized: boolean;
|
|
7
10
|
installationId?: string;
|
|
8
11
|
deviceState: 'unknown' | 'unregistered' | 'pending' | 'active' | 'cancelled' | 'revoked' | 'superseded';
|
|
9
|
-
/** True only for
|
|
12
|
+
/** True only for an assigned account and this backend-approved device key. */
|
|
10
13
|
authorized: boolean;
|
|
14
|
+
/** OAuth-backed preference scoped to this user + app + installation. */
|
|
15
|
+
controlPresentation?: 'auto' | 'minimized-y';
|
|
16
|
+
gestureSupported?: boolean;
|
|
17
|
+
gestureCapabilityReason?: string;
|
|
18
|
+
controlOnboardingSeen?: boolean;
|
|
11
19
|
}
|
|
12
20
|
export interface DogfoodFlowSnapshot {
|
|
13
21
|
phase: 'idle' | 'denied' | 'auth-required' | 'machine-required' | 'opening' | 'error';
|
|
@@ -44,6 +52,19 @@ export interface SDKDogfoodConfig {
|
|
|
44
52
|
appShortcut?: boolean | {
|
|
45
53
|
label?: string;
|
|
46
54
|
};
|
|
55
|
+
/** Smart in-app quick controls. On supported standalone iOS/Android builds,
|
|
56
|
+
* a three-finger hold opens a two-action card with no persistent overlay.
|
|
57
|
+
* Unsupported/accessibility-conflicted devices may show a minimized,
|
|
58
|
+
* draggable Y fallback. Yaver host/container mode suppresses both. */
|
|
59
|
+
controlGesture?: boolean | {
|
|
60
|
+
/** Hold duration, clamped to 650–2000 ms. Default 900 ms. */
|
|
61
|
+
durationMs?: number;
|
|
62
|
+
/** Default `minimized-y`; use `none` when Settings is the only fallback. */
|
|
63
|
+
fallback?: 'minimized-y' | 'none';
|
|
64
|
+
/** Initial user-facing presentation before their persisted SDK preference
|
|
65
|
+
* exists. `auto` keeps pixels clear when the gesture works. */
|
|
66
|
+
defaultPresentation?: 'auto' | 'minimized-y';
|
|
67
|
+
};
|
|
47
68
|
}
|
|
48
69
|
export interface SDKDogfoodStatus {
|
|
49
70
|
active: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
* ```
|
|
29
29
|
*/
|
|
30
30
|
export { YaverFeedback } from './YaverFeedback';
|
|
31
|
-
export type { DogfoodOnboardingOptions, DogfoodFlowPhase, DogfoodFlowState } from './YaverFeedback';
|
|
31
|
+
export type { DogfoodOnboardingOptions, DogfoodFlowPhase, DogfoodFlowState, DogfoodControlTriggerState, } from './YaverFeedback';
|
|
32
32
|
export { captureStoreScreenshots } from './storeShots';
|
|
33
33
|
export type { CaptureStoreScreenshotsOptions, CaptureStoreScreenshotsResult, StoreShotFrame, } from './storeShots';
|
|
34
34
|
export { BlackBox } from './BlackBox';
|
|
@@ -59,7 +59,10 @@ export { YaverDeviceDogfood } from './deviceDogfood';
|
|
|
59
59
|
export type { DeviceDogfoodOptions, DeviceDogfoodSession, DeviceDogfoodState } from './deviceDogfood';
|
|
60
60
|
export { DogfoodController, DogfoodRuntimeError, defaultDogfoodLane, dogfoodLaneOptions, dogfoodLogLinesFromDevEvent, runtimeLogLinesFromDevEvent, validateDogfoodProject, } from './DogfoodRuntime';
|
|
61
61
|
export type { DogfoodControllerOptions, DogfoodDriver, DogfoodFailure, DogfoodLane, DogfoodLaneOption, DogfoodLogLine, DogfoodPhase, DogfoodProject, DogfoodResult, DogfoodRunContext, DogfoodSnapshot, } from './DogfoodRuntime';
|
|
62
|
+
export { DogfoodLanePicker, DogfoodLiveConsole, DogfoodStatusRail } from './DogfoodSessionUi';
|
|
63
|
+
export type { DogfoodStatusStep, DogfoodStatusTone, DogfoodUiColors, } from './DogfoodSessionUi';
|
|
62
64
|
export { FeedbackModal } from './FeedbackModal';
|
|
65
|
+
export { DogfoodQuickControls } from './DogfoodQuickControls';
|
|
63
66
|
export { QuickActionIcon } from './QuickActionIcon';
|
|
64
67
|
export type { QuickActionIconProps } from './QuickActionIcon';
|
|
65
68
|
export { FixReport } from './FixReport';
|
package/dist/index.js
CHANGED
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
* ```
|
|
30
30
|
*/
|
|
31
31
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
-
exports.
|
|
33
|
-
exports.uploadFeedback = exports.isVideoRecording = exports.stopVideoRecording = exports.startVideoRecording = exports.pickFeedbackFile = exports.captureScreenshot = exports.DEFAULT_OAUTH_REDIRECT = exports.DEFAULT_WEB_BASE_URL = exports.DEFAULT_CONVEX_SITE_URL = exports.listReachableDevices = exports.loginWithEmail = exports.signupWithEmail = exports.signInWithOAuth = exports.signInWithApple = exports.validateToken = exports.clearSelectedDeviceId = exports.saveSelectedDeviceId = exports.getDogfoodAccountAccess = exports.getSelectedDeviceId = void 0;
|
|
32
|
+
exports.getToken = exports.getWebBaseUrl = exports.getConvexSiteUrl = exports.configureAuthEndpoints = exports.setPreferredDogfoodLane = exports.getPreferredDogfoodLane = exports.clearQuickIconDisabled = exports.setQuickIconDisabled = exports.getQuickIconDisabled = exports.FixReport = exports.QuickActionIcon = exports.DogfoodQuickControls = exports.FeedbackModal = exports.DogfoodStatusRail = exports.DogfoodLiveConsole = exports.DogfoodLanePicker = exports.validateDogfoodProject = exports.runtimeLogLinesFromDevEvent = exports.dogfoodLogLinesFromDevEvent = exports.dogfoodLaneOptions = exports.defaultDogfoodLane = exports.DogfoodRuntimeError = exports.DogfoodController = exports.YaverDeviceDogfood = exports.resolveSDKDogfood = exports.isYaverModeBadgeHidden = exports.showYaverModeBadge = exports.hideYaverModeBadge = exports.YaverModeBadge = exports.FloatingButton = exports.ShakeDetector = exports.AuthOverlay = exports.PairDeviceModal = exports.YaverMachinePickerScreen = exports.YaverLoginScreen = exports.YaverConnectionScreen = exports.RELOAD_APP_PATH = exports.RELOAD_PATH = exports.describeReloadFailure = exports.reloadFrameworkFamily = exports.reloadRequest = exports.reloadActions = exports.createP2PDogfoodDriver = exports.P2PClient = exports.YaverDiscovery = exports.initExpo = exports.YaverUpdates = exports.BlackBox = exports.captureStoreScreenshots = exports.YaverFeedback = void 0;
|
|
33
|
+
exports.uploadFeedback = exports.isVideoRecording = exports.stopVideoRecording = exports.startVideoRecording = exports.pickFeedbackFile = exports.captureScreenshot = exports.DEFAULT_OAUTH_REDIRECT = exports.DEFAULT_WEB_BASE_URL = exports.DEFAULT_CONVEX_SITE_URL = exports.listReachableDevices = exports.loginWithEmail = exports.signupWithEmail = exports.signInWithOAuth = exports.signInWithApple = exports.validateToken = exports.clearSelectedDeviceId = exports.saveSelectedDeviceId = exports.getDogfoodAccountAccess = exports.getSelectedDeviceId = exports.saveUser = exports.getUser = exports.clearToken = exports.saveToken = void 0;
|
|
34
34
|
var YaverFeedback_1 = require("./YaverFeedback");
|
|
35
35
|
Object.defineProperty(exports, "YaverFeedback", { enumerable: true, get: function () { return YaverFeedback_1.YaverFeedback; } });
|
|
36
36
|
var storeShots_1 = require("./storeShots");
|
|
@@ -88,8 +88,14 @@ Object.defineProperty(exports, "dogfoodLaneOptions", { enumerable: true, get: fu
|
|
|
88
88
|
Object.defineProperty(exports, "dogfoodLogLinesFromDevEvent", { enumerable: true, get: function () { return DogfoodRuntime_1.dogfoodLogLinesFromDevEvent; } });
|
|
89
89
|
Object.defineProperty(exports, "runtimeLogLinesFromDevEvent", { enumerable: true, get: function () { return DogfoodRuntime_1.runtimeLogLinesFromDevEvent; } });
|
|
90
90
|
Object.defineProperty(exports, "validateDogfoodProject", { enumerable: true, get: function () { return DogfoodRuntime_1.validateDogfoodProject; } });
|
|
91
|
+
var DogfoodSessionUi_1 = require("./DogfoodSessionUi");
|
|
92
|
+
Object.defineProperty(exports, "DogfoodLanePicker", { enumerable: true, get: function () { return DogfoodSessionUi_1.DogfoodLanePicker; } });
|
|
93
|
+
Object.defineProperty(exports, "DogfoodLiveConsole", { enumerable: true, get: function () { return DogfoodSessionUi_1.DogfoodLiveConsole; } });
|
|
94
|
+
Object.defineProperty(exports, "DogfoodStatusRail", { enumerable: true, get: function () { return DogfoodSessionUi_1.DogfoodStatusRail; } });
|
|
91
95
|
var FeedbackModal_1 = require("./FeedbackModal");
|
|
92
96
|
Object.defineProperty(exports, "FeedbackModal", { enumerable: true, get: function () { return FeedbackModal_1.FeedbackModal; } });
|
|
97
|
+
var DogfoodQuickControls_1 = require("./DogfoodQuickControls");
|
|
98
|
+
Object.defineProperty(exports, "DogfoodQuickControls", { enumerable: true, get: function () { return DogfoodQuickControls_1.DogfoodQuickControls; } });
|
|
93
99
|
var QuickActionIcon_1 = require("./QuickActionIcon");
|
|
94
100
|
Object.defineProperty(exports, "QuickActionIcon", { enumerable: true, get: function () { return QuickActionIcon_1.QuickActionIcon; } });
|
|
95
101
|
var FixReport_1 = require("./FixReport");
|
package/dist/preferences.d.ts
CHANGED
|
@@ -12,6 +12,19 @@
|
|
|
12
12
|
* still works (it just can't remember the disable beyond the
|
|
13
13
|
* in-memory session).
|
|
14
14
|
*/
|
|
15
|
+
export type DogfoodControlPresentation = 'auto' | 'minimized-y';
|
|
16
|
+
export type DogfoodControlEdge = 'left' | 'right';
|
|
17
|
+
export interface DogfoodControlPosition {
|
|
18
|
+
edge: DogfoodControlEdge;
|
|
19
|
+
/** 0–1 within the safe vertical travel area. */
|
|
20
|
+
yRatio: number;
|
|
21
|
+
}
|
|
22
|
+
export declare function getDogfoodControlPresentation(scope?: string): Promise<DogfoodControlPresentation | null>;
|
|
23
|
+
export declare function setDogfoodControlPresentation(value: DogfoodControlPresentation, scope?: string): Promise<void>;
|
|
24
|
+
export declare function getDogfoodControlPosition(orientation: 'portrait' | 'landscape', scope?: string): Promise<DogfoodControlPosition | null>;
|
|
25
|
+
export declare function setDogfoodControlPosition(orientation: 'portrait' | 'landscape', position: DogfoodControlPosition, scope?: string): Promise<void>;
|
|
26
|
+
export declare function getDogfoodControlOnboardingSeen(scope?: string): Promise<boolean>;
|
|
27
|
+
export declare function setDogfoodControlOnboardingSeen(seen: boolean, scope?: string): Promise<void>;
|
|
15
28
|
export type QuickIconColorPreset = 'orange' | 'lime' | 'cyan' | 'pink' | 'yellow' | 'slate';
|
|
16
29
|
export declare const QUICK_ICON_COLOR_PRESETS: Record<QuickIconColorPreset, {
|
|
17
30
|
label: string;
|
package/dist/preferences.js
CHANGED
|
@@ -15,6 +15,12 @@
|
|
|
15
15
|
*/
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
exports.QUICK_ICON_COLOR_PRESETS = void 0;
|
|
18
|
+
exports.getDogfoodControlPresentation = getDogfoodControlPresentation;
|
|
19
|
+
exports.setDogfoodControlPresentation = setDogfoodControlPresentation;
|
|
20
|
+
exports.getDogfoodControlPosition = getDogfoodControlPosition;
|
|
21
|
+
exports.setDogfoodControlPosition = setDogfoodControlPosition;
|
|
22
|
+
exports.getDogfoodControlOnboardingSeen = getDogfoodControlOnboardingSeen;
|
|
23
|
+
exports.setDogfoodControlOnboardingSeen = setDogfoodControlOnboardingSeen;
|
|
18
24
|
exports.getQuickIconDisabled = getQuickIconDisabled;
|
|
19
25
|
exports.setQuickIconDisabled = setQuickIconDisabled;
|
|
20
26
|
exports.clearQuickIconDisabled = clearQuickIconDisabled;
|
|
@@ -36,6 +42,84 @@ catch {
|
|
|
36
42
|
}
|
|
37
43
|
const QUICK_ICON_DISABLED_KEY = 'yaver_feedback_quickicon_disabled';
|
|
38
44
|
const QUICK_ICON_COLOR_KEY = 'yaver_feedback_quickicon_color';
|
|
45
|
+
const DOGFOOD_CONTROL_PRESENTATION_KEY = 'yaver_dogfood_control_presentation';
|
|
46
|
+
const DOGFOOD_CONTROL_POSITION_PREFIX = 'yaver_dogfood_control_position_';
|
|
47
|
+
const DOGFOOD_CONTROL_ONBOARDING_PREFIX = 'yaver_dogfood_control_onboarding_';
|
|
48
|
+
function dogfoodPreferenceKey(base, scope) {
|
|
49
|
+
const normalized = String(scope || 'legacy').trim() || 'legacy';
|
|
50
|
+
return `${base}_${encodeURIComponent(normalized)}`;
|
|
51
|
+
}
|
|
52
|
+
async function getDogfoodControlPresentation(scope) {
|
|
53
|
+
if (!AsyncStorage)
|
|
54
|
+
return null;
|
|
55
|
+
try {
|
|
56
|
+
const value = await AsyncStorage.getItem(dogfoodPreferenceKey(DOGFOOD_CONTROL_PRESENTATION_KEY, scope));
|
|
57
|
+
return value === 'auto' || value === 'minimized-y' ? value : null;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async function setDogfoodControlPresentation(value, scope) {
|
|
64
|
+
if (!AsyncStorage)
|
|
65
|
+
return;
|
|
66
|
+
try {
|
|
67
|
+
await AsyncStorage.setItem(dogfoodPreferenceKey(DOGFOOD_CONTROL_PRESENTATION_KEY, scope), value);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// best-effort
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async function getDogfoodControlPosition(orientation, scope) {
|
|
74
|
+
if (!AsyncStorage)
|
|
75
|
+
return null;
|
|
76
|
+
try {
|
|
77
|
+
const raw = await AsyncStorage.getItem(dogfoodPreferenceKey(`${DOGFOOD_CONTROL_POSITION_PREFIX}${orientation}`, scope));
|
|
78
|
+
if (!raw)
|
|
79
|
+
return null;
|
|
80
|
+
const parsed = JSON.parse(raw);
|
|
81
|
+
if ((parsed.edge !== 'left' && parsed.edge !== 'right') || typeof parsed.yRatio !== 'number')
|
|
82
|
+
return null;
|
|
83
|
+
return { edge: parsed.edge, yRatio: Math.max(0, Math.min(1, parsed.yRatio)) };
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async function setDogfoodControlPosition(orientation, position, scope) {
|
|
90
|
+
if (!AsyncStorage)
|
|
91
|
+
return;
|
|
92
|
+
try {
|
|
93
|
+
await AsyncStorage.setItem(dogfoodPreferenceKey(`${DOGFOOD_CONTROL_POSITION_PREFIX}${orientation}`, scope), JSON.stringify(position));
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// best-effort
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async function getDogfoodControlOnboardingSeen(scope) {
|
|
100
|
+
if (!AsyncStorage)
|
|
101
|
+
return false;
|
|
102
|
+
try {
|
|
103
|
+
return await AsyncStorage.getItem(dogfoodPreferenceKey(DOGFOOD_CONTROL_ONBOARDING_PREFIX, scope)) === '1';
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
async function setDogfoodControlOnboardingSeen(seen, scope) {
|
|
110
|
+
if (!AsyncStorage)
|
|
111
|
+
return;
|
|
112
|
+
try {
|
|
113
|
+
const key = dogfoodPreferenceKey(DOGFOOD_CONTROL_ONBOARDING_PREFIX, scope);
|
|
114
|
+
if (seen)
|
|
115
|
+
await AsyncStorage.setItem(key, '1');
|
|
116
|
+
else
|
|
117
|
+
await AsyncStorage.removeItem(key);
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// best-effort startup cache; Convex remains authoritative.
|
|
121
|
+
}
|
|
122
|
+
}
|
|
39
123
|
exports.QUICK_ICON_COLOR_PRESETS = {
|
|
40
124
|
orange: {
|
|
41
125
|
label: 'Orange',
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#import <React/RCTBridgeModule.h>
|
|
2
|
+
#import <React/RCTEventEmitter.h>
|
|
3
|
+
|
|
4
|
+
@interface RCT_EXTERN_MODULE(YaverDogfoodGesture, RCTEventEmitter)
|
|
5
|
+
|
|
6
|
+
RCT_EXTERN_METHOD(getCapability:(RCTPromiseResolveBlock)resolve
|
|
7
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
8
|
+
|
|
9
|
+
RCT_EXTERN_METHOD(setEnabled:(BOOL)enabled
|
|
10
|
+
durationMs:(double)durationMs
|
|
11
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
12
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
13
|
+
|
|
14
|
+
@end
|