@tastic/shell 0.6.0 → 0.8.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 +10 -9
- package/dist/index.d.mts +10 -6
- package/dist/index.d.ts +10 -6
- package/dist/index.js +146 -128
- package/dist/index.mjs +118 -100
- package/package.json +9 -9
- package/src/components/MatchChips.tsx +12 -12
- package/src/components/OpponentPicker.tsx +112 -0
- package/src/components/SettingsDialog.tsx +8 -3
- package/src/hooks/useAtComputer.ts +13 -0
- package/src/index.ts +2 -1
- package/src/redux/opponentSlice.ts +1 -1
- package/src/screens/HomeScreen.tsx +1 -1
- package/src/screens/LoadoutScreen.tsx +86 -37
- package/src/types.ts +16 -4
- package/src/components/SeatTwoPanel.tsx +0 -144
package/dist/index.js
CHANGED
|
@@ -35,7 +35,6 @@ __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
38
|
MATCH_CHIPS_FADE_MS: () => MATCH_CHIPS_FADE_MS,
|
|
40
39
|
MatchChips: () => MatchChips,
|
|
41
40
|
PREVIEW_ASPECT: () => PREVIEW_ASPECT,
|
|
@@ -67,12 +66,13 @@ __export(index_exports, {
|
|
|
67
66
|
profileSelectionActions: () => profileSelectionActions,
|
|
68
67
|
profileSelectionReducer: () => profileSelectionSlice_default,
|
|
69
68
|
roundModeFor: () => roundModeFor,
|
|
70
|
-
safeBack: () =>
|
|
69
|
+
safeBack: () => import_core8.safeBack,
|
|
71
70
|
seatColorsActions: () => seatColorsActions,
|
|
72
71
|
seatPlayerKey: () => seatPlayerKey,
|
|
73
72
|
seatTwoFor: () => seatTwoFor,
|
|
74
73
|
useActiveRound: () => useActiveRound,
|
|
75
74
|
useAppSettings: () => useAppSettings,
|
|
75
|
+
useAtComputer: () => useAtComputer,
|
|
76
76
|
useGameGuide: () => useGameGuide,
|
|
77
77
|
useOpponent: () => useOpponent,
|
|
78
78
|
usePack: () => usePack,
|
|
@@ -525,7 +525,7 @@ var styles = import_react_native2.StyleSheet.create({
|
|
|
525
525
|
// src/screens/GameRoute.tsx
|
|
526
526
|
var import_expo_router5 = require("expo-router");
|
|
527
527
|
var import_react14 = require("react");
|
|
528
|
-
var
|
|
528
|
+
var import_react_native6 = require("react-native");
|
|
529
529
|
|
|
530
530
|
// src/routes.ts
|
|
531
531
|
var playHref = (game) => ({ pathname: "/play/[game]", params: { game } });
|
|
@@ -535,91 +535,66 @@ var PROFILES_HREF = "/profiles";
|
|
|
535
535
|
|
|
536
536
|
// src/screens/LoadoutScreen.tsx
|
|
537
537
|
var import_auto_paper4 = require("@rific/auto-paper");
|
|
538
|
-
var
|
|
538
|
+
var import_core10 = require("@tastic/core");
|
|
539
539
|
var import_chrome4 = require("@tastic/hud/chrome");
|
|
540
540
|
var import_lobby2 = require("@tastic/hud/lobby");
|
|
541
541
|
var import_split_screen = require("@tastic/split-screen");
|
|
542
542
|
var import_expo_router4 = require("expo-router");
|
|
543
543
|
var import_react13 = require("react");
|
|
544
|
-
var
|
|
544
|
+
var import_react_native5 = require("react-native");
|
|
545
545
|
var import_react_native_reanimated2 = __toESM(require("react-native-reanimated"));
|
|
546
546
|
var import_react_native_safe_area_context2 = require("react-native-safe-area-context");
|
|
547
547
|
var import_react_redux9 = require("react-redux");
|
|
548
548
|
|
|
549
|
-
// src/components/
|
|
549
|
+
// src/components/OpponentPicker.tsx
|
|
550
550
|
var import_lobby = require("@tastic/hud/lobby");
|
|
551
551
|
var import_profile4 = require("@tastic/profile");
|
|
552
552
|
var import_react9 = require("react");
|
|
553
553
|
var import_react_native3 = require("react-native");
|
|
554
554
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
555
555
|
var CPU_PREFIX = "cpu:";
|
|
556
|
-
var PROFILE_PREFIX = "profile:";
|
|
557
556
|
var NOBODY = "nobody";
|
|
558
|
-
var
|
|
559
|
-
var
|
|
557
|
+
var PERSON = "person";
|
|
558
|
+
var PERSON_ICON = "account-outline";
|
|
560
559
|
var NOBODY_ICON = "account-off-outline";
|
|
561
560
|
var CPU_ICON = "robot";
|
|
562
|
-
function
|
|
563
|
-
return `${idPrefix}-
|
|
561
|
+
function getOpponentPopoverId(idPrefix) {
|
|
562
|
+
return `${idPrefix}-opponent`;
|
|
564
563
|
}
|
|
565
|
-
function
|
|
566
|
-
const isPerson = seatTwo === "person";
|
|
564
|
+
function OpponentPicker({ idPrefix, host, choices, seatTwo, onSeatTwoChange, cpuDifficulty, color, onColorChange, swatches, takenColor, allowSwapTaken, dark, previewValue, triggerStyle, usePickerAlign }) {
|
|
567
565
|
const drawn = previewValue ? previewValue(color) : color;
|
|
568
|
-
const selectedProfile = isPerson ? profiles.find((p) => p.id === selectedProfileId) ?? null : null;
|
|
569
566
|
const cpuOptions = cpuDifficulty?.options;
|
|
570
567
|
const options = (0, import_react9.useMemo)(() => {
|
|
571
568
|
const list = [];
|
|
572
569
|
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 }]);
|
|
573
|
-
if (choices.includes("nobody")) list.push({ value: NOBODY, label: "
|
|
574
|
-
if (choices.includes("person")) {
|
|
575
|
-
list.push({ value: GUEST, label: "Player 2", icon: GUEST_ICON });
|
|
576
|
-
list.push(...[...profiles].sort((a, b) => a.name.localeCompare(b.name)).map((p) => ({ value: `${PROFILE_PREFIX}${p.id}`, label: p.name, icon: "account", color: previewValue ? previewValue(p.color) : p.color })));
|
|
577
|
-
}
|
|
570
|
+
if (choices.includes("nobody")) list.push({ value: NOBODY, label: "Solo", icon: NOBODY_ICON, dividerBefore: true });
|
|
571
|
+
if (choices.includes("person")) list.push({ value: PERSON, label: "Player", icon: PERSON_ICON, dividerBefore: true });
|
|
578
572
|
return list;
|
|
579
|
-
}, [choices, cpuOptions
|
|
580
|
-
const value = seatTwo === "cpu" ? `${CPU_PREFIX}${cpuDifficulty?.value ?? ""}` : seatTwo === "nobody" ? NOBODY :
|
|
581
|
-
const icon = seatTwo === "cpu" ? CPU_ICON : seatTwo === "nobody" ? NOBODY_ICON :
|
|
573
|
+
}, [choices, cpuOptions]);
|
|
574
|
+
const value = seatTwo === "cpu" ? `${CPU_PREFIX}${cpuDifficulty?.value ?? ""}` : seatTwo === "nobody" ? NOBODY : PERSON;
|
|
575
|
+
const icon = seatTwo === "cpu" ? CPU_ICON : seatTwo === "nobody" ? NOBODY_ICON : PERSON_ICON;
|
|
582
576
|
const handleChange = (next) => {
|
|
583
577
|
if (next.startsWith(CPU_PREFIX)) {
|
|
584
578
|
cpuDifficulty?.onChange(next.slice(CPU_PREFIX.length));
|
|
585
579
|
onSeatTwoChange("cpu");
|
|
586
|
-
} else if (next === NOBODY) {
|
|
587
|
-
onSeatTwoChange("nobody");
|
|
588
580
|
} else {
|
|
589
|
-
|
|
590
|
-
onSeatTwoChange("person");
|
|
581
|
+
onSeatTwoChange(next === NOBODY ? "nobody" : "person");
|
|
591
582
|
}
|
|
592
583
|
};
|
|
593
|
-
const colorSection = seatTwo === "
|
|
594
|
-
const pickerId =
|
|
595
|
-
const size = (0, import_profile4.getOptionPickerContentSize)(options
|
|
584
|
+
const colorSection = seatTwo === "cpu" ? { value: color, onChange: onColorChange, swatches, takenValue: takenColor, allowSwapTaken, previewValue } : void 0;
|
|
585
|
+
const pickerId = getOpponentPopoverId(idPrefix);
|
|
586
|
+
const size = (0, import_profile4.getOptionPickerContentSize)(options, colorSection);
|
|
596
587
|
const useAlign = usePickerAlign ?? import_lobby.useZoneClampedAlign;
|
|
597
588
|
const align = useAlign(host.openId === pickerId, size.width, size.height);
|
|
598
|
-
|
|
599
|
-
const pickerRowOpen = secondPickerId !== void 0 && host.openId === secondPickerId;
|
|
600
|
-
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react_native3.View, { style: [styles2.panel, ownPopoverOpen && styles2.panelOpen], children: [
|
|
601
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_profile4.OptionPicker, { id: pickerId, host, options, value, onChange: handleChange, color: drawn, dark, icon, colorSection, alignOverride: align, triggerStyle }),
|
|
602
|
-
isPerson && secondPicker && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native3.View, { style: [styles2.pickerRow, pickerRowOpen && styles2.pickerRowOpen], children: secondPicker }),
|
|
603
|
-
isPerson && showReadyButton && onToggleReady && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lobby.ReadyButton, { color: drawn, ready: ready ?? false, onToggleReady })
|
|
604
|
-
] });
|
|
589
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_native3.View, { style: [styles2.button, host.openId === pickerId && styles2.buttonOpen], children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_profile4.OptionPicker, { id: pickerId, host, options, value, onChange: handleChange, color: drawn, dark, icon, colorSection, alignOverride: align, triggerStyle }) });
|
|
605
590
|
}
|
|
606
591
|
var styles2 = import_react_native3.StyleSheet.create({
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
},
|
|
611
|
-
// A popover escaping this panel needs the panel itself elevated to paint above a later sibling.
|
|
612
|
-
panelOpen: {
|
|
613
|
-
zIndex: 100
|
|
614
|
-
},
|
|
615
|
-
pickerRow: {
|
|
616
|
-
alignItems: "center",
|
|
617
|
-
flexDirection: "row",
|
|
618
|
-
gap: 12
|
|
592
|
+
// Its own column, so a row of seat buttons doesn't stretch the pill to the tallest of them.
|
|
593
|
+
button: {
|
|
594
|
+
alignItems: "center"
|
|
619
595
|
},
|
|
620
|
-
//
|
|
621
|
-
|
|
622
|
-
pickerRowOpen: {
|
|
596
|
+
// A popover escaping this button needs the button itself elevated to paint above a later sibling.
|
|
597
|
+
buttonOpen: {
|
|
623
598
|
zIndex: 100
|
|
624
599
|
}
|
|
625
600
|
});
|
|
@@ -660,25 +635,35 @@ function useAppSettings() {
|
|
|
660
635
|
|
|
661
636
|
// src/components/SettingsDialog.tsx
|
|
662
637
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
638
|
+
var noSettingsRules = () => null;
|
|
663
639
|
function SettingsDialog({ visible, onDismiss, onShowHowToPlay, children }) {
|
|
664
640
|
const onUpdateError = (0, import_toaster3.useUpdateErrorToast)();
|
|
665
641
|
const { settings, setSettings } = useAppSettings();
|
|
666
|
-
const { otaVersion, SettingsSections, edgeGuard = true } = usePack();
|
|
642
|
+
const { otaVersion, SettingsSections, edgeGuard = true, useSettingsRules = noSettingsRules } = usePack();
|
|
643
|
+
const rules = useSettingsRules();
|
|
667
644
|
const edgeGuardProps = edgeGuard ? { deferBottomEdgeGestures: settings.deferBottomEdgeGestures, onDeferBottomEdgeGestures: (value) => setSettings({ deferBottomEdgeGestures: value }) } : {};
|
|
668
|
-
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_chrome3.BaseSettingsDialog, { visible, onDismiss, version: otaVersion, ...edgeGuardProps, onUpdateError, onShowHowToPlay, children: [
|
|
645
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_chrome3.BaseSettingsDialog, { visible, onDismiss, version: otaVersion, ...edgeGuardProps, onUpdateError, onShowHowToPlay, leading: rules, children: [
|
|
669
646
|
children,
|
|
670
647
|
SettingsSections && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SettingsSections, {})
|
|
671
648
|
] });
|
|
672
649
|
}
|
|
673
650
|
|
|
651
|
+
// src/hooks/useAtComputer.ts
|
|
652
|
+
var import_core6 = require("@tastic/core");
|
|
653
|
+
var import_react_native4 = require("react-native");
|
|
654
|
+
function useAtComputer() {
|
|
655
|
+
const touchPrimary = (0, import_core6.useIsTouchPrimaryDevice)();
|
|
656
|
+
return import_react_native4.Platform.OS === "web" && !touchPrimary;
|
|
657
|
+
}
|
|
658
|
+
|
|
674
659
|
// src/hooks/useOpponent.ts
|
|
675
660
|
var import_react11 = require("react");
|
|
676
661
|
var import_react_redux7 = require("react-redux");
|
|
677
662
|
|
|
678
663
|
// src/redux/opponentSlice.ts
|
|
679
|
-
var
|
|
664
|
+
var import_core7 = require("@rific/core");
|
|
680
665
|
var DEFAULT_OPPONENT = { seatTwo: "cpu" };
|
|
681
|
-
var { actions: actions4, reducer: reducer4 } = (0,
|
|
666
|
+
var { actions: actions4, reducer: reducer4 } = (0, import_core7.createSettingsSlice)("opponent", {
|
|
682
667
|
initialState: DEFAULT_OPPONENT
|
|
683
668
|
});
|
|
684
669
|
var opponentActions = actions4;
|
|
@@ -811,13 +796,13 @@ function useSeatColors(p2IsHuman) {
|
|
|
811
796
|
}
|
|
812
797
|
|
|
813
798
|
// src/navigation.ts
|
|
814
|
-
var
|
|
799
|
+
var import_core8 = require("@rific/core");
|
|
815
800
|
var import_expo_router3 = require("expo-router");
|
|
816
|
-
(0,
|
|
801
|
+
(0, import_core8.configureNavigation)({ router: import_expo_router3.router });
|
|
817
802
|
|
|
818
803
|
// src/redux/liveplaySlice.ts
|
|
819
|
-
var
|
|
820
|
-
var { actions: actions5, reducer: reducer5 } = (0,
|
|
804
|
+
var import_core9 = require("@rific/core");
|
|
805
|
+
var { actions: actions5, reducer: reducer5 } = (0, import_core9.createSettingsSlice)("liveplay", {
|
|
821
806
|
initialState: { activelyPlaying: false, activeRound: null }
|
|
822
807
|
});
|
|
823
808
|
var liveplayActions = actions5;
|
|
@@ -826,6 +811,8 @@ var liveplaySlice_default = reducer5;
|
|
|
826
811
|
// src/screens/LoadoutScreen.tsx
|
|
827
812
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
828
813
|
var PANEL_SWAP_FADE_MS = 180;
|
|
814
|
+
var P1_CONTROL_ID = "p1-control";
|
|
815
|
+
var P2_CONTROL_ID = "p2-control";
|
|
829
816
|
function LoadoutScreen({ game }) {
|
|
830
817
|
const pack = usePack();
|
|
831
818
|
const { seatTwo: savedSeatTwo, setSeatTwo } = useOpponent();
|
|
@@ -837,8 +824,10 @@ function LoadoutScreen({ game }) {
|
|
|
837
824
|
const loadout = game.useLoadout(mode);
|
|
838
825
|
const { openFor } = useGameGuide();
|
|
839
826
|
const { profiles, lastSelected, selectProfile } = useProfiles();
|
|
840
|
-
const { orientationMode } = (0,
|
|
841
|
-
const
|
|
827
|
+
const { orientationMode } = (0, import_core10.useOrientationState)();
|
|
828
|
+
const atComputer = useAtComputer();
|
|
829
|
+
const twoPlayerMode = game.sideBySideAtComputer && atComputer ? "sideBySide" : game.sideBySideWhenWide ? orientationMode : "faceToFace";
|
|
830
|
+
const panelMode = p2IsHuman ? twoPlayerMode : orientationMode;
|
|
842
831
|
const { panelLayout, panelFadeStyle } = (0, import_split_screen.useDualZoneLayout)(panelMode, false, true, false, PANEL_SWAP_FADE_MS);
|
|
843
832
|
const playersRowFade = panelFadeStyle;
|
|
844
833
|
const [settingsOpen, setSettingsOpen] = (0, import_react13.useState)(false);
|
|
@@ -847,7 +836,7 @@ function LoadoutScreen({ game }) {
|
|
|
847
836
|
const { p1Color, p2Color, handleP1ColorChange, handleP2ColorChange } = useSeatColors(p2IsHuman);
|
|
848
837
|
const dispatch = (0, import_react_redux9.useDispatch)();
|
|
849
838
|
const handleP1ProfileSelect = (0, import_react13.useCallback)((profile) => selectProfile(1, profile?.id ?? null), [selectProfile]);
|
|
850
|
-
const handleP2ProfileSelect = (0, import_react13.useCallback)((
|
|
839
|
+
const handleP2ProfileSelect = (0, import_react13.useCallback)((profile) => selectProfile(2, profile?.id ?? null), [selectProfile]);
|
|
851
840
|
const [ready, setReady] = (0, import_react13.useState)({ 1: false, 2: false });
|
|
852
841
|
(0, import_expo_router4.useFocusEffect)(
|
|
853
842
|
(0, import_react13.useCallback)(() => {
|
|
@@ -878,16 +867,16 @@ function LoadoutScreen({ game }) {
|
|
|
878
867
|
const p1Drawn = seatPreview ? seatPreview(p1Color) : p1Color;
|
|
879
868
|
const p2Drawn = seatPreview ? seatPreview(p2Color) : p2Color;
|
|
880
869
|
const triggerStyle = (0, import_react13.useMemo)(() => pack.Backdrop ? [styles3.pill, { backgroundColor: themeColors.surface }] : void 0, [pack.Backdrop, themeColors.surface]);
|
|
870
|
+
const readySurface = pack.Backdrop ? themeColors.surface : void 0;
|
|
881
871
|
const isPortrait = panelLayout.orientationMode === "faceToFace";
|
|
882
872
|
const showMetaInSharedBand = (0, import_split_screen.needsSharedNeutralZone)(panelLayout.orientationMode, humanSeats.length);
|
|
883
873
|
const p2ZoneStyle = p2IsHuman ? isPortrait ? styles3.p2ZoneTop : styles3.p2ZoneRight : null;
|
|
884
|
-
const showReadyButton = p2IsHuman;
|
|
885
874
|
const seatPickerAlign = p2IsHuman ? void 0 : pack.usePickerAlign;
|
|
886
875
|
const layoutKey = p2IsHuman ? "zones" : "row";
|
|
887
876
|
const controlsHost = (0, import_chrome4.usePopoverHost)();
|
|
888
|
-
const
|
|
889
|
-
const
|
|
890
|
-
const
|
|
877
|
+
const p2Host = (0, import_chrome4.usePopoverHost)();
|
|
878
|
+
const p1PickerOpen = controlsHost.openId?.startsWith("p1-") ?? false;
|
|
879
|
+
const p1ControlOpen = controlsHost.openId === P1_CONTROL_ID;
|
|
891
880
|
const optionsRow = loadout.options({
|
|
892
881
|
host: controlsHost,
|
|
893
882
|
accentColor: themeColors.tertiary,
|
|
@@ -899,36 +888,44 @@ function LoadoutScreen({ game }) {
|
|
|
899
888
|
onReset: showMetaInSharedBand ? void 0 : loadout.reset
|
|
900
889
|
});
|
|
901
890
|
const optionsPopoverOpen = controlsHost.openId !== null && loadout.optionIds.includes(controlsHost.openId);
|
|
902
|
-
const sharedControls = showMetaInSharedBand ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lobby2.SharedActionBand, { onBack:
|
|
891
|
+
const sharedControls = showMetaInSharedBand ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lobby2.SharedActionBand, { onBack: import_core8.safeBack, onSettings: () => setSettingsOpen(true), onRandomize: loadout.randomize, onReset: loadout.reset, fg, popoverOpen: optionsPopoverOpen, children: optionsRow }) : optionsRow;
|
|
903
892
|
const controlLook = { accentColor: themeColors.tertiary, mutedColor: fgMuted, dark };
|
|
904
893
|
const p1Control = loadout.seatControl(1, controlsHost, { ...controlLook, seatColor: p1Drawn });
|
|
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,
|
|
894
|
+
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, dark, showReadyButton: false, 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}`);
|
|
895
|
+
const opponentPicker = game.seatTwo && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(OpponentPicker, { idPrefix: "p1", host: controlsHost, choices: game.seatTwo, seatTwo, onSeatTwoChange: changeSeatTwo, cpuDifficulty: loadout.cpuDifficulty, color: p2Color, onColorChange: handleP2ColorChange, swatches: import_auto_paper4.defaultColors, takenColor: p1Color, allowSwapTaken: mode === "vsCpu", dark, previewValue: seatPreview, triggerStyle, usePickerAlign: seatPickerAlign }, `opponent-${layoutKey}`);
|
|
896
|
+
const toggleP1Ready = () => setReady((r) => ({ ...r, 1: !r[1] }));
|
|
897
|
+
const seatOne = /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native5.View, { style: [styles3.seatOne, !p2IsHuman && styles3.seatOneAlone, p1PickerOpen && styles3.raised], children: [
|
|
898
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native5.View, { style: [styles3.seatOneButtons, p1PickerOpen && styles3.raised], children: [
|
|
899
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native_reanimated2.default.View, { style: [styles3.playersRow, p1PickerOpen && styles3.raised, !p2IsHuman && playersRowFade], children: [
|
|
900
|
+
p1Panel,
|
|
901
|
+
opponentPicker
|
|
902
|
+
] }),
|
|
903
|
+
p1Control && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_native5.View, { style: [styles3.controlRow, p1ControlOpen && styles3.raised], children: p1Control })
|
|
904
|
+
] }),
|
|
905
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lobby2.ReadyButton, { color: p1Drawn, ready: ready[1], onToggleReady: toggleP1Ready, surfaceColor: readySurface, dark, style: !p2IsHuman && p1PickerOpen && styles3.readyButtonHidden })
|
|
906
|
+
] });
|
|
906
907
|
const p2Control = p2IsHuman ? loadout.seatControl(2, p2Host, { ...controlLook, seatColor: p2Drawn }) : void 0;
|
|
907
|
-
const p2Panel =
|
|
908
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
909
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
908
|
+
const p2Panel = p2IsHuman && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lobby2.PlayerSetupPanel, { idPrefix: "p2", host: p2Host, color: p2Color, onColorChange: handleP2ColorChange, swatches: import_auto_paper4.defaultColors, takenColor: p1Color, colorCaption: pack.colorCaption, isHuman: true, ready: ready[2], onToggleReady: () => setReady((r) => ({ ...r, 2: !r[2] })), dark, secondPicker: p2Control, secondPickerId: p2Control ? P2_CONTROL_ID : void 0, profiles, selectedProfileId: lastSelected[2], takenProfileId: lastSelected[1], guestLabel: pack.guestLabel ?? "P2", nullLabel: pack.nullLabel, onProfileSelect: handleP2ProfileSelect, previewValue: seatPreview, triggerStyle, readySurfaceColor: readySurface }, "p2-zones");
|
|
909
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native5.View, { style: [styles3.container, { backgroundColor: bg }], children: [
|
|
910
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native5.View, { style: styles3.frame, children: [
|
|
910
911
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_chrome4.PressAwayOverlay, { active: controlsHost.openId !== null, onPress: controlsHost.close }),
|
|
911
912
|
p2ZoneStyle && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_chrome4.PressAwayOverlay, { active: controlsHost.openId !== null || p2Host.openId !== null, onPress: p2Host.close, style: p2ZoneStyle }),
|
|
912
|
-
!showMetaInSharedBand && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_chrome4.CornerActionButtons, { onBack:
|
|
913
|
+
!showMetaInSharedBand && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_chrome4.CornerActionButtons, { onBack: import_core8.safeBack, onSettings: () => setSettingsOpen(true), fg, insets }),
|
|
913
914
|
p2IsHuman ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
914
915
|
import_split_screen.DualZoneLayout,
|
|
915
916
|
{
|
|
916
917
|
panelLayout,
|
|
917
918
|
panelFadeStyle,
|
|
918
|
-
p1:
|
|
919
|
+
p1: seatOne,
|
|
919
920
|
p2: p2Panel,
|
|
920
921
|
shared: sharedControls,
|
|
921
|
-
p1Elevated:
|
|
922
|
+
p1Elevated: p1PickerOpen,
|
|
922
923
|
p2Elevated: p2Host.openId !== null,
|
|
923
924
|
sharedElevated: optionsPopoverOpen
|
|
924
925
|
}
|
|
925
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
926
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_react_native5.View, { style: styles3.stackedZone, children: [
|
|
926
927
|
sharedControls,
|
|
927
|
-
|
|
928
|
-
p1Panel,
|
|
929
|
-
p2Panel
|
|
930
|
-
] }),
|
|
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 })
|
|
928
|
+
seatOne
|
|
932
929
|
] })
|
|
933
930
|
] }),
|
|
934
931
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SettingsDialog, { visible: settingsOpen, onDismiss: () => setSettingsOpen(false), onShowHowToPlay: () => openFor(game.id) })
|
|
@@ -938,10 +935,16 @@ function halfOf(color) {
|
|
|
938
935
|
const rgb = (0, import_auto_paper4.getRgb)(color);
|
|
939
936
|
return rgb ? `rgba(${rgb.r},${rgb.g},${rgb.b},0.5)` : void 0;
|
|
940
937
|
}
|
|
941
|
-
var styles3 =
|
|
938
|
+
var styles3 = import_react_native5.StyleSheet.create({
|
|
942
939
|
container: {
|
|
943
940
|
flex: 1
|
|
944
941
|
},
|
|
942
|
+
// Player 1's controls, under their row of buttons.
|
|
943
|
+
controlRow: {
|
|
944
|
+
alignItems: "center",
|
|
945
|
+
flexDirection: "row",
|
|
946
|
+
gap: 12
|
|
947
|
+
},
|
|
945
948
|
// A real full-bleed box to size the absolutely-positioned children against.
|
|
946
949
|
frame: {
|
|
947
950
|
alignItems: "center",
|
|
@@ -968,21 +971,37 @@ var styles3 = import_react_native4.StyleSheet.create({
|
|
|
968
971
|
pill: {
|
|
969
972
|
borderRadius: 999
|
|
970
973
|
},
|
|
971
|
-
//
|
|
972
|
-
//
|
|
974
|
+
// Seat 1's button and the opponent button read as one evenly spaced row of buttons, at
|
|
975
|
+
// PlayerSetupPanel's own pickerRow gap (12).
|
|
973
976
|
playersRow: {
|
|
974
977
|
flexDirection: "row",
|
|
975
978
|
gap: 12
|
|
976
979
|
},
|
|
977
|
-
|
|
980
|
+
// Lifts whichever piece of player 1's has a menu open above its later siblings (each View is its
|
|
981
|
+
// own stacking context on the web).
|
|
982
|
+
raised: {
|
|
978
983
|
zIndex: 100
|
|
979
984
|
},
|
|
980
|
-
// See
|
|
985
|
+
// See p1PickerOpen: opacity 0 (not display:'none') keeps the button's layout space, and
|
|
981
986
|
// pointerEvents:'none' keeps the sliver an open menu doesn't cover from being a hidden tap target.
|
|
982
987
|
readyButtonHidden: {
|
|
983
988
|
opacity: 0,
|
|
984
989
|
pointerEvents: "none"
|
|
985
990
|
},
|
|
991
|
+
// Player 1's column: their row of buttons and controls, then Ready, at PlayerSetupPanel's own
|
|
992
|
+
// rhythm in their half of 2 Player.
|
|
993
|
+
seatOne: {
|
|
994
|
+
alignItems: "center",
|
|
995
|
+
gap: 12
|
|
996
|
+
},
|
|
997
|
+
// With one person, Ready sits as far under the buttons as the match options sit above them.
|
|
998
|
+
seatOneAlone: {
|
|
999
|
+
gap: 28
|
|
1000
|
+
},
|
|
1001
|
+
seatOneButtons: {
|
|
1002
|
+
alignItems: "center",
|
|
1003
|
+
gap: 12
|
|
1004
|
+
},
|
|
986
1005
|
stackedZone: {
|
|
987
1006
|
alignItems: "center",
|
|
988
1007
|
gap: 28
|
|
@@ -1015,7 +1034,7 @@ function useResumePoint(gameId) {
|
|
|
1015
1034
|
if (!gameId) return;
|
|
1016
1035
|
setLastActiveGame(gameId);
|
|
1017
1036
|
return () => {
|
|
1018
|
-
if (
|
|
1037
|
+
if (import_react_native6.AppState.currentState === "active") clearLastActiveGame();
|
|
1019
1038
|
};
|
|
1020
1039
|
}, [gameId, setLastActiveGame, clearLastActiveGame]);
|
|
1021
1040
|
}
|
|
@@ -1027,7 +1046,7 @@ var import_chrome5 = require("@tastic/hud/chrome");
|
|
|
1027
1046
|
var import_profile7 = require("@tastic/profile");
|
|
1028
1047
|
var import_expo_router6 = require("expo-router");
|
|
1029
1048
|
var import_react16 = require("react");
|
|
1030
|
-
var
|
|
1049
|
+
var import_react_native8 = require("react-native");
|
|
1031
1050
|
var import_react_native_paper = require("react-native-paper");
|
|
1032
1051
|
|
|
1033
1052
|
// src/hooks/useFrozenWhileHidden.ts
|
|
@@ -1047,8 +1066,8 @@ function useFrozenWhileHidden(value, hidden) {
|
|
|
1047
1066
|
}
|
|
1048
1067
|
|
|
1049
1068
|
// src/screens/homeLayout.ts
|
|
1050
|
-
var
|
|
1051
|
-
var
|
|
1069
|
+
var import_core11 = require("@tastic/core");
|
|
1070
|
+
var import_react_native7 = require("react-native");
|
|
1052
1071
|
var import_react_native_safe_area_context3 = require("react-native-safe-area-context");
|
|
1053
1072
|
var PREVIEW_ASPECT = 360 / 200;
|
|
1054
1073
|
var ROW_PREVIEW_WIDTH = 92;
|
|
@@ -1077,9 +1096,9 @@ function computeHomeLayout(windowWidth, windowHeight, insets) {
|
|
|
1077
1096
|
const inner = Math.max(0, usable - HOME_WIDE_EDGE_PADDING - HOME_WIDE_RIGHT_GUTTER);
|
|
1078
1097
|
const content = Math.min(inner, HOME_WIDE_MAX_CONTENT_WIDTH);
|
|
1079
1098
|
const slack = (inner - content) / 2;
|
|
1080
|
-
const leftPaneWidth = Math.min((0,
|
|
1099
|
+
const leftPaneWidth = Math.min((0, import_core11.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));
|
|
1081
1100
|
const rightPaneWidth = Math.max(0, content - HOME_WIDE_PANE_GAP - leftPaneWidth);
|
|
1082
|
-
const columns = (0,
|
|
1101
|
+
const columns = (0, import_core11.clamp)(Math.floor((rightPaneWidth + HOME_GRID_GAP) / (HOME_MIN_TILE_WIDTH + HOME_GRID_GAP)), 1, HOME_MAX_COLUMNS);
|
|
1083
1102
|
const tileWidth = Math.max(0, Math.floor((rightPaneWidth - (columns - 1) * HOME_GRID_GAP) / columns));
|
|
1084
1103
|
const previewWidth = Math.max(0, tileWidth - 2 * HOME_TILE_PADDING);
|
|
1085
1104
|
const heroFit = {
|
|
@@ -1102,7 +1121,7 @@ function computeHomeLayout(windowWidth, windowHeight, insets) {
|
|
|
1102
1121
|
};
|
|
1103
1122
|
}
|
|
1104
1123
|
function useHomeLayout() {
|
|
1105
|
-
const { width, height } = (0,
|
|
1124
|
+
const { width, height } = (0, import_react_native7.useWindowDimensions)();
|
|
1106
1125
|
const insets = (0, import_react_native_safe_area_context3.useSafeAreaInsets)();
|
|
1107
1126
|
return computeHomeLayout(width, height, insets);
|
|
1108
1127
|
}
|
|
@@ -1132,9 +1151,9 @@ function HomeMenu() {
|
|
|
1132
1151
|
const [settingsOpen, setSettingsOpen] = (0, import_react16.useState)(false);
|
|
1133
1152
|
const [rulesGame, setRulesGame] = (0, import_react16.useState)(null);
|
|
1134
1153
|
const isFocused = (0, import_expo_router6.useIsFocused)();
|
|
1135
|
-
const [appState, setAppState] = (0, import_react16.useState)(
|
|
1154
|
+
const [appState, setAppState] = (0, import_react16.useState)(import_react_native8.AppState.currentState);
|
|
1136
1155
|
(0, import_react16.useEffect)(() => {
|
|
1137
|
-
const subscription =
|
|
1156
|
+
const subscription = import_react_native8.AppState.addEventListener("change", setAppState);
|
|
1138
1157
|
return () => subscription.remove();
|
|
1139
1158
|
}, []);
|
|
1140
1159
|
const heroActive = isFocused && appState === "active";
|
|
@@ -1176,24 +1195,24 @@ function HomeMenu() {
|
|
|
1176
1195
|
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 });
|
|
1177
1196
|
const pressAway = /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_chrome5.PressAwayOverlay, { active: pickerHost.openId !== null, onPress: pickerHost.close, style: styles4.pressAway });
|
|
1178
1197
|
const RulesSheet = rulesGame?.Rules;
|
|
1179
|
-
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
1180
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1198
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native8.View, { style: [styles4.container, { backgroundColor: bg }], children: [
|
|
1199
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native8.View, { style: styles4.frame, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(RulesHost, { enabled: pack.games.some((game) => game.Rules), children: [
|
|
1181
1200
|
isWide ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
|
|
1182
1201
|
pressAway,
|
|
1183
1202
|
/* @__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: [
|
|
1184
|
-
tabBar && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1185
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1203
|
+
tabBar && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native8.View, { style: [styles4.wideTabs, { width: layout.rightPaneWidth }], children: tabBar }),
|
|
1204
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native8.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)) })
|
|
1186
1205
|
] }),
|
|
1187
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
1206
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native8.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: [
|
|
1188
1207
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(pack.HeroTitle, { words: pack.wordmark, color: fg, p1Color, p2Color, active: heroActive, fit: layout.heroFit }),
|
|
1189
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1208
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native8.View, { style: styles4.widePicker, children: picker })
|
|
1190
1209
|
] })
|
|
1191
1210
|
] }) : /* @__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: [
|
|
1192
1211
|
pressAway,
|
|
1193
1212
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(pack.HeroTitle, { words: pack.wordmark, color: fg, p1Color, p2Color, active: heroActive }),
|
|
1194
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1195
|
-
tabBar && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1196
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1213
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native8.View, { style: [styles4.picker, pickerHost.openId !== null && styles4.pickerOpen], children: picker }),
|
|
1214
|
+
tabBar && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native8.View, { style: styles4.listWidth, children: tabBar }),
|
|
1215
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native8.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)) })
|
|
1197
1216
|
] }),
|
|
1198
1217
|
/* @__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" }),
|
|
1199
1218
|
/* @__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" }),
|
|
@@ -1244,10 +1263,10 @@ function GameRow({ game, hidden, dark, p1Color, p2Color, previewRevealed, onPres
|
|
|
1244
1263
|
return (
|
|
1245
1264
|
// The rules button sits beside the row's own button, laid over its end, not inside it: a button
|
|
1246
1265
|
// inside a button is invalid on the web.
|
|
1247
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
1266
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native8.View, { style: hidden ? styles4.hidden : void 0, children: [
|
|
1248
1267
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_feedback_press3.Pressable, { onPress, style: [styles4.row, { backgroundColor: well.bg }], accessibilityRole: "button", accessibilityLabel: game.title, children: [
|
|
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)(
|
|
1250
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
1268
|
+
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_native8.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 }) }),
|
|
1269
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native8.View, { style: styles4.rowText, children: [
|
|
1251
1270
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native_paper.Text, { variant: "titleLarge", style: [styles4.rowTitle, { color: well.fg }], numberOfLines: 1, children: game.title }),
|
|
1252
1271
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native_paper.Text, { variant: "bodyMedium", style: { color: well.fgMuted }, numberOfLines: 2, children: game.blurb })
|
|
1253
1272
|
] })
|
|
@@ -1258,7 +1277,7 @@ function GameRow({ game, hidden, dark, p1Color, p2Color, previewRevealed, onPres
|
|
|
1258
1277
|
}
|
|
1259
1278
|
function GameTile({ game, hidden, width, previewWidth, dark, p1Color, p2Color, previewRevealed, onPress, onRules }) {
|
|
1260
1279
|
const well = (0, import_chrome5.useWellColors)();
|
|
1261
|
-
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
1280
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react_native8.View, { style: [{ width }, hidden && styles4.hidden], children: [
|
|
1262
1281
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_feedback_press3.Pressable, { onPress, style: [styles4.tile, { backgroundColor: well.bg }], accessibilityRole: "button", accessibilityLabel: game.title, children: [
|
|
1263
1282
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(PreviewBox, { game, width: previewWidth, revealed: previewRevealed, dark, p1Color, p2Color }),
|
|
1264
1283
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native_paper.Text, { variant: "titleMedium", style: [styles4.rowTitle, { color: well.fg }], numberOfLines: 1, children: game.title }),
|
|
@@ -1271,13 +1290,13 @@ function PreviewBox({ game, width, revealed, dark, p1Color, p2Color }) {
|
|
|
1271
1290
|
const height = Math.round(width / PREVIEW_ASPECT);
|
|
1272
1291
|
const { Preview, icon: GameIcon } = game;
|
|
1273
1292
|
const iconSize = Math.min(height, ROW_ICON_SIZE);
|
|
1274
|
-
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1293
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_native8.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_native8.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 }) }) });
|
|
1275
1294
|
}
|
|
1276
1295
|
var ROW_ICON_SIZE = 56;
|
|
1277
1296
|
var ICON_LIGHT_BG = "#FAFAFA";
|
|
1278
1297
|
var ICON_DARK_BG = "#050505";
|
|
1279
1298
|
var RULES_BUTTON_SPACE = 44;
|
|
1280
|
-
var styles4 =
|
|
1299
|
+
var styles4 = import_react_native8.StyleSheet.create({
|
|
1281
1300
|
container: {
|
|
1282
1301
|
flex: 1
|
|
1283
1302
|
},
|
|
@@ -1433,7 +1452,7 @@ function useRosterAlign(open, contentWidth, contentHeight) {
|
|
|
1433
1452
|
function ProfilesRoute() {
|
|
1434
1453
|
const { profiles, createProfile, updateProfile, deleteProfile } = useProfiles();
|
|
1435
1454
|
const { Backdrop, foreground, newProfileColor, usePickerAlign } = usePack();
|
|
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:
|
|
1455
|
+
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_core8.safeBack, fg: foreground, bg: Backdrop ? "transparent" : void 0, useColorPickerAlign: usePickerAlign ? useRosterAlign : void 0 }) });
|
|
1437
1456
|
}
|
|
1438
1457
|
|
|
1439
1458
|
// src/screens/StatsScreen.tsx
|
|
@@ -1441,7 +1460,7 @@ var import_auto_paper7 = require("@rific/auto-paper");
|
|
|
1441
1460
|
var import_chrome7 = require("@tastic/hud/chrome");
|
|
1442
1461
|
var import_profile9 = require("@tastic/profile");
|
|
1443
1462
|
var import_react17 = require("react");
|
|
1444
|
-
var
|
|
1463
|
+
var import_react_native9 = require("react-native");
|
|
1445
1464
|
var import_react_native_paper2 = require("react-native-paper");
|
|
1446
1465
|
var import_react_native_safe_area_context4 = require("react-native-safe-area-context");
|
|
1447
1466
|
var import_react_redux10 = require("react-redux");
|
|
@@ -1464,7 +1483,7 @@ function StatsScreen() {
|
|
|
1464
1483
|
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 }) }) });
|
|
1465
1484
|
}
|
|
1466
1485
|
function StatsPressAway({ host, children }) {
|
|
1467
|
-
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
1486
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native9.View, { testID: "stats-press-away", style: styles5.screen, onStartShouldSetResponder: () => host.openId !== null, onResponderRelease: host.close, children });
|
|
1468
1487
|
}
|
|
1469
1488
|
var useNoPackReset = () => null;
|
|
1470
1489
|
var noPickerAlign2 = () => void 0;
|
|
@@ -1498,10 +1517,10 @@ function StatsContent({ pickerHost }) {
|
|
|
1498
1517
|
const surface = pack.Backdrop ? { backgroundColor: colors.surface } : void 0;
|
|
1499
1518
|
const triggerStyle = pack.Backdrop ? [styles5.pill, surface] : void 0;
|
|
1500
1519
|
const PackTabContent = packTab?.Content;
|
|
1501
|
-
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_chrome7.BaseStatsScreen, { title, onBack:
|
|
1520
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_chrome7.BaseStatsScreen, { title, onBack: import_core8.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: [
|
|
1502
1521
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_chrome7.PressAwayOverlay, { active: pickerHost.openId !== null, onPress: pickerHost.close, style: styles5.pressAway }),
|
|
1503
1522
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native_paper2.SegmentedButtons, { value: tab, onValueChange: setTab, buttons: tabButtons, style: [styles5.tabs, surface] }),
|
|
1504
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
1523
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native9.View, { style: [styles5.filters, pickerHost.openId !== null && styles5.filtersOpen], onStartShouldSetResponder: () => pickerHost.openId !== null, children: [
|
|
1505
1524
|
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 }),
|
|
1506
1525
|
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 })
|
|
1507
1526
|
] }),
|
|
@@ -1522,12 +1541,12 @@ function GameStats({ game, tab, profileId, showTitle, titleColor }) {
|
|
|
1522
1541
|
const { StatsSections, AchievementList } = game;
|
|
1523
1542
|
const Sections = tab === STATS ? StatsSections : AchievementList;
|
|
1524
1543
|
if (!Sections) return null;
|
|
1525
|
-
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
1544
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react_native9.View, { style: styles5.game, children: [
|
|
1526
1545
|
showTitle && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_native_paper2.Text, { variant: "titleLarge", style: [styles5.gameTitle, { color: titleColor }], children: game.title }),
|
|
1527
1546
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Sections, { profileId })
|
|
1528
1547
|
] });
|
|
1529
1548
|
}
|
|
1530
|
-
var styles5 =
|
|
1549
|
+
var styles5 = import_react_native9.StyleSheet.create({
|
|
1531
1550
|
filters: {
|
|
1532
1551
|
flexDirection: "row",
|
|
1533
1552
|
flexWrap: "wrap",
|
|
@@ -1561,11 +1580,11 @@ var styles5 = import_react_native8.StyleSheet.create({
|
|
|
1561
1580
|
});
|
|
1562
1581
|
|
|
1563
1582
|
// src/components/imageGameIcon.tsx
|
|
1564
|
-
var
|
|
1583
|
+
var import_react_native10 = require("react-native");
|
|
1565
1584
|
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1566
1585
|
function imageGameIcon(images) {
|
|
1567
1586
|
return function ImageGameIcon({ size, dark }) {
|
|
1568
|
-
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1587
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react_native10.Image, { source: dark ? images.dark : images.light, style: { height: size, width: size }, accessibilityIgnoresInvertColors: true });
|
|
1569
1588
|
};
|
|
1570
1589
|
}
|
|
1571
1590
|
|
|
@@ -1573,20 +1592,19 @@ function imageGameIcon(images) {
|
|
|
1573
1592
|
var import_auto_paper8 = require("@rific/auto-paper");
|
|
1574
1593
|
var import_feedback_press4 = require("@rific/feedback-press");
|
|
1575
1594
|
var import_react18 = require("react");
|
|
1576
|
-
var
|
|
1595
|
+
var import_react_native11 = require("react-native");
|
|
1577
1596
|
var import_react_native_reanimated3 = __toESM(require("react-native-reanimated"));
|
|
1578
1597
|
var import_react_native_safe_area_context5 = require("react-native-safe-area-context");
|
|
1579
1598
|
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1580
|
-
var MATCH_CHIPS_DESKTOP_MIN_WIDTH = 768;
|
|
1581
1599
|
var MATCH_CHIPS_FADE_MS = 150;
|
|
1582
1600
|
var CHIP_SIZE = 48;
|
|
1583
1601
|
var EDGE_PAD = 8;
|
|
1584
1602
|
function MatchChips({ playing, faceToFace, centerLineY, onBack, onSettings }) {
|
|
1585
|
-
const {
|
|
1603
|
+
const { height } = (0, import_react_native11.useWindowDimensions)();
|
|
1586
1604
|
const insets = (0, import_react_native_safe_area_context5.useSafeAreaInsets)();
|
|
1587
1605
|
const { dark } = (0, import_auto_paper8.useAutoPaperTheme)();
|
|
1588
|
-
const
|
|
1589
|
-
const visible =
|
|
1606
|
+
const atComputer = useAtComputer();
|
|
1607
|
+
const visible = atComputer || !playing;
|
|
1590
1608
|
const opacity = (0, import_react_native_reanimated3.useSharedValue)(visible ? 1 : 0);
|
|
1591
1609
|
(0, import_react18.useEffect)(() => {
|
|
1592
1610
|
opacity.value = (0, import_react_native_reanimated3.withTiming)(visible ? 1 : 0, { duration: MATCH_CHIPS_FADE_MS });
|
|
@@ -1594,7 +1612,7 @@ function MatchChips({ playing, faceToFace, centerLineY, onBack, onSettings }) {
|
|
|
1594
1612
|
const fadeStyle = (0, import_react_native_reanimated3.useAnimatedStyle)(() => ({ opacity: opacity.value }));
|
|
1595
1613
|
const iconColor = dark ? "#FFFFFF" : "#000000";
|
|
1596
1614
|
const containerColor = dark ? "rgba(0,0,0,0.55)" : "rgba(255,255,255,0.55)";
|
|
1597
|
-
const between = faceToFace && !
|
|
1615
|
+
const between = faceToFace && !atComputer;
|
|
1598
1616
|
const top = between ? (centerLineY ?? height / 2) - CHIP_SIZE / 2 : EDGE_PAD + insets.top;
|
|
1599
1617
|
const backSlot = { top, left: EDGE_PAD + insets.left };
|
|
1600
1618
|
const settingsSlot = { top, right: EDGE_PAD + insets.right };
|
|
@@ -1604,7 +1622,7 @@ function MatchChips({ playing, faceToFace, centerLineY, onBack, onSettings }) {
|
|
|
1604
1622
|
/* @__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
1623
|
] });
|
|
1606
1624
|
}
|
|
1607
|
-
var styles6 =
|
|
1625
|
+
var styles6 = import_react_native11.StyleSheet.create({
|
|
1608
1626
|
chip: { margin: 0 },
|
|
1609
1627
|
slot: { position: "absolute" }
|
|
1610
1628
|
});
|
|
@@ -1625,7 +1643,7 @@ var import_redux_persist = require("redux-persist");
|
|
|
1625
1643
|
|
|
1626
1644
|
// src/redux/shellState.ts
|
|
1627
1645
|
var import_auto_paper9 = require("@rific/auto-paper");
|
|
1628
|
-
var
|
|
1646
|
+
var import_core12 = require("@rific/core");
|
|
1629
1647
|
var import_feedback_press5 = require("@rific/feedback-press");
|
|
1630
1648
|
var import_profile10 = require("@tastic/profile");
|
|
1631
1649
|
var initialSoundSettings = { ...import_feedback_press5.defaultSoundSettings, enabled: !__DEV__ };
|
|
@@ -1646,7 +1664,7 @@ function createShellReducers({ seatColors, appearance = "system", seatTheme }) {
|
|
|
1646
1664
|
sound: appSoundReducer,
|
|
1647
1665
|
// @rific/core's Keep Awake setting (see Providers.tsx's KeepAwakeBridge), under the namespace its
|
|
1648
1666
|
// REHYDRATE handling expects.
|
|
1649
|
-
keepAwake:
|
|
1667
|
+
keepAwake: import_core12.keepAwakeReducer,
|
|
1650
1668
|
// The shared App Group roster (see @tastic/profile's resolveInitialProfiles/
|
|
1651
1669
|
// useSharedProfilesSync, wired in hooks/useProfiles.tsx) is layered on top of this as a separate
|
|
1652
1670
|
// sync target - this slice persisting normally via redux-persist is what gives it local-fallback
|
|
@@ -1865,7 +1883,6 @@ function createPlayerSettings({ id, defaults, distinctControls }) {
|
|
|
1865
1883
|
GUEST_PLAYER_ID,
|
|
1866
1884
|
HomeScreen,
|
|
1867
1885
|
LoadoutRoute,
|
|
1868
|
-
MATCH_CHIPS_DESKTOP_MIN_WIDTH,
|
|
1869
1886
|
MATCH_CHIPS_FADE_MS,
|
|
1870
1887
|
MatchChips,
|
|
1871
1888
|
PREVIEW_ASPECT,
|
|
@@ -1903,6 +1920,7 @@ function createPlayerSettings({ id, defaults, distinctControls }) {
|
|
|
1903
1920
|
seatTwoFor,
|
|
1904
1921
|
useActiveRound,
|
|
1905
1922
|
useAppSettings,
|
|
1923
|
+
useAtComputer,
|
|
1906
1924
|
useGameGuide,
|
|
1907
1925
|
useOpponent,
|
|
1908
1926
|
usePack,
|