@tiledev/sdk-apptile-live-selling 0.12.1 → 0.14.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 +116 -19
- package/dist/giveawayPrizeLines.d.ts +10 -0
- package/dist/giveawayPrizeLines.d.ts.map +1 -1
- package/dist/giveawayPrizeLines.js +11 -1
- package/dist/giveawayPrizeLines.js.map +1 -1
- package/dist/heldComments.d.ts +13 -2
- package/dist/heldComments.d.ts.map +1 -1
- package/dist/heldComments.js +16 -2
- package/dist/heldComments.js.map +1 -1
- package/dist/hiddenShows.d.ts +10 -0
- package/dist/hiddenShows.d.ts.map +1 -1
- package/dist/hiddenShows.js +11 -0
- package/dist/hiddenShows.js.map +1 -1
- package/dist/index.d.ts +9 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +35 -2
- package/dist/index.js.map +1 -1
- package/dist/livePages.d.ts +79 -0
- package/dist/livePages.d.ts.map +1 -0
- package/dist/livePages.js +90 -0
- package/dist/livePages.js.map +1 -0
- package/dist/liveRoom.d.ts +21 -0
- package/dist/liveRoom.d.ts.map +1 -0
- package/dist/liveRoom.js +28 -0
- package/dist/liveRoom.js.map +1 -0
- package/dist/pageOptions.d.ts +100 -0
- package/dist/pageOptions.d.ts.map +1 -0
- package/dist/pageOptions.js +82 -0
- package/dist/pageOptions.js.map +1 -0
- package/dist/pageTypes.d.ts +127 -0
- package/dist/pageTypes.d.ts.map +1 -0
- package/dist/pageTypes.js +3 -0
- package/dist/pageTypes.js.map +1 -0
- package/dist/react/LiveSellingProvider.d.ts +23 -1
- package/dist/react/LiveSellingProvider.d.ts.map +1 -1
- package/dist/react/LiveSellingProvider.js +26 -2
- package/dist/react/LiveSellingProvider.js.map +1 -1
- package/dist/react/index.d.ts +10 -0
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +29 -1
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.web.d.ts +11 -32
- package/dist/react/index.web.d.ts.map +1 -1
- package/dist/react/index.web.js +46 -139
- package/dist/react/index.web.js.map +1 -1
- package/dist/react/navigation.d.ts +13 -0
- package/dist/react/navigation.d.ts.map +1 -0
- package/dist/react/navigation.js +7 -0
- package/dist/react/navigation.js.map +1 -0
- package/dist/react/platformSession.d.ts +16 -0
- package/dist/react/platformSession.d.ts.map +1 -0
- package/dist/react/platformSession.js +28 -0
- package/dist/react/platformSession.js.map +1 -0
- package/dist/react/platformSession.web.d.ts +35 -0
- package/dist/react/platformSession.web.d.ts.map +1 -0
- package/dist/react/platformSession.web.js +148 -0
- package/dist/react/platformSession.web.js.map +1 -0
- package/dist/react/replayPlayer.d.ts +74 -0
- package/dist/react/replayPlayer.d.ts.map +1 -0
- package/dist/react/replayPlayer.js +279 -0
- package/dist/react/replayPlayer.js.map +1 -0
- package/dist/react/shopifyProviders.d.ts +68 -0
- package/dist/react/shopifyProviders.d.ts.map +1 -0
- package/dist/react/shopifyProviders.js +98 -0
- package/dist/react/shopifyProviders.js.map +1 -0
- package/dist/react/showPages.d.ts +5 -1
- package/dist/react/showPages.d.ts.map +1 -1
- package/dist/react/showPages.js +14 -5
- package/dist/react/showPages.js.map +1 -1
- package/dist/react/useKeepScreenAwake.d.ts +2 -0
- package/dist/react/useKeepScreenAwake.d.ts.map +1 -0
- package/dist/react/useKeepScreenAwake.js +34 -0
- package/dist/react/useKeepScreenAwake.js.map +1 -0
- package/dist/react/useLiveAuction.d.ts +104 -0
- package/dist/react/useLiveAuction.d.ts.map +1 -0
- package/dist/react/useLiveAuction.js +244 -0
- package/dist/react/useLiveAuction.js.map +1 -0
- package/dist/react/useLiveChat.d.ts +75 -0
- package/dist/react/useLiveChat.d.ts.map +1 -0
- package/dist/react/useLiveChat.js +131 -0
- package/dist/react/useLiveChat.js.map +1 -0
- package/dist/react/useLiveGiveawaysAndPolls.d.ts +84 -0
- package/dist/react/useLiveGiveawaysAndPolls.d.ts.map +1 -0
- package/dist/react/useLiveGiveawaysAndPolls.js +180 -0
- package/dist/react/useLiveGiveawaysAndPolls.js.map +1 -0
- package/dist/react/useLivePage.d.ts +113 -0
- package/dist/react/useLivePage.d.ts.map +1 -0
- package/dist/react/useLivePage.js +264 -0
- package/dist/react/useLivePage.js.map +1 -0
- package/dist/react/useLiveSession.d.ts +8 -0
- package/dist/react/useLiveSession.d.ts.map +1 -1
- package/dist/react/useLiveSession.js +43 -27
- package/dist/react/useLiveSession.js.map +1 -1
- package/dist/react/useLiveShop.d.ts +83 -0
- package/dist/react/useLiveShop.d.ts.map +1 -0
- package/dist/react/useLiveShop.js +165 -0
- package/dist/react/useLiveShop.js.map +1 -0
- package/dist/react/useReplayPage.d.ts +117 -0
- package/dist/react/useReplayPage.d.ts.map +1 -0
- package/dist/react/useReplayPage.js +504 -0
- package/dist/react/useReplayPage.js.map +1 -0
- package/dist/sessionTypes.d.ts +17 -9
- package/dist/sessionTypes.d.ts.map +1 -1
- package/dist/sessionTypes.js.map +1 -1
- package/dist/shopifyIdentity.d.ts +7 -4
- package/dist/shopifyIdentity.d.ts.map +1 -1
- package/dist/shopifyIdentity.js +11 -5
- package/dist/shopifyIdentity.js.map +1 -1
- package/dist/showCredit.d.ts +87 -0
- package/dist/showCredit.d.ts.map +1 -0
- package/dist/showCredit.js +120 -0
- package/dist/showCredit.js.map +1 -0
- package/dist/showNames.d.ts +24 -3
- package/dist/showNames.d.ts.map +1 -1
- package/dist/showNames.js +57 -10
- package/dist/showNames.js.map +1 -1
- package/dist/showPages.d.ts +12 -0
- package/dist/showPages.d.ts.map +1 -1
- package/dist/showPages.js +10 -0
- package/dist/showPages.js.map +1 -1
- package/dist/ui/BubbleFrame.d.ts +38 -0
- package/dist/ui/BubbleFrame.d.ts.map +1 -0
- package/dist/ui/BubbleFrame.js +181 -0
- package/dist/ui/BubbleFrame.js.map +1 -0
- package/dist/ui/LiveBubble.d.ts +37 -0
- package/dist/ui/LiveBubble.d.ts.map +1 -0
- package/dist/ui/LiveBubble.js +101 -0
- package/dist/ui/LiveBubble.js.map +1 -0
- package/dist/ui/ReplayBubble.d.ts +23 -0
- package/dist/ui/ReplayBubble.d.ts.map +1 -0
- package/dist/ui/ReplayBubble.js +65 -0
- package/dist/ui/ReplayBubble.js.map +1 -0
- package/dist/ui.d.ts +27 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +34 -0
- package/dist/ui.js.map +1 -0
- package/package.json +36 -5
- package/ui/package.json +6 -0
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useLivePage = useLivePage;
|
|
4
|
+
/**
|
|
5
|
+
* The Live screen's page model (0.14.0, moved from amore-v2's `src/core/hooks/useLivePage.ts`:
|
|
6
|
+
* Freckled Poppy's Live, phase 1, watching and the in-app bubble). The routes are the app's
|
|
7
|
+
* (`LiveSellingProvider`'s `routes`); the route's `streamId` param is read here.
|
|
8
|
+
*/
|
|
9
|
+
const sdk_analytics_core_1 = require("@tiledev/sdk-analytics-core");
|
|
10
|
+
const sdk_shopify_1 = require("@tiledev/sdk-shopify");
|
|
11
|
+
const react_1 = require("react");
|
|
12
|
+
const react_native_1 = require("react-native");
|
|
13
|
+
const client_1 = require("../client");
|
|
14
|
+
const hiddenShows_1 = require("../hiddenShows");
|
|
15
|
+
const liveSelling_1 = require("../liveSelling");
|
|
16
|
+
const livePages_1 = require("../livePages");
|
|
17
|
+
const pageOptions_1 = require("../pageOptions");
|
|
18
|
+
const sessionTypes_1 = require("../sessionTypes");
|
|
19
|
+
const LiveSellingProvider_1 = require("./LiveSellingProvider");
|
|
20
|
+
const platformSession_1 = require("./platformSession");
|
|
21
|
+
const replayPlayer_1 = require("./replayPlayer");
|
|
22
|
+
const useKeepScreenAwake_1 = require("./useKeepScreenAwake");
|
|
23
|
+
const useLiveChat_1 = require("./useLiveChat");
|
|
24
|
+
const useStreamInfo_1 = require("./useStreamInfo");
|
|
25
|
+
const navigation_1 = require("./navigation");
|
|
26
|
+
/**
|
|
27
|
+
* Shows already reported as joined (`liveJoin`) in this run of the app: once per show per run, so a
|
|
28
|
+
* trip through the bubble, the Cart or another screen and back isn't a second join (amore-v2's audit,
|
|
29
|
+
* L5: production reported on every viewer-count tick).
|
|
30
|
+
*/
|
|
31
|
+
const joinedThisRun = new Set();
|
|
32
|
+
/**
|
|
33
|
+
* Everything the Live screen wires, so the screen stays plain tiles. Call it from the Live screen and
|
|
34
|
+
* from each of its tiles' wiring: every call reads the same session.
|
|
35
|
+
*
|
|
36
|
+
* - **The session is the app's** (`ShopifyLiveSessionProvider`), joined above the navigator; this
|
|
37
|
+
* screen binds to its picture (the player tile's `LiveVideoTarget`) and never owns the room.
|
|
38
|
+
* - **Pinned to the route's show** while watching (`holdStream(streamId)`, at every arrival), so a host
|
|
39
|
+
* restarting the broadcast can't swap the room underneath; released when the shopper closes the show
|
|
40
|
+
* (back on a show that has ended or is still joining, ✕ on the bubble, or leaving any other way
|
|
41
|
+
* without the bubble), and kept when the bubble takes the show.
|
|
42
|
+
* - **Which show** (`useLiveShow`): the session's record once it is this show's (just after the pin it
|
|
43
|
+
* can still hold the last show's), where it stands, and whether it is on air.
|
|
44
|
+
* - **Where the link lands** (`streams.destinationFor`, one read of the show's record on arrival): a
|
|
45
|
+
* show on air stays; an ended show with a recording is replaced by its Replay
|
|
46
|
+
* (`routes.replaceWithReplay`); anything else (a rehearsal this shopper can't see included) by the
|
|
47
|
+
* Live tab (`routes.backToLiveTab`). Not on the web, where nothing can play: the Tile preview stays on
|
|
48
|
+
* this page to show its tiles, with the record's poster and the ended words.
|
|
49
|
+
* - **Every arrival** reads the record again (`refreshStreamRecords`, which restarts the session's
|
|
50
|
+
* off-air wait, so a push tapped in the foreground can't be declared over on a stale record) and ends
|
|
51
|
+
* the bubble: this screen shows the picture again.
|
|
52
|
+
* - **Back, every kind** (the header's arrow, the iOS swipe, Android's back; decided 2026-10-05,
|
|
53
|
+
* amore-v2's Head of Engineering) shrinks a show that is playing or waiting for its host into the
|
|
54
|
+
* bubble as the screen leaves, and closes one that has ended. One path: the screen's `beforeRemove`,
|
|
55
|
+
* for the navigation's back actions (`BACK_ACTIONS`). Picture-in-picture is a back that always
|
|
56
|
+
* shrinks; the cart shrinks the show and opens the Cart over this screen (Items You Won on an auction
|
|
57
|
+
* show: `routes.openCart`). Android's back with nothing behind this screen (a link on a cold start)
|
|
58
|
+
* does what the arrow does: back to the Live tab.
|
|
59
|
+
* - **One shrunk show at a time:** arriving here stops a replay's bubble (and the Replay screen stops
|
|
60
|
+
* this show's bubble).
|
|
61
|
+
* - **The screen stays on** while it shows the show playing or waiting for its host.
|
|
62
|
+
* - **Under a sheet** (`routes.sheets`: the variant page, opened from the shop; the Sign In page) the
|
|
63
|
+
* show plays on here, with the screen on and the light status bar, as Replay's does.
|
|
64
|
+
* - **Put away** while the show plays here (a sheet over it included), it goes on in the phone's own
|
|
65
|
+
* floating window (`systemWindowWhenAway`); coming back finds it here again.
|
|
66
|
+
* - **`liveJoin`** (`track`) once per show per app run; never for a rehearsal, a show the config's
|
|
67
|
+
* `hiddenShows` names, whoever watches it.
|
|
68
|
+
* - **Hidden shows** (`hiddenShows`): for a shopper who isn't on the team the session never holds one,
|
|
69
|
+
* so it is never on air here (the link goes to the Live tab).
|
|
70
|
+
* - **Chat and reactions** are `useLiveChat`'s, shown only while the show is on air.
|
|
71
|
+
*/
|
|
72
|
+
function useLivePage() {
|
|
73
|
+
var _a, _b, _c, _d;
|
|
74
|
+
const nav = (0, navigation_1.useNavigation)();
|
|
75
|
+
const route = (0, navigation_1.useRoute)();
|
|
76
|
+
const streamId = (_b = (_a = route.params) === null || _a === void 0 ? void 0 : _a.streamId) !== null && _b !== void 0 ? _b : '';
|
|
77
|
+
const isFocused = (0, navigation_1.useIsFocused)();
|
|
78
|
+
const { routes, track } = (0, LiveSellingProvider_1.useLivePageOptions)();
|
|
79
|
+
// The session changes only on the room's events, never on a clock: the header and the auction tiles keep their own.
|
|
80
|
+
const session = (0, platformSession_1.useLiveSession)();
|
|
81
|
+
const { holdStream, releaseStream, enterPip, exitPip, setMuted } = session.actions;
|
|
82
|
+
const { viewerEmail: email } = (0, LiveSellingProvider_1.useLiveSelling)();
|
|
83
|
+
const { show: sessionShow, status, onAir } = (0, platformSession_1.useLiveShow)(streamId);
|
|
84
|
+
const { itemCount } = (0, sdk_shopify_1.useCart)();
|
|
85
|
+
const { bubbleShown: replayInBubble, stop: stopReplay } = (0, replayPlayer_1.useReplayPlayer)();
|
|
86
|
+
// ─── Which show ────────────────────────────────────────────────────────────────────────────────
|
|
87
|
+
// `sessionShow` (above) is the session's record once it is this show's. The record the link's answer
|
|
88
|
+
// was read from stands in for its poster until then, and on the web.
|
|
89
|
+
const [linkedShow, setLinkedShow] = (0, react_1.useState)(null);
|
|
90
|
+
const show = sessionShow !== null && sessionShow !== void 0 ? sessionShow : (linkedShow && linkedShow.streamingId === streamId ? linkedShow : null);
|
|
91
|
+
/** The screen is leaving for good (closed, or sent on by the link's answer): going doesn't shrink the show. */
|
|
92
|
+
const leavingForGood = (0, react_1.useRef)(false);
|
|
93
|
+
// ─── Where the link lands ──────────────────────────────────────────────────────────────────────
|
|
94
|
+
(0, react_1.useEffect)(() => {
|
|
95
|
+
if (!streamId)
|
|
96
|
+
return;
|
|
97
|
+
let stillHere = true;
|
|
98
|
+
void liveSelling_1.liveSelling.streams.destinationFor(streamId, { viewerEmail: email }).then(({ destination, show: record, readError }) => {
|
|
99
|
+
if (readError)
|
|
100
|
+
(0, pageOptions_1.reportLiveWarning)(readError, { at: 'live.destinationFor', streamId });
|
|
101
|
+
if (!stillHere)
|
|
102
|
+
return;
|
|
103
|
+
setLinkedShow(record);
|
|
104
|
+
if (react_native_1.Platform.OS === 'web' || destination.to === 'livePlayer')
|
|
105
|
+
return;
|
|
106
|
+
leavingForGood.current = true;
|
|
107
|
+
if (destination.to === 'replay')
|
|
108
|
+
routes.replaceWithReplay(destination.feedId, nav);
|
|
109
|
+
// Back to the tabs already in the stack, or in this screen's place when it opened alone (a link on a cold start).
|
|
110
|
+
else
|
|
111
|
+
routes.backToLiveTab(nav);
|
|
112
|
+
});
|
|
113
|
+
return () => {
|
|
114
|
+
stillHere = false;
|
|
115
|
+
};
|
|
116
|
+
}, [streamId, email, nav, routes]);
|
|
117
|
+
// ─── Arriving ──────────────────────────────────────────────────────────────────────────────────
|
|
118
|
+
(0, navigation_1.useFocusEffect)((0, react_1.useCallback)(() => {
|
|
119
|
+
holdStream(streamId || undefined);
|
|
120
|
+
(0, useStreamInfo_1.refreshStreamRecords)();
|
|
121
|
+
exitPip();
|
|
122
|
+
}, [streamId, holdStream, exitPip]));
|
|
123
|
+
(0, react_1.useEffect)(() => {
|
|
124
|
+
if (isFocused && replayInBubble)
|
|
125
|
+
stopReplay();
|
|
126
|
+
}, [isFocused, replayInBubble, stopReplay]);
|
|
127
|
+
// ─── Leaving ───────────────────────────────────────────────────────────────────────────────────
|
|
128
|
+
/** The show went into the bubble on the way out: leaving keeps it playing there, pinned. */
|
|
129
|
+
const shrunk = (0, react_1.useRef)(false);
|
|
130
|
+
(0, react_1.useEffect)(() => {
|
|
131
|
+
if (!isFocused)
|
|
132
|
+
return;
|
|
133
|
+
shrunk.current = false;
|
|
134
|
+
leavingForGood.current = false;
|
|
135
|
+
}, [isFocused]);
|
|
136
|
+
const pipModeNow = (0, react_1.useRef)(session.pipMode);
|
|
137
|
+
pipModeNow.current = session.pipMode;
|
|
138
|
+
// Gone without the bubble (back on an ended show, replaced by the Replay or the Live tab): the show
|
|
139
|
+
// stops and the pin goes. Not when the bubble took it.
|
|
140
|
+
(0, react_1.useEffect)(() => () => {
|
|
141
|
+
if (shrunk.current || pipModeNow.current !== 'none')
|
|
142
|
+
return;
|
|
143
|
+
exitPip({ stopVideo: true });
|
|
144
|
+
releaseStream();
|
|
145
|
+
}, [exitPip, releaseStream]);
|
|
146
|
+
// ─── Where the show stands ─────────────────────────────────────────────────────────────────────
|
|
147
|
+
// `status` and `onAir` are `useLiveShow`'s: joining until the session holds this show's record. The
|
|
148
|
+
// controls follow the link's record until then (an auction's cart is Items You Won from the start).
|
|
149
|
+
const capabilities = (0, sessionTypes_1.capabilitiesFor)(show);
|
|
150
|
+
const canShrink = capabilities.canPip && onAir;
|
|
151
|
+
// On show, or covered only by a page drawn as a sheet (the variant page, from the shop): the picture
|
|
152
|
+
// stays here, playing behind it, and the screen stays on.
|
|
153
|
+
const coveredOnlyBySheet = (0, navigation_1.useNavigationState)((state) => (0, livePages_1.isCoveredOnlyBySheet)(state, route.key, routes.sheets));
|
|
154
|
+
const onScreen = isFocused || coveredOnlyBySheet;
|
|
155
|
+
const showing = onScreen && session.pipMode === 'none';
|
|
156
|
+
// Chat and reactions: only while this show is on air. Its own hook (`useLiveChat`).
|
|
157
|
+
const chat = (0, useLiveChat_1.useLiveChat)({ onAir, canComment: capabilities.canComment, canReact: capabilities.canReact });
|
|
158
|
+
// Every back press (`BACK_ACTIONS`) passes here as the screen goes: a show on air enters the bubble,
|
|
159
|
+
// then the screen is let go. Nothing is prevented.
|
|
160
|
+
const canShrinkNow = (0, react_1.useRef)(canShrink);
|
|
161
|
+
canShrinkNow.current = canShrink;
|
|
162
|
+
(0, react_1.useEffect)(() => nav.addListener('beforeRemove', (event) => {
|
|
163
|
+
if (!livePages_1.BACK_ACTIONS.has(event.data.action.type))
|
|
164
|
+
return;
|
|
165
|
+
if (leavingForGood.current || !canShrinkNow.current || pipModeNow.current !== 'none')
|
|
166
|
+
return;
|
|
167
|
+
shrunk.current = true;
|
|
168
|
+
enterPip();
|
|
169
|
+
}), [nav, enterPip]);
|
|
170
|
+
(0, useKeepScreenAwake_1.useKeepScreenAwake)(showing && onAir, 'live');
|
|
171
|
+
// ─── liveJoin, once per show per app run ───────────────────────────────────────────────────────
|
|
172
|
+
const viewerCount = session.viewerCount;
|
|
173
|
+
(0, react_1.useEffect)(() => {
|
|
174
|
+
if (!isFocused || !sessionShow || sessionShow.status !== 'live' || (0, hiddenShows_1.isHiddenShow)(sessionShow, (0, client_1.hiddenShowsRule)()))
|
|
175
|
+
return;
|
|
176
|
+
if (joinedThisRun.has(sessionShow.streamingId))
|
|
177
|
+
return;
|
|
178
|
+
joinedThisRun.add(sessionShow.streamingId);
|
|
179
|
+
track(sdk_analytics_core_1.DefaultEvents.LIVE_JOIN, (0, sdk_analytics_core_1.liveJoinParams)(sessionShow.streamingId, viewerCount));
|
|
180
|
+
}, [isFocused, sessionShow, viewerCount, track]);
|
|
181
|
+
// ─── The header's buttons ──────────────────────────────────────────────────────────────────────
|
|
182
|
+
/** Back: to the screen behind, or to the Live tab when this one opened alone. A show on air shrinks on the way (above). */
|
|
183
|
+
const goBack = (0, react_1.useCallback)(() => {
|
|
184
|
+
if (nav.canGoBack())
|
|
185
|
+
nav.goBack();
|
|
186
|
+
else
|
|
187
|
+
routes.backToLiveTab(nav);
|
|
188
|
+
}, [nav, routes]);
|
|
189
|
+
const close = (0, react_1.useCallback)(() => {
|
|
190
|
+
leavingForGood.current = true;
|
|
191
|
+
// Stopped outright: without `stopVideo` the room plays on with no surface.
|
|
192
|
+
exitPip({ stopVideo: true });
|
|
193
|
+
releaseStream();
|
|
194
|
+
goBack();
|
|
195
|
+
}, [exitPip, releaseStream, goBack]);
|
|
196
|
+
const back = canShrink ? goBack : close;
|
|
197
|
+
// Android's back with nothing behind this screen (a link on a cold start) would close the app: it does
|
|
198
|
+
// what the arrow does instead. With a screen behind, the navigator goes back, through `beforeRemove`.
|
|
199
|
+
const backNow = (0, react_1.useRef)(back);
|
|
200
|
+
backNow.current = back;
|
|
201
|
+
(0, navigation_1.useFocusEffect)((0, react_1.useCallback)(() => {
|
|
202
|
+
const subscription = react_native_1.BackHandler.addEventListener('hardwareBackPress', () => {
|
|
203
|
+
if (nav.canGoBack())
|
|
204
|
+
return false;
|
|
205
|
+
backNow.current();
|
|
206
|
+
return true;
|
|
207
|
+
});
|
|
208
|
+
return () => subscription.remove();
|
|
209
|
+
}, [nav]));
|
|
210
|
+
const isAuction = capabilities.canBid;
|
|
211
|
+
const openCart = (0, react_1.useCallback)(() => {
|
|
212
|
+
if (canShrink) {
|
|
213
|
+
shrunk.current = true;
|
|
214
|
+
enterPip();
|
|
215
|
+
}
|
|
216
|
+
// A bidder's cart is what they've won: their bids never land in the shopping cart (Freckled Poppy's).
|
|
217
|
+
routes.openCart({ itemsYouWon: isAuction }, nav);
|
|
218
|
+
}, [canShrink, enterPip, isAuction, nav, routes]);
|
|
219
|
+
// One surface at a time: not while the bubble or the phone's own window has it, or another screen is over this one.
|
|
220
|
+
const videoActive = showing && !!sessionShow;
|
|
221
|
+
return {
|
|
222
|
+
/**
|
|
223
|
+
* Android's own picture-in-picture window is up. It shrinks the whole app, and every sheet on the
|
|
224
|
+
* Live screen (poll, giveaway, shop, custom bid, name, reactions) is a window of its own above the
|
|
225
|
+
* app, so it rode the shrink and covered the video (fixed 2026-10-08; Freckled Poppy hides its
|
|
226
|
+
* sheets the same way). The screen then draws only the player; the sheets' open state is the
|
|
227
|
+
* hooks', so they come back. iOS's window shows the video alone.
|
|
228
|
+
*/
|
|
229
|
+
inSystemWindow: react_native_1.Platform.OS === 'android' && session.pipMode === 'system',
|
|
230
|
+
/** The screen is on show (or under a sheet), over the dark video: light status bar text. */
|
|
231
|
+
lightStatusBar: onScreen,
|
|
232
|
+
player: {
|
|
233
|
+
status,
|
|
234
|
+
posterUrl: (_c = show === null || show === void 0 ? void 0 : show.thumbnailUrl) !== null && _c !== void 0 ? _c : null,
|
|
235
|
+
isAuction: !!(show === null || show === void 0 ? void 0 : show.isAuction),
|
|
236
|
+
videoActive,
|
|
237
|
+
// Put away while the show plays here, it goes on in the phone's own floating window. Not while
|
|
238
|
+
// joining, waiting for the host or ended: there is no picture.
|
|
239
|
+
systemWindowWhenAway: videoActive && status === 'playing' && capabilities.canPip,
|
|
240
|
+
},
|
|
241
|
+
header: {
|
|
242
|
+
ended: status === 'ended',
|
|
243
|
+
// An auction show: the header's own LIVE words for one (sparkl-v2's and k-marie-v2's LiveHeader01 `auctionLiveLabel`).
|
|
244
|
+
isAuction: !!(show === null || show === void 0 ? void 0 : show.isAuction),
|
|
245
|
+
// The header counts its clock up from it on its own (`useShowClock`), so the screen isn't drawn each second.
|
|
246
|
+
startedAt: (_d = sessionShow === null || sessionShow === void 0 ? void 0 : sessionShow.startedAtMs) !== null && _d !== void 0 ? _d : null,
|
|
247
|
+
// Known once the room has said: 0 means it hasn't yet.
|
|
248
|
+
viewerCount: onAir && capabilities.showViewerCount && viewerCount > 0 ? viewerCount : null,
|
|
249
|
+
muted: session.muted,
|
|
250
|
+
canMute: status !== 'ended' && status !== 'error',
|
|
251
|
+
canPip: canShrink,
|
|
252
|
+
backShrinks: canShrink,
|
|
253
|
+
cartCount: itemCount,
|
|
254
|
+
onBack: back,
|
|
255
|
+
onToggleMute: () => setMuted(!session.muted),
|
|
256
|
+
// Shown only while the show can shrink: a back press, which shrinks it on the way.
|
|
257
|
+
onPip: goBack,
|
|
258
|
+
onCart: openCart,
|
|
259
|
+
},
|
|
260
|
+
/** The chat, the comment box, reactions and the pinned comment: one set of props per tile (`useLiveChat`). */
|
|
261
|
+
chat,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=useLivePage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useLivePage.js","sourceRoot":"","sources":["../../src/react/useLivePage.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,6 +16,14 @@ export interface LiveSessionProviderProps {
|
|
|
16
16
|
streamingId?: string;
|
|
17
17
|
/** Shown next to this viewer's own comments and sent with them. Overrides the identity adapter. */
|
|
18
18
|
viewerName?: string | null;
|
|
19
|
+
/**
|
|
20
|
+
* Names this viewer may never be shown under, as the show's team uses them (0.13.0): compared whole,
|
|
21
|
+
* with capitals, accents, spaces and punctuation left out (`isBlockedViewerName`). A blocked name,
|
|
22
|
+
* whether the account's, the identity's or one typed on this phone, counts as no name
|
|
23
|
+
* (`viewerName` null, so the app asks), and `chooseViewerName` refuses one. Defaults to
|
|
24
|
+
* `DEFAULT_BLOCKED_VIEWER_NAMES` (Host, Moderator); an empty list blocks none.
|
|
25
|
+
*/
|
|
26
|
+
blockedNames?: readonly string[];
|
|
19
27
|
/**
|
|
20
28
|
* Called when the system PIP window gives the picture back to a full-screen player: the user expanded
|
|
21
29
|
* a window that the player opened (or, on iOS, came back to the app with it still up). Navigate to
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLiveSession.d.ts","sourceRoot":"","sources":["../../src/react/useLiveSession.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AA6CvC,OAAO,KAAK,EASV,WAAW,EAEZ,MAAM,iBAAiB,CAAC;AAwCzB;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,GAAG,OAAO,KAAK,WAAW,CAAC,IAAI,CAAC,CAIlE;AAED,MAAM,WAAW,wBAAwB;IACvC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mGAAmG;IACnG,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IACzD,QAAQ,EAAE,SAAS,CAAC;CACrB;
|
|
1
|
+
{"version":3,"file":"useLiveSession.d.ts","sourceRoot":"","sources":["../../src/react/useLiveSession.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AA6CvC,OAAO,KAAK,EASV,WAAW,EAEZ,MAAM,iBAAiB,CAAC;AAwCzB;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,GAAG,OAAO,KAAK,WAAW,CAAC,IAAI,CAAC,CAIlE;AAED,MAAM,WAAW,wBAAwB;IACvC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mGAAmG;IACnG,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IACzD,QAAQ,EAAE,SAAS,CAAC;CACrB;AAshDD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,wBAAwB,+FA0CnF"}
|
|
@@ -89,8 +89,16 @@ function useLiveSession() {
|
|
|
89
89
|
/* Everything but the stream hold, which belongs to the provider component: it owns which stream this
|
|
90
90
|
hook is watching, so it is the only thing that can pin it. */
|
|
91
91
|
function useSessionValue(props) {
|
|
92
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y;
|
|
92
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z;
|
|
93
93
|
const { streamingId, viewerName: viewerNameInput, onPipRestore } = props;
|
|
94
|
+
const blockedNames = (_a = props.blockedNames) !== null && _a !== void 0 ? _a : showNames_1.DEFAULT_BLOCKED_VIEWER_NAMES;
|
|
95
|
+
const blockedNamesRef = (0, react_1.useRef)(blockedNames);
|
|
96
|
+
blockedNamesRef.current = blockedNames;
|
|
97
|
+
/** A name the room may show for this viewer: made safe (`publicName`) and not one of the team's. */
|
|
98
|
+
const allowedName = (name) => {
|
|
99
|
+
const shown = (0, showNames_1.publicName)(name);
|
|
100
|
+
return shown && !(0, showNames_1.isBlockedViewerName)(shown, blockedNames) ? shown : null;
|
|
101
|
+
};
|
|
94
102
|
const [state, dispatch] = (0, react_1.useReducer)(session_1.sessionReducer, session_1.initialSessionState);
|
|
95
103
|
const [joining, setJoining] = (0, react_1.useState)(false);
|
|
96
104
|
const [error, setError] = (0, react_1.useState)(null);
|
|
@@ -138,8 +146,9 @@ function useSessionValue(props) {
|
|
|
138
146
|
* name is consulted at all so a signed-in bidder is never asked to invent one.
|
|
139
147
|
*/
|
|
140
148
|
const [chosenName, setChosenName] = (0, react_1.useState)(() => liveSelling_1.liveSelling.viewer.cachedName());
|
|
141
|
-
// Every name here is published to the whole room, so none may be an email (`publicName`, 0.9.0)
|
|
142
|
-
|
|
149
|
+
// Every name here is published to the whole room, so none may be an email (`publicName`, 0.9.0), nor
|
|
150
|
+
// a name the show's team goes by (`blockedNames`, 0.13.0).
|
|
151
|
+
const accountName = allowedName(viewerNameInput);
|
|
143
152
|
(0, react_1.useEffect)(() => {
|
|
144
153
|
if (accountName || chosenName)
|
|
145
154
|
return;
|
|
@@ -152,22 +161,22 @@ function useSessionValue(props) {
|
|
|
152
161
|
alive = false;
|
|
153
162
|
};
|
|
154
163
|
}, [accountName, chosenName]);
|
|
155
|
-
const customerName = (
|
|
156
|
-
const namedBy = (
|
|
164
|
+
const customerName = allowedName((_b = identity === null || identity === void 0 ? void 0 : identity.customerName) === null || _b === void 0 ? void 0 : _b.call(identity));
|
|
165
|
+
const namedBy = (_c = accountName !== null && accountName !== void 0 ? accountName : allowedName(chosenName)) !== null && _c !== void 0 ? _c : customerName;
|
|
157
166
|
const viewerName = namedBy !== null && namedBy !== void 0 ? namedBy : 'Anonymous';
|
|
158
|
-
const bidderId = (
|
|
167
|
+
const bidderId = (_e = (_d = identity === null || identity === void 0 ? void 0 : identity.bidderId) === null || _d === void 0 ? void 0 : _d.call(identity)) !== null && _e !== void 0 ? _e : null;
|
|
159
168
|
/**
|
|
160
|
-
*
|
|
161
|
-
*
|
|
169
|
+
* The signed-in customer is still loading (app open, or just signed in), so their name isn't known
|
|
170
|
+
* yet. The room waits for it, up to `NAME_WAIT_MS`: it is entered once, and the name it is entered
|
|
171
|
+
* under is the one the host sees join. Before 0.9.2 an app opened during a show joined at once,
|
|
172
|
+
* before the sign-in was read, and every shopper joined as "Anonymous" (2026-10-08).
|
|
162
173
|
*/
|
|
163
|
-
const
|
|
174
|
+
const customerLoading = (_g = (_f = identity === null || identity === void 0 ? void 0 : identity.customerLoading) === null || _f === void 0 ? void 0 : _f.call(identity)) !== null && _g !== void 0 ? _g : false;
|
|
164
175
|
/**
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
* one the host sees join. Before 0.9.2 an app opened during a show joined at once, before the
|
|
168
|
-
* sign-in was read, and every shopper joined as "Anonymous" (2026-10-08).
|
|
176
|
+
* A comment sent now is held until the account has named the shopper (L6), and only while it loads:
|
|
177
|
+
* an account read with no name on it isn't waited for (`waitsForAccountName`, 0.13.0).
|
|
169
178
|
*/
|
|
170
|
-
const
|
|
179
|
+
const nameResolving = (0, heldComments_1.waitsForAccountName)(customerLoading, accountName !== null && accountName !== void 0 ? accountName : customerName);
|
|
171
180
|
const [nameWaitOver, setNameWaitOver] = (0, react_1.useState)(false);
|
|
172
181
|
(0, react_1.useEffect)(() => {
|
|
173
182
|
if (!customerLoading)
|
|
@@ -223,14 +232,18 @@ function useSessionValue(props) {
|
|
|
223
232
|
// A comment held for the last show's room must not be said in this one.
|
|
224
233
|
(_a = heldCommentsRef.current) === null || _a === void 0 ? void 0 : _a.drop();
|
|
225
234
|
}, [watching]);
|
|
226
|
-
/**
|
|
235
|
+
/**
|
|
236
|
+
* The account has loaded: say the name to the engine first, then send what was waiting for it, in
|
|
237
|
+
* order. Loaded with no name, they go under the session's name (one typed on this phone, or
|
|
238
|
+
* "Anonymous"), as they would after the longest wait: an app asks for a name before sending.
|
|
239
|
+
*/
|
|
227
240
|
(0, react_1.useEffect)(() => {
|
|
228
241
|
var _a;
|
|
229
|
-
if (
|
|
242
|
+
if (nameResolving || !((_a = heldCommentsRef.current) === null || _a === void 0 ? void 0 : _a.size))
|
|
230
243
|
return;
|
|
231
244
|
liveSelling_1.liveSelling.engine.setViewerName(namedBy);
|
|
232
245
|
void heldCommentsRef.current.release();
|
|
233
|
-
}, [namedBy]);
|
|
246
|
+
}, [namedBy, nameResolving]);
|
|
234
247
|
(0, react_1.useEffect)(() => liveSelling_1.liveSelling.engine.subscribe((event) => {
|
|
235
248
|
dispatch({ kind: 'event', event, at: Date.now() });
|
|
236
249
|
}), []);
|
|
@@ -305,7 +318,7 @@ function useSessionValue(props) {
|
|
|
305
318
|
* importantly an *unmute*, which is otherwise invisible until the app restarts. Keyed on the joined
|
|
306
319
|
* ids because the array is a fresh object on every poll.
|
|
307
320
|
*/
|
|
308
|
-
const mutedKey = ((
|
|
321
|
+
const mutedKey = ((_h = stream === null || stream === void 0 ? void 0 : stream.mutedDeviceIds) !== null && _h !== void 0 ? _h : []).join(',');
|
|
309
322
|
(0, react_1.useEffect)(() => {
|
|
310
323
|
if (!stream)
|
|
311
324
|
return;
|
|
@@ -328,7 +341,7 @@ function useSessionValue(props) {
|
|
|
328
341
|
*/
|
|
329
342
|
const nothingOnAir = (0, session_1.isNothingOnAir)({
|
|
330
343
|
hasRead,
|
|
331
|
-
streamStatus: (
|
|
344
|
+
streamStatus: (_j = stream === null || stream === void 0 ? void 0 : stream.status) !== null && _j !== void 0 ? _j : null,
|
|
332
345
|
status: derivedStatus,
|
|
333
346
|
});
|
|
334
347
|
const graceMs = (0, client_1.offAirGraceMs)();
|
|
@@ -602,7 +615,7 @@ function useSessionValue(props) {
|
|
|
602
615
|
* enter a giveaway they are already in.
|
|
603
616
|
*/
|
|
604
617
|
const activeGiveaway = (0, react_1.useMemo)(() => { var _a; return (_a = stream === null || stream === void 0 ? void 0 : stream.giveaways.find((giveaway) => giveaway.status === 'active')) !== null && _a !== void 0 ? _a : null; }, [stream]);
|
|
605
|
-
const customerRef = (
|
|
618
|
+
const customerRef = (_l = (_k = identity === null || identity === void 0 ? void 0 : identity.customerRef) === null || _k === void 0 ? void 0 : _k.call(identity)) !== null && _l !== void 0 ? _l : null;
|
|
606
619
|
/**
|
|
607
620
|
* Closes the gap between the realtime giveaway start and the polled record it depends on.
|
|
608
621
|
*
|
|
@@ -782,8 +795,8 @@ function useSessionValue(props) {
|
|
|
782
795
|
* the first record after it is taken whatever it says. Joining counts as a reconnect, so arriving
|
|
783
796
|
* costs one extra read.
|
|
784
797
|
*/
|
|
785
|
-
const recordPin = (
|
|
786
|
-
const recordPinKey = `${watching !== null && watching !== void 0 ? watching : ''}\u0000${(
|
|
798
|
+
const recordPin = (_m = stream === null || stream === void 0 ? void 0 : stream.pinnedComment) !== null && _m !== void 0 ? _m : null;
|
|
799
|
+
const recordPinKey = `${watching !== null && watching !== void 0 ? watching : ''}\u0000${(_o = recordPin === null || recordPin === void 0 ? void 0 : recordPin.id) !== null && _o !== void 0 ? _o : ''}\u0000${(_p = recordPin === null || recordPin === void 0 ? void 0 : recordPin.text) !== null && _p !== void 0 ? _p : ''}`;
|
|
787
800
|
const lastRecordPinKey = (0, react_1.useRef)(null);
|
|
788
801
|
const takeNextRecordPin = (0, react_1.useRef)(false);
|
|
789
802
|
(0, react_1.useEffect)(() => {
|
|
@@ -845,7 +858,7 @@ function useSessionValue(props) {
|
|
|
845
858
|
if (!activeRetryRef.current) {
|
|
846
859
|
activeRetryRef.current = new activeProductRetry_1.ActiveProductRetry(() => setCatalogueRetry((n) => n + 1));
|
|
847
860
|
}
|
|
848
|
-
const featuredId = (
|
|
861
|
+
const featuredId = (_s = (_q = state.activeStoreProductId) !== null && _q !== void 0 ? _q : (_r = stream === null || stream === void 0 ? void 0 : stream.products.find((product) => product.isCurrent)) === null || _r === void 0 ? void 0 : _r.storeProductId) !== null && _s !== void 0 ? _s : null;
|
|
849
862
|
const featuredCatalogueId = featuredId && productKey.split(',').includes(featuredId) ? featuredId : null;
|
|
850
863
|
const answerSeq = (catalogueAnswer === null || catalogueAnswer === void 0 ? void 0 : catalogueAnswer.key) === productKey ? catalogueAnswer.seq : null;
|
|
851
864
|
const hasFeatured = !!featuredCatalogueId &&
|
|
@@ -918,10 +931,10 @@ function useSessionValue(props) {
|
|
|
918
931
|
return null;
|
|
919
932
|
return (_f = products[0]) !== null && _f !== void 0 ? _f : null;
|
|
920
933
|
}, [products, state.activeStoreProductId, stream]);
|
|
921
|
-
const multiplier = (
|
|
934
|
+
const multiplier = (_u = (_t = state.multiplierOverride) !== null && _t !== void 0 ? _t : stream === null || stream === void 0 ? void 0 : stream.viewerMultiplier) !== null && _u !== void 0 ? _u : 1;
|
|
922
935
|
/* Same precedence as the multiplier: the host's live word wins, the record stands until they
|
|
923
936
|
give one. Both fall back rather than throw, so a stream row missing `meta` still renders. */
|
|
924
|
-
const reactionStyle = (
|
|
937
|
+
const reactionStyle = (_w = (_v = state.reactionModeOverride) !== null && _v !== void 0 ? _v : stream === null || stream === void 0 ? void 0 : stream.reactionStyle) !== null && _w !== void 0 ? _w : 'single';
|
|
925
938
|
/**
|
|
926
939
|
* Percentages come off the raw counts, so the multiplier cannot skew them — it inflates only the
|
|
927
940
|
* total on display, exactly as the host's own dashboard does.
|
|
@@ -999,7 +1012,7 @@ function useSessionValue(props) {
|
|
|
999
1012
|
alive = false;
|
|
1000
1013
|
};
|
|
1001
1014
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1002
|
-
}, [(
|
|
1015
|
+
}, [(_x = state.poll) === null || _x === void 0 ? void 0 : _x.pollUuid]);
|
|
1003
1016
|
const bindVideoView = (0, react_1.useCallback)((reactTag, force = false) => {
|
|
1004
1017
|
// Stopped because the app is away: a claim now would start it behind the app, with sound. The
|
|
1005
1018
|
// surface claims again once the app is back (`LiveVideoTarget`'s foreground re-claim).
|
|
@@ -1142,6 +1155,9 @@ function useSessionValue(props) {
|
|
|
1142
1155
|
*/
|
|
1143
1156
|
const chooseViewerName = (0, react_1.useCallback)(async (raw) => {
|
|
1144
1157
|
var _a;
|
|
1158
|
+
// A name the show's team goes by isn't saved (0.13.0): the app says why (`isBlockedViewerName`).
|
|
1159
|
+
if ((0, showNames_1.isBlockedViewerName)(raw, blockedNamesRef.current))
|
|
1160
|
+
return null;
|
|
1145
1161
|
const saved = await liveSelling_1.liveSelling.viewer.saveName(raw);
|
|
1146
1162
|
if (saved) {
|
|
1147
1163
|
liveSelling_1.liveSelling.engine.setViewerName((_a = accountNameRef.current) !== null && _a !== void 0 ? _a : saved);
|
|
@@ -1245,7 +1261,7 @@ function useSessionValue(props) {
|
|
|
1245
1261
|
* into a cart. It is also what comes back on the host's broadcast, so `isLeading` compares like
|
|
1246
1262
|
* with like. Null when signed out, which is exactly when bidding is not offered.
|
|
1247
1263
|
*/
|
|
1248
|
-
const bidderEmail = (
|
|
1264
|
+
const bidderEmail = (_z = (_y = identity === null || identity === void 0 ? void 0 : identity.customerEmail) === null || _y === void 0 ? void 0 : _y.call(identity)) !== null && _z !== void 0 ? _z : null;
|
|
1249
1265
|
const bidder = (0, react_1.useMemo)(() => (bidderId ? { userId: bidderId, userName: viewerName, email: bidderEmail } : null), [bidderId, viewerName, bidderEmail]);
|
|
1250
1266
|
/**
|
|
1251
1267
|
* The hammer, with whether it is this shopper's (0.9.0): they led the round as it closed and the
|