@tastic/shell 0.4.0 → 0.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/README.md +41 -15
- package/dist/index.d.mts +29 -14
- package/dist/index.d.ts +29 -14
- package/dist/index.js +208 -182
- package/dist/index.mjs +139 -116
- package/package.json +16 -18
- package/src/RootLayout.tsx +27 -66
- package/src/components/GuideHost.tsx +4 -6
- package/src/components/MatchChips.tsx +72 -0
- package/src/components/SettingsDialog.tsx +4 -10
- package/src/components/Theme.tsx +3 -2
- package/src/components/UpdateDialog.tsx +1 -3
- package/src/hooks/useFrozenWhileHidden.ts +2 -2
- package/src/index.ts +1 -0
- package/src/redux/appSettingsSlice.ts +0 -11
- package/src/screens/HomeScreen.tsx +13 -17
- package/src/screens/LoadoutScreen.tsx +35 -53
- package/src/screens/ProfilesRoute.tsx +5 -5
- package/src/screens/StatsScreen.tsx +4 -5
- package/src/screens/homeLayout.ts +15 -19
- package/src/types.ts +13 -21
package/dist/index.js
CHANGED
|
@@ -35,6 +35,9 @@ __export(index_exports, {
|
|
|
35
35
|
GUEST_PLAYER_ID: () => GUEST_PLAYER_ID,
|
|
36
36
|
HomeScreen: () => HomeScreen,
|
|
37
37
|
LoadoutRoute: () => LoadoutRoute,
|
|
38
|
+
MATCH_CHIPS_DESKTOP_MIN_WIDTH: () => MATCH_CHIPS_DESKTOP_MIN_WIDTH,
|
|
39
|
+
MATCH_CHIPS_FADE_MS: () => MATCH_CHIPS_FADE_MS,
|
|
40
|
+
MatchChips: () => MatchChips,
|
|
38
41
|
PREVIEW_ASPECT: () => PREVIEW_ASPECT,
|
|
39
42
|
PackProvider: () => PackProvider,
|
|
40
43
|
PlayRoute: () => PlayRoute,
|
|
@@ -64,7 +67,7 @@ __export(index_exports, {
|
|
|
64
67
|
profileSelectionActions: () => profileSelectionActions,
|
|
65
68
|
profileSelectionReducer: () => profileSelectionSlice_default,
|
|
66
69
|
roundModeFor: () => roundModeFor,
|
|
67
|
-
safeBack: () =>
|
|
70
|
+
safeBack: () => import_core7.safeBack,
|
|
68
71
|
seatColorsActions: () => seatColorsActions,
|
|
69
72
|
seatPlayerKey: () => seatPlayerKey,
|
|
70
73
|
seatTwoFor: () => seatTwoFor,
|
|
@@ -99,13 +102,12 @@ function usePackGame(id) {
|
|
|
99
102
|
var import_auto_paper2 = require("@rific/auto-paper");
|
|
100
103
|
var import_feedback_press2 = require("@rific/feedback-press");
|
|
101
104
|
var import_toaster2 = require("@rific/toaster");
|
|
102
|
-
var
|
|
105
|
+
var import_core4 = require("@tastic/core");
|
|
103
106
|
var import_chrome2 = require("@tastic/hud/chrome");
|
|
104
107
|
var import_profile3 = require("@tastic/profile");
|
|
105
108
|
var Haptics = __toESM(require("expo-haptics"));
|
|
106
109
|
var import_expo_router = require("expo-router");
|
|
107
|
-
var
|
|
108
|
-
var import_react9 = require("react");
|
|
110
|
+
var import_react8 = require("react");
|
|
109
111
|
var import_react_native2 = require("react-native");
|
|
110
112
|
var import_react_native_gesture_handler = require("react-native-gesture-handler");
|
|
111
113
|
var RNPaper2 = __toESM(require("react-native-paper"));
|
|
@@ -163,7 +165,6 @@ function GuideHost({ children }) {
|
|
|
163
165
|
const packGuide = subject === PACK_GUIDE ? pack.guide : void 0;
|
|
164
166
|
const game = subject === PACK_GUIDE ? void 0 : pack.games.find((g) => g.id === subject);
|
|
165
167
|
const gameGuide = game?.guide;
|
|
166
|
-
const rotation = (0, import_core.useRotation)();
|
|
167
168
|
const touch = (0, import_core.useIsTouchPrimaryDevice)();
|
|
168
169
|
const seatTwo = (0, import_react_redux.useSelector)((state) => state.opponent.seatTwo);
|
|
169
170
|
const input = (0, import_react_redux.useSelector)((state) => gameGuide ? gameGuide.selectInput(state) : NO_INPUT, import_react_redux.shallowEqual);
|
|
@@ -178,7 +179,7 @@ function GuideHost({ children }) {
|
|
|
178
179
|
},
|
|
179
180
|
[dispatch, packGuide, gameGuide]
|
|
180
181
|
);
|
|
181
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_guide.GuideProvider, { steps, currentVersion: (packGuide ?? gameGuide)?.version ?? 0, seenVersion, onSeen,
|
|
182
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_guide.GuideProvider, { steps, currentVersion: (packGuide ?? gameGuide)?.version ?? 0, seenVersion, onSeen, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(GameGuideBridge, { onPick: setSubject, children }) });
|
|
182
183
|
}
|
|
183
184
|
function GameGuideBridge({ onPick, children }) {
|
|
184
185
|
const pack = usePack();
|
|
@@ -301,66 +302,33 @@ function Theme({ children }) {
|
|
|
301
302
|
|
|
302
303
|
// src/components/UpdateDialog.tsx
|
|
303
304
|
var import_toaster = require("@rific/toaster");
|
|
304
|
-
var import_core3 = require("@tastic/core");
|
|
305
305
|
var import_chrome = require("@tastic/hud/chrome");
|
|
306
306
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
307
307
|
function UpdateDialog() {
|
|
308
308
|
const onError = (0, import_toaster.useUpdateErrorToast)();
|
|
309
|
-
|
|
310
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_chrome.UpdateDialog, { onError, rotation });
|
|
309
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_chrome.UpdateDialog, { onError });
|
|
311
310
|
}
|
|
312
311
|
|
|
313
|
-
// src/hooks/
|
|
312
|
+
// src/hooks/useLastActiveGame.tsx
|
|
314
313
|
var import_react6 = require("react");
|
|
315
314
|
var import_react_redux4 = require("react-redux");
|
|
316
315
|
|
|
317
|
-
// src/redux/appSettingsSlice.ts
|
|
318
|
-
var import_core4 = require("@rific/core");
|
|
319
|
-
var DEFAULT_APP_SETTINGS = {
|
|
320
|
-
lockOrientation: false,
|
|
321
|
-
deferBottomEdgeGestures: false
|
|
322
|
-
};
|
|
323
|
-
var { actions, reducer } = (0, import_core4.createSettingsSlice)("appSettings", {
|
|
324
|
-
initialState: DEFAULT_APP_SETTINGS,
|
|
325
|
-
initializeMode: "merge",
|
|
326
|
-
fieldSetters: []
|
|
327
|
-
});
|
|
328
|
-
var appSettingsActions = actions;
|
|
329
|
-
var appSettingsSlice_default = reducer;
|
|
330
|
-
|
|
331
|
-
// src/hooks/useAppSettings.ts
|
|
332
|
-
function useAppSettings() {
|
|
333
|
-
const settings = (0, import_react_redux4.useSelector)((state) => state.appSettings);
|
|
334
|
-
const dispatch = (0, import_react_redux4.useDispatch)();
|
|
335
|
-
const setSettings = (0, import_react6.useCallback)(
|
|
336
|
-
(patch) => {
|
|
337
|
-
dispatch(appSettingsActions.initialize(patch));
|
|
338
|
-
},
|
|
339
|
-
[dispatch]
|
|
340
|
-
);
|
|
341
|
-
return { settings, setSettings };
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
// src/hooks/useLastActiveGame.tsx
|
|
345
|
-
var import_react7 = require("react");
|
|
346
|
-
var import_react_redux5 = require("react-redux");
|
|
347
|
-
|
|
348
316
|
// src/redux/lastActiveGameSlice.ts
|
|
349
|
-
var
|
|
350
|
-
var { actions
|
|
351
|
-
var lastActiveGameActions =
|
|
352
|
-
var lastActiveGameSlice_default =
|
|
317
|
+
var import_core3 = require("@rific/core");
|
|
318
|
+
var { actions, reducer } = (0, import_core3.createSettingsSlice)("lastActiveGame", { initialState: { gameId: null } });
|
|
319
|
+
var lastActiveGameActions = actions;
|
|
320
|
+
var lastActiveGameSlice_default = reducer;
|
|
353
321
|
|
|
354
322
|
// src/hooks/useLastActiveGame.tsx
|
|
355
323
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
356
|
-
var LastActiveGameContext = (0,
|
|
324
|
+
var LastActiveGameContext = (0, import_react6.createContext)(null);
|
|
357
325
|
function LastActiveGameProvider({ children }) {
|
|
358
|
-
const store = (0,
|
|
359
|
-
const dispatch = (0,
|
|
360
|
-
const [initial] = (0,
|
|
361
|
-
const pendingResume = (0,
|
|
362
|
-
const persisted = (0,
|
|
363
|
-
const value = (0,
|
|
326
|
+
const store = (0, import_react_redux4.useStore)();
|
|
327
|
+
const dispatch = (0, import_react_redux4.useDispatch)();
|
|
328
|
+
const [initial] = (0, import_react6.useState)(() => store.getState().lastActiveGame?.gameId ?? null);
|
|
329
|
+
const pendingResume = (0, import_react6.useRef)(initial);
|
|
330
|
+
const persisted = (0, import_react6.useRef)(initial);
|
|
331
|
+
const value = (0, import_react6.useMemo)(
|
|
364
332
|
() => ({
|
|
365
333
|
consumeResumeGame: () => {
|
|
366
334
|
const game = pendingResume.current;
|
|
@@ -388,33 +356,33 @@ function LastActiveGameProvider({ children }) {
|
|
|
388
356
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(LastActiveGameContext.Provider, { value, children });
|
|
389
357
|
}
|
|
390
358
|
function useLastActiveGame() {
|
|
391
|
-
const ctx = (0,
|
|
359
|
+
const ctx = (0, import_react6.useContext)(LastActiveGameContext);
|
|
392
360
|
if (!ctx) throw new Error("useLastActiveGame must be used within a LastActiveGameProvider");
|
|
393
361
|
return ctx;
|
|
394
362
|
}
|
|
395
363
|
|
|
396
364
|
// src/hooks/useProfiles.tsx
|
|
397
365
|
var import_profile2 = require("@tastic/profile");
|
|
398
|
-
var
|
|
399
|
-
var
|
|
366
|
+
var import_react7 = require("react");
|
|
367
|
+
var import_react_redux5 = require("react-redux");
|
|
400
368
|
|
|
401
369
|
// src/redux/profileSelectionSlice.ts
|
|
402
370
|
var import_profile = require("@tastic/profile");
|
|
403
371
|
var defaultProfileSelectionState = { 1: null, 2: null };
|
|
404
|
-
var { actions:
|
|
405
|
-
var profileSelectionActions =
|
|
406
|
-
var profileSelectionSlice_default =
|
|
372
|
+
var { actions: actions2, reducer: reducer2 } = (0, import_profile.createProfileSelectionSlice)("pack", defaultProfileSelectionState);
|
|
373
|
+
var profileSelectionActions = actions2;
|
|
374
|
+
var profileSelectionSlice_default = reducer2;
|
|
407
375
|
|
|
408
376
|
// src/hooks/useProfiles.tsx
|
|
409
377
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
410
378
|
var SHARED_GROUP_ID = "group.com.infinitetoken.tastic";
|
|
411
|
-
var ProfilesContext = (0,
|
|
379
|
+
var ProfilesContext = (0, import_react7.createContext)(null);
|
|
412
380
|
function ProfilesProvider({ children }) {
|
|
413
|
-
const profiles = (0,
|
|
414
|
-
const lastSelected = (0,
|
|
415
|
-
const dispatch = (0,
|
|
416
|
-
const [loaded, setLoaded] = (0,
|
|
417
|
-
(0,
|
|
381
|
+
const profiles = (0, import_react_redux5.useSelector)((state) => state.profiles);
|
|
382
|
+
const lastSelected = (0, import_react_redux5.useSelector)((state) => state.profileSelection);
|
|
383
|
+
const dispatch = (0, import_react_redux5.useDispatch)();
|
|
384
|
+
const [loaded, setLoaded] = (0, import_react7.useState)(false);
|
|
385
|
+
(0, import_react7.useEffect)(() => {
|
|
418
386
|
let cancelled = false;
|
|
419
387
|
(0, import_profile2.resolveInitialProfiles)(SHARED_GROUP_ID, profiles).then((resolved) => {
|
|
420
388
|
if (cancelled) return;
|
|
@@ -428,7 +396,7 @@ function ProfilesProvider({ children }) {
|
|
|
428
396
|
}, []);
|
|
429
397
|
const { syncToShared } = (0, import_profile2.useSharedProfilesSync)({
|
|
430
398
|
groupId: SHARED_GROUP_ID,
|
|
431
|
-
onRemoteChange: (0,
|
|
399
|
+
onRemoteChange: (0, import_react7.useCallback)(
|
|
432
400
|
(remote) => {
|
|
433
401
|
dispatch(import_profile2.profilesActions.setAll(remote));
|
|
434
402
|
dispatch(profileSelectionActions.pruneToRoster(remote.map((p) => p.id)));
|
|
@@ -436,7 +404,7 @@ function ProfilesProvider({ children }) {
|
|
|
436
404
|
[dispatch]
|
|
437
405
|
)
|
|
438
406
|
});
|
|
439
|
-
const createProfile = (0,
|
|
407
|
+
const createProfile = (0, import_react7.useCallback)(
|
|
440
408
|
(input) => {
|
|
441
409
|
const record = (0, import_profile2.createProfileRecord)(input);
|
|
442
410
|
dispatch(import_profile2.profilesActions.add(record));
|
|
@@ -445,14 +413,14 @@ function ProfilesProvider({ children }) {
|
|
|
445
413
|
},
|
|
446
414
|
[profiles, dispatch, syncToShared]
|
|
447
415
|
);
|
|
448
|
-
const updateProfile = (0,
|
|
416
|
+
const updateProfile = (0, import_react7.useCallback)(
|
|
449
417
|
(id, patch) => {
|
|
450
418
|
dispatch(import_profile2.profilesActions.update({ id, patch }));
|
|
451
419
|
syncToShared(profiles.map((p) => p.id === id ? { ...p, ...patch, updatedAt: Date.now() } : p));
|
|
452
420
|
},
|
|
453
421
|
[profiles, dispatch, syncToShared]
|
|
454
422
|
);
|
|
455
|
-
const deleteProfile = (0,
|
|
423
|
+
const deleteProfile = (0, import_react7.useCallback)(
|
|
456
424
|
(id) => {
|
|
457
425
|
dispatch(import_profile2.profilesActions.remove(id));
|
|
458
426
|
syncToShared(profiles.filter((p) => p.id !== id));
|
|
@@ -460,7 +428,7 @@ function ProfilesProvider({ children }) {
|
|
|
460
428
|
},
|
|
461
429
|
[profiles, dispatch, syncToShared]
|
|
462
430
|
);
|
|
463
|
-
const selectProfile = (0,
|
|
431
|
+
const selectProfile = (0, import_react7.useCallback)(
|
|
464
432
|
(seat, profileId) => {
|
|
465
433
|
dispatch(profileSelectionActions.select({ profileId, seat }));
|
|
466
434
|
},
|
|
@@ -469,7 +437,7 @@ function ProfilesProvider({ children }) {
|
|
|
469
437
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ProfilesContext.Provider, { value: { profiles, lastSelected, loaded, createProfile, updateProfile, deleteProfile, selectProfile }, children });
|
|
470
438
|
}
|
|
471
439
|
function useProfiles() {
|
|
472
|
-
const ctx = (0,
|
|
440
|
+
const ctx = (0, import_react7.useContext)(ProfilesContext);
|
|
473
441
|
if (!ctx) throw new Error("useProfiles must be used within a ProfilesProvider");
|
|
474
442
|
return ctx;
|
|
475
443
|
}
|
|
@@ -485,11 +453,11 @@ function AppStack() {
|
|
|
485
453
|
const { Backdrop } = pack;
|
|
486
454
|
const { dark } = (0, import_auto_paper2.useAutoPaperTheme)();
|
|
487
455
|
const darkRoot = Backdrop ? true : dark;
|
|
488
|
-
const rootBackground = (0,
|
|
489
|
-
const
|
|
456
|
+
const rootBackground = (0, import_core4.useThemedRootBackground)(darkRoot, false);
|
|
457
|
+
const statusBarStyle = darkRoot ? "light" : "dark";
|
|
490
458
|
const packOptions = (pack.useScreenOptions ?? noScreenOptions)();
|
|
491
459
|
const backdropOptions = Backdrop ? { contentStyle: TRANSPARENT_CONTENT, animation: import_react_native2.Platform.select({ android: "fade" }) } : void 0;
|
|
492
|
-
const playOptions = (0,
|
|
460
|
+
const playOptions = (0, import_react8.useCallback)(
|
|
493
461
|
({ route }) => {
|
|
494
462
|
const id = route.params?.game;
|
|
495
463
|
return pack.games.some((g) => g.id === id && g.keepStatusBar) ? KEEP_STATUS_BAR_OPTIONS : PLAY_OPTIONS;
|
|
@@ -497,11 +465,11 @@ function AppStack() {
|
|
|
497
465
|
[pack.games]
|
|
498
466
|
);
|
|
499
467
|
const navigationBackground = Backdrop ? TRANSPARENT_CONTENT.backgroundColor : rootBackground.contentStyle.backgroundColor;
|
|
500
|
-
const navigationTheme = (0,
|
|
468
|
+
const navigationTheme = (0, import_react8.useMemo)(() => {
|
|
501
469
|
const base = darkRoot ? import_expo_router.DarkTheme : import_expo_router.DefaultTheme;
|
|
502
470
|
return { ...base, colors: { ...base.colors, background: navigationBackground } };
|
|
503
471
|
}, [darkRoot, navigationBackground]);
|
|
504
|
-
const stack = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_expo_router.ThemeProvider, { value: navigationTheme, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_expo_router.Stack, { screenOptions: { ...rootBackground,
|
|
472
|
+
const stack = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_expo_router.ThemeProvider, { value: navigationTheme, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_expo_router.Stack, { screenOptions: { ...rootBackground, statusBarStyle, ...backdropOptions, ...packOptions }, children: [
|
|
505
473
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_expo_router.Stack.Screen, { name: "index" }),
|
|
506
474
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_expo_router.Stack.Screen, { name: "play/[game]", options: playOptions })
|
|
507
475
|
] }) });
|
|
@@ -511,11 +479,6 @@ function AppStack() {
|
|
|
511
479
|
stack
|
|
512
480
|
] });
|
|
513
481
|
}
|
|
514
|
-
function OrientationBridge({ children }) {
|
|
515
|
-
const { settings, setSettings } = useAppSettings();
|
|
516
|
-
const { portraitWhileKeyboard } = usePack();
|
|
517
|
-
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_core6.OrientationProvider, { deviceMotion: import_expo_sensors.DeviceMotion, freezeWhileLocked: true, lockInitialValue: { locked: settings.lockOrientation, rotation: settings.lockedRotation }, onLockChange: (next) => setSettings({ lockOrientation: next.locked, lockedRotation: next.rotation }), portraitWhileKeyboard, children });
|
|
518
|
-
}
|
|
519
482
|
function GatedApp({ children }) {
|
|
520
483
|
const { loaded } = useProfiles();
|
|
521
484
|
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SplashGate, { gate: "profiles", ready: loaded, children });
|
|
@@ -526,7 +489,7 @@ function HapticGatedToastProvider({ children }) {
|
|
|
526
489
|
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_toaster2.ToastProvider, { haptics: settings.vibrate ? Haptics : void 0, paper: PackToasterComponent ? void 0 : RNPaper2, children });
|
|
527
490
|
}
|
|
528
491
|
function RotatingToaster() {
|
|
529
|
-
const renderFrame = (0,
|
|
492
|
+
const renderFrame = (0, import_react8.useCallback)(
|
|
530
493
|
(toasts) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_chrome2.RotatedFrame, { rotatedSafeArea: true, passThrough: true, children: toasts }),
|
|
531
494
|
[]
|
|
532
495
|
);
|
|
@@ -540,7 +503,7 @@ function GameProviders({ games, children }) {
|
|
|
540
503
|
}
|
|
541
504
|
function PreviewColors({ previewColor, children }) {
|
|
542
505
|
const { dark } = (0, import_auto_paper2.useAutoPaperTheme)();
|
|
543
|
-
const preview = (0,
|
|
506
|
+
const preview = (0, import_react8.useCallback)((hex) => previewColor(hex, dark), [previewColor, dark]);
|
|
544
507
|
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_profile3.ProfileColorProvider, { preview, children });
|
|
545
508
|
}
|
|
546
509
|
function PackRoot({ pack, children }) {
|
|
@@ -549,11 +512,11 @@ function PackRoot({ pack, children }) {
|
|
|
549
512
|
return previewColor ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(PreviewColors, { previewColor, children: inner }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: inner });
|
|
550
513
|
}
|
|
551
514
|
function RootLayout({ pack, store, persistor }) {
|
|
552
|
-
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_gesture_handler.GestureHandlerRootView, { style: styles.root, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_safe_area_context.SafeAreaProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(PackProvider, { pack, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Fonts, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Providers, { store, persistor, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Theme, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ProfilesProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(LastActiveGameProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(GameProviders, { games: pack.games, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(PackRoot, { pack, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(GatedApp, { children: /* @__PURE__ */ (0, import_jsx_runtime9.
|
|
515
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_gesture_handler.GestureHandlerRootView, { style: styles.root, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_react_native_safe_area_context.SafeAreaProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(PackProvider, { pack, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Fonts, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Providers, { store, persistor, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Theme, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ProfilesProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(LastActiveGameProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(GameProviders, { games: pack.games, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(PackRoot, { pack, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(GatedApp, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(HapticGatedToastProvider, { children: [
|
|
553
516
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(GuideHost, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(AppStack, {}) }),
|
|
554
517
|
pack.Toaster ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(PackToaster, { Toaster: pack.Toaster }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(RotatingToaster, {}),
|
|
555
518
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(UpdateDialog, {})
|
|
556
|
-
] }) }) }) }) }) }) }) }) }) }) }) })
|
|
519
|
+
] }) }) }) }) }) }) }) }) }) }) }) });
|
|
557
520
|
}
|
|
558
521
|
var styles = import_react_native2.StyleSheet.create({
|
|
559
522
|
root: { flex: 1 }
|
|
@@ -572,7 +535,7 @@ var PROFILES_HREF = "/profiles";
|
|
|
572
535
|
|
|
573
536
|
// src/screens/LoadoutScreen.tsx
|
|
574
537
|
var import_auto_paper4 = require("@rific/auto-paper");
|
|
575
|
-
var
|
|
538
|
+
var import_core9 = require("@tastic/core");
|
|
576
539
|
var import_chrome4 = require("@tastic/hud/chrome");
|
|
577
540
|
var import_lobby2 = require("@tastic/hud/lobby");
|
|
578
541
|
var import_split_screen = require("@tastic/split-screen");
|
|
@@ -586,7 +549,7 @@ var import_react_redux9 = require("react-redux");
|
|
|
586
549
|
// src/components/SeatTwoPanel.tsx
|
|
587
550
|
var import_lobby = require("@tastic/hud/lobby");
|
|
588
551
|
var import_profile4 = require("@tastic/profile");
|
|
589
|
-
var
|
|
552
|
+
var import_react9 = require("react");
|
|
590
553
|
var import_react_native3 = require("react-native");
|
|
591
554
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
592
555
|
var CPU_PREFIX = "cpu:";
|
|
@@ -604,7 +567,7 @@ function SeatTwoPanel({ idPrefix, host, choices, seatTwo, onSeatTwoChange, cpuDi
|
|
|
604
567
|
const drawn = previewValue ? previewValue(color) : color;
|
|
605
568
|
const selectedProfile = isPerson ? profiles.find((p) => p.id === selectedProfileId) ?? null : null;
|
|
606
569
|
const cpuOptions = cpuDifficulty?.options;
|
|
607
|
-
const options = (0,
|
|
570
|
+
const options = (0, import_react9.useMemo)(() => {
|
|
608
571
|
const list = [];
|
|
609
572
|
if (choices.includes("cpu")) list.push(...cpuOptions ? cpuOptions.map((o) => ({ value: `${CPU_PREFIX}${o.value}`, label: o.label, icon: o.icon })) : [{ value: CPU_PREFIX, label: "CPU", icon: CPU_ICON }]);
|
|
610
573
|
if (choices.includes("nobody")) list.push({ value: NOBODY, label: "Nobody", icon: NOBODY_ICON });
|
|
@@ -664,13 +627,45 @@ var styles2 = import_react_native3.StyleSheet.create({
|
|
|
664
627
|
// src/components/SettingsDialog.tsx
|
|
665
628
|
var import_toaster3 = require("@rific/toaster");
|
|
666
629
|
var import_chrome3 = require("@tastic/hud/chrome");
|
|
630
|
+
|
|
631
|
+
// src/hooks/useAppSettings.ts
|
|
632
|
+
var import_react10 = require("react");
|
|
633
|
+
var import_react_redux6 = require("react-redux");
|
|
634
|
+
|
|
635
|
+
// src/redux/appSettingsSlice.ts
|
|
636
|
+
var import_core5 = require("@rific/core");
|
|
637
|
+
var DEFAULT_APP_SETTINGS = {
|
|
638
|
+
deferBottomEdgeGestures: false
|
|
639
|
+
};
|
|
640
|
+
var { actions: actions3, reducer: reducer3 } = (0, import_core5.createSettingsSlice)("appSettings", {
|
|
641
|
+
initialState: DEFAULT_APP_SETTINGS,
|
|
642
|
+
initializeMode: "merge",
|
|
643
|
+
fieldSetters: []
|
|
644
|
+
});
|
|
645
|
+
var appSettingsActions = actions3;
|
|
646
|
+
var appSettingsSlice_default = reducer3;
|
|
647
|
+
|
|
648
|
+
// src/hooks/useAppSettings.ts
|
|
649
|
+
function useAppSettings() {
|
|
650
|
+
const settings = (0, import_react_redux6.useSelector)((state) => state.appSettings);
|
|
651
|
+
const dispatch = (0, import_react_redux6.useDispatch)();
|
|
652
|
+
const setSettings = (0, import_react10.useCallback)(
|
|
653
|
+
(patch) => {
|
|
654
|
+
dispatch(appSettingsActions.initialize(patch));
|
|
655
|
+
},
|
|
656
|
+
[dispatch]
|
|
657
|
+
);
|
|
658
|
+
return { settings, setSettings };
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
// src/components/SettingsDialog.tsx
|
|
667
662
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
668
|
-
function SettingsDialog({ visible, onDismiss,
|
|
663
|
+
function SettingsDialog({ visible, onDismiss, onShowHowToPlay, children }) {
|
|
669
664
|
const onUpdateError = (0, import_toaster3.useUpdateErrorToast)();
|
|
670
665
|
const { settings, setSettings } = useAppSettings();
|
|
671
666
|
const { otaVersion, SettingsSections, edgeGuard = true } = usePack();
|
|
672
667
|
const edgeGuardProps = edgeGuard ? { deferBottomEdgeGestures: settings.deferBottomEdgeGestures, onDeferBottomEdgeGestures: (value) => setSettings({ deferBottomEdgeGestures: value }) } : {};
|
|
673
|
-
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_chrome3.BaseSettingsDialog, { visible, onDismiss,
|
|
668
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_chrome3.BaseSettingsDialog, { visible, onDismiss, version: otaVersion, ...edgeGuardProps, onUpdateError, onShowHowToPlay, children: [
|
|
674
669
|
children,
|
|
675
670
|
SettingsSections && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SettingsSections, {})
|
|
676
671
|
] });
|
|
@@ -681,9 +676,9 @@ var import_react11 = require("react");
|
|
|
681
676
|
var import_react_redux7 = require("react-redux");
|
|
682
677
|
|
|
683
678
|
// src/redux/opponentSlice.ts
|
|
684
|
-
var
|
|
679
|
+
var import_core6 = require("@rific/core");
|
|
685
680
|
var DEFAULT_OPPONENT = { seatTwo: "cpu" };
|
|
686
|
-
var { actions: actions4, reducer: reducer4 } = (0,
|
|
681
|
+
var { actions: actions4, reducer: reducer4 } = (0, import_core6.createSettingsSlice)("opponent", {
|
|
687
682
|
initialState: DEFAULT_OPPONENT
|
|
688
683
|
});
|
|
689
684
|
var opponentActions = actions4;
|
|
@@ -816,13 +811,13 @@ function useSeatColors(p2IsHuman) {
|
|
|
816
811
|
}
|
|
817
812
|
|
|
818
813
|
// src/navigation.ts
|
|
819
|
-
var
|
|
814
|
+
var import_core7 = require("@rific/core");
|
|
820
815
|
var import_expo_router3 = require("expo-router");
|
|
821
|
-
(0,
|
|
816
|
+
(0, import_core7.configureNavigation)({ router: import_expo_router3.router });
|
|
822
817
|
|
|
823
818
|
// src/redux/liveplaySlice.ts
|
|
824
|
-
var
|
|
825
|
-
var { actions: actions5, reducer: reducer5 } = (0,
|
|
819
|
+
var import_core8 = require("@rific/core");
|
|
820
|
+
var { actions: actions5, reducer: reducer5 } = (0, import_core8.createSettingsSlice)("liveplay", {
|
|
826
821
|
initialState: { activelyPlaying: false, activeRound: null }
|
|
827
822
|
});
|
|
828
823
|
var liveplayActions = actions5;
|
|
@@ -842,14 +837,12 @@ function LoadoutScreen({ game }) {
|
|
|
842
837
|
const loadout = game.useLoadout(mode);
|
|
843
838
|
const { openFor } = useGameGuide();
|
|
844
839
|
const { profiles, lastSelected, selectProfile } = useProfiles();
|
|
845
|
-
const { orientationMode
|
|
846
|
-
const
|
|
847
|
-
const
|
|
848
|
-
const { panelLayout, panelFadeStyle } = (0, import_split_screen.useDualZoneLayout)(fixedSeats ? "faceToFace" : orientationMode, fixedSeats ? true : p1OnRight, fixedSeats || p1OnRightResolved, fixedSeats ? fixedUpsideDown : upsideDown, PANEL_SWAP_FADE_MS);
|
|
840
|
+
const { orientationMode } = (0, import_core9.useOrientationState)();
|
|
841
|
+
const panelMode = p2IsHuman && !game.sideBySideWhenWide ? "faceToFace" : orientationMode;
|
|
842
|
+
const { panelLayout, panelFadeStyle } = (0, import_split_screen.useDualZoneLayout)(panelMode, false, true, false, PANEL_SWAP_FADE_MS);
|
|
849
843
|
const playersRowFade = panelFadeStyle;
|
|
850
844
|
const [settingsOpen, setSettingsOpen] = (0, import_react13.useState)(false);
|
|
851
|
-
const
|
|
852
|
-
const insets = (0, import_core10.rotateInsets)((0, import_react_native_safe_area_context2.useSafeAreaInsets)(), rotation);
|
|
845
|
+
const insets = (0, import_react_native_safe_area_context2.useSafeAreaInsets)();
|
|
853
846
|
const { colors: themeColors, dark } = (0, import_auto_paper4.useAutoPaperTheme)();
|
|
854
847
|
const { p1Color, p2Color, handleP1ColorChange, handleP2ColorChange } = useSeatColors(p2IsHuman);
|
|
855
848
|
const dispatch = (0, import_react_redux9.useDispatch)();
|
|
@@ -887,7 +880,7 @@ function LoadoutScreen({ game }) {
|
|
|
887
880
|
const triggerStyle = (0, import_react13.useMemo)(() => pack.Backdrop ? [styles3.pill, { backgroundColor: themeColors.surface }] : void 0, [pack.Backdrop, themeColors.surface]);
|
|
888
881
|
const isPortrait = panelLayout.orientationMode === "faceToFace";
|
|
889
882
|
const showMetaInSharedBand = (0, import_split_screen.needsSharedNeutralZone)(panelLayout.orientationMode, humanSeats.length);
|
|
890
|
-
const p2ZoneStyle = p2IsHuman ? isPortrait ? styles3.p2ZoneTop :
|
|
883
|
+
const p2ZoneStyle = p2IsHuman ? isPortrait ? styles3.p2ZoneTop : styles3.p2ZoneRight : null;
|
|
891
884
|
const showReadyButton = p2IsHuman;
|
|
892
885
|
const seatPickerAlign = p2IsHuman ? void 0 : pack.usePickerAlign;
|
|
893
886
|
const layoutKey = p2IsHuman ? "zones" : "row";
|
|
@@ -897,7 +890,6 @@ function LoadoutScreen({ game }) {
|
|
|
897
890
|
const anyPlayerPickerOpen = !!(controlsHost.openId?.startsWith("p1-") || controlsHost.openId?.startsWith("p2-"));
|
|
898
891
|
const optionsRow = loadout.options({
|
|
899
892
|
host: controlsHost,
|
|
900
|
-
rotation,
|
|
901
893
|
accentColor: themeColors.tertiary,
|
|
902
894
|
mutedColor: fgMuted,
|
|
903
895
|
onAccentColor: themeColors.onTertiary,
|
|
@@ -907,17 +899,17 @@ function LoadoutScreen({ game }) {
|
|
|
907
899
|
onReset: showMetaInSharedBand ? void 0 : loadout.reset
|
|
908
900
|
});
|
|
909
901
|
const optionsPopoverOpen = controlsHost.openId !== null && loadout.optionIds.includes(controlsHost.openId);
|
|
910
|
-
const sharedControls = showMetaInSharedBand ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lobby2.SharedActionBand, { onBack:
|
|
911
|
-
const controlLook = { accentColor: themeColors.tertiary, mutedColor: fgMuted, dark
|
|
902
|
+
const sharedControls = showMetaInSharedBand ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lobby2.SharedActionBand, { onBack: import_core7.safeBack, onSettings: () => setSettingsOpen(true), onRandomize: loadout.randomize, onReset: loadout.reset, fg, popoverOpen: optionsPopoverOpen, children: optionsRow }) : optionsRow;
|
|
903
|
+
const controlLook = { accentColor: themeColors.tertiary, mutedColor: fgMuted, dark };
|
|
912
904
|
const p1Control = loadout.seatControl(1, controlsHost, { ...controlLook, seatColor: p1Drawn });
|
|
913
905
|
const p1Panel = /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lobby2.PlayerSetupPanel, { idPrefix: "p1", host: controlsHost, color: p1Color, onColorChange: handleP1ColorChange, swatches: import_auto_paper4.defaultColors, takenColor: p2Exists ? p2Color : void 0, allowSwapTaken: mode === "vsCpu", colorCaption: pack.colorCaption, isHuman: true, ready: ready[1], onToggleReady: () => setReady((r) => ({ ...r, 1: !r[1] })), dark, showReadyButton, secondPicker: p1Control, secondPickerId: p1Control ? "p1-control" : void 0, profiles, selectedProfileId: lastSelected[1], takenProfileId: p2IsHuman ? lastSelected[2] : null, guestLabel: pack.guestLabel ?? "P1", nullLabel: pack.nullLabel, onProfileSelect: handleP1ProfileSelect, onManageProfiles: () => import_expo_router4.router.push(PROFILES_HREF), previewValue: seatPreview, triggerStyle, useSeatPickerAlign: seatPickerAlign }, `p1-${layoutKey}`);
|
|
914
906
|
const p2Control = p2IsHuman ? loadout.seatControl(2, p2Host, { ...controlLook, seatColor: p2Drawn }) : void 0;
|
|
915
907
|
const p2Panel = game.seatTwo && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SeatTwoPanel, { idPrefix: "p2", host: p2Host, choices: game.seatTwo, seatTwo, onSeatTwoChange: changeSeatTwo, cpuDifficulty: loadout.cpuDifficulty, profiles, selectedProfileId: lastSelected[2], onProfileSelect: handleP2ProfileSelect, color: p2Color, onColorChange: handleP2ColorChange, swatches: import_auto_paper4.defaultColors, takenColor: p1Color, allowSwapTaken: mode === "vsCpu", colorCaption: pack.colorCaption, dark, secondPicker: p2Control, secondPickerId: p2Control ? "p2-control" : void 0, ready: ready[2], onToggleReady: () => setReady((r) => ({ ...r, 2: !r[2] })), showReadyButton, previewValue: seatPreview, triggerStyle, usePickerAlign: seatPickerAlign }, `p2-${layoutKey}`);
|
|
916
908
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native4.View, { style: [styles3.container, { backgroundColor: bg }], children: [
|
|
917
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
909
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native4.View, { style: styles3.frame, children: [
|
|
918
910
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_chrome4.PressAwayOverlay, { active: controlsHost.openId !== null, onPress: controlsHost.close }),
|
|
919
911
|
p2ZoneStyle && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_chrome4.PressAwayOverlay, { active: controlsHost.openId !== null || p2Host.openId !== null, onPress: p2Host.close, style: p2ZoneStyle }),
|
|
920
|
-
!showMetaInSharedBand && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_chrome4.CornerActionButtons, { onBack:
|
|
912
|
+
!showMetaInSharedBand && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_chrome4.CornerActionButtons, { onBack: import_core7.safeBack, onSettings: () => setSettingsOpen(true), fg, insets }),
|
|
921
913
|
p2IsHuman ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
922
914
|
import_split_screen.DualZoneLayout,
|
|
923
915
|
{
|
|
@@ -933,13 +925,13 @@ function LoadoutScreen({ game }) {
|
|
|
933
925
|
) : /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native4.View, { style: styles3.stackedZone, children: [
|
|
934
926
|
sharedControls,
|
|
935
927
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native_reanimated2.default.View, { style: [styles3.playersRow, anyPlayerPickerOpen && styles3.playersRowOpen, playersRowFade], children: [
|
|
936
|
-
|
|
937
|
-
|
|
928
|
+
p1Panel,
|
|
929
|
+
p2Panel
|
|
938
930
|
] }),
|
|
939
931
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lobby2.ReadyButton, { color: p1Drawn, ready: ready[1], onToggleReady: () => setReady((r) => ({ ...r, 1: !r[1] })), style: anyPlayerPickerOpen && styles3.readyButtonHidden })
|
|
940
932
|
] })
|
|
941
933
|
] }),
|
|
942
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SettingsDialog, { visible: settingsOpen, onDismiss: () => setSettingsOpen(false),
|
|
934
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SettingsDialog, { visible: settingsOpen, onDismiss: () => setSettingsOpen(false), onShowHowToPlay: () => openFor(game.id) })
|
|
943
935
|
] });
|
|
944
936
|
}
|
|
945
937
|
function halfOf(color) {
|
|
@@ -950,12 +942,13 @@ var styles3 = import_react_native4.StyleSheet.create({
|
|
|
950
942
|
container: {
|
|
951
943
|
flex: 1
|
|
952
944
|
},
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
945
|
+
// A real full-bleed box to size the absolutely-positioned children against.
|
|
946
|
+
frame: {
|
|
947
|
+
alignItems: "center",
|
|
948
|
+
flex: 1,
|
|
949
|
+
gap: 32,
|
|
950
|
+
justifyContent: "center",
|
|
951
|
+
paddingHorizontal: 16
|
|
959
952
|
},
|
|
960
953
|
p2ZoneRight: {
|
|
961
954
|
bottom: 0,
|
|
@@ -990,14 +983,6 @@ var styles3 = import_react_native4.StyleSheet.create({
|
|
|
990
983
|
opacity: 0,
|
|
991
984
|
pointerEvents: "none"
|
|
992
985
|
},
|
|
993
|
-
// A real full-bleed box for FakeLandscapeView to size its absolutely-positioned children against.
|
|
994
|
-
rotatable: {
|
|
995
|
-
alignItems: "center",
|
|
996
|
-
flex: 1,
|
|
997
|
-
gap: 32,
|
|
998
|
-
justifyContent: "center",
|
|
999
|
-
paddingHorizontal: 16
|
|
1000
|
-
},
|
|
1001
986
|
stackedZone: {
|
|
1002
987
|
alignItems: "center",
|
|
1003
988
|
gap: 28
|
|
@@ -1038,12 +1023,11 @@ function useResumePoint(gameId) {
|
|
|
1038
1023
|
// src/screens/HomeScreen.tsx
|
|
1039
1024
|
var import_auto_paper5 = require("@rific/auto-paper");
|
|
1040
1025
|
var import_feedback_press3 = require("@rific/feedback-press");
|
|
1041
|
-
var import_core12 = require("@tastic/core");
|
|
1042
1026
|
var import_chrome5 = require("@tastic/hud/chrome");
|
|
1043
1027
|
var import_profile7 = require("@tastic/profile");
|
|
1044
1028
|
var import_expo_router6 = require("expo-router");
|
|
1045
1029
|
var import_react16 = require("react");
|
|
1046
|
-
var
|
|
1030
|
+
var import_react_native7 = require("react-native");
|
|
1047
1031
|
var import_react_native_paper = require("react-native-paper");
|
|
1048
1032
|
|
|
1049
1033
|
// src/hooks/useFrozenWhileHidden.ts
|
|
@@ -1063,7 +1047,8 @@ function useFrozenWhileHidden(value, hidden) {
|
|
|
1063
1047
|
}
|
|
1064
1048
|
|
|
1065
1049
|
// src/screens/homeLayout.ts
|
|
1066
|
-
var
|
|
1050
|
+
var import_core10 = require("@tastic/core");
|
|
1051
|
+
var import_react_native6 = require("react-native");
|
|
1067
1052
|
var import_react_native_safe_area_context3 = require("react-native-safe-area-context");
|
|
1068
1053
|
var PREVIEW_ASPECT = 360 / 200;
|
|
1069
1054
|
var ROW_PREVIEW_WIDTH = 92;
|
|
@@ -1092,9 +1077,9 @@ function computeHomeLayout(windowWidth, windowHeight, insets) {
|
|
|
1092
1077
|
const inner = Math.max(0, usable - HOME_WIDE_EDGE_PADDING - HOME_WIDE_RIGHT_GUTTER);
|
|
1093
1078
|
const content = Math.min(inner, HOME_WIDE_MAX_CONTENT_WIDTH);
|
|
1094
1079
|
const slack = (inner - content) / 2;
|
|
1095
|
-
const leftPaneWidth = Math.min((0,
|
|
1080
|
+
const leftPaneWidth = Math.min((0, import_core10.clamp)(Math.round(HOME_LEFT_PANE_FRACTION * content), HOME_LEFT_PANE_MIN, HOME_LEFT_PANE_MAX), Math.max(0, content - HOME_WIDE_PANE_GAP - HOME_MIN_TILE_WIDTH));
|
|
1096
1081
|
const rightPaneWidth = Math.max(0, content - HOME_WIDE_PANE_GAP - leftPaneWidth);
|
|
1097
|
-
const columns = (0,
|
|
1082
|
+
const columns = (0, import_core10.clamp)(Math.floor((rightPaneWidth + HOME_GRID_GAP) / (HOME_MIN_TILE_WIDTH + HOME_GRID_GAP)), 1, HOME_MAX_COLUMNS);
|
|
1098
1083
|
const tileWidth = Math.max(0, Math.floor((rightPaneWidth - (columns - 1) * HOME_GRID_GAP) / columns));
|
|
1099
1084
|
const previewWidth = Math.max(0, tileWidth - 2 * HOME_TILE_PADDING);
|
|
1100
1085
|
const heroFit = {
|
|
@@ -1117,9 +1102,8 @@ function computeHomeLayout(windowWidth, windowHeight, insets) {
|
|
|
1117
1102
|
};
|
|
1118
1103
|
}
|
|
1119
1104
|
function useHomeLayout() {
|
|
1120
|
-
const { width, height } = (0,
|
|
1121
|
-
const
|
|
1122
|
-
const insets = (0, import_core11.rotateInsets)((0, import_react_native_safe_area_context3.useSafeAreaInsets)(), rotation);
|
|
1105
|
+
const { width, height } = (0, import_react_native6.useWindowDimensions)();
|
|
1106
|
+
const insets = (0, import_react_native_safe_area_context3.useSafeAreaInsets)();
|
|
1123
1107
|
return computeHomeLayout(width, height, insets);
|
|
1124
1108
|
}
|
|
1125
1109
|
|
|
@@ -1141,7 +1125,6 @@ function HomeScreen() {
|
|
|
1141
1125
|
}
|
|
1142
1126
|
function HomeMenu() {
|
|
1143
1127
|
const pack = usePack();
|
|
1144
|
-
const rotation = (0, import_core12.useRotation)();
|
|
1145
1128
|
const layout = useHomeLayout();
|
|
1146
1129
|
const { insets } = layout;
|
|
1147
1130
|
const { dark, colors } = (0, import_auto_paper5.useAutoPaperTheme)();
|
|
@@ -1149,9 +1132,9 @@ function HomeMenu() {
|
|
|
1149
1132
|
const [settingsOpen, setSettingsOpen] = (0, import_react16.useState)(false);
|
|
1150
1133
|
const [rulesGame, setRulesGame] = (0, import_react16.useState)(null);
|
|
1151
1134
|
const isFocused = (0, import_expo_router6.useIsFocused)();
|
|
1152
|
-
const [appState, setAppState] = (0, import_react16.useState)(
|
|
1135
|
+
const [appState, setAppState] = (0, import_react16.useState)(import_react_native7.AppState.currentState);
|
|
1153
1136
|
(0, import_react16.useEffect)(() => {
|
|
1154
|
-
const subscription =
|
|
1137
|
+
const subscription = import_react_native7.AppState.addEventListener("change", setAppState);
|
|
1155
1138
|
return () => subscription.remove();
|
|
1156
1139
|
}, []);
|
|
1157
1140
|
const heroActive = isFocused && appState === "active";
|
|
@@ -1171,7 +1154,7 @@ function HomeMenu() {
|
|
|
1171
1154
|
const closePicker = pickerHost.close;
|
|
1172
1155
|
(0, import_react16.useEffect)(() => {
|
|
1173
1156
|
closePicker();
|
|
1174
|
-
}, [isWide,
|
|
1157
|
+
}, [isWide, layout.windowWidth, layout.windowHeight, closePicker]);
|
|
1175
1158
|
const bg = pack.Backdrop ? "transparent" : dark ? "#000000" : "#FFFFFF";
|
|
1176
1159
|
const fg = pack.foreground ?? (dark ? "#FFFFFF" : "#000000");
|
|
1177
1160
|
const { previewColor } = pack;
|
|
@@ -1193,30 +1176,30 @@ function HomeMenu() {
|
|
|
1193
1176
|
const picker = /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_profile7.ProfilePicker, { idPrefix: SEAT_ONE_PICKER, host: pickerHost, profiles, selectedId: lastSelected[1], color: p1Drawn, dark, guestLabel: pack.guestLabel ?? "P1", nullLabel: pack.nullLabel, onSelect: (profile) => selectProfile(1, profile?.id ?? null), onManage: () => import_expo_router6.router.push(PROFILES_HREF), colorSection, alignOverride: pickerAlign, triggerStyle });
|
|
1194
1177
|
const pressAway = /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_chrome5.PressAwayOverlay, { active: pickerHost.openId !== null, onPress: pickerHost.close, style: styles4.pressAway });
|
|
1195
1178
|
const RulesSheet = rulesGame?.Rules;
|
|
1196
|
-
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
1197
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1179
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native7.View, { style: [styles4.container, { backgroundColor: bg }], children: [
|
|
1180
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native7.View, { style: styles4.frame, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(RulesHost, { enabled: pack.games.some((game) => game.Rules), children: [
|
|
1198
1181
|
isWide ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
|
|
1199
1182
|
pressAway,
|
|
1200
1183
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_auto_paper5.FadingScrollView, { ...tab && gridClamp, style: [styles4.wideRightPane, { left: layout.paddingLeft + layout.leftPaneWidth + HOME_WIDE_PANE_GAP }], contentContainerStyle: { paddingTop: 16 + insets.top, paddingBottom: 16 + insets.bottom, paddingRight: layout.paddingRight }, children: [
|
|
1201
|
-
tabBar && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1202
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1184
|
+
tabBar && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native7.View, { style: [styles4.wideTabs, { width: layout.rightPaneWidth }], children: tabBar }),
|
|
1185
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native7.View, { style: [styles4.grid, { width: layout.rightPaneWidth }], children: pack.games.map((game) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(GameTile, { game, hidden: isHidden(tab, game), width: layout.tileWidth, previewWidth: layout.previewWidth, previewRevealed: previewsRevealed, dark, p1Color, p2Color, onPress: () => openGame(game), onRules: hasRules(game) ? () => openRules(game) : void 0 }, game.id)) })
|
|
1203
1186
|
] }),
|
|
1204
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
1187
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native7.View, { style: [styles4.wideLeftPane, { left: layout.paddingLeft, width: layout.leftPaneWidth, paddingTop: HOME_TOP_BAND + insets.top, paddingBottom: 16 + insets.bottom }, pickerHost.openId !== null && styles4.pickerOpen], children: [
|
|
1205
1188
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(pack.HeroTitle, { words: pack.wordmark, color: fg, p1Color, p2Color, active: heroActive, fit: layout.heroFit }),
|
|
1206
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1189
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native7.View, { style: styles4.widePicker, children: picker })
|
|
1207
1190
|
] })
|
|
1208
1191
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_auto_paper5.FadingScrollView, { ...tab && columnClamp, style: styles4.scroll, contentContainerStyle: [styles4.content, { paddingTop: 56 + insets.top, paddingBottom: 24 + insets.bottom, paddingLeft: 16 + insets.left, paddingRight: 16 + insets.right }], children: [
|
|
1209
1192
|
pressAway,
|
|
1210
1193
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(pack.HeroTitle, { words: pack.wordmark, color: fg, p1Color, p2Color, active: heroActive }),
|
|
1211
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1212
|
-
tabBar && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1213
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1194
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native7.View, { style: [styles4.picker, pickerHost.openId !== null && styles4.pickerOpen], children: picker }),
|
|
1195
|
+
tabBar && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native7.View, { style: styles4.listWidth, children: tabBar }),
|
|
1196
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native7.View, { style: styles4.list, children: pack.games.map((game) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(GameRow, { game, hidden: isHidden(tab, game), dark, p1Color, p2Color, previewRevealed: previewsRevealed, onPress: () => openGame(game), onRules: hasRules(game) ? () => openRules(game) : void 0 }, game.id)) })
|
|
1214
1197
|
] }),
|
|
1215
1198
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_feedback_press3.IconButton, { icon: "trophy", iconColor: fg, size: 24, style: [styles4.corner, { top: 8 + insets.top, left: 8 + insets.left }], onPress: () => import_expo_router6.router.push(STATS_HREF), accessibilityLabel: "Stats & Achievements" }),
|
|
1216
1199
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_feedback_press3.IconButton, { icon: "cog", iconColor: fg, size: 24, style: [styles4.corner, { top: 8 + insets.top, right: 8 + insets.right }], onPress: () => setSettingsOpen(true), accessibilityLabel: "Settings" }),
|
|
1217
1200
|
RulesSheet && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(RulesSheet, { visible: true, onDismiss: () => setRulesGame(null) })
|
|
1218
1201
|
] }) }),
|
|
1219
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(SettingsDialog, { visible: settingsOpen, onDismiss: () => setSettingsOpen(false),
|
|
1202
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(SettingsDialog, { visible: settingsOpen, onDismiss: () => setSettingsOpen(false), onShowHowToPlay: pack.guide ? openPack : void 0 })
|
|
1220
1203
|
] });
|
|
1221
1204
|
}
|
|
1222
1205
|
var SEAT_ONE_PICKER = "home-p1";
|
|
@@ -1261,10 +1244,10 @@ function GameRow({ game, hidden, dark, p1Color, p2Color, previewRevealed, onPres
|
|
|
1261
1244
|
return (
|
|
1262
1245
|
// The rules button sits beside the row's own button, laid over its end, not inside it: a button
|
|
1263
1246
|
// inside a button is invalid on the web.
|
|
1264
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
1247
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native7.View, { style: hidden ? styles4.hidden : void 0, children: [
|
|
1265
1248
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_feedback_press3.Pressable, { onPress, style: [styles4.row, { backgroundColor: well.bg }], accessibilityRole: "button", accessibilityLabel: game.title, children: [
|
|
1266
|
-
game.Preview ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(PreviewBox, { game, width: ROW_PREVIEW_WIDTH, revealed: previewRevealed, dark, p1Color, p2Color }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1267
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
1249
|
+
game.Preview ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(PreviewBox, { game, width: ROW_PREVIEW_WIDTH, revealed: previewRevealed, dark, p1Color, p2Color }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native7.View, { style: [styles4.rowIcon, { backgroundColor: dark ? ICON_DARK_BG : ICON_LIGHT_BG }], children: GameIcon && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(GameIcon, { size: ROW_ICON_SIZE, p1Color, p2Color, dark }) }),
|
|
1250
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native7.View, { style: styles4.rowText, children: [
|
|
1268
1251
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native_paper.Text, { variant: "titleLarge", style: [styles4.rowTitle, { color: well.fg }], numberOfLines: 1, children: game.title }),
|
|
1269
1252
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native_paper.Text, { variant: "bodyMedium", style: { color: well.fgMuted }, numberOfLines: 2, children: game.blurb })
|
|
1270
1253
|
] })
|
|
@@ -1275,7 +1258,7 @@ function GameRow({ game, hidden, dark, p1Color, p2Color, previewRevealed, onPres
|
|
|
1275
1258
|
}
|
|
1276
1259
|
function GameTile({ game, hidden, width, previewWidth, dark, p1Color, p2Color, previewRevealed, onPress, onRules }) {
|
|
1277
1260
|
const well = (0, import_chrome5.useWellColors)();
|
|
1278
|
-
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
1261
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native7.View, { style: [{ width }, hidden && styles4.hidden], children: [
|
|
1279
1262
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_feedback_press3.Pressable, { onPress, style: [styles4.tile, { backgroundColor: well.bg }], accessibilityRole: "button", accessibilityLabel: game.title, children: [
|
|
1280
1263
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(PreviewBox, { game, width: previewWidth, revealed: previewRevealed, dark, p1Color, p2Color }),
|
|
1281
1264
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native_paper.Text, { variant: "titleMedium", style: [styles4.rowTitle, { color: well.fg }], numberOfLines: 1, children: game.title }),
|
|
@@ -1288,13 +1271,13 @@ function PreviewBox({ game, width, revealed, dark, p1Color, p2Color }) {
|
|
|
1288
1271
|
const height = Math.round(width / PREVIEW_ASPECT);
|
|
1289
1272
|
const { Preview, icon: GameIcon } = game;
|
|
1290
1273
|
const iconSize = Math.min(height, ROW_ICON_SIZE);
|
|
1291
|
-
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1274
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native7.View, { style: [styles4.preview, { width, height, backgroundColor: dark ? ICON_DARK_BG : ICON_LIGHT_BG }], children: Preview ? revealed && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Preview, { width, height, p1Color, p2Color, dark }) : GameIcon && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native7.View, { style: [styles4.previewIcon, { width: iconSize, height: iconSize, borderRadius: iconSize * 0.22 }], children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(GameIcon, { size: iconSize, p1Color, p2Color, dark }) }) });
|
|
1292
1275
|
}
|
|
1293
1276
|
var ROW_ICON_SIZE = 56;
|
|
1294
1277
|
var ICON_LIGHT_BG = "#FAFAFA";
|
|
1295
1278
|
var ICON_DARK_BG = "#050505";
|
|
1296
1279
|
var RULES_BUTTON_SPACE = 44;
|
|
1297
|
-
var styles4 =
|
|
1280
|
+
var styles4 = import_react_native7.StyleSheet.create({
|
|
1298
1281
|
container: {
|
|
1299
1282
|
flex: 1
|
|
1300
1283
|
},
|
|
@@ -1305,6 +1288,9 @@ var styles4 = import_react_native6.StyleSheet.create({
|
|
|
1305
1288
|
corner: {
|
|
1306
1289
|
position: "absolute"
|
|
1307
1290
|
},
|
|
1291
|
+
frame: {
|
|
1292
|
+
flex: 1
|
|
1293
|
+
},
|
|
1308
1294
|
// The wide layout's tiles: wrapped rows of tiles the layout sizes to fill the pane's width.
|
|
1309
1295
|
grid: {
|
|
1310
1296
|
flexDirection: "row",
|
|
@@ -1351,9 +1337,6 @@ var styles4 = import_react_native6.StyleSheet.create({
|
|
|
1351
1337
|
previewIcon: {
|
|
1352
1338
|
overflow: "hidden"
|
|
1353
1339
|
},
|
|
1354
|
-
rotatable: {
|
|
1355
|
-
flex: 1
|
|
1356
|
-
},
|
|
1357
1340
|
// A well (@tastic/hud's wellSurface): the theme's surface on MD3's level-1 shadow, the same surface
|
|
1358
1341
|
// as Solitaire's game rows, the stats screen's sections and every dialog.
|
|
1359
1342
|
row: {
|
|
@@ -1450,7 +1433,7 @@ function useRosterAlign(open, contentWidth, contentHeight) {
|
|
|
1450
1433
|
function ProfilesRoute() {
|
|
1451
1434
|
const { profiles, createProfile, updateProfile, deleteProfile } = useProfiles();
|
|
1452
1435
|
const { Backdrop, foreground, newProfileColor, usePickerAlign } = usePack();
|
|
1453
|
-
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_chrome6.RotatedFrame, { rotatedSafeArea: true, portalHost: true, maxContentWidth: ROSTER_MAX_WIDTH, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_profile8.ProfilesScreen, { profiles, defaultColor: newProfileColor ?? import_auto_paper6.defaultColors[0].value, onCreate: (patch) => createProfile(patch), onSave: (id, patch) => updateProfile(id, patch), onDelete: deleteProfile, onBack:
|
|
1436
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_chrome6.RotatedFrame, { rotatedSafeArea: true, portalHost: true, maxContentWidth: ROSTER_MAX_WIDTH, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_profile8.ProfilesScreen, { profiles, defaultColor: newProfileColor ?? import_auto_paper6.defaultColors[0].value, onCreate: (patch) => createProfile(patch), onSave: (id, patch) => updateProfile(id, patch), onDelete: deleteProfile, onBack: import_core7.safeBack, fg: foreground, bg: Backdrop ? "transparent" : void 0, useColorPickerAlign: usePickerAlign ? useRosterAlign : void 0 }) });
|
|
1454
1437
|
}
|
|
1455
1438
|
|
|
1456
1439
|
// src/screens/StatsScreen.tsx
|
|
@@ -1458,7 +1441,7 @@ var import_auto_paper7 = require("@rific/auto-paper");
|
|
|
1458
1441
|
var import_chrome7 = require("@tastic/hud/chrome");
|
|
1459
1442
|
var import_profile9 = require("@tastic/profile");
|
|
1460
1443
|
var import_react17 = require("react");
|
|
1461
|
-
var
|
|
1444
|
+
var import_react_native8 = require("react-native");
|
|
1462
1445
|
var import_react_native_paper2 = require("react-native-paper");
|
|
1463
1446
|
var import_react_native_safe_area_context4 = require("react-native-safe-area-context");
|
|
1464
1447
|
var import_react_redux10 = require("react-redux");
|
|
@@ -1481,7 +1464,7 @@ function StatsScreen() {
|
|
|
1481
1464
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(StatsPressAway, { host: pickerHost, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_chrome7.RotatedFrame, { rotatedSafeArea: true, portalHost: true, maxContentWidth: STATS_MAX_WIDTH, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(StatsContent, { pickerHost }) }) });
|
|
1482
1465
|
}
|
|
1483
1466
|
function StatsPressAway({ host, children }) {
|
|
1484
|
-
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
1467
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native8.View, { testID: "stats-press-away", style: styles5.screen, onStartShouldSetResponder: () => host.openId !== null, onResponderRelease: host.close, children });
|
|
1485
1468
|
}
|
|
1486
1469
|
var useNoPackReset = () => null;
|
|
1487
1470
|
var noPickerAlign2 = () => void 0;
|
|
@@ -1515,10 +1498,10 @@ function StatsContent({ pickerHost }) {
|
|
|
1515
1498
|
const surface = pack.Backdrop ? { backgroundColor: colors.surface } : void 0;
|
|
1516
1499
|
const triggerStyle = pack.Backdrop ? [styles5.pill, surface] : void 0;
|
|
1517
1500
|
const PackTabContent = packTab?.Content;
|
|
1518
|
-
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_chrome7.BaseStatsScreen, { title, onBack:
|
|
1501
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_chrome7.BaseStatsScreen, { title, onBack: import_core7.safeBack, insets, onReset: reset.onReset, resetLabel: reset.label, resetConfirmTitle: reset.title, resetConfirmBody: reset.body, fg: pack.foreground, bg: pack.Backdrop ? "transparent" : void 0, rotation: 0, children: [
|
|
1519
1502
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_chrome7.PressAwayOverlay, { active: pickerHost.openId !== null, onPress: pickerHost.close, style: styles5.pressAway }),
|
|
1520
1503
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native_paper2.SegmentedButtons, { value: tab, onValueChange: setTab, buttons: tabButtons, style: [styles5.tabs, surface] }),
|
|
1521
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
1504
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native8.View, { style: [styles5.filters, pickerHost.openId !== null && styles5.filtersOpen], onStartShouldSetResponder: () => pickerHost.openId !== null, children: [
|
|
1522
1505
|
profiles.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_profile9.OptionPicker, { id: PLAYER_PICKER_ID, host: pickerHost, options: playerOptions, value: profileId ?? EVERYONE, onChange: (value) => setSelectedProfileId(value === EVERYONE ? null : value), color: colors.primary, dark, icon: profileId ? "account" : "account-group", alignOverride: playerAlign, triggerStyle }),
|
|
1523
1506
|
showGamePicker && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_profile9.OptionPicker, { id: GAME_PICKER_ID, host: pickerHost, options: gameOptions, value: gameId, onChange: setGameId, color: colors.primary, dark, icon: "view-grid-outline", alignOverride: gameAlign, triggerStyle })
|
|
1524
1507
|
] }),
|
|
@@ -1539,12 +1522,12 @@ function GameStats({ game, tab, profileId, showTitle, titleColor }) {
|
|
|
1539
1522
|
const { StatsSections, AchievementList } = game;
|
|
1540
1523
|
const Sections = tab === STATS ? StatsSections : AchievementList;
|
|
1541
1524
|
if (!Sections) return null;
|
|
1542
|
-
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
1525
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native8.View, { style: styles5.game, children: [
|
|
1543
1526
|
showTitle && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native_paper2.Text, { variant: "titleLarge", style: [styles5.gameTitle, { color: titleColor }], children: game.title }),
|
|
1544
1527
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Sections, { profileId })
|
|
1545
1528
|
] });
|
|
1546
1529
|
}
|
|
1547
|
-
var styles5 =
|
|
1530
|
+
var styles5 = import_react_native8.StyleSheet.create({
|
|
1548
1531
|
filters: {
|
|
1549
1532
|
flexDirection: "row",
|
|
1550
1533
|
flexWrap: "wrap",
|
|
@@ -1578,14 +1561,54 @@ var styles5 = import_react_native7.StyleSheet.create({
|
|
|
1578
1561
|
});
|
|
1579
1562
|
|
|
1580
1563
|
// src/components/imageGameIcon.tsx
|
|
1581
|
-
var
|
|
1564
|
+
var import_react_native9 = require("react-native");
|
|
1582
1565
|
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1583
1566
|
function imageGameIcon(images) {
|
|
1584
1567
|
return function ImageGameIcon({ size, dark }) {
|
|
1585
|
-
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1568
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react_native9.Image, { source: dark ? images.dark : images.light, style: { height: size, width: size }, accessibilityIgnoresInvertColors: true });
|
|
1586
1569
|
};
|
|
1587
1570
|
}
|
|
1588
1571
|
|
|
1572
|
+
// src/components/MatchChips.tsx
|
|
1573
|
+
var import_auto_paper8 = require("@rific/auto-paper");
|
|
1574
|
+
var import_feedback_press4 = require("@rific/feedback-press");
|
|
1575
|
+
var import_react18 = require("react");
|
|
1576
|
+
var import_react_native10 = require("react-native");
|
|
1577
|
+
var import_react_native_reanimated3 = __toESM(require("react-native-reanimated"));
|
|
1578
|
+
var import_react_native_safe_area_context5 = require("react-native-safe-area-context");
|
|
1579
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1580
|
+
var MATCH_CHIPS_DESKTOP_MIN_WIDTH = 768;
|
|
1581
|
+
var MATCH_CHIPS_FADE_MS = 150;
|
|
1582
|
+
var CHIP_SIZE = 48;
|
|
1583
|
+
var EDGE_PAD = 8;
|
|
1584
|
+
function MatchChips({ playing, faceToFace, centerLineY, onBack, onSettings }) {
|
|
1585
|
+
const { width, height } = (0, import_react_native10.useWindowDimensions)();
|
|
1586
|
+
const insets = (0, import_react_native_safe_area_context5.useSafeAreaInsets)();
|
|
1587
|
+
const { dark } = (0, import_auto_paper8.useAutoPaperTheme)();
|
|
1588
|
+
const desktopWeb = import_react_native10.Platform.OS === "web" && width >= MATCH_CHIPS_DESKTOP_MIN_WIDTH;
|
|
1589
|
+
const visible = desktopWeb || !playing;
|
|
1590
|
+
const opacity = (0, import_react_native_reanimated3.useSharedValue)(visible ? 1 : 0);
|
|
1591
|
+
(0, import_react18.useEffect)(() => {
|
|
1592
|
+
opacity.value = (0, import_react_native_reanimated3.withTiming)(visible ? 1 : 0, { duration: MATCH_CHIPS_FADE_MS });
|
|
1593
|
+
}, [visible]);
|
|
1594
|
+
const fadeStyle = (0, import_react_native_reanimated3.useAnimatedStyle)(() => ({ opacity: opacity.value }));
|
|
1595
|
+
const iconColor = dark ? "#FFFFFF" : "#000000";
|
|
1596
|
+
const containerColor = dark ? "rgba(0,0,0,0.55)" : "rgba(255,255,255,0.55)";
|
|
1597
|
+
const between = faceToFace && !desktopWeb;
|
|
1598
|
+
const top = between ? (centerLineY ?? height / 2) - CHIP_SIZE / 2 : EDGE_PAD + insets.top;
|
|
1599
|
+
const backSlot = { top, left: EDGE_PAD + insets.left };
|
|
1600
|
+
const settingsSlot = { top, right: EDGE_PAD + insets.right };
|
|
1601
|
+
const pointerEvents = visible ? "box-none" : "none";
|
|
1602
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
|
|
1603
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native_reanimated3.default.View, { pointerEvents, style: [styles6.slot, backSlot, fadeStyle], testID: "match-chips-back", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_feedback_press4.IconButton, { icon: "arrow-left", iconColor, containerColor, style: styles6.chip, size: 24, onPress: onBack, accessibilityLabel: "Back" }) }),
|
|
1604
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_native_reanimated3.default.View, { pointerEvents, style: [styles6.slot, settingsSlot, fadeStyle], testID: "match-chips-settings", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_feedback_press4.IconButton, { icon: "cog", iconColor, containerColor, style: styles6.chip, size: 24, onPress: onSettings, accessibilityLabel: "Settings" }) })
|
|
1605
|
+
] });
|
|
1606
|
+
}
|
|
1607
|
+
var styles6 = import_react_native10.StyleSheet.create({
|
|
1608
|
+
chip: { margin: 0 },
|
|
1609
|
+
slot: { position: "absolute" }
|
|
1610
|
+
});
|
|
1611
|
+
|
|
1589
1612
|
// src/hooks/useActiveRound.ts
|
|
1590
1613
|
var import_react_redux11 = require("react-redux");
|
|
1591
1614
|
function useActiveRound(game, defaults) {
|
|
@@ -1601,12 +1624,12 @@ var import_toolkit = require("@reduxjs/toolkit");
|
|
|
1601
1624
|
var import_redux_persist = require("redux-persist");
|
|
1602
1625
|
|
|
1603
1626
|
// src/redux/shellState.ts
|
|
1604
|
-
var
|
|
1605
|
-
var
|
|
1606
|
-
var
|
|
1627
|
+
var import_auto_paper9 = require("@rific/auto-paper");
|
|
1628
|
+
var import_core11 = require("@rific/core");
|
|
1629
|
+
var import_feedback_press5 = require("@rific/feedback-press");
|
|
1607
1630
|
var import_profile10 = require("@tastic/profile");
|
|
1608
|
-
var initialSoundSettings = { ...
|
|
1609
|
-
var appSoundReducer = (state = initialSoundSettings, action) => (0,
|
|
1631
|
+
var initialSoundSettings = { ...import_feedback_press5.defaultSoundSettings, enabled: !__DEV__ };
|
|
1632
|
+
var appSoundReducer = (state = initialSoundSettings, action) => (0, import_feedback_press5.soundReducer)(state, action);
|
|
1610
1633
|
function createShellReducers({ seatColors, appearance = "system", seatTheme }) {
|
|
1611
1634
|
return {
|
|
1612
1635
|
// Explicit primary/secondary triad (rather than a single seed expanded via harmony) so the pack's
|
|
@@ -1618,12 +1641,12 @@ function createShellReducers({ seatColors, appearance = "system", seatTheme }) {
|
|
|
1618
1641
|
// createThemeReducer's own default, when it sets none).
|
|
1619
1642
|
// A pack with its own seatTheme starts from what seat 1's default color makes of it instead (dark
|
|
1620
1643
|
// only when the pack's appearance is; hooks/useSeatColors.ts re-applies it with the live mode).
|
|
1621
|
-
theme: (0,
|
|
1622
|
-
haptic:
|
|
1644
|
+
theme: (0, import_auto_paper9.createThemeReducer)(seatTheme ? { appearance, ...seatTheme(seatColors, appearance === "dark") } : { appearance, color: { primary: seatColors[1], secondary: seatColors[2], tertiary: (0, import_auto_paper9.getThirdColor)(seatColors[1], seatColors[2]) } }),
|
|
1645
|
+
haptic: import_feedback_press5.hapticReducer,
|
|
1623
1646
|
sound: appSoundReducer,
|
|
1624
1647
|
// @rific/core's Keep Awake setting (see Providers.tsx's KeepAwakeBridge), under the namespace its
|
|
1625
1648
|
// REHYDRATE handling expects.
|
|
1626
|
-
keepAwake:
|
|
1649
|
+
keepAwake: import_core11.keepAwakeReducer,
|
|
1627
1650
|
// The shared App Group roster (see @tastic/profile's resolveInitialProfiles/
|
|
1628
1651
|
// useSharedProfilesSync, wired in hooks/useProfiles.tsx) is layered on top of this as a separate
|
|
1629
1652
|
// sync target - this slice persisting normally via redux-persist is what gives it local-fallback
|
|
@@ -1729,8 +1752,8 @@ function forgetProfileAchievements(dropStats) {
|
|
|
1729
1752
|
|
|
1730
1753
|
// src/gameStats.tsx
|
|
1731
1754
|
var import_achievements2 = require("@tastic/achievements");
|
|
1732
|
-
var
|
|
1733
|
-
var
|
|
1755
|
+
var import_react19 = require("react");
|
|
1756
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
1734
1757
|
var SEATS = [1, 2];
|
|
1735
1758
|
function createGameStats({ key, defaultStats, isValidStats, catalog, getProfileStatsView }) {
|
|
1736
1759
|
const { actions: actions6, reducer: sliceReducer } = (0, import_achievements2.createAchievementsSlice)({
|
|
@@ -1747,7 +1770,7 @@ function createGameStats({ key, defaultStats, isValidStats, catalog, getProfileS
|
|
|
1747
1770
|
};
|
|
1748
1771
|
const reducer6 = onProfileRemoved(sliceReducer, forgetProfileAchievements(dropProfileStats));
|
|
1749
1772
|
const profileViews = (stats) => Object.fromEntries(Object.entries(stats.profiles).map(([profileId, bucket]) => [profileId, getProfileStatsView(bucket)]));
|
|
1750
|
-
const Context = (0,
|
|
1773
|
+
const Context = (0, import_react19.createContext)(null);
|
|
1751
1774
|
function Provider({ children }) {
|
|
1752
1775
|
const { stats, unlockedAchievements, recordOutcome, resetAll } = (0, import_achievements2.useAchievements)({
|
|
1753
1776
|
catalog,
|
|
@@ -1755,18 +1778,18 @@ function createGameStats({ key, defaultStats, isValidStats, catalog, getProfileS
|
|
|
1755
1778
|
actions: actions6,
|
|
1756
1779
|
profileViews
|
|
1757
1780
|
});
|
|
1758
|
-
const record = (0,
|
|
1781
|
+
const record = (0, import_react19.useCallback)(
|
|
1759
1782
|
(update, profileIds) => {
|
|
1760
1783
|
const result = recordOutcome(update);
|
|
1761
1784
|
return { device: result.device, profiles: (0, import_achievements2.mapUnlocksBySeat)(SEATS, profileIds, result.profiles) };
|
|
1762
1785
|
},
|
|
1763
1786
|
[recordOutcome]
|
|
1764
1787
|
);
|
|
1765
|
-
const value = (0,
|
|
1766
|
-
return /* @__PURE__ */ (0,
|
|
1788
|
+
const value = (0, import_react19.useMemo)(() => ({ stats, unlockedAchievements, record, resetAll }), [stats, unlockedAchievements, record, resetAll]);
|
|
1789
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Context.Provider, { value, children });
|
|
1767
1790
|
}
|
|
1768
1791
|
function useStats() {
|
|
1769
|
-
const ctx = (0,
|
|
1792
|
+
const ctx = (0, import_react19.useContext)(Context);
|
|
1770
1793
|
if (!ctx) throw new Error(`The ${key} stats are read within their game's Provider`);
|
|
1771
1794
|
return ctx;
|
|
1772
1795
|
}
|
|
@@ -1774,7 +1797,7 @@ function createGameStats({ key, defaultStats, isValidStats, catalog, getProfileS
|
|
|
1774
1797
|
}
|
|
1775
1798
|
|
|
1776
1799
|
// src/playerSettings.ts
|
|
1777
|
-
var
|
|
1800
|
+
var import_react20 = require("react");
|
|
1778
1801
|
var import_react_redux12 = require("react-redux");
|
|
1779
1802
|
var SEATS2 = [1, 2];
|
|
1780
1803
|
function seatPlayerKey(selection, seat) {
|
|
@@ -1818,8 +1841,8 @@ function createPlayerSettings({ id, defaults, distinctControls }) {
|
|
|
1818
1841
|
const saved = (0, import_react_redux12.useSelector)((state) => state[settingsKey]);
|
|
1819
1842
|
const controls = (0, import_react_redux12.useSelector)((state) => state[controlsKey]);
|
|
1820
1843
|
const dispatch = (0, import_react_redux12.useDispatch)();
|
|
1821
|
-
const settings = (0,
|
|
1822
|
-
const setSettings = (0,
|
|
1844
|
+
const settings = (0, import_react20.useMemo)(() => compose(saved, controls, selection, seatTwoIsPerson), [saved, controls, selection, seatTwoIsPerson]);
|
|
1845
|
+
const setSettings = (0, import_react20.useCallback)(
|
|
1823
1846
|
(next) => {
|
|
1824
1847
|
const { controlScheme, ...changes } = next;
|
|
1825
1848
|
if (Object.keys(changes).length > 0) dispatch(patch(seatPlayerKey(selection, 1), changes));
|
|
@@ -1842,6 +1865,9 @@ function createPlayerSettings({ id, defaults, distinctControls }) {
|
|
|
1842
1865
|
GUEST_PLAYER_ID,
|
|
1843
1866
|
HomeScreen,
|
|
1844
1867
|
LoadoutRoute,
|
|
1868
|
+
MATCH_CHIPS_DESKTOP_MIN_WIDTH,
|
|
1869
|
+
MATCH_CHIPS_FADE_MS,
|
|
1870
|
+
MatchChips,
|
|
1845
1871
|
PREVIEW_ASPECT,
|
|
1846
1872
|
PackProvider,
|
|
1847
1873
|
PlayRoute,
|