@moviie/player-expo 0.4.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/LICENSE +21 -0
- package/README.md +230 -0
- package/app.plugin.cjs +3 -0
- package/dist/cast.cjs +100 -0
- package/dist/cast.cjs.map +1 -0
- package/dist/cast.d.cts +15 -0
- package/dist/cast.d.ts +15 -0
- package/dist/cast.mjs +92 -0
- package/dist/cast.mjs.map +1 -0
- package/dist/chunk-67DJ7NOB.mjs +294 -0
- package/dist/chunk-67DJ7NOB.mjs.map +1 -0
- package/dist/chunk-7U2LKIGU.mjs +12 -0
- package/dist/chunk-7U2LKIGU.mjs.map +1 -0
- package/dist/chunk-BJTO5JO5.mjs +10 -0
- package/dist/chunk-BJTO5JO5.mjs.map +1 -0
- package/dist/index.cjs +3934 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +450 -0
- package/dist/index.d.ts +450 -0
- package/dist/index.mjs +3571 -0
- package/dist/index.mjs.map +1 -0
- package/dist/layout.cjs +217 -0
- package/dist/layout.cjs.map +1 -0
- package/dist/layout.d.cts +20 -0
- package/dist/layout.d.ts +20 -0
- package/dist/layout.mjs +4 -0
- package/dist/layout.mjs.map +1 -0
- package/dist/moviie-cast-adapter-DmSU2u3j.d.cts +53 -0
- package/dist/moviie-cast-adapter-DmSU2u3j.d.ts +53 -0
- package/dist/plugin/with-moviie.cjs +88 -0
- package/dist/plugin/with-moviie.cjs.map +1 -0
- package/dist/plugin/with-moviie.d.cts +52 -0
- package/dist/plugin/with-moviie.d.ts +52 -0
- package/dist/plugin/with-moviie.mjs +76 -0
- package/dist/plugin/with-moviie.mjs.map +1 -0
- package/package.json +134 -0
- package/plugin/validate-options.ts +31 -0
- package/plugin/with-moviie-types.ts +21 -0
- package/plugin/with-moviie.ts +84 -0
- package/src/apply-expo-moviie-endpoints.ts +47 -0
- package/src/cast/google-cast-adapter.ts +111 -0
- package/src/cast/index.ts +12 -0
- package/src/components/controls/moviie-bottom-timeline.tsx +477 -0
- package/src/components/controls/moviie-cast-buttons.tsx +96 -0
- package/src/components/controls/moviie-chrome-edge-gradients.tsx +162 -0
- package/src/components/controls/moviie-controls.tsx +585 -0
- package/src/components/controls/moviie-skin-chrome-context.tsx +374 -0
- package/src/components/controls/moviie-skin-smart-progress.tsx +157 -0
- package/src/components/icons/embed-media-icons.tsx +282 -0
- package/src/components/icons/moviie-embed-brand-mark.tsx +58 -0
- package/src/components/moviie-error-boundary.tsx +80 -0
- package/src/components/moviie-player-error-shell.tsx +143 -0
- package/src/components/moviie-player-loading-shell.tsx +59 -0
- package/src/components/moviie-skin-custom-fullscreen-modal.tsx +232 -0
- package/src/components/moviie-video-props.ts +134 -0
- package/src/components/moviie-video.tsx +568 -0
- package/src/components/moviie-video.web.tsx +167 -0
- package/src/components/overlays/moviie-watermark.tsx +53 -0
- package/src/constants.ts +374 -0
- package/src/hooks/use-moviie-event.ts +103 -0
- package/src/hooks/use-moviie-playback-ended.ts +14 -0
- package/src/hooks/use-moviie-playback-resume-persistence.ts +76 -0
- package/src/hooks/use-moviie-playback.ts +99 -0
- package/src/hooks/use-moviie-player-types.ts +55 -0
- package/src/hooks/use-moviie-player.ts +236 -0
- package/src/hooks/use-moviie-player.web.ts +57 -0
- package/src/hooks/use-moviie-telemetry.ts +133 -0
- package/src/index.ts +90 -0
- package/src/layout.ts +4 -0
- package/src/lib/add-moviie-playback-ended-listener.ts +16 -0
- package/src/lib/build-moviie-branding-marketing-url.ts +14 -0
- package/src/lib/build-moviie-embed-brand-home-url.ts +16 -0
- package/src/lib/build-moviie-skin-layout-metrics.ts +166 -0
- package/src/lib/build-moviie-video-presentation.ts +42 -0
- package/src/lib/build-moviie-watch-embed-url.ts +30 -0
- package/src/lib/cast-adapter-registry.ts +13 -0
- package/src/lib/clamp-unit-interval.ts +3 -0
- package/src/lib/compute-custom-fullscreen-stage-dimensions.ts +39 -0
- package/src/lib/compute-moviie-playback-ended.ts +31 -0
- package/src/lib/compute-playback-buffering.ts +41 -0
- package/src/lib/compute-playback-progress-ratio.ts +33 -0
- package/src/lib/compute-timeline-scrub-commit-time.ts +40 -0
- package/src/lib/custom-fullscreen-native-orientation.ts +88 -0
- package/src/lib/format-playback-clock.ts +27 -0
- package/src/lib/jsx-native-bridge.ts +45 -0
- package/src/lib/map-smart-progress-display-ratio.ts +43 -0
- package/src/lib/moviie-cast-adapter.ts +53 -0
- package/src/lib/moviie-error-display.ts +149 -0
- package/src/lib/moviie-shell-tokens.ts +27 -0
- package/src/lib/moviie-telemetry-callbacks.ts +76 -0
- package/src/lib/optional-status-bar.ts +48 -0
- package/src/lib/partition-moviie-video-host-style.ts +54 -0
- package/src/lib/remember-playback-position-storage.ts +98 -0
- package/src/lib/resolve-moviie-skin-layout-scale.ts +17 -0
- package/src/lib/resolve-orientation-lock-for-rotate-z-deg.ts +21 -0
- package/src/lib/resolve-skin-accent-color.ts +10 -0
- package/src/lib/resolve-web-embed-iframe-src.ts +17 -0
- package/src/lib/warn-once.ts +23 -0
- package/src/platform/native-application-id.ts +10 -0
- package/src/platform/platform-client-info.ts +31 -0
- package/src/playback/fetch-playback-fresh.ts +27 -0
- package/src/playback/playback-memory-cache.ts +52 -0
- package/src/provider/moviie-provider.tsx +99 -0
- package/src/secure-store-viewer-token-store.ts +80 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,3934 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var playerSdk = require('@moviie/player-sdk');
|
|
4
|
+
var React = require('react');
|
|
5
|
+
var reactNative = require('react-native');
|
|
6
|
+
var Application = require('expo-application');
|
|
7
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
8
|
+
var expoVideo = require('expo-video');
|
|
9
|
+
var playerTypes = require('@moviie/player-types');
|
|
10
|
+
var AnimatedReanimated = require('react-native-reanimated');
|
|
11
|
+
var RNSvg = require('react-native-svg');
|
|
12
|
+
var reactNativeSafeAreaContext = require('react-native-safe-area-context');
|
|
13
|
+
var reactNativeGestureHandler = require('react-native-gesture-handler');
|
|
14
|
+
var expoScreenOrientation = require('expo-screen-orientation');
|
|
15
|
+
|
|
16
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
17
|
+
|
|
18
|
+
function _interopNamespace(e) {
|
|
19
|
+
if (e && e.__esModule) return e;
|
|
20
|
+
var n = Object.create(null);
|
|
21
|
+
if (e) {
|
|
22
|
+
Object.keys(e).forEach(function (k) {
|
|
23
|
+
if (k !== 'default') {
|
|
24
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
25
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
26
|
+
enumerable: true,
|
|
27
|
+
get: function () { return e[k]; }
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
n.default = e;
|
|
33
|
+
return Object.freeze(n);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
37
|
+
var Application__namespace = /*#__PURE__*/_interopNamespace(Application);
|
|
38
|
+
var AnimatedReanimated__default = /*#__PURE__*/_interopDefault(AnimatedReanimated);
|
|
39
|
+
var RNSvg__default = /*#__PURE__*/_interopDefault(RNSvg);
|
|
40
|
+
|
|
41
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
42
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
43
|
+
}) : x)(function(x) {
|
|
44
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
45
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// src/constants.ts
|
|
49
|
+
var MOVIIE_PLAYER_EXPO_PKG_VERSION = "0.4.0";
|
|
50
|
+
var MOVIIE_PLAYBACK_MEMORY_CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
51
|
+
var MOVIIE_PLAYBACK_PROFILE = {
|
|
52
|
+
VSL: "vsl",
|
|
53
|
+
CUSTOM: "custom"
|
|
54
|
+
};
|
|
55
|
+
var MOVIIE_SMART_PROGRESS_CONFIG = {
|
|
56
|
+
R1: 0.18,
|
|
57
|
+
P1: 0.62,
|
|
58
|
+
R2: 0.8,
|
|
59
|
+
P2: 0.95,
|
|
60
|
+
P_MAX_BEFORE_END: 0.99
|
|
61
|
+
};
|
|
62
|
+
var MOVIIE_SMART_PROGRESS_FILL_TRANSITION_MS = 150;
|
|
63
|
+
var MOVIIE_SMART_PROGRESS_BAR_HEIGHT_DP = 12;
|
|
64
|
+
var MOVIIE_SMART_PROGRESS_Z_INDEX = 34;
|
|
65
|
+
var MOVIIE_REMEMBER_POSITION_STORAGE_PREFIX = "moviie.resume_position.";
|
|
66
|
+
var MOVIIE_REMEMBER_POSITION_DEBOUNCE_MS = 5e3;
|
|
67
|
+
var MOVIIE_VIDEO_DEFAULT_CONTENT_FIT = {
|
|
68
|
+
VERTICAL: "contain",
|
|
69
|
+
HORIZONTAL: "cover"
|
|
70
|
+
};
|
|
71
|
+
var MOVIIE_BRANDING_MARKETING_ORIGIN = "https://moviie.ai";
|
|
72
|
+
var MOVIIE_WATCH_ORIGIN_DEFAULT = "https://watch.moviie.ai";
|
|
73
|
+
var EXPO_PUBLIC_MOVIIE_WATCH_ORIGIN_ENV = "EXPO_PUBLIC_MOVIIE_WATCH_ORIGIN";
|
|
74
|
+
var MOVIIE_WATCH_EMBED_JS_PATH = "/embed.js";
|
|
75
|
+
var MOVIIE_PLAYER_EXPO_EMBED_JS_MARKER_ATTR = "data-moviie-player-expo-embed-js";
|
|
76
|
+
var EXPO_PUBLIC_MOVIIE_API_BASE_URL_ENV = "EXPO_PUBLIC_MOVIIE_API_BASE_URL";
|
|
77
|
+
var EXPO_PUBLIC_MOVIIE_EVENTS_BASE_URL_ENV = "EXPO_PUBLIC_MOVIIE_EVENTS_BASE_URL";
|
|
78
|
+
var MOVIIE_BRANDING_UTM_PARAM_SOURCE = "utm_source";
|
|
79
|
+
var MOVIIE_BRANDING_UTM_PARAM_MEDIUM = "utm_medium";
|
|
80
|
+
var MOVIIE_BRANDING_UTM_PARAM_CAMPAIGN = "utm_campaign";
|
|
81
|
+
var MOVIIE_EMBED_BRAND_UTM = {
|
|
82
|
+
SOURCE: "moviie_embed_player",
|
|
83
|
+
MEDIUM: "video_control_bar",
|
|
84
|
+
CAMPAIGN: "logo_click"
|
|
85
|
+
};
|
|
86
|
+
var MOVIIE_SKIN_DEFAULT_ACCENT_HEX = "#6366f1";
|
|
87
|
+
var MOVIIE_SKIN_CONTROLS_AUTO_HIDE_MS = 3e3;
|
|
88
|
+
var MOVIIE_SKIN_CONTROLS_FADE_MS = 240;
|
|
89
|
+
var MOVIIE_SKIN_CONTROL_ICON_PX = 22;
|
|
90
|
+
var MOVIIE_SKIN_LAYOUT_REFERENCE_WIDTH_PT = 390;
|
|
91
|
+
var MOVIIE_SKIN_LAYOUT_SCALE_MIN = 0.72;
|
|
92
|
+
var MOVIIE_SKIN_LAYOUT_SCALE_MAX = 1;
|
|
93
|
+
var MOVIIE_SKIN_FLOATING_HUD_EDGE_INSET_PX = 6;
|
|
94
|
+
var MOVIIE_SKIN_FLOATING_HUD_ABOVE_TIMELINE_GAP_AT_REFERENCE_PT = 0;
|
|
95
|
+
var MOVIIE_SKIN_FLOATING_HUD_TRAILING_HIT_SLOP_PX = 8;
|
|
96
|
+
var MOVIIE_SKIN_FLOATING_FULLSCREEN_SCRIM_DIAMETER_AT_REFERENCE_PT = 44;
|
|
97
|
+
var MOVIIE_SKIN_FLOATING_FULLSCREEN_ICON_AT_REFERENCE_PT = 26;
|
|
98
|
+
var MOVIIE_SKIN_FLOATING_FULLSCREEN_TOP_ICON_AT_REFERENCE_PT = 36;
|
|
99
|
+
var MOVIIE_SKIN_TOP_ICON_CAST_VISUAL_SCALE = 0.65;
|
|
100
|
+
var MOVIIE_SKIN_TOP_ICON_PIP_VISUAL_SCALE = 0.8;
|
|
101
|
+
var MOVIIE_SKIN_TOP_ICON_FULLSCREEN_VISUAL_SCALE = 0.8;
|
|
102
|
+
var MOVIIE_SKIN_FLOATING_HUD_BUTTON_GAP_AT_REFERENCE_PT = 10;
|
|
103
|
+
var MOVIIE_SKIN_FLOATING_HUD_CLOCK_CORNER_RADIUS_PX = 6;
|
|
104
|
+
var MOVIIE_SKIN_CHROME_SCRIM_BLACK_ALPHA = 0.5;
|
|
105
|
+
var MOVIIE_SKIN_CHROME_SCRIM_BLACK_RGBA = `rgba(0,0,0,${MOVIIE_SKIN_CHROME_SCRIM_BLACK_ALPHA})`;
|
|
106
|
+
var MOVIIE_SKIN_CHROME_CONTROL_REST_OPACITY = 1;
|
|
107
|
+
var MOVIIE_SKIN_CHROME_CONTROL_PRESSED_OPACITY = 0.72;
|
|
108
|
+
var MOVIIE_SKIN_CHROME_GRADIENT_BLACK_HEX = "#000000";
|
|
109
|
+
var MOVIIE_SKIN_CHROME_GRADIENT_EDGE_ALPHA = 0.62;
|
|
110
|
+
var MOVIIE_SKIN_CHROME_EDGE_GRADIENT_HEIGHT_AT_REFERENCE_PT = 104;
|
|
111
|
+
var MOVIIE_SKIN_CHROME_EDGE_GRADIENT_EDGE_SOLID_FADE_END_FRACTION = 0.48;
|
|
112
|
+
var MOVIIE_SKIN_CHROME_EDGE_GRADIENT_MIN_CLEAR_MIDDLE_PX = 56;
|
|
113
|
+
var MOVIIE_SKIN_CHROME_SVG_GRADIENT_BOTTOM_EDGE_ID = "moviie_skin_chrome_gradient_bottom_edge";
|
|
114
|
+
var MOVIIE_SKIN_CHROME_SVG_GRADIENT_TOP_EDGE_ID = "moviie_skin_chrome_gradient_top_edge";
|
|
115
|
+
var MOVIIE_SKIN_VOLUME_LOW_ICON_THRESHOLD = 0.45;
|
|
116
|
+
var MOVIIE_SKIN_CHROME_FOREGROUND_HEX = "#ffffff";
|
|
117
|
+
var MOVIIE_EXPO_SCREEN_ORIENTATION_LOCK_VALUE = {
|
|
118
|
+
LANDSCAPE_RIGHT: 7
|
|
119
|
+
};
|
|
120
|
+
var MOVIIE_SKIN_CUSTOM_FULLSCREEN_TRANSITION_MS = 420;
|
|
121
|
+
var MOVIIE_SKIN_CUSTOM_FULLSCREEN_ROTATE_Z_DEGREES = 90;
|
|
122
|
+
var MOVIIE_SKIN_CUSTOM_FULLSCREEN_ENTER_SCALE_START = 0.78;
|
|
123
|
+
var MOVIIE_SKIN_CUSTOM_FULLSCREEN_VIDEO_CONTENT_FIT = "contain";
|
|
124
|
+
var MOVIIE_SKIN_CUSTOM_FULLSCREEN_STAGE_BACKGROUND_HEX = "#000000";
|
|
125
|
+
var MOVIIE_SKIN_CUSTOM_FULLSCREEN_STAGE_OVERSCAN_PX = 12;
|
|
126
|
+
var MOVIIE_SKIN_CUSTOM_FULLSCREEN_HUD_EDGE_BOOST_REFERENCE_PT = 14;
|
|
127
|
+
var MOVIIE_SKIN_BUFFER_UNDERRUN_LEAD_SECONDS = 0.35;
|
|
128
|
+
var MOVIIE_SKIN_SEEK_JUMP_SECONDS = 10;
|
|
129
|
+
var MOVIIE_SKIN_CENTER_PLAY_ICON_PX = 40;
|
|
130
|
+
var MOVIIE_SKIN_CENTER_PLAY_SCRIM_DIAMETER_AT_REFERENCE_PT = 80;
|
|
131
|
+
var MOVIIE_SKIN_CENTER_SEEK_SCRIM_DIAMETER_AT_REFERENCE_PT = 46;
|
|
132
|
+
var MOVIIE_SKIN_SEEK_ICON_PX = 28;
|
|
133
|
+
var MOVIIE_SKIN_CENTER_CLUSTER_COLUMN_GAP_PX = 12;
|
|
134
|
+
var MOVIIE_SKIN_CLOCK_TEXT_FONT_SIZE_AT_REFERENCE_PT = 12;
|
|
135
|
+
var MOVIIE_SKIN_TIMELINE_BAR_HEIGHT_PX = 3;
|
|
136
|
+
var MOVIIE_SKIN_TIMELINE_THUMB_DIAMETER_PX = 14;
|
|
137
|
+
var MOVIIE_SKIN_TIMELINE_TOUCH_PADDING_VERTICAL_PX = 0;
|
|
138
|
+
var MOVIIE_SKIN_TIMELINE_TOUCH_EXPANSION_VERTICAL_DP = 2;
|
|
139
|
+
var MOVIIE_SKIN_TIMELINE_SCRUB_HIT_SLOP_HORIZONTAL_DP = 3;
|
|
140
|
+
var MOVIIE_SKIN_TIMELINE_SCRUB_HIT_SLOP_TOP_DP = 2;
|
|
141
|
+
var MOVIIE_SKIN_TIMELINE_SCRUB_HIT_SLOP_BOTTOM_DP = 14;
|
|
142
|
+
var MOVIIE_SKIN_TIMELINE_RAIL_BACKGROUND_RGBA = "rgba(255,255,255,0.3)";
|
|
143
|
+
var MOVIIE_SKIN_TIMELINE_BUFFER_LAYER_RGBA = MOVIIE_SKIN_TIMELINE_RAIL_BACKGROUND_RGBA;
|
|
144
|
+
var MOVIIE_SKIN_TIMELINE_THUMB_BORDER_RGBA = "rgba(0,0,0,0.35)";
|
|
145
|
+
var MOVIIE_SKIN_TIMELINE_THUMB_DRAG_DIAMETER_MULTIPLIER = 1.65;
|
|
146
|
+
var MOVIIE_SKIN_TIMELINE_END_SNAP_EPSILON_SECONDS = 0.15;
|
|
147
|
+
var MOVIIE_SKIN_TIMELINE_CHAPTER_SNAP_THRESHOLD_SECONDS = 2;
|
|
148
|
+
var MOVIIE_SKIN_BUFFERING_INDICATOR_SLOT_PX = 28;
|
|
149
|
+
var MOVIIE_SKIN_BRAND_MARK_ARTBOARD_WIDTH_PX = 173;
|
|
150
|
+
var MOVIIE_SKIN_BRAND_MARK_ARTBOARD_HEIGHT_PX = 46;
|
|
151
|
+
var MOVIIE_SKIN_BRAND_MARK_TARGET_WIDTH_AT_REFERENCE_PT = 68;
|
|
152
|
+
var MOVIIE_EMBED_BRAND_VIEW_BOX = "0 0 173 46";
|
|
153
|
+
var MOVIIE_EMBED_BRAND_LETTERMARK_STROKE_WIDTH = 3;
|
|
154
|
+
|
|
155
|
+
// src/apply-expo-moviie-endpoints.ts
|
|
156
|
+
function normalize(raw) {
|
|
157
|
+
if (typeof raw !== "string") return void 0;
|
|
158
|
+
const trimmed = raw.trim();
|
|
159
|
+
return trimmed.length > 0 ? trimmed.replace(/\/+$/, "") : void 0;
|
|
160
|
+
}
|
|
161
|
+
var devMode = typeof __DEV__ !== "undefined" ? __DEV__ : typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
|
|
162
|
+
if (devMode) {
|
|
163
|
+
const apiBaseUrl = normalize(process.env[EXPO_PUBLIC_MOVIIE_API_BASE_URL_ENV]);
|
|
164
|
+
const eventsBaseUrl = normalize(process.env[EXPO_PUBLIC_MOVIIE_EVENTS_BASE_URL_ENV]);
|
|
165
|
+
const opts = {};
|
|
166
|
+
if (apiBaseUrl != null) opts.apiBaseUrl = apiBaseUrl;
|
|
167
|
+
if (eventsBaseUrl != null) opts.eventsBaseUrl = eventsBaseUrl;
|
|
168
|
+
if (opts.apiBaseUrl != null || opts.eventsBaseUrl != null) {
|
|
169
|
+
playerSdk.configureMoviieEndpoints(opts);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// src/lib/warn-once.ts
|
|
174
|
+
var FIRED_KEYS = /* @__PURE__ */ new Set();
|
|
175
|
+
function warnOnce(key, message) {
|
|
176
|
+
if (FIRED_KEYS.has(key)) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
FIRED_KEYS.add(key);
|
|
180
|
+
console.warn(message);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// src/secure-store-viewer-token-store.ts
|
|
184
|
+
var MOVIIE_VIEWER_TOKEN_SECURE_STORE_KEY = "moviie_viewer_token_v1";
|
|
185
|
+
var SECURE_STORE_MISSING_WARNING = "[@moviie/player-expo] `expo-secure-store` n\xE3o est\xE1 instalado \u2014 viewer token ser\xE1 mantido apenas em mem\xF3ria (perde ao matar app). Instala com `pnpm add expo-secure-store` se quiseres persist\xEAncia entre sess\xF5es.";
|
|
186
|
+
function isStoredEnvelope(value) {
|
|
187
|
+
if (!value || typeof value !== "object") return false;
|
|
188
|
+
const v = value;
|
|
189
|
+
return typeof v.token === "string" && typeof v.expiresAt === "number";
|
|
190
|
+
}
|
|
191
|
+
var SecureStoreViewerTokenStore = class {
|
|
192
|
+
fallback;
|
|
193
|
+
storageKey;
|
|
194
|
+
constructor(options) {
|
|
195
|
+
this.fallback = options?.fallback ?? new playerSdk.MemoryViewerTokenStore();
|
|
196
|
+
this.storageKey = options?.storageKey ?? MOVIIE_VIEWER_TOKEN_SECURE_STORE_KEY;
|
|
197
|
+
}
|
|
198
|
+
async loadSecureStore() {
|
|
199
|
+
try {
|
|
200
|
+
return await import('expo-secure-store');
|
|
201
|
+
} catch {
|
|
202
|
+
warnOnce("moviie:expo-secure-store-missing", SECURE_STORE_MISSING_WARNING);
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
async get() {
|
|
207
|
+
const SecureStore = await this.loadSecureStore();
|
|
208
|
+
if (!SecureStore) {
|
|
209
|
+
return this.fallback.get();
|
|
210
|
+
}
|
|
211
|
+
try {
|
|
212
|
+
const raw = await SecureStore.getItemAsync(this.storageKey);
|
|
213
|
+
if (!raw) return null;
|
|
214
|
+
const parsed = JSON.parse(raw);
|
|
215
|
+
if (!isStoredEnvelope(parsed)) {
|
|
216
|
+
await SecureStore.deleteItemAsync(this.storageKey).catch(() => {
|
|
217
|
+
});
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
if (parsed.expiresAt <= Date.now()) {
|
|
221
|
+
await SecureStore.deleteItemAsync(this.storageKey).catch(() => {
|
|
222
|
+
});
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
return parsed.token;
|
|
226
|
+
} catch {
|
|
227
|
+
return this.fallback.get();
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
async set(token, ttlSec) {
|
|
231
|
+
const SecureStore = await this.loadSecureStore();
|
|
232
|
+
const envelope = {
|
|
233
|
+
token,
|
|
234
|
+
expiresAt: Date.now() + Math.max(0, ttlSec) * 1e3
|
|
235
|
+
};
|
|
236
|
+
if (!SecureStore) {
|
|
237
|
+
await this.fallback.set(token, ttlSec);
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
try {
|
|
241
|
+
await SecureStore.setItemAsync(this.storageKey, JSON.stringify(envelope));
|
|
242
|
+
} catch {
|
|
243
|
+
await this.fallback.set(token, ttlSec);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
function readNativeApplicationId() {
|
|
248
|
+
try {
|
|
249
|
+
const id = Application__namespace.applicationId;
|
|
250
|
+
return id ?? void 0;
|
|
251
|
+
} catch {
|
|
252
|
+
return void 0;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// src/platform/platform-client-info.ts
|
|
257
|
+
var cached = null;
|
|
258
|
+
function buildPlatformClientInfo(sdkVersion) {
|
|
259
|
+
if (cached) {
|
|
260
|
+
return cached;
|
|
261
|
+
}
|
|
262
|
+
const os = reactNative.Platform.OS;
|
|
263
|
+
const platform = os === "ios" ? "ios" : os === "android" ? "android" : "web";
|
|
264
|
+
const bundleId = platform === "web" ? void 0 : readNativeApplicationId();
|
|
265
|
+
cached = {
|
|
266
|
+
platform,
|
|
267
|
+
bundleId,
|
|
268
|
+
sdkVersion
|
|
269
|
+
};
|
|
270
|
+
return cached;
|
|
271
|
+
}
|
|
272
|
+
var MoviieContext = React.createContext(null);
|
|
273
|
+
var fallbackContext = null;
|
|
274
|
+
function getOrCreateFallbackContext() {
|
|
275
|
+
if (!fallbackContext) {
|
|
276
|
+
const sdkVersion = MOVIIE_PLAYER_EXPO_PKG_VERSION;
|
|
277
|
+
const clientInfo = buildPlatformClientInfo(sdkVersion);
|
|
278
|
+
const viewerTokenStore = new playerSdk.MemoryViewerTokenStore();
|
|
279
|
+
const client = new playerSdk.MoviieClient({
|
|
280
|
+
publishableKey: void 0,
|
|
281
|
+
clientInfo,
|
|
282
|
+
sdkVersion
|
|
283
|
+
});
|
|
284
|
+
fallbackContext = {
|
|
285
|
+
client,
|
|
286
|
+
viewerTokenStore,
|
|
287
|
+
publishableKey: null,
|
|
288
|
+
clientInfo,
|
|
289
|
+
sdkVersion,
|
|
290
|
+
telemetryHeaders: playerSdk.buildClientHeaders({
|
|
291
|
+
clientInfo,
|
|
292
|
+
sdkVersion
|
|
293
|
+
})
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
return fallbackContext;
|
|
297
|
+
}
|
|
298
|
+
function useMoviieContext() {
|
|
299
|
+
const ctx = React.useContext(MoviieContext);
|
|
300
|
+
return ctx ?? getOrCreateFallbackContext();
|
|
301
|
+
}
|
|
302
|
+
function MoviieProvider({
|
|
303
|
+
publishableKey,
|
|
304
|
+
children
|
|
305
|
+
}) {
|
|
306
|
+
const value = React.useMemo(() => {
|
|
307
|
+
const sdkVersion = MOVIIE_PLAYER_EXPO_PKG_VERSION;
|
|
308
|
+
const clientInfo = buildPlatformClientInfo(sdkVersion);
|
|
309
|
+
const trimmedKey = publishableKey?.trim();
|
|
310
|
+
const viewerTokenStore = new SecureStoreViewerTokenStore();
|
|
311
|
+
const client = new playerSdk.MoviieClient({
|
|
312
|
+
publishableKey: trimmedKey || void 0,
|
|
313
|
+
clientInfo,
|
|
314
|
+
sdkVersion
|
|
315
|
+
});
|
|
316
|
+
const telemetryHeaders = playerSdk.buildClientHeaders({
|
|
317
|
+
publishableKey: trimmedKey || void 0,
|
|
318
|
+
clientInfo,
|
|
319
|
+
sdkVersion
|
|
320
|
+
});
|
|
321
|
+
return {
|
|
322
|
+
client,
|
|
323
|
+
viewerTokenStore,
|
|
324
|
+
publishableKey: trimmedKey ?? null,
|
|
325
|
+
clientInfo,
|
|
326
|
+
sdkVersion,
|
|
327
|
+
telemetryHeaders
|
|
328
|
+
};
|
|
329
|
+
}, [publishableKey]);
|
|
330
|
+
return /* @__PURE__ */ jsxRuntime.jsx(MoviieContext.Provider, { value, children });
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// src/playback/playback-memory-cache.ts
|
|
334
|
+
var playbackCache = /* @__PURE__ */ new Map();
|
|
335
|
+
function cacheKey(scope, embedId) {
|
|
336
|
+
return `${scope ?? "__anon__"}::${embedId}`;
|
|
337
|
+
}
|
|
338
|
+
function resolveEntryExpiry(data) {
|
|
339
|
+
const now = Date.now();
|
|
340
|
+
const fallback = now + MOVIIE_PLAYBACK_MEMORY_CACHE_TTL_MS;
|
|
341
|
+
const serverExpiry = data.playback?.expiresAt;
|
|
342
|
+
if (!serverExpiry) return fallback;
|
|
343
|
+
const parsed = Date.parse(serverExpiry);
|
|
344
|
+
if (!Number.isFinite(parsed)) return fallback;
|
|
345
|
+
return Math.min(fallback, parsed);
|
|
346
|
+
}
|
|
347
|
+
function readPlaybackCache(scope, embedId) {
|
|
348
|
+
const key = cacheKey(scope, embedId);
|
|
349
|
+
const hit = playbackCache.get(key);
|
|
350
|
+
if (!hit || hit.expiresAt <= Date.now()) {
|
|
351
|
+
playbackCache.delete(key);
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
return hit.data;
|
|
355
|
+
}
|
|
356
|
+
function writePlaybackCache(scope, embedId, data) {
|
|
357
|
+
playbackCache.set(cacheKey(scope, embedId), {
|
|
358
|
+
data,
|
|
359
|
+
expiresAt: resolveEntryExpiry(data)
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// src/playback/fetch-playback-fresh.ts
|
|
364
|
+
async function fetchPlaybackFreshWriteCache(scope, embedId, signal, getPlayback) {
|
|
365
|
+
try {
|
|
366
|
+
const data = await getPlayback(embedId, signal);
|
|
367
|
+
writePlaybackCache(scope, embedId, data);
|
|
368
|
+
return { ok: true, data };
|
|
369
|
+
} catch (unknownError) {
|
|
370
|
+
const error = unknownError instanceof Error ? unknownError : new Error(String(unknownError));
|
|
371
|
+
return { ok: false, error };
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// src/hooks/use-moviie-playback.ts
|
|
376
|
+
function useMoviiePlayback(args) {
|
|
377
|
+
const trimmedEmbedId = args.embedId?.trim();
|
|
378
|
+
const missingEmbedId = !trimmedEmbedId;
|
|
379
|
+
const { client, publishableKey } = useMoviieContext();
|
|
380
|
+
const [data, setData] = React.useState(null);
|
|
381
|
+
const [fetchError, setFetchError] = React.useState(null);
|
|
382
|
+
const [isLoading, setIsLoading] = React.useState(!missingEmbedId);
|
|
383
|
+
const [retryNonce, setRetryNonce] = React.useState(0);
|
|
384
|
+
const retry = React.useCallback(() => {
|
|
385
|
+
setRetryNonce((n) => n + 1);
|
|
386
|
+
}, []);
|
|
387
|
+
React.useEffect(() => {
|
|
388
|
+
if (!trimmedEmbedId) {
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
const embedKey = trimmedEmbedId;
|
|
392
|
+
const controller = new AbortController();
|
|
393
|
+
let cancelled = false;
|
|
394
|
+
async function load() {
|
|
395
|
+
setIsLoading(true);
|
|
396
|
+
setFetchError(null);
|
|
397
|
+
try {
|
|
398
|
+
const cached2 = readPlaybackCache(publishableKey, embedKey);
|
|
399
|
+
if (cached2 && !controller.signal.aborted) {
|
|
400
|
+
setData(cached2);
|
|
401
|
+
}
|
|
402
|
+
const outcome = await fetchPlaybackFreshWriteCache(
|
|
403
|
+
publishableKey,
|
|
404
|
+
embedKey,
|
|
405
|
+
controller.signal,
|
|
406
|
+
(id, sig) => client.getPlayback(id, sig)
|
|
407
|
+
);
|
|
408
|
+
if (cancelled || controller.signal.aborted) {
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
if (outcome.ok) {
|
|
412
|
+
setData(outcome.data);
|
|
413
|
+
} else {
|
|
414
|
+
setFetchError(outcome.error);
|
|
415
|
+
setData(readPlaybackCache(publishableKey, embedKey));
|
|
416
|
+
}
|
|
417
|
+
} finally {
|
|
418
|
+
if (!cancelled && !controller.signal.aborted) {
|
|
419
|
+
setIsLoading(false);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
void load();
|
|
424
|
+
return () => {
|
|
425
|
+
cancelled = true;
|
|
426
|
+
controller.abort();
|
|
427
|
+
};
|
|
428
|
+
}, [trimmedEmbedId, client, publishableKey, retryNonce]);
|
|
429
|
+
const error = missingEmbedId ? new Error("Informe um embedId v\xE1lido (UUID p\xFAblico do embed).") : fetchError;
|
|
430
|
+
return {
|
|
431
|
+
data: missingEmbedId ? null : data,
|
|
432
|
+
error,
|
|
433
|
+
isLoading: missingEmbedId ? false : isLoading,
|
|
434
|
+
retry
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
function useMoviieTelemetry(player, playback, eventsBaseUrl, defaultHeaders, viewerTokenStore) {
|
|
438
|
+
const hasStartedPlaybackRef = React.useRef(false);
|
|
439
|
+
React.useEffect(() => {
|
|
440
|
+
if (!playback?.telemetry.bootstrapUrl) {
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
const telemetry = new playerSdk.TelemetryClient({
|
|
444
|
+
eventsBaseUrl,
|
|
445
|
+
defaultHeaders,
|
|
446
|
+
viewerTokenStore,
|
|
447
|
+
getPositionSeconds: () => player.currentTime
|
|
448
|
+
});
|
|
449
|
+
let disposed = false;
|
|
450
|
+
const subs = [];
|
|
451
|
+
void (async () => {
|
|
452
|
+
try {
|
|
453
|
+
await telemetry.bootstrap({
|
|
454
|
+
bootstrapUrl: playback.telemetry.bootstrapUrl
|
|
455
|
+
});
|
|
456
|
+
if (disposed) {
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
await telemetry.recordEvent({
|
|
460
|
+
eventType: playerSdk.PLAYBACK_EVENT_TYPE.SESSION_START,
|
|
461
|
+
positionSeconds: 0
|
|
462
|
+
});
|
|
463
|
+
} catch {
|
|
464
|
+
}
|
|
465
|
+
})();
|
|
466
|
+
subs.push(
|
|
467
|
+
player.addListener("playingChange", ({ isPlaying }) => {
|
|
468
|
+
telemetry.updatePosition(Math.max(0, player.currentTime));
|
|
469
|
+
if (isPlaying) {
|
|
470
|
+
void telemetry.recordEvent({
|
|
471
|
+
eventType: hasStartedPlaybackRef.current ? playerSdk.PLAYBACK_EVENT_TYPE.RESUME : playerSdk.PLAYBACK_EVENT_TYPE.PLAY_START,
|
|
472
|
+
positionSeconds: Math.floor(Math.max(0, player.currentTime))
|
|
473
|
+
});
|
|
474
|
+
hasStartedPlaybackRef.current = true;
|
|
475
|
+
telemetry.startHeartbeats();
|
|
476
|
+
} else {
|
|
477
|
+
void telemetry.recordEvent({
|
|
478
|
+
eventType: playerSdk.PLAYBACK_EVENT_TYPE.PAUSE,
|
|
479
|
+
positionSeconds: Math.floor(Math.max(0, player.currentTime))
|
|
480
|
+
});
|
|
481
|
+
telemetry.stopHeartbeats();
|
|
482
|
+
}
|
|
483
|
+
})
|
|
484
|
+
);
|
|
485
|
+
subs.push(
|
|
486
|
+
player.addListener("playToEnd", () => {
|
|
487
|
+
telemetry.updatePosition(Math.max(0, player.currentTime));
|
|
488
|
+
void telemetry.recordEvent({
|
|
489
|
+
eventType: playerSdk.PLAYBACK_EVENT_TYPE.ENDED,
|
|
490
|
+
positionSeconds: Math.floor(Math.max(0, player.duration))
|
|
491
|
+
});
|
|
492
|
+
telemetry.stopHeartbeats();
|
|
493
|
+
})
|
|
494
|
+
);
|
|
495
|
+
subs.push(
|
|
496
|
+
player.addListener("statusChange", ({ status }) => {
|
|
497
|
+
if (status === "error") {
|
|
498
|
+
void telemetry.recordEvent({
|
|
499
|
+
eventType: playerSdk.PLAYBACK_EVENT_TYPE.ERROR,
|
|
500
|
+
positionSeconds: Math.floor(Math.max(0, player.currentTime)),
|
|
501
|
+
errorCode: "player_status_error"
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
})
|
|
505
|
+
);
|
|
506
|
+
subs.push(
|
|
507
|
+
player.addListener("timeUpdate", ({ currentTime }) => {
|
|
508
|
+
telemetry.updatePosition(Math.max(0, currentTime));
|
|
509
|
+
})
|
|
510
|
+
);
|
|
511
|
+
const appStateSub = reactNative.AppState.addEventListener(
|
|
512
|
+
"change",
|
|
513
|
+
(next) => {
|
|
514
|
+
if (next === "active") {
|
|
515
|
+
telemetry.resumeHeartbeats();
|
|
516
|
+
} else {
|
|
517
|
+
telemetry.pauseHeartbeats();
|
|
518
|
+
void telemetry.flush();
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
);
|
|
522
|
+
return () => {
|
|
523
|
+
disposed = true;
|
|
524
|
+
hasStartedPlaybackRef.current = false;
|
|
525
|
+
subs.forEach((s) => {
|
|
526
|
+
s.remove();
|
|
527
|
+
});
|
|
528
|
+
appStateSub.remove();
|
|
529
|
+
void telemetry.destroy();
|
|
530
|
+
};
|
|
531
|
+
}, [
|
|
532
|
+
player,
|
|
533
|
+
playback?.embedId,
|
|
534
|
+
playback?.telemetry.bootstrapUrl,
|
|
535
|
+
eventsBaseUrl,
|
|
536
|
+
defaultHeaders,
|
|
537
|
+
viewerTokenStore
|
|
538
|
+
]);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// src/lib/remember-playback-position-storage.ts
|
|
542
|
+
var RESUME_SECURE_STORE_MISSING_WARNING = "[@moviie/player-expo] `expo-secure-store` n\xE3o est\xE1 instalado \u2014 resume position n\xE3o ser\xE1 persistido. Instala com `pnpm add expo-secure-store` se quiseres retomar onde o utilizador parou.";
|
|
543
|
+
var SECURE_STORE_KEY_SAFE_PATTERN = /^[A-Za-z0-9._-]+$/;
|
|
544
|
+
function isSecureStoreSafeEmbedId(embedId) {
|
|
545
|
+
return SECURE_STORE_KEY_SAFE_PATTERN.test(embedId);
|
|
546
|
+
}
|
|
547
|
+
function rememberPlaybackPositionStorageKey(embedId) {
|
|
548
|
+
return `${MOVIIE_REMEMBER_POSITION_STORAGE_PREFIX}${embedId}`;
|
|
549
|
+
}
|
|
550
|
+
function parseStoredResumeSeconds(raw) {
|
|
551
|
+
if (raw == null || raw === "") {
|
|
552
|
+
return null;
|
|
553
|
+
}
|
|
554
|
+
const n = Number(raw);
|
|
555
|
+
if (!Number.isFinite(n) || n < 0) {
|
|
556
|
+
return null;
|
|
557
|
+
}
|
|
558
|
+
return n;
|
|
559
|
+
}
|
|
560
|
+
function clampResumeTimeSeconds(seconds, durationSeconds) {
|
|
561
|
+
if (seconds == null || !Number.isFinite(seconds) || seconds < 0.25) {
|
|
562
|
+
return null;
|
|
563
|
+
}
|
|
564
|
+
if (durationSeconds != null && Number.isFinite(durationSeconds) && durationSeconds > 0) {
|
|
565
|
+
if (seconds >= durationSeconds - 1) {
|
|
566
|
+
return null;
|
|
567
|
+
}
|
|
568
|
+
return Math.min(seconds, durationSeconds - 0.25);
|
|
569
|
+
}
|
|
570
|
+
return seconds;
|
|
571
|
+
}
|
|
572
|
+
async function loadSecureStore() {
|
|
573
|
+
try {
|
|
574
|
+
return await import('expo-secure-store');
|
|
575
|
+
} catch {
|
|
576
|
+
warnOnce("moviie:expo-secure-store-missing-resume", RESUME_SECURE_STORE_MISSING_WARNING);
|
|
577
|
+
return null;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
async function readStoredResumeSeconds(embedId) {
|
|
581
|
+
if (!isSecureStoreSafeEmbedId(embedId)) {
|
|
582
|
+
return null;
|
|
583
|
+
}
|
|
584
|
+
const SecureStore = await loadSecureStore();
|
|
585
|
+
if (!SecureStore) {
|
|
586
|
+
return null;
|
|
587
|
+
}
|
|
588
|
+
try {
|
|
589
|
+
const raw = await SecureStore.getItemAsync(rememberPlaybackPositionStorageKey(embedId));
|
|
590
|
+
return parseStoredResumeSeconds(raw);
|
|
591
|
+
} catch {
|
|
592
|
+
return null;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
async function writeStoredResumeSeconds(embedId, seconds) {
|
|
596
|
+
if (!isSecureStoreSafeEmbedId(embedId)) {
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
const SecureStore = await loadSecureStore();
|
|
600
|
+
if (!SecureStore) {
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
try {
|
|
604
|
+
await SecureStore.setItemAsync(rememberPlaybackPositionStorageKey(embedId), String(seconds));
|
|
605
|
+
} catch {
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
async function clearStoredResumeSeconds(embedId) {
|
|
610
|
+
if (!isSecureStoreSafeEmbedId(embedId)) {
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
const SecureStore = await loadSecureStore();
|
|
614
|
+
if (!SecureStore) {
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
try {
|
|
618
|
+
await SecureStore.deleteItemAsync(rememberPlaybackPositionStorageKey(embedId));
|
|
619
|
+
} catch {
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
// src/hooks/use-moviie-playback-resume-persistence.ts
|
|
625
|
+
function useMoviiePlaybackResumePersistence(options) {
|
|
626
|
+
const { player, embedId, durationSeconds, enabled } = options;
|
|
627
|
+
const debounceTimerRef = React.useRef(null);
|
|
628
|
+
React.useEffect(() => {
|
|
629
|
+
if (!enabled || embedId == null || embedId === "") {
|
|
630
|
+
return;
|
|
631
|
+
}
|
|
632
|
+
const clearDebounce = () => {
|
|
633
|
+
if (debounceTimerRef.current != null) {
|
|
634
|
+
clearTimeout(debounceTimerRef.current);
|
|
635
|
+
debounceTimerRef.current = null;
|
|
636
|
+
}
|
|
637
|
+
};
|
|
638
|
+
const persistNow = (seconds) => {
|
|
639
|
+
const clamped = clampResumeTimeSeconds(seconds, durationSeconds);
|
|
640
|
+
if (clamped == null) {
|
|
641
|
+
void clearStoredResumeSeconds(embedId);
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
void writeStoredResumeSeconds(embedId, clamped);
|
|
645
|
+
};
|
|
646
|
+
const schedulePersist = (seconds) => {
|
|
647
|
+
clearDebounce();
|
|
648
|
+
debounceTimerRef.current = setTimeout(() => {
|
|
649
|
+
debounceTimerRef.current = null;
|
|
650
|
+
persistNow(seconds);
|
|
651
|
+
}, MOVIIE_REMEMBER_POSITION_DEBOUNCE_MS);
|
|
652
|
+
};
|
|
653
|
+
const subTime = player.addListener("timeUpdate", ({ currentTime }) => {
|
|
654
|
+
if (player.playing) {
|
|
655
|
+
schedulePersist(currentTime);
|
|
656
|
+
}
|
|
657
|
+
});
|
|
658
|
+
const subPlaying = player.addListener("playingChange", ({ isPlaying }) => {
|
|
659
|
+
if (!isPlaying) {
|
|
660
|
+
clearDebounce();
|
|
661
|
+
persistNow(player.currentTime);
|
|
662
|
+
}
|
|
663
|
+
});
|
|
664
|
+
const subEnd = player.addListener("playToEnd", () => {
|
|
665
|
+
clearDebounce();
|
|
666
|
+
void clearStoredResumeSeconds(embedId);
|
|
667
|
+
});
|
|
668
|
+
return () => {
|
|
669
|
+
clearDebounce();
|
|
670
|
+
subTime.remove();
|
|
671
|
+
subPlaying.remove();
|
|
672
|
+
subEnd.remove();
|
|
673
|
+
};
|
|
674
|
+
}, [durationSeconds, embedId, enabled, player]);
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// src/lib/build-moviie-video-presentation.ts
|
|
678
|
+
function buildMoviieVideoPresentationProps(args) {
|
|
679
|
+
const allowsPictureInPicture = args.pictureInPicture !== void 0 ? args.pictureInPicture : args.showPip;
|
|
680
|
+
return {
|
|
681
|
+
allowsPictureInPicture,
|
|
682
|
+
startsPictureInPictureAutomatically: args.pictureInPictureAutoStart ?? false,
|
|
683
|
+
requiresLinearPlayback: args.profile === MOVIIE_PLAYBACK_PROFILE.VSL
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
// src/hooks/use-moviie-player.ts
|
|
688
|
+
var PLAYBACK_REQUEST_HEADER_ALLOWLIST = /* @__PURE__ */ new Set([
|
|
689
|
+
"authorization",
|
|
690
|
+
"referer",
|
|
691
|
+
"user-agent",
|
|
692
|
+
"x-moviie-playback-token",
|
|
693
|
+
"x-moviie-signature",
|
|
694
|
+
"x-playback-token"
|
|
695
|
+
]);
|
|
696
|
+
function filterPlaybackRequestHeaders(raw) {
|
|
697
|
+
if (!raw) return void 0;
|
|
698
|
+
const safe = {};
|
|
699
|
+
for (const [name, value] of Object.entries(raw)) {
|
|
700
|
+
if (typeof name !== "string" || typeof value !== "string") continue;
|
|
701
|
+
if (!PLAYBACK_REQUEST_HEADER_ALLOWLIST.has(name.toLowerCase())) continue;
|
|
702
|
+
if (/[\r\n]/.test(value)) continue;
|
|
703
|
+
safe[name] = value;
|
|
704
|
+
}
|
|
705
|
+
return Object.keys(safe).length > 0 ? safe : void 0;
|
|
706
|
+
}
|
|
707
|
+
function buildVideoSource(data) {
|
|
708
|
+
const headers = filterPlaybackRequestHeaders(data.playback.requestHeaders);
|
|
709
|
+
const base = {
|
|
710
|
+
uri: data.playback.uri,
|
|
711
|
+
metadata: {
|
|
712
|
+
title: data.title,
|
|
713
|
+
artist: data.branding.organizationName ?? void 0,
|
|
714
|
+
artwork: data.posterUrl ?? void 0
|
|
715
|
+
}
|
|
716
|
+
};
|
|
717
|
+
if (headers) {
|
|
718
|
+
return { ...base, headers };
|
|
719
|
+
}
|
|
720
|
+
return base;
|
|
721
|
+
}
|
|
722
|
+
function configurePlaybackDefaults(player, data) {
|
|
723
|
+
const c = data.controls;
|
|
724
|
+
player.loop = c.loop;
|
|
725
|
+
player.muted = c.muted;
|
|
726
|
+
player.timeUpdateEventInterval = 1;
|
|
727
|
+
}
|
|
728
|
+
function applyNativePlaybackPresentation(player, opts) {
|
|
729
|
+
player.staysActiveInBackground = opts.backgroundPlayback ?? false;
|
|
730
|
+
player.showNowPlayingNotification = opts.lockScreenNowPlaying ?? false;
|
|
731
|
+
}
|
|
732
|
+
function syncPlaybackIntent(player, shouldPlay) {
|
|
733
|
+
if (shouldPlay) {
|
|
734
|
+
player.play();
|
|
735
|
+
} else {
|
|
736
|
+
player.pause();
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
var EMPTY_PRESENTATION = buildMoviieVideoPresentationProps({
|
|
740
|
+
profile: "",
|
|
741
|
+
showPip: false
|
|
742
|
+
});
|
|
743
|
+
function useMoviiePlayer(options) {
|
|
744
|
+
const ctx = useMoviieContext();
|
|
745
|
+
const { data, error, isLoading, retry } = useMoviiePlayback({
|
|
746
|
+
embedId: options.embedId
|
|
747
|
+
});
|
|
748
|
+
const rememberEnabled = React.useMemo(() => {
|
|
749
|
+
if (options.rememberPosition === false) {
|
|
750
|
+
return false;
|
|
751
|
+
}
|
|
752
|
+
if (options.rememberPosition === true) {
|
|
753
|
+
return true;
|
|
754
|
+
}
|
|
755
|
+
return data?.controls.rememberPosition === true;
|
|
756
|
+
}, [data?.controls.rememberPosition, options.rememberPosition]);
|
|
757
|
+
const player = expoVideo.useVideoPlayer(null, (initialPlayer) => {
|
|
758
|
+
initialPlayer.timeUpdateEventInterval = 1;
|
|
759
|
+
});
|
|
760
|
+
useMoviiePlaybackResumePersistence({
|
|
761
|
+
durationSeconds: data?.durationSeconds,
|
|
762
|
+
embedId: data?.embedId,
|
|
763
|
+
enabled: rememberEnabled && data != null,
|
|
764
|
+
player
|
|
765
|
+
});
|
|
766
|
+
const resumeHandledRef = React.useRef(false);
|
|
767
|
+
React.useEffect(() => {
|
|
768
|
+
resumeHandledRef.current = false;
|
|
769
|
+
}, [data?.embedId, data?.playback.uri]);
|
|
770
|
+
React.useEffect(() => {
|
|
771
|
+
if (!data) {
|
|
772
|
+
return;
|
|
773
|
+
}
|
|
774
|
+
const src = buildVideoSource(data);
|
|
775
|
+
const shouldPlay = options.autoplay !== void 0 ? options.autoplay : data.controls.autoplay;
|
|
776
|
+
player.replace(src);
|
|
777
|
+
configurePlaybackDefaults(player, data);
|
|
778
|
+
applyNativePlaybackPresentation(player, {
|
|
779
|
+
backgroundPlayback: options.backgroundPlayback,
|
|
780
|
+
lockScreenNowPlaying: options.lockScreenNowPlaying
|
|
781
|
+
});
|
|
782
|
+
const restoreAndSync = async () => {
|
|
783
|
+
if (player.status !== "readyToPlay") {
|
|
784
|
+
return;
|
|
785
|
+
}
|
|
786
|
+
if (!resumeHandledRef.current) {
|
|
787
|
+
resumeHandledRef.current = true;
|
|
788
|
+
if (rememberEnabled) {
|
|
789
|
+
const stored = await readStoredResumeSeconds(data.embedId);
|
|
790
|
+
const clamped = clampResumeTimeSeconds(stored, data.durationSeconds);
|
|
791
|
+
if (clamped != null) {
|
|
792
|
+
player.currentTime = clamped;
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
syncPlaybackIntent(player, shouldPlay);
|
|
797
|
+
};
|
|
798
|
+
const sub = player.addListener("statusChange", (payload) => {
|
|
799
|
+
if (payload.status === "readyToPlay") {
|
|
800
|
+
void restoreAndSync();
|
|
801
|
+
}
|
|
802
|
+
});
|
|
803
|
+
void restoreAndSync();
|
|
804
|
+
return () => {
|
|
805
|
+
sub.remove();
|
|
806
|
+
};
|
|
807
|
+
}, [
|
|
808
|
+
data,
|
|
809
|
+
player,
|
|
810
|
+
options.autoplay,
|
|
811
|
+
options.backgroundPlayback,
|
|
812
|
+
options.lockScreenNowPlaying,
|
|
813
|
+
rememberEnabled
|
|
814
|
+
]);
|
|
815
|
+
const videoPresentation = React.useMemo(() => {
|
|
816
|
+
if (!data) {
|
|
817
|
+
return EMPTY_PRESENTATION;
|
|
818
|
+
}
|
|
819
|
+
return buildMoviieVideoPresentationProps({
|
|
820
|
+
pictureInPicture: options.pictureInPicture,
|
|
821
|
+
pictureInPictureAutoStart: options.pictureInPictureAutoStart,
|
|
822
|
+
profile: data.profile,
|
|
823
|
+
showPip: data.controls.showPip
|
|
824
|
+
});
|
|
825
|
+
}, [
|
|
826
|
+
data,
|
|
827
|
+
options.pictureInPicture,
|
|
828
|
+
options.pictureInPictureAutoStart
|
|
829
|
+
]);
|
|
830
|
+
const eventsBaseUrl = data?.telemetry.bootstrapUrl != null ? playerSdk.deriveTelemetryEventsBaseUrlFromBootstrapUrl(data.telemetry.bootstrapUrl) ?? ctx.client.getEventsBaseUrl() : ctx.client.getEventsBaseUrl();
|
|
831
|
+
useMoviieTelemetry(
|
|
832
|
+
player,
|
|
833
|
+
data,
|
|
834
|
+
eventsBaseUrl,
|
|
835
|
+
ctx.telemetryHeaders,
|
|
836
|
+
ctx.viewerTokenStore
|
|
837
|
+
);
|
|
838
|
+
return {
|
|
839
|
+
player,
|
|
840
|
+
playback: data,
|
|
841
|
+
error,
|
|
842
|
+
isLoading,
|
|
843
|
+
videoPresentation,
|
|
844
|
+
retry
|
|
845
|
+
};
|
|
846
|
+
}
|
|
847
|
+
function useMoviieEvent(player, eventName, handler) {
|
|
848
|
+
React.useEffect(() => {
|
|
849
|
+
if (!player) {
|
|
850
|
+
return;
|
|
851
|
+
}
|
|
852
|
+
if (eventName === playerTypes.PLAYER_API_EVENTS.TIME_UPDATE) {
|
|
853
|
+
const previousInterval = player.timeUpdateEventInterval;
|
|
854
|
+
if (player.timeUpdateEventInterval <= 0) {
|
|
855
|
+
player.timeUpdateEventInterval = 0.25;
|
|
856
|
+
}
|
|
857
|
+
const sub = player.addListener("timeUpdate", () => {
|
|
858
|
+
handler();
|
|
859
|
+
});
|
|
860
|
+
return () => {
|
|
861
|
+
sub.remove();
|
|
862
|
+
player.timeUpdateEventInterval = previousInterval;
|
|
863
|
+
};
|
|
864
|
+
}
|
|
865
|
+
if (eventName === playerTypes.PLAYER_API_EVENTS.PLAY) {
|
|
866
|
+
const sub = player.addListener("playingChange", ({ isPlaying }) => {
|
|
867
|
+
if (isPlaying) {
|
|
868
|
+
handler();
|
|
869
|
+
}
|
|
870
|
+
});
|
|
871
|
+
return () => {
|
|
872
|
+
sub.remove();
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
if (eventName === playerTypes.PLAYER_API_EVENTS.PAUSE) {
|
|
876
|
+
const sub = player.addListener("playingChange", ({ isPlaying }) => {
|
|
877
|
+
if (!isPlaying) {
|
|
878
|
+
handler();
|
|
879
|
+
}
|
|
880
|
+
});
|
|
881
|
+
return () => {
|
|
882
|
+
sub.remove();
|
|
883
|
+
};
|
|
884
|
+
}
|
|
885
|
+
if (eventName === playerTypes.PLAYER_API_EVENTS.ENDED) {
|
|
886
|
+
const sub = player.addListener("playToEnd", () => {
|
|
887
|
+
handler();
|
|
888
|
+
});
|
|
889
|
+
return () => {
|
|
890
|
+
sub.remove();
|
|
891
|
+
};
|
|
892
|
+
}
|
|
893
|
+
if (eventName === playerTypes.PLAYER_API_EVENTS.DURATION_CHANGE) {
|
|
894
|
+
const sub = player.addListener("sourceChange", () => {
|
|
895
|
+
handler();
|
|
896
|
+
});
|
|
897
|
+
return () => {
|
|
898
|
+
sub.remove();
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
if (eventName === playerTypes.PLAYER_API_EVENTS.VOLUME_CHANGE) {
|
|
902
|
+
const sub = player.addListener("volumeChange", () => {
|
|
903
|
+
handler();
|
|
904
|
+
});
|
|
905
|
+
return () => {
|
|
906
|
+
sub.remove();
|
|
907
|
+
};
|
|
908
|
+
}
|
|
909
|
+
if (eventName === playerTypes.PLAYER_API_EVENTS.READY) {
|
|
910
|
+
const sub = player.addListener("statusChange", ({ status }) => {
|
|
911
|
+
if (status === "readyToPlay") {
|
|
912
|
+
handler();
|
|
913
|
+
}
|
|
914
|
+
});
|
|
915
|
+
return () => {
|
|
916
|
+
sub.remove();
|
|
917
|
+
};
|
|
918
|
+
}
|
|
919
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
920
|
+
console.warn(
|
|
921
|
+
`[@moviie/player-expo] useMoviieEvent: "${eventName}" n\xE3o tem mapeamento para expo-video nesta vers\xE3o`
|
|
922
|
+
);
|
|
923
|
+
}
|
|
924
|
+
return void 0;
|
|
925
|
+
}, [player, eventName, handler]);
|
|
926
|
+
}
|
|
927
|
+
function useMoviiePlaybackEnded(player, onEnded) {
|
|
928
|
+
useMoviieEvent(player, playerTypes.PLAYER_API_EVENTS.ENDED, onEnded);
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
// src/lib/compute-moviie-playback-ended.ts
|
|
932
|
+
function computeMoviiePlaybackEnded(args) {
|
|
933
|
+
if (args.loop) {
|
|
934
|
+
return false;
|
|
935
|
+
}
|
|
936
|
+
if (args.isLive) {
|
|
937
|
+
return false;
|
|
938
|
+
}
|
|
939
|
+
if (args.playing) {
|
|
940
|
+
return false;
|
|
941
|
+
}
|
|
942
|
+
if (!Number.isFinite(args.duration) || args.duration <= 0) {
|
|
943
|
+
return false;
|
|
944
|
+
}
|
|
945
|
+
if (!Number.isFinite(args.currentTime)) {
|
|
946
|
+
return false;
|
|
947
|
+
}
|
|
948
|
+
return args.currentTime >= args.duration - MOVIIE_SKIN_TIMELINE_END_SNAP_EPSILON_SECONDS;
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
// src/lib/add-moviie-playback-ended-listener.ts
|
|
952
|
+
function addMoviiePlaybackEndedListener(player, onEnded) {
|
|
953
|
+
const sub = player.addListener("playToEnd", onEnded);
|
|
954
|
+
return { remove: () => sub.remove() };
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
// src/lib/build-moviie-watch-embed-url.ts
|
|
958
|
+
function normalizeWatchOrigin(origin) {
|
|
959
|
+
return origin.trim().replace(/\/+$/, "");
|
|
960
|
+
}
|
|
961
|
+
function buildMoviieWatchEmbedUrl(embedId, watchOrigin) {
|
|
962
|
+
const base = normalizeWatchOrigin(watchOrigin);
|
|
963
|
+
const id = embedId.trim();
|
|
964
|
+
return `${base}/embed/${encodeURIComponent(id)}`;
|
|
965
|
+
}
|
|
966
|
+
function resolveMoviieWatchOrigin() {
|
|
967
|
+
try {
|
|
968
|
+
const raw = typeof process !== "undefined" ? process.env.EXPO_PUBLIC_MOVIIE_WATCH_ORIGIN?.trim() : void 0;
|
|
969
|
+
if (raw) {
|
|
970
|
+
return normalizeWatchOrigin(raw);
|
|
971
|
+
}
|
|
972
|
+
} catch {
|
|
973
|
+
}
|
|
974
|
+
return MOVIIE_WATCH_ORIGIN_DEFAULT;
|
|
975
|
+
}
|
|
976
|
+
var Svg = RNSvg__default.default;
|
|
977
|
+
var jsx_native_bridge_default = Svg;
|
|
978
|
+
var Path = RNSvg.Path;
|
|
979
|
+
var Defs = RNSvg.Defs;
|
|
980
|
+
var LinearGradient = RNSvg.LinearGradient;
|
|
981
|
+
var Rect = RNSvg.Rect;
|
|
982
|
+
var Stop = RNSvg.Stop;
|
|
983
|
+
var AnimatedView = reactNative.Animated.View;
|
|
984
|
+
var ReanimatedView = AnimatedReanimated__default.default.View;
|
|
985
|
+
|
|
986
|
+
// src/lib/moviie-telemetry-callbacks.ts
|
|
987
|
+
function safeInvokeMoviieTelemetry(callback, ...args) {
|
|
988
|
+
if (callback == null) {
|
|
989
|
+
return;
|
|
990
|
+
}
|
|
991
|
+
try {
|
|
992
|
+
callback(...args);
|
|
993
|
+
} catch (err) {
|
|
994
|
+
console.warn("[@moviie/player-expo] telemetry callback threw \u2014 ignorado", err);
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
// src/lib/moviie-shell-tokens.ts
|
|
999
|
+
var MOVIIE_SHELL_BACKGROUND_HEX = "#0a0a0a";
|
|
1000
|
+
var MOVIIE_SHELL_RADIAL_INNER_HEX = "#1a1a1a";
|
|
1001
|
+
var MOVIIE_SHELL_HEADING_HEX = "#f8fafc";
|
|
1002
|
+
var MOVIIE_SHELL_DESCRIPTION_HEX = "#e5e7eb";
|
|
1003
|
+
var MOVIIE_SHELL_ERROR_CODE_HEX = "#4b5563";
|
|
1004
|
+
var MOVIIE_SHELL_BUTTON_BG_HEX = "#0a0a0a";
|
|
1005
|
+
var MOVIIE_SHELL_BUTTON_BORDER_RGBA = "rgba(255,255,255,0.15)";
|
|
1006
|
+
var MOVIIE_SHELL_BUTTON_LABEL_HEX = "#f8fafc";
|
|
1007
|
+
var MOVIIE_SHELL_HEADING_FONT_SIZE_PX = 22;
|
|
1008
|
+
var MOVIIE_SHELL_DESCRIPTION_FONT_SIZE_PX = 14;
|
|
1009
|
+
var MOVIIE_SHELL_BUTTON_LABEL_FONT_SIZE_PX = 14;
|
|
1010
|
+
var MOVIIE_SHELL_CONTENT_MAX_WIDTH_PX = 280;
|
|
1011
|
+
var MOVIIE_SHELL_BUTTON_PADDING_H_PX = 22;
|
|
1012
|
+
var MOVIIE_SHELL_BUTTON_PADDING_V_PX = 12;
|
|
1013
|
+
var MOVIIE_SHELL_BUTTON_RADIUS_PX = 9999;
|
|
1014
|
+
var MOVIIE_SHELL_CROSSFADE_DURATION_MS = 240;
|
|
1015
|
+
var MOVIIE_SHELL_DEFAULT_ASPECT_RATIO = 16 / 9;
|
|
1016
|
+
var MOVIIE_DASHBOARD_URL = "https://app.moviie.ai";
|
|
1017
|
+
|
|
1018
|
+
// src/lib/partition-moviie-video-host-style.ts
|
|
1019
|
+
var VIDEO_SURFACE_STYLE_KEYS = /* @__PURE__ */ new Set([
|
|
1020
|
+
"backgroundColor",
|
|
1021
|
+
"borderRadius",
|
|
1022
|
+
"borderTopLeftRadius",
|
|
1023
|
+
"borderTopRightRadius",
|
|
1024
|
+
"borderBottomLeftRadius",
|
|
1025
|
+
"borderBottomRightRadius",
|
|
1026
|
+
"borderCurve",
|
|
1027
|
+
"borderWidth",
|
|
1028
|
+
"borderColor"
|
|
1029
|
+
]);
|
|
1030
|
+
function partitionMoviieVideoHostStyle(flatStyle) {
|
|
1031
|
+
if (flatStyle == null || Object.keys(flatStyle).length === 0) {
|
|
1032
|
+
return { columnStyle: void 0, surfaceStyle: void 0 };
|
|
1033
|
+
}
|
|
1034
|
+
const flat = flatStyle;
|
|
1035
|
+
const column = {};
|
|
1036
|
+
const surface = {};
|
|
1037
|
+
for (const key of Object.keys(flat)) {
|
|
1038
|
+
const value = flat[key];
|
|
1039
|
+
if (value === void 0) {
|
|
1040
|
+
continue;
|
|
1041
|
+
}
|
|
1042
|
+
if (VIDEO_SURFACE_STYLE_KEYS.has(key)) {
|
|
1043
|
+
surface[key] = value;
|
|
1044
|
+
} else {
|
|
1045
|
+
column[key] = value;
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
return {
|
|
1049
|
+
columnStyle: Object.keys(column).length > 0 ? column : void 0,
|
|
1050
|
+
surfaceStyle: Object.keys(surface).length > 0 ? surface : void 0
|
|
1051
|
+
};
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
// src/lib/compute-custom-fullscreen-stage-dimensions.ts
|
|
1055
|
+
function computeCustomFullscreenStageDimensions(args) {
|
|
1056
|
+
const pad = args.stageOverscanPx;
|
|
1057
|
+
const usableW = Math.max(
|
|
1058
|
+
0,
|
|
1059
|
+
args.windowWidth - args.safeInsets.left - args.safeInsets.right - 2 * pad
|
|
1060
|
+
);
|
|
1061
|
+
const usableH = Math.max(
|
|
1062
|
+
0,
|
|
1063
|
+
args.windowHeight - args.safeInsets.top - args.safeInsets.bottom - 2 * pad
|
|
1064
|
+
);
|
|
1065
|
+
const longSide = Math.max(usableW, usableH);
|
|
1066
|
+
const shortSide = Math.min(usableW, usableH);
|
|
1067
|
+
return {
|
|
1068
|
+
longSide,
|
|
1069
|
+
shortSide,
|
|
1070
|
+
layoutMetricsBasisWidth: longSide
|
|
1071
|
+
};
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
// src/lib/cast-adapter-registry.ts
|
|
1075
|
+
var _registered = null;
|
|
1076
|
+
function getRegisteredCastAdapter() {
|
|
1077
|
+
return _registered;
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
// src/lib/format-playback-clock.ts
|
|
1081
|
+
function pad2(value) {
|
|
1082
|
+
return String(Math.floor(value)).padStart(2, "0");
|
|
1083
|
+
}
|
|
1084
|
+
function formatSegment(totalSeconds) {
|
|
1085
|
+
if (!Number.isFinite(totalSeconds) || totalSeconds < 0) {
|
|
1086
|
+
return "0:00";
|
|
1087
|
+
}
|
|
1088
|
+
const seconds = totalSeconds % 60;
|
|
1089
|
+
const minutes = Math.floor(totalSeconds / 60) % 60;
|
|
1090
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
1091
|
+
if (hours > 0) {
|
|
1092
|
+
return `${hours}:${pad2(minutes)}:${pad2(seconds)}`;
|
|
1093
|
+
}
|
|
1094
|
+
return `${Math.floor(minutes)}:${pad2(seconds)}`;
|
|
1095
|
+
}
|
|
1096
|
+
function formatPlaybackClock(currentSeconds, durationSeconds) {
|
|
1097
|
+
const current = formatSegment(currentSeconds);
|
|
1098
|
+
if (!Number.isFinite(durationSeconds) || durationSeconds <= 0) {
|
|
1099
|
+
return current;
|
|
1100
|
+
}
|
|
1101
|
+
return `${current} / ${formatSegment(durationSeconds)}`;
|
|
1102
|
+
}
|
|
1103
|
+
var MOVIIE_EMBED_MEDIA_ICON_VIEW_BOX = "0 0 32 32";
|
|
1104
|
+
function IconShell({
|
|
1105
|
+
size,
|
|
1106
|
+
children
|
|
1107
|
+
}) {
|
|
1108
|
+
const pixels = size ?? 22;
|
|
1109
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1110
|
+
jsx_native_bridge_default,
|
|
1111
|
+
{
|
|
1112
|
+
accessibilityElementsHidden: true,
|
|
1113
|
+
height: pixels,
|
|
1114
|
+
importantForAccessibility: "no",
|
|
1115
|
+
viewBox: MOVIIE_EMBED_MEDIA_ICON_VIEW_BOX,
|
|
1116
|
+
width: pixels,
|
|
1117
|
+
children
|
|
1118
|
+
}
|
|
1119
|
+
);
|
|
1120
|
+
}
|
|
1121
|
+
function EmbedMediaIconPlay(props) {
|
|
1122
|
+
return /* @__PURE__ */ jsxRuntime.jsx(IconShell, { size: props.size, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1123
|
+
Path,
|
|
1124
|
+
{
|
|
1125
|
+
d: "M10.6667 6.6548C10.6667 6.10764 11.2894 5.79346 11.7295 6.11862L24.377 15.4634C24.7377 15.7298 24.7377 16.2692 24.3771 16.5357L11.7295 25.8813C11.2895 26.2065 10.6667 25.8923 10.6667 25.3451L10.6667 6.6548Z",
|
|
1126
|
+
fill: props.color
|
|
1127
|
+
}
|
|
1128
|
+
) });
|
|
1129
|
+
}
|
|
1130
|
+
function EmbedMediaIconPause(props) {
|
|
1131
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(IconShell, { size: props.size, children: [
|
|
1132
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1133
|
+
Path,
|
|
1134
|
+
{
|
|
1135
|
+
d: "M8.66667 6.66667C8.29848 6.66667 8 6.96514 8 7.33333V24.6667C8 25.0349 8.29848 25.3333 8.66667 25.3333H12.6667C13.0349 25.3333 13.3333 25.0349 13.3333 24.6667V7.33333C13.3333 6.96514 13.0349 6.66667 12.6667 6.66667H8.66667Z",
|
|
1136
|
+
fill: props.color
|
|
1137
|
+
}
|
|
1138
|
+
),
|
|
1139
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1140
|
+
Path,
|
|
1141
|
+
{
|
|
1142
|
+
d: "M19.3333 6.66667C18.9651 6.66667 18.6667 6.96514 18.6667 7.33333V24.6667C18.6667 25.0349 18.9651 25.3333 19.3333 25.3333H23.3333C23.7015 25.3333 24 25.0349 24 24.6667V7.33333C24 6.96514 23.7015 6.66667 23.3333 6.66667H19.3333Z",
|
|
1143
|
+
fill: props.color
|
|
1144
|
+
}
|
|
1145
|
+
)
|
|
1146
|
+
] });
|
|
1147
|
+
}
|
|
1148
|
+
function EmbedMediaIconReplay(props) {
|
|
1149
|
+
return /* @__PURE__ */ jsxRuntime.jsx(IconShell, { size: props.size, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1150
|
+
Path,
|
|
1151
|
+
{
|
|
1152
|
+
d: "M15.6038 12.2147C16.0439 12.5399 16.6667 12.2257 16.6667 11.6786V10.1789C16.6667 10.1001 16.7351 10.0384 16.8134 10.0479C20.1116 10.4494 22.6667 13.2593 22.6667 16.6659C22.6667 20.3481 19.6817 23.3332 15.9995 23.3332C12.542 23.3332 9.69927 20.7014 9.36509 17.332C9.32875 16.9655 9.03371 16.6662 8.66548 16.6662L6.66655 16.6666C6.29841 16.6666 5.99769 16.966 6.02187 17.3334C6.36494 22.5454 10.7012 26.6667 16 26.6667C21.5228 26.6667 26 22.1895 26 16.6667C26 11.4103 21.9444 7.10112 16.7916 6.69757C16.7216 6.69209 16.6667 6.63396 16.6667 6.56372V4.98824C16.6667 4.44106 16.0439 4.12689 15.6038 4.45206L11.0765 7.79738C10.7159 8.06387 10.7159 8.60326 11.0766 8.86973L15.6038 12.2147Z",
|
|
1153
|
+
fill: props.color
|
|
1154
|
+
}
|
|
1155
|
+
) });
|
|
1156
|
+
}
|
|
1157
|
+
function EmbedMediaIconSeekBackward10(props) {
|
|
1158
|
+
const fill = props.color;
|
|
1159
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(IconShell, { size: props.size, children: [
|
|
1160
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1161
|
+
Path,
|
|
1162
|
+
{
|
|
1163
|
+
d: "M16.6667 10.3452C16.6667 10.8924 16.0439 11.2066 15.6038 10.8814L11.0766 7.5364C10.7159 7.26993 10.7159 6.73054 11.0766 6.46405L15.6038 3.11873C16.0439 2.79356 16.6667 3.10773 16.6667 3.6549V5.22682C16.6667 5.29746 16.7223 5.35579 16.7927 5.36066C22.6821 5.76757 27.3333 10.674 27.3333 16.6667C27.3333 22.9259 22.2592 28 16 28C9.96483 28 5.03145 23.2827 4.68601 17.3341C4.66466 16.9665 4.96518 16.6673 5.33339 16.6673H7.3334C7.70157 16.6673 7.99714 16.9668 8.02743 17.3337C8.36638 21.4399 11.8064 24.6667 16 24.6667C20.4183 24.6667 24 21.085 24 16.6667C24 12.5225 20.8483 9.11428 16.8113 8.70739C16.7337 8.69957 16.6667 8.76096 16.6667 8.83893V10.3452Z",
|
|
1164
|
+
fill
|
|
1165
|
+
}
|
|
1166
|
+
),
|
|
1167
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1168
|
+
Path,
|
|
1169
|
+
{
|
|
1170
|
+
clipRule: "evenodd",
|
|
1171
|
+
d: "M17.0879 19.679C17.4553 19.9195 17.8928 20.0398 18.4004 20.0398C18.9099 20.0398 19.3474 19.9205 19.7129 19.6818C20.0803 19.4413 20.3635 19.0938 20.5623 18.6392C20.7612 18.1847 20.8606 17.6373 20.8606 16.9972C20.8625 16.3608 20.764 15.8192 20.5652 15.3722C20.3663 14.9252 20.0822 14.5853 19.7129 14.3523C19.3455 14.1175 18.908 14 18.4004 14C17.8928 14 17.4553 14.1175 17.0879 14.3523C16.7224 14.5853 16.4402 14.9252 16.2413 15.3722C16.0443 15.8173 15.9449 16.3589 15.943 16.9972C15.9411 17.6354 16.0396 18.1818 16.2385 18.6364C16.4373 19.089 16.7205 19.4366 17.0879 19.679ZM19.1362 18.4262C18.9487 18.7349 18.7034 18.8892 18.4004 18.8892C18.1996 18.8892 18.0226 18.8211 17.8691 18.6847C17.7157 18.5464 17.5964 18.3372 17.5112 18.0568C17.4279 17.7765 17.3871 17.4233 17.389 16.9972C17.3909 16.3684 17.4847 15.9025 17.6703 15.5995C17.8559 15.2945 18.0993 15.1421 18.4004 15.1421C18.603 15.1421 18.7801 15.2093 18.9316 15.3438C19.0832 15.4782 19.2015 15.6828 19.2868 15.9574C19.372 16.2301 19.4146 16.5767 19.4146 16.9972C19.4165 17.6392 19.3237 18.1156 19.1362 18.4262Z",
|
|
1172
|
+
fill,
|
|
1173
|
+
fillRule: "evenodd"
|
|
1174
|
+
}
|
|
1175
|
+
),
|
|
1176
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1177
|
+
Path,
|
|
1178
|
+
{
|
|
1179
|
+
d: "M13.7746 19.8978C13.8482 19.8978 13.9079 19.8381 13.9079 19.7644V14.2129C13.9079 14.1393 13.8482 14.0796 13.7746 14.0796H12.642C12.6171 14.0796 12.5927 14.0865 12.5716 14.0997L11.2322 14.9325C11.1931 14.9568 11.1693 14.9996 11.1693 15.0457V15.9497C11.1693 16.0539 11.2833 16.1178 11.3722 16.0635L12.464 15.396C12.4682 15.3934 12.473 15.3921 12.4779 15.3921C12.4926 15.3921 12.5045 15.404 12.5045 15.4187V19.7644C12.5045 19.8381 12.5642 19.8978 12.6378 19.8978H13.7746Z",
|
|
1180
|
+
fill
|
|
1181
|
+
}
|
|
1182
|
+
)
|
|
1183
|
+
] });
|
|
1184
|
+
}
|
|
1185
|
+
function EmbedMediaIconSeekForward10(props) {
|
|
1186
|
+
const fill = props.color;
|
|
1187
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(IconShell, { size: props.size, children: [
|
|
1188
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1189
|
+
Path,
|
|
1190
|
+
{
|
|
1191
|
+
d: "M15.3333 10.3452C15.3333 10.8924 15.9561 11.2066 16.3962 10.8814L20.9234 7.5364C21.2841 7.26993 21.2841 6.73054 20.9235 6.46405L16.3962 3.11873C15.9561 2.79356 15.3333 3.10773 15.3333 3.6549V5.22682C15.3333 5.29746 15.2778 5.35579 15.2073 5.36066C9.31791 5.76757 4.66667 10.674 4.66667 16.6667C4.66667 22.9259 9.74078 28 16 28C22.0352 28 26.9686 23.2827 27.314 17.3341C27.3354 16.9665 27.0348 16.6673 26.6666 16.6673H24.6666C24.2984 16.6673 24.0029 16.9668 23.9726 17.3337C23.6336 21.4399 20.1937 24.6667 16 24.6667C11.5817 24.6667 8 21.085 8 16.6667C8 12.5225 11.1517 9.11428 15.1887 8.70739C15.2663 8.69957 15.3333 8.76096 15.3333 8.83893V10.3452Z",
|
|
1192
|
+
fill
|
|
1193
|
+
}
|
|
1194
|
+
),
|
|
1195
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1196
|
+
Path,
|
|
1197
|
+
{
|
|
1198
|
+
clipRule: "evenodd",
|
|
1199
|
+
d: "M17.0879 19.679C17.4553 19.9195 17.8928 20.0398 18.4004 20.0398C18.9099 20.0398 19.3474 19.9205 19.7129 19.6818C20.0803 19.4413 20.3635 19.0938 20.5623 18.6392C20.7612 18.1847 20.8606 17.6373 20.8606 16.9972C20.8625 16.3608 20.764 15.8192 20.5652 15.3722C20.3663 14.9252 20.0822 14.5853 19.7129 14.3523C19.3455 14.1175 18.908 14 18.4004 14C17.8928 14 17.4553 14.1175 17.0879 14.3523C16.7224 14.5853 16.4402 14.9252 16.2413 15.3722C16.0443 15.8173 15.9449 16.3589 15.943 16.9972C15.9411 17.6354 16.0396 18.1818 16.2385 18.6364C16.4373 19.089 16.7205 19.4366 17.0879 19.679ZM19.1362 18.4262C18.9487 18.7349 18.7034 18.8892 18.4004 18.8892C18.1996 18.8892 18.0225 18.8211 17.8691 18.6847C17.7157 18.5464 17.5964 18.3372 17.5112 18.0568C17.4278 17.7765 17.3871 17.4233 17.389 16.9972C17.3909 16.3684 17.4847 15.9025 17.6703 15.5995C17.8559 15.2945 18.0992 15.1421 18.4004 15.1421C18.603 15.1421 18.7801 15.2093 18.9316 15.3438C19.0831 15.4782 19.2015 15.6828 19.2867 15.9574C19.372 16.2301 19.4146 16.5767 19.4146 16.9972C19.4165 17.6392 19.3237 18.1156 19.1362 18.4262Z",
|
|
1200
|
+
fill,
|
|
1201
|
+
fillRule: "evenodd"
|
|
1202
|
+
}
|
|
1203
|
+
),
|
|
1204
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1205
|
+
Path,
|
|
1206
|
+
{
|
|
1207
|
+
d: "M13.7746 19.8978C13.8482 19.8978 13.9079 19.8381 13.9079 19.7644V14.2129C13.9079 14.1393 13.8482 14.0796 13.7746 14.0796H12.642C12.6171 14.0796 12.5927 14.0865 12.5716 14.0997L11.2322 14.9325C11.1931 14.9568 11.1693 14.9996 11.1693 15.0457V15.9497C11.1693 16.0539 11.2833 16.1178 11.3722 16.0635L12.464 15.396C12.4682 15.3934 12.473 15.3921 12.4779 15.3921C12.4926 15.3921 12.5045 15.404 12.5045 15.4187V19.7644C12.5045 19.8381 12.5642 19.8978 12.6378 19.8978H13.7746Z",
|
|
1208
|
+
fill
|
|
1209
|
+
}
|
|
1210
|
+
)
|
|
1211
|
+
] });
|
|
1212
|
+
}
|
|
1213
|
+
function EmbedMediaIconFullscreen(props) {
|
|
1214
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(IconShell, { size: props.size, children: [
|
|
1215
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1216
|
+
Path,
|
|
1217
|
+
{
|
|
1218
|
+
d: "M25.3299 7.26517C25.2958 6.929 25.0119 6.66666 24.6667 6.66666H19.3334C18.9652 6.66666 18.6667 6.96514 18.6667 7.33333V9.33333C18.6667 9.70152 18.9652 10 19.3334 10L21.8667 10C21.9403 10 22 10.0597 22 10.1333V12.6667C22 13.0349 22.2985 13.3333 22.6667 13.3333H24.6667C25.0349 13.3333 25.3334 13.0349 25.3334 12.6667V7.33333C25.3334 7.31032 25.3322 7.28758 25.3299 7.26517Z",
|
|
1219
|
+
fill: props.color
|
|
1220
|
+
}
|
|
1221
|
+
),
|
|
1222
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1223
|
+
Path,
|
|
1224
|
+
{
|
|
1225
|
+
d: "M22 21.8667C22 21.9403 21.9403 22 21.8667 22L19.3334 22C18.9652 22 18.6667 22.2985 18.6667 22.6667V24.6667C18.6667 25.0349 18.9652 25.3333 19.3334 25.3333L24.6667 25.3333C25.0349 25.3333 25.3334 25.0349 25.3334 24.6667V19.3333C25.3334 18.9651 25.0349 18.6667 24.6667 18.6667H22.6667C22.2985 18.6667 22 18.9651 22 19.3333V21.8667Z",
|
|
1226
|
+
fill: props.color
|
|
1227
|
+
}
|
|
1228
|
+
),
|
|
1229
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1230
|
+
Path,
|
|
1231
|
+
{
|
|
1232
|
+
d: "M12.6667 22H10.1334C10.0597 22 10 21.9403 10 21.8667V19.3333C10 18.9651 9.70154 18.6667 9.33335 18.6667H7.33335C6.96516 18.6667 6.66669 18.9651 6.66669 19.3333V24.6667C6.66669 25.0349 6.96516 25.3333 7.33335 25.3333H12.6667C13.0349 25.3333 13.3334 25.0349 13.3334 24.6667V22.6667C13.3334 22.2985 13.0349 22 12.6667 22Z",
|
|
1233
|
+
fill: props.color
|
|
1234
|
+
}
|
|
1235
|
+
),
|
|
1236
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1237
|
+
Path,
|
|
1238
|
+
{
|
|
1239
|
+
d: "M10 12.6667V10.1333C10 10.0597 10.0597 10 10.1334 10L12.6667 10C13.0349 10 13.3334 9.70152 13.3334 9.33333V7.33333C13.3334 6.96514 13.0349 6.66666 12.6667 6.66666H7.33335C6.96516 6.66666 6.66669 6.96514 6.66669 7.33333V12.6667C6.66669 13.0349 6.96516 13.3333 7.33335 13.3333H9.33335C9.70154 13.3333 10 13.0349 10 12.6667Z",
|
|
1240
|
+
fill: props.color
|
|
1241
|
+
}
|
|
1242
|
+
)
|
|
1243
|
+
] });
|
|
1244
|
+
}
|
|
1245
|
+
function EmbedMediaIconFullscreenExit(props) {
|
|
1246
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(IconShell, { size: props.size, children: [
|
|
1247
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1248
|
+
Path,
|
|
1249
|
+
{
|
|
1250
|
+
d: "M19.3334 13.3333C18.9652 13.3333 18.6667 13.0349 18.6667 12.6667L18.6667 7.33333C18.6667 6.96514 18.9652 6.66666 19.3334 6.66666H21.3334C21.7015 6.66666 22 6.96514 22 7.33333V9.86666C22 9.9403 22.0597 10 22.1334 10L24.6667 10C25.0349 10 25.3334 10.2985 25.3334 10.6667V12.6667C25.3334 13.0349 25.0349 13.3333 24.6667 13.3333L19.3334 13.3333Z",
|
|
1251
|
+
fill: props.color
|
|
1252
|
+
}
|
|
1253
|
+
),
|
|
1254
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1255
|
+
Path,
|
|
1256
|
+
{
|
|
1257
|
+
d: "M13.3334 19.3333C13.3334 18.9651 13.0349 18.6667 12.6667 18.6667H7.33335C6.96516 18.6667 6.66669 18.9651 6.66669 19.3333V21.3333C6.66669 21.7015 6.96516 22 7.33335 22H9.86669C9.94032 22 10 22.0597 10 22.1333L10 24.6667C10 25.0349 10.2985 25.3333 10.6667 25.3333H12.6667C13.0349 25.3333 13.3334 25.0349 13.3334 24.6667L13.3334 19.3333Z",
|
|
1258
|
+
fill: props.color
|
|
1259
|
+
}
|
|
1260
|
+
),
|
|
1261
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1262
|
+
Path,
|
|
1263
|
+
{
|
|
1264
|
+
d: "M18.6667 24.6667C18.6667 25.0349 18.9652 25.3333 19.3334 25.3333H21.3334C21.7015 25.3333 22 25.0349 22 24.6667V22.1333C22 22.0597 22.0597 22 22.1334 22H24.6667C25.0349 22 25.3334 21.7015 25.3334 21.3333V19.3333C25.3334 18.9651 25.0349 18.6667 24.6667 18.6667L19.3334 18.6667C18.9652 18.6667 18.6667 18.9651 18.6667 19.3333L18.6667 24.6667Z",
|
|
1265
|
+
fill: props.color
|
|
1266
|
+
}
|
|
1267
|
+
),
|
|
1268
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1269
|
+
Path,
|
|
1270
|
+
{
|
|
1271
|
+
d: "M10.6667 13.3333H12.6667C13.0349 13.3333 13.3334 13.0349 13.3334 12.6667L13.3334 10.6667V7.33333C13.3334 6.96514 13.0349 6.66666 12.6667 6.66666H10.6667C10.2985 6.66666 10 6.96514 10 7.33333L10 9.86666C10 9.9403 9.94033 10 9.86669 10L7.33335 10C6.96516 10 6.66669 10.2985 6.66669 10.6667V12.6667C6.66669 13.0349 6.96516 13.3333 7.33335 13.3333L10.6667 13.3333Z",
|
|
1272
|
+
fill: props.color
|
|
1273
|
+
}
|
|
1274
|
+
)
|
|
1275
|
+
] });
|
|
1276
|
+
}
|
|
1277
|
+
function EmbedMediaIconPictureInPicture(props) {
|
|
1278
|
+
const pixels = props.size ?? 22;
|
|
1279
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1280
|
+
jsx_native_bridge_default,
|
|
1281
|
+
{
|
|
1282
|
+
accessibilityElementsHidden: true,
|
|
1283
|
+
height: pixels,
|
|
1284
|
+
importantForAccessibility: "no",
|
|
1285
|
+
viewBox: "0 0 24 24",
|
|
1286
|
+
width: pixels,
|
|
1287
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1288
|
+
Path,
|
|
1289
|
+
{
|
|
1290
|
+
d: "M19 7h-8v6h8V7zm0-2c1.1 0 2 .9 2 2v6c0 1.1-.9 2-2 2h-8c-1.1 0-2-.9-2-2V7c0-1.1.9-2 2-2h8zM5 5v14h14v-2H7V5H5z",
|
|
1291
|
+
fill: props.color
|
|
1292
|
+
}
|
|
1293
|
+
)
|
|
1294
|
+
}
|
|
1295
|
+
);
|
|
1296
|
+
}
|
|
1297
|
+
function EmbedMediaIconCast(props) {
|
|
1298
|
+
const pixels = props.size ?? 22;
|
|
1299
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1300
|
+
jsx_native_bridge_default,
|
|
1301
|
+
{
|
|
1302
|
+
accessibilityElementsHidden: true,
|
|
1303
|
+
height: pixels,
|
|
1304
|
+
importantForAccessibility: "no",
|
|
1305
|
+
viewBox: "0 0 24 24",
|
|
1306
|
+
width: pixels,
|
|
1307
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1308
|
+
Path,
|
|
1309
|
+
{
|
|
1310
|
+
d: "M21 3H3c-1.1 0-2 .9-2 2v3h2V5h18v14h-7v2h7c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM1 18v3h3c0-1.66-1.34-3-3-3zm0-4v2c2.76 0 5 2.24 5 5h2c0-3.87-3.13-7-7-7zm0-4v2c4.97 0 9 4.03 9 9h2c0-6.08-4.93-11-11-11z",
|
|
1311
|
+
fill: props.color
|
|
1312
|
+
}
|
|
1313
|
+
)
|
|
1314
|
+
}
|
|
1315
|
+
);
|
|
1316
|
+
}
|
|
1317
|
+
function EmbedMediaIconCastConnected(props) {
|
|
1318
|
+
const pixels = props.size ?? 22;
|
|
1319
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1320
|
+
jsx_native_bridge_default,
|
|
1321
|
+
{
|
|
1322
|
+
accessibilityElementsHidden: true,
|
|
1323
|
+
height: pixels,
|
|
1324
|
+
importantForAccessibility: "no",
|
|
1325
|
+
viewBox: "0 0 24 24",
|
|
1326
|
+
width: pixels,
|
|
1327
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1328
|
+
Path,
|
|
1329
|
+
{
|
|
1330
|
+
d: "M1 18v3h3c0-1.66-1.34-3-3-3zm0-4v2c2.76 0 5 2.24 5 5h2c0-3.87-3.13-7-7-7zm18-7H5v1.63c3.96 1.28 7.09 4.41 8.37 8.37H19V7zM1 10v2c4.97 0 9 4.03 9 9h2c0-6.08-4.93-11-11-11zm20-7H3c-1.1 0-2 .9-2 2v3h2V5h18v14h-7v2h7c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z",
|
|
1331
|
+
fill: props.color
|
|
1332
|
+
}
|
|
1333
|
+
)
|
|
1334
|
+
}
|
|
1335
|
+
);
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
// src/lib/build-moviie-embed-brand-home-url.ts
|
|
1339
|
+
function buildMoviieEmbedBrandHomeUrl() {
|
|
1340
|
+
const url = new URL(`${MOVIIE_BRANDING_MARKETING_ORIGIN}/`);
|
|
1341
|
+
url.searchParams.set(MOVIIE_BRANDING_UTM_PARAM_SOURCE, MOVIIE_EMBED_BRAND_UTM.SOURCE);
|
|
1342
|
+
url.searchParams.set(MOVIIE_BRANDING_UTM_PARAM_MEDIUM, MOVIIE_EMBED_BRAND_UTM.MEDIUM);
|
|
1343
|
+
url.searchParams.set(MOVIIE_BRANDING_UTM_PARAM_CAMPAIGN, MOVIIE_EMBED_BRAND_UTM.CAMPAIGN);
|
|
1344
|
+
return url.toString();
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
// src/lib/resolve-moviie-skin-layout-scale.ts
|
|
1348
|
+
function clampBetween(value, min, max) {
|
|
1349
|
+
return Math.min(Math.max(value, min), max);
|
|
1350
|
+
}
|
|
1351
|
+
function resolveMoviieSkinLayoutScale(windowWidth) {
|
|
1352
|
+
if (!Number.isFinite(windowWidth) || windowWidth <= 0) {
|
|
1353
|
+
return 1;
|
|
1354
|
+
}
|
|
1355
|
+
const raw = windowWidth / MOVIIE_SKIN_LAYOUT_REFERENCE_WIDTH_PT;
|
|
1356
|
+
return clampBetween(raw, MOVIIE_SKIN_LAYOUT_SCALE_MIN, MOVIIE_SKIN_LAYOUT_SCALE_MAX);
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
// src/lib/build-moviie-skin-layout-metrics.ts
|
|
1360
|
+
function scaleSkinLayoutDp(layoutScale, baseAtReference) {
|
|
1361
|
+
return baseAtReference * layoutScale;
|
|
1362
|
+
}
|
|
1363
|
+
function buildMoviieSkinLayoutMetrics(windowWidth, options) {
|
|
1364
|
+
const layoutScale = resolveMoviieSkinLayoutScale(windowWidth);
|
|
1365
|
+
const brandMarkWidthPx = scaleSkinLayoutDp(
|
|
1366
|
+
layoutScale,
|
|
1367
|
+
MOVIIE_SKIN_BRAND_MARK_TARGET_WIDTH_AT_REFERENCE_PT
|
|
1368
|
+
);
|
|
1369
|
+
const brandMarkHeightPx = brandMarkWidthPx * (MOVIIE_SKIN_BRAND_MARK_ARTBOARD_HEIGHT_PX / MOVIIE_SKIN_BRAND_MARK_ARTBOARD_WIDTH_PX);
|
|
1370
|
+
const timelineThumbDiameterPx = scaleSkinLayoutDp(
|
|
1371
|
+
layoutScale,
|
|
1372
|
+
MOVIIE_SKIN_TIMELINE_THUMB_DIAMETER_PX
|
|
1373
|
+
);
|
|
1374
|
+
const timelineBarHeightPx = scaleSkinLayoutDp(layoutScale, MOVIIE_SKIN_TIMELINE_BAR_HEIGHT_PX);
|
|
1375
|
+
const timelineThumbBottomInsetPx = timelineBarHeightPx / 2 - timelineThumbDiameterPx / 2;
|
|
1376
|
+
const timelineTouchPaddingVerticalPx = scaleSkinLayoutDp(
|
|
1377
|
+
layoutScale,
|
|
1378
|
+
MOVIIE_SKIN_TIMELINE_TOUCH_PADDING_VERTICAL_PX
|
|
1379
|
+
);
|
|
1380
|
+
const fullscreenHudBoostPx = options?.fullscreenHudProtection === true ? scaleSkinLayoutDp(layoutScale, MOVIIE_SKIN_CUSTOM_FULLSCREEN_HUD_EDGE_BOOST_REFERENCE_PT) : 0;
|
|
1381
|
+
const hudEdgeInsetPx = scaleSkinLayoutDp(layoutScale, MOVIIE_SKIN_FLOATING_HUD_EDGE_INSET_PX) + fullscreenHudBoostPx;
|
|
1382
|
+
return {
|
|
1383
|
+
layoutScale,
|
|
1384
|
+
brandMarkWidthPx,
|
|
1385
|
+
brandMarkHeightPx,
|
|
1386
|
+
hudEdgeInsetPx,
|
|
1387
|
+
floatingHudAboveTimelineGapPx: scaleSkinLayoutDp(
|
|
1388
|
+
layoutScale,
|
|
1389
|
+
MOVIIE_SKIN_FLOATING_HUD_ABOVE_TIMELINE_GAP_AT_REFERENCE_PT
|
|
1390
|
+
),
|
|
1391
|
+
hudClockCornerRadiusPx: scaleSkinLayoutDp(
|
|
1392
|
+
layoutScale,
|
|
1393
|
+
MOVIIE_SKIN_FLOATING_HUD_CLOCK_CORNER_RADIUS_PX
|
|
1394
|
+
),
|
|
1395
|
+
controlIconPx: scaleSkinLayoutDp(layoutScale, MOVIIE_SKIN_CONTROL_ICON_PX),
|
|
1396
|
+
seekIconPx: scaleSkinLayoutDp(layoutScale, MOVIIE_SKIN_SEEK_ICON_PX),
|
|
1397
|
+
seekScrimOuterDiameterPx: scaleSkinLayoutDp(
|
|
1398
|
+
layoutScale,
|
|
1399
|
+
MOVIIE_SKIN_CENTER_SEEK_SCRIM_DIAMETER_AT_REFERENCE_PT
|
|
1400
|
+
),
|
|
1401
|
+
centerPlayIconPx: scaleSkinLayoutDp(layoutScale, MOVIIE_SKIN_CENTER_PLAY_ICON_PX),
|
|
1402
|
+
centerClusterColumnGapPx: scaleSkinLayoutDp(
|
|
1403
|
+
layoutScale,
|
|
1404
|
+
MOVIIE_SKIN_CENTER_CLUSTER_COLUMN_GAP_PX
|
|
1405
|
+
),
|
|
1406
|
+
playScrimOuterDiameterPx: scaleSkinLayoutDp(
|
|
1407
|
+
layoutScale,
|
|
1408
|
+
MOVIIE_SKIN_CENTER_PLAY_SCRIM_DIAMETER_AT_REFERENCE_PT
|
|
1409
|
+
),
|
|
1410
|
+
clockTextFontSizePx: scaleSkinLayoutDp(
|
|
1411
|
+
layoutScale,
|
|
1412
|
+
MOVIIE_SKIN_CLOCK_TEXT_FONT_SIZE_AT_REFERENCE_PT
|
|
1413
|
+
),
|
|
1414
|
+
timelineThumbDiameterPx,
|
|
1415
|
+
timelineTouchPaddingVerticalPx,
|
|
1416
|
+
timelineBarHeightPx,
|
|
1417
|
+
timelineThumbBottomInsetPx,
|
|
1418
|
+
timelineStackHeightChromeVisiblePx: timelineTouchPaddingVerticalPx + timelineThumbDiameterPx,
|
|
1419
|
+
bufferingIndicatorSlotPx: scaleSkinLayoutDp(
|
|
1420
|
+
layoutScale,
|
|
1421
|
+
MOVIIE_SKIN_BUFFERING_INDICATOR_SLOT_PX
|
|
1422
|
+
),
|
|
1423
|
+
chromeEdgeGradientHeightPx: scaleSkinLayoutDp(
|
|
1424
|
+
layoutScale,
|
|
1425
|
+
MOVIIE_SKIN_CHROME_EDGE_GRADIENT_HEIGHT_AT_REFERENCE_PT
|
|
1426
|
+
),
|
|
1427
|
+
floatingHudFullscreenScrimDiameterPx: scaleSkinLayoutDp(
|
|
1428
|
+
layoutScale,
|
|
1429
|
+
MOVIIE_SKIN_FLOATING_FULLSCREEN_SCRIM_DIAMETER_AT_REFERENCE_PT
|
|
1430
|
+
),
|
|
1431
|
+
floatingHudFullscreenIconPx: scaleSkinLayoutDp(
|
|
1432
|
+
layoutScale,
|
|
1433
|
+
MOVIIE_SKIN_FLOATING_FULLSCREEN_ICON_AT_REFERENCE_PT
|
|
1434
|
+
),
|
|
1435
|
+
floatingHudFullscreenTopIconPx: scaleSkinLayoutDp(
|
|
1436
|
+
layoutScale,
|
|
1437
|
+
MOVIIE_SKIN_FLOATING_FULLSCREEN_TOP_ICON_AT_REFERENCE_PT
|
|
1438
|
+
),
|
|
1439
|
+
floatingHudButtonGapPx: scaleSkinLayoutDp(
|
|
1440
|
+
layoutScale,
|
|
1441
|
+
MOVIIE_SKIN_FLOATING_HUD_BUTTON_GAP_AT_REFERENCE_PT
|
|
1442
|
+
)
|
|
1443
|
+
};
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1446
|
+
// src/lib/compute-playback-buffering.ts
|
|
1447
|
+
var PLAYER_STATUS_LOADING = "loading";
|
|
1448
|
+
function computePlaybackBuffering(state) {
|
|
1449
|
+
if (computeMoviiePlaybackEnded({
|
|
1450
|
+
playing: state.playing,
|
|
1451
|
+
currentTime: state.currentTime,
|
|
1452
|
+
duration: state.duration,
|
|
1453
|
+
isLive: state.isLive,
|
|
1454
|
+
loop: state.loop
|
|
1455
|
+
})) {
|
|
1456
|
+
return false;
|
|
1457
|
+
}
|
|
1458
|
+
if (state.status === PLAYER_STATUS_LOADING) {
|
|
1459
|
+
return true;
|
|
1460
|
+
}
|
|
1461
|
+
if (state.playing && Number.isFinite(state.duration) && state.duration > 0 && state.bufferedPosition >= 0 && state.currentTime > 0.08 && state.bufferedPosition < state.currentTime + MOVIIE_SKIN_BUFFER_UNDERRUN_LEAD_SECONDS) {
|
|
1462
|
+
return true;
|
|
1463
|
+
}
|
|
1464
|
+
return false;
|
|
1465
|
+
}
|
|
1466
|
+
function usePlaybackUiSync(player) {
|
|
1467
|
+
const [snapshot, setSnapshot] = React.useState({
|
|
1468
|
+
bufferedPosition: player.bufferedPosition,
|
|
1469
|
+
currentTime: player.currentTime,
|
|
1470
|
+
duration: player.duration,
|
|
1471
|
+
playing: player.playing,
|
|
1472
|
+
status: player.status
|
|
1473
|
+
});
|
|
1474
|
+
React.useEffect(() => {
|
|
1475
|
+
const subscriptions = [
|
|
1476
|
+
player.addListener("timeUpdate", ({ currentTime }) => {
|
|
1477
|
+
setSnapshot((previous) => ({
|
|
1478
|
+
...previous,
|
|
1479
|
+
bufferedPosition: player.bufferedPosition,
|
|
1480
|
+
currentTime,
|
|
1481
|
+
duration: player.duration,
|
|
1482
|
+
status: player.status
|
|
1483
|
+
}));
|
|
1484
|
+
}),
|
|
1485
|
+
player.addListener("playingChange", ({ isPlaying }) => {
|
|
1486
|
+
setSnapshot((previous) => ({
|
|
1487
|
+
...previous,
|
|
1488
|
+
playing: isPlaying,
|
|
1489
|
+
bufferedPosition: player.bufferedPosition,
|
|
1490
|
+
status: player.status
|
|
1491
|
+
}));
|
|
1492
|
+
}),
|
|
1493
|
+
player.addListener("sourceChange", () => {
|
|
1494
|
+
setSnapshot({
|
|
1495
|
+
bufferedPosition: player.bufferedPosition,
|
|
1496
|
+
currentTime: player.currentTime,
|
|
1497
|
+
duration: player.duration,
|
|
1498
|
+
playing: player.playing,
|
|
1499
|
+
status: player.status
|
|
1500
|
+
});
|
|
1501
|
+
}),
|
|
1502
|
+
player.addListener("statusChange", ({ status }) => {
|
|
1503
|
+
setSnapshot((previous) => ({
|
|
1504
|
+
...previous,
|
|
1505
|
+
bufferedPosition: player.bufferedPosition,
|
|
1506
|
+
status
|
|
1507
|
+
}));
|
|
1508
|
+
}),
|
|
1509
|
+
player.addListener("playToEnd", () => {
|
|
1510
|
+
setSnapshot((previous) => ({
|
|
1511
|
+
...previous,
|
|
1512
|
+
playing: false,
|
|
1513
|
+
bufferedPosition: player.bufferedPosition,
|
|
1514
|
+
currentTime: player.currentTime,
|
|
1515
|
+
duration: player.duration,
|
|
1516
|
+
status: player.status
|
|
1517
|
+
}));
|
|
1518
|
+
})
|
|
1519
|
+
];
|
|
1520
|
+
return () => {
|
|
1521
|
+
for (const sub of subscriptions) {
|
|
1522
|
+
sub.remove();
|
|
1523
|
+
}
|
|
1524
|
+
};
|
|
1525
|
+
}, [player]);
|
|
1526
|
+
return snapshot;
|
|
1527
|
+
}
|
|
1528
|
+
var MoviieSkinChromeContext = React.createContext(
|
|
1529
|
+
null
|
|
1530
|
+
);
|
|
1531
|
+
function useMoviieSkinChrome() {
|
|
1532
|
+
const ctx = React.useContext(MoviieSkinChromeContext);
|
|
1533
|
+
if (ctx == null) {
|
|
1534
|
+
throw new Error("useMoviieSkinChrome must be used within MoviieSkinChromeProvider");
|
|
1535
|
+
}
|
|
1536
|
+
return ctx;
|
|
1537
|
+
}
|
|
1538
|
+
function MoviieSkinChromeProvider({
|
|
1539
|
+
children,
|
|
1540
|
+
player,
|
|
1541
|
+
playback,
|
|
1542
|
+
videoViewRef,
|
|
1543
|
+
customFullscreen = false,
|
|
1544
|
+
skinLayoutMetricsWidth,
|
|
1545
|
+
onRequestEnterCustomFullscreen,
|
|
1546
|
+
onRequestExitCustomFullscreenAnimated,
|
|
1547
|
+
autoHideMs: _unusedAutoHideMs,
|
|
1548
|
+
visibleByDefault = true,
|
|
1549
|
+
pictureInPictureControlEnabled = false,
|
|
1550
|
+
pictureInPictureActive = false,
|
|
1551
|
+
togglePictureInPicture: togglePictureInPictureProp,
|
|
1552
|
+
castControlEnabled = false,
|
|
1553
|
+
castConnected = false,
|
|
1554
|
+
openCastPicker: openCastPickerProp
|
|
1555
|
+
}) {
|
|
1556
|
+
const noopPictureInPicture = React.useCallback(() => {
|
|
1557
|
+
}, []);
|
|
1558
|
+
const togglePictureInPicture = togglePictureInPictureProp ?? noopPictureInPicture;
|
|
1559
|
+
const noopOpenCastPicker = React.useCallback(() => {
|
|
1560
|
+
}, []);
|
|
1561
|
+
const openCastPicker = openCastPickerProp ?? noopOpenCastPicker;
|
|
1562
|
+
const { width: windowWidth } = reactNative.useWindowDimensions();
|
|
1563
|
+
const layoutBasisWidth = skinLayoutMetricsWidth ?? windowWidth;
|
|
1564
|
+
const layout = React.useMemo(
|
|
1565
|
+
() => buildMoviieSkinLayoutMetrics(layoutBasisWidth, {
|
|
1566
|
+
fullscreenHudProtection: customFullscreen
|
|
1567
|
+
}),
|
|
1568
|
+
[customFullscreen, layoutBasisWidth]
|
|
1569
|
+
);
|
|
1570
|
+
const ui = usePlaybackUiSync(player);
|
|
1571
|
+
const [chromeVisible, setChromeVisible] = React.useState(visibleByDefault);
|
|
1572
|
+
const [timelineScrubClockSeconds, setTimelineScrubClockSeconds] = React.useState(null);
|
|
1573
|
+
const playbackEndedForChrome = React.useMemo(
|
|
1574
|
+
() => computeMoviiePlaybackEnded({
|
|
1575
|
+
playing: ui.playing,
|
|
1576
|
+
currentTime: ui.currentTime,
|
|
1577
|
+
duration: ui.duration,
|
|
1578
|
+
isLive: player.isLive,
|
|
1579
|
+
loop: player.loop
|
|
1580
|
+
}),
|
|
1581
|
+
[ui.playing, ui.currentTime, ui.duration, player.isLive, player.loop]
|
|
1582
|
+
);
|
|
1583
|
+
React.useEffect(() => {
|
|
1584
|
+
if (playbackEndedForChrome) {
|
|
1585
|
+
setChromeVisible(true);
|
|
1586
|
+
}
|
|
1587
|
+
}, [playbackEndedForChrome]);
|
|
1588
|
+
const chromeOpacity = React.useRef(new reactNative.Animated.Value(visibleByDefault ? 1 : 0)).current;
|
|
1589
|
+
React.useEffect(() => {
|
|
1590
|
+
reactNative.Animated.timing(chromeOpacity, {
|
|
1591
|
+
duration: MOVIIE_SKIN_CONTROLS_FADE_MS,
|
|
1592
|
+
easing: reactNative.Easing.out(reactNative.Easing.quad),
|
|
1593
|
+
toValue: chromeVisible ? 1 : 0,
|
|
1594
|
+
useNativeDriver: true
|
|
1595
|
+
}).start();
|
|
1596
|
+
}, [chromeOpacity, chromeVisible]);
|
|
1597
|
+
const bumpChromeInteraction = React.useCallback(() => {
|
|
1598
|
+
setChromeVisible(true);
|
|
1599
|
+
}, []);
|
|
1600
|
+
const dismissChrome = React.useCallback(() => {
|
|
1601
|
+
setChromeVisible(false);
|
|
1602
|
+
}, []);
|
|
1603
|
+
const togglePlay = React.useCallback(() => {
|
|
1604
|
+
if (player.playing) {
|
|
1605
|
+
player.pause();
|
|
1606
|
+
return;
|
|
1607
|
+
}
|
|
1608
|
+
if (computeMoviiePlaybackEnded({
|
|
1609
|
+
playing: false,
|
|
1610
|
+
currentTime: player.currentTime,
|
|
1611
|
+
duration: player.duration,
|
|
1612
|
+
isLive: player.isLive,
|
|
1613
|
+
loop: player.loop
|
|
1614
|
+
})) {
|
|
1615
|
+
player.currentTime = 0;
|
|
1616
|
+
}
|
|
1617
|
+
player.play();
|
|
1618
|
+
setChromeVisible(false);
|
|
1619
|
+
}, [player]);
|
|
1620
|
+
const seekBack = React.useCallback(() => {
|
|
1621
|
+
void player.seekBy(-MOVIIE_SKIN_SEEK_JUMP_SECONDS);
|
|
1622
|
+
setChromeVisible(false);
|
|
1623
|
+
}, [player]);
|
|
1624
|
+
const seekForward = React.useCallback(() => {
|
|
1625
|
+
void player.seekBy(MOVIIE_SKIN_SEEK_JUMP_SECONDS);
|
|
1626
|
+
setChromeVisible(false);
|
|
1627
|
+
}, [player]);
|
|
1628
|
+
const toggleFullscreen = React.useCallback(() => {
|
|
1629
|
+
if (customFullscreen) {
|
|
1630
|
+
onRequestExitCustomFullscreenAnimated?.();
|
|
1631
|
+
return;
|
|
1632
|
+
}
|
|
1633
|
+
setChromeVisible(false);
|
|
1634
|
+
if (onRequestEnterCustomFullscreen != null) {
|
|
1635
|
+
onRequestEnterCustomFullscreen();
|
|
1636
|
+
return;
|
|
1637
|
+
}
|
|
1638
|
+
void videoViewRef.current?.enterFullscreen?.().catch(() => void 0);
|
|
1639
|
+
}, [
|
|
1640
|
+
customFullscreen,
|
|
1641
|
+
onRequestEnterCustomFullscreen,
|
|
1642
|
+
onRequestExitCustomFullscreenAnimated,
|
|
1643
|
+
videoViewRef
|
|
1644
|
+
]);
|
|
1645
|
+
const isBuffering = React.useMemo(
|
|
1646
|
+
() => computePlaybackBuffering({
|
|
1647
|
+
...ui,
|
|
1648
|
+
isLive: player.isLive,
|
|
1649
|
+
loop: player.loop
|
|
1650
|
+
}),
|
|
1651
|
+
[ui, player.isLive, player.loop]
|
|
1652
|
+
);
|
|
1653
|
+
const value = React.useMemo(
|
|
1654
|
+
() => ({
|
|
1655
|
+
playback,
|
|
1656
|
+
player,
|
|
1657
|
+
videoViewRef,
|
|
1658
|
+
chromeVisible,
|
|
1659
|
+
chromeOpacity,
|
|
1660
|
+
timelineScrubClockSeconds,
|
|
1661
|
+
setTimelineScrubClockSeconds,
|
|
1662
|
+
bumpChromeInteraction,
|
|
1663
|
+
dismissChrome,
|
|
1664
|
+
ui,
|
|
1665
|
+
isBuffering,
|
|
1666
|
+
layout,
|
|
1667
|
+
togglePlay,
|
|
1668
|
+
seekBack,
|
|
1669
|
+
seekForward,
|
|
1670
|
+
toggleFullscreen,
|
|
1671
|
+
isCustomFullscreen: customFullscreen,
|
|
1672
|
+
pictureInPictureActive,
|
|
1673
|
+
pictureInPictureControlEnabled,
|
|
1674
|
+
togglePictureInPicture,
|
|
1675
|
+
castControlEnabled,
|
|
1676
|
+
castConnected,
|
|
1677
|
+
openCastPicker
|
|
1678
|
+
}),
|
|
1679
|
+
[
|
|
1680
|
+
playback,
|
|
1681
|
+
player,
|
|
1682
|
+
videoViewRef,
|
|
1683
|
+
chromeVisible,
|
|
1684
|
+
chromeOpacity,
|
|
1685
|
+
timelineScrubClockSeconds,
|
|
1686
|
+
setTimelineScrubClockSeconds,
|
|
1687
|
+
bumpChromeInteraction,
|
|
1688
|
+
dismissChrome,
|
|
1689
|
+
ui,
|
|
1690
|
+
isBuffering,
|
|
1691
|
+
layout,
|
|
1692
|
+
togglePlay,
|
|
1693
|
+
seekBack,
|
|
1694
|
+
seekForward,
|
|
1695
|
+
toggleFullscreen,
|
|
1696
|
+
customFullscreen,
|
|
1697
|
+
pictureInPictureActive,
|
|
1698
|
+
pictureInPictureControlEnabled,
|
|
1699
|
+
togglePictureInPicture,
|
|
1700
|
+
castControlEnabled,
|
|
1701
|
+
castConnected,
|
|
1702
|
+
openCastPicker
|
|
1703
|
+
]
|
|
1704
|
+
);
|
|
1705
|
+
return /* @__PURE__ */ jsxRuntime.jsx(MoviieSkinChromeContext.Provider, { value, children });
|
|
1706
|
+
}
|
|
1707
|
+
function MoviieEmbedBrandMark() {
|
|
1708
|
+
const { layout } = useMoviieSkinChrome();
|
|
1709
|
+
const fg = MOVIIE_SKIN_CHROME_FOREGROUND_HEX;
|
|
1710
|
+
const openMarketingSite = React.useCallback(() => {
|
|
1711
|
+
void reactNative.Linking.openURL(buildMoviieEmbedBrandHomeUrl());
|
|
1712
|
+
}, []);
|
|
1713
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1714
|
+
reactNative.Pressable,
|
|
1715
|
+
{
|
|
1716
|
+
accessibilityHint: "Abre o site da Moviie no navegador",
|
|
1717
|
+
accessibilityLabel: "Moviie \u2014 p\xE1gina inicial",
|
|
1718
|
+
accessibilityRole: "link",
|
|
1719
|
+
hitSlop: MOVIIE_SKIN_FLOATING_HUD_TRAILING_HIT_SLOP_PX,
|
|
1720
|
+
onPress: openMarketingSite,
|
|
1721
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1722
|
+
jsx_native_bridge_default,
|
|
1723
|
+
{
|
|
1724
|
+
accessibilityElementsHidden: true,
|
|
1725
|
+
height: layout.brandMarkHeightPx,
|
|
1726
|
+
importantForAccessibility: "no",
|
|
1727
|
+
viewBox: MOVIIE_EMBED_BRAND_VIEW_BOX,
|
|
1728
|
+
width: layout.brandMarkWidthPx,
|
|
1729
|
+
children: [
|
|
1730
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1731
|
+
Path,
|
|
1732
|
+
{
|
|
1733
|
+
d: "M6.066 43.725H0V0h6.066L21.8 36.77 37.533 0h6.192v43.725H37.66V26.43c0-8.165.063-11.128.38-14.212L24.706 43.725h-5.813L5.623 12.337c.317 2.117.443 6.593.443 12.7z",
|
|
1734
|
+
fill: fg
|
|
1735
|
+
}
|
|
1736
|
+
),
|
|
1737
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1738
|
+
Path,
|
|
1739
|
+
{
|
|
1740
|
+
d: "M47.527 29.467c0-9.494 6.454-16.16 15.239-16.16 8.725 0 15.179 6.666 15.179 16.16s-6.454 16.16-15.179 16.16c-8.785 0-15.239-6.666-15.239-16.16m5.678 0c0 6.413 3.884 10.878 9.561 10.878 5.617 0 9.562-4.465 9.562-10.878S68.383 18.59 62.766 18.59c-5.677 0-9.561 4.465-9.561 10.878M159.227 45.626c-8.737 0-14.744-6.526-14.744-16.065 0-9.601 5.886-16.253 14.501-16.253 8.434 0 13.955 6.024 13.955 15.124v2.196l-22.934.063c.424 6.464 3.701 10.04 9.343 10.04 4.43 0 7.342-1.882 8.313-5.396H173c-1.456 6.589-6.431 10.291-13.773 10.291m-.243-27.36c-4.975 0-8.13 3.074-8.858 8.471h17.11c0-5.083-3.216-8.472-8.252-8.472",
|
|
1741
|
+
fill: fg
|
|
1742
|
+
}
|
|
1743
|
+
),
|
|
1744
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1745
|
+
Path,
|
|
1746
|
+
{
|
|
1747
|
+
d: "m140.681 15.209-12.313 28.516h-4.794l12.313-28.516zm-14.384 0-12.312 28.516h-4.811l12.313-28.516zm-39.363 0 6.553 16.138c1.06 2.768 1.927 5.221 2.42 7.006l.944-.007c.49-1.892 1.476-4.393 2.539-6.988l6.68-16.15h5.054L98.799 43.726h-5.15L81.747 15.21z",
|
|
1748
|
+
fill: "none",
|
|
1749
|
+
stroke: fg,
|
|
1750
|
+
strokeLinejoin: "bevel",
|
|
1751
|
+
strokeWidth: MOVIIE_EMBED_BRAND_LETTERMARK_STROKE_WIDTH
|
|
1752
|
+
}
|
|
1753
|
+
)
|
|
1754
|
+
]
|
|
1755
|
+
}
|
|
1756
|
+
)
|
|
1757
|
+
}
|
|
1758
|
+
);
|
|
1759
|
+
}
|
|
1760
|
+
function pressOpacity(pressed) {
|
|
1761
|
+
return {
|
|
1762
|
+
opacity: pressed ? MOVIIE_SKIN_CHROME_CONTROL_PRESSED_OPACITY : MOVIIE_SKIN_CHROME_CONTROL_REST_OPACITY
|
|
1763
|
+
};
|
|
1764
|
+
}
|
|
1765
|
+
function ScrimPad(props) {
|
|
1766
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1767
|
+
reactNative.Pressable,
|
|
1768
|
+
{
|
|
1769
|
+
accessibilityLabel: props.accessibilityLabel,
|
|
1770
|
+
accessibilityRole: "button",
|
|
1771
|
+
accessibilityState: { selected: props.selected },
|
|
1772
|
+
hitSlop: props.hitSlop,
|
|
1773
|
+
onPress: props.onPress,
|
|
1774
|
+
style: (state) => [props.chromeScrimBaseStyle, props.style, pressOpacity(state.pressed)],
|
|
1775
|
+
children: props.children
|
|
1776
|
+
}
|
|
1777
|
+
);
|
|
1778
|
+
}
|
|
1779
|
+
function MoviieSkinCastCircleButton(props) {
|
|
1780
|
+
const Icon = props.castConnected ? EmbedMediaIconCastConnected : EmbedMediaIconCast;
|
|
1781
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1782
|
+
ScrimPad,
|
|
1783
|
+
{
|
|
1784
|
+
accessibilityLabel: props.castConnected ? "Encerrar transmiss\xE3o" : "Transmitir",
|
|
1785
|
+
chromeScrimBaseStyle: props.chromeScrimBaseStyle,
|
|
1786
|
+
hitSlop: MOVIIE_SKIN_FLOATING_HUD_TRAILING_HIT_SLOP_PX,
|
|
1787
|
+
onPress: props.onPress,
|
|
1788
|
+
selected: props.castConnected,
|
|
1789
|
+
style: props.circleScrimStyle,
|
|
1790
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1791
|
+
Icon,
|
|
1792
|
+
{
|
|
1793
|
+
color: MOVIIE_SKIN_CHROME_FOREGROUND_HEX,
|
|
1794
|
+
size: props.layout.floatingHudFullscreenIconPx
|
|
1795
|
+
}
|
|
1796
|
+
)
|
|
1797
|
+
}
|
|
1798
|
+
);
|
|
1799
|
+
}
|
|
1800
|
+
function MoviieSkinCastTopBareButton(props) {
|
|
1801
|
+
const Icon = props.castConnected ? EmbedMediaIconCastConnected : EmbedMediaIconCast;
|
|
1802
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1803
|
+
reactNative.Pressable,
|
|
1804
|
+
{
|
|
1805
|
+
accessibilityLabel: props.castConnected ? "Encerrar transmiss\xE3o" : "Transmitir",
|
|
1806
|
+
accessibilityRole: "button",
|
|
1807
|
+
accessibilityState: { selected: props.castConnected },
|
|
1808
|
+
hitSlop: MOVIIE_SKIN_FLOATING_HUD_TRAILING_HIT_SLOP_PX,
|
|
1809
|
+
onPress: props.onPress,
|
|
1810
|
+
style: (state) => pressOpacity(state.pressed),
|
|
1811
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1812
|
+
Icon,
|
|
1813
|
+
{
|
|
1814
|
+
color: MOVIIE_SKIN_CHROME_FOREGROUND_HEX,
|
|
1815
|
+
size: props.layout.floatingHudFullscreenTopIconPx * MOVIIE_SKIN_TOP_ICON_CAST_VISUAL_SCALE
|
|
1816
|
+
}
|
|
1817
|
+
) })
|
|
1818
|
+
}
|
|
1819
|
+
);
|
|
1820
|
+
}
|
|
1821
|
+
function MoviieSkinChromeEdgeGradients(props) {
|
|
1822
|
+
const [hostWidth, setHostWidth] = React.useState(0);
|
|
1823
|
+
const [hostHeight, setHostHeight] = React.useState(0);
|
|
1824
|
+
const onHostLayout = React.useCallback((event) => {
|
|
1825
|
+
const { height, width } = event.nativeEvent.layout;
|
|
1826
|
+
setHostWidth(width);
|
|
1827
|
+
setHostHeight(height);
|
|
1828
|
+
}, []);
|
|
1829
|
+
const rawTopPx = props.layout.chromeEdgeGradientHeightPx;
|
|
1830
|
+
const rawBottomPx = props.layout.chromeEdgeGradientHeightPx + (props.showProgress ? props.layout.timelineStackHeightChromeVisiblePx : 0);
|
|
1831
|
+
const { effBottomPx, effTopPx, svgWidthPx } = React.useMemo(() => {
|
|
1832
|
+
if (hostWidth <= 0 || hostHeight <= 0) {
|
|
1833
|
+
return { effBottomPx: 0, effTopPx: 0, svgWidthPx: 0 };
|
|
1834
|
+
}
|
|
1835
|
+
const svgWidthPx2 = hostWidth;
|
|
1836
|
+
const maxTotalPx = Math.max(
|
|
1837
|
+
0,
|
|
1838
|
+
hostHeight - MOVIIE_SKIN_CHROME_EDGE_GRADIENT_MIN_CLEAR_MIDDLE_PX
|
|
1839
|
+
);
|
|
1840
|
+
const rawSum = rawTopPx + rawBottomPx;
|
|
1841
|
+
const scale = rawSum > maxTotalPx && maxTotalPx > 0 && rawSum > 0 ? maxTotalPx / rawSum : 1;
|
|
1842
|
+
return {
|
|
1843
|
+
effBottomPx: rawBottomPx * scale,
|
|
1844
|
+
effTopPx: rawTopPx * scale,
|
|
1845
|
+
svgWidthPx: svgWidthPx2
|
|
1846
|
+
};
|
|
1847
|
+
}, [hostHeight, hostWidth, rawBottomPx, rawTopPx]);
|
|
1848
|
+
const topFillUrl = `url(#${MOVIIE_SKIN_CHROME_SVG_GRADIENT_TOP_EDGE_ID})`;
|
|
1849
|
+
const bottomFillUrl = `url(#${MOVIIE_SKIN_CHROME_SVG_GRADIENT_BOTTOM_EDGE_ID})`;
|
|
1850
|
+
const layoutReady = hostWidth > 0 && hostHeight > 0 && svgWidthPx > 0;
|
|
1851
|
+
const fadeEndOffset = String(MOVIIE_SKIN_CHROME_EDGE_GRADIENT_EDGE_SOLID_FADE_END_FRACTION);
|
|
1852
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1853
|
+
reactNative.View,
|
|
1854
|
+
{
|
|
1855
|
+
accessibilityElementsHidden: true,
|
|
1856
|
+
importantForAccessibility: "no-hide-descendants",
|
|
1857
|
+
onLayout: onHostLayout,
|
|
1858
|
+
pointerEvents: "none",
|
|
1859
|
+
style: reactNative.StyleSheet.absoluteFillObject,
|
|
1860
|
+
testID: "moviie-chrome-edge-gradients",
|
|
1861
|
+
children: [
|
|
1862
|
+
layoutReady && effTopPx > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1863
|
+
reactNative.View,
|
|
1864
|
+
{
|
|
1865
|
+
accessibilityElementsHidden: true,
|
|
1866
|
+
importantForAccessibility: "no-hide-descendants",
|
|
1867
|
+
pointerEvents: "none",
|
|
1868
|
+
style: {
|
|
1869
|
+
height: effTopPx,
|
|
1870
|
+
left: 0,
|
|
1871
|
+
overflow: "hidden",
|
|
1872
|
+
position: "absolute",
|
|
1873
|
+
top: 0,
|
|
1874
|
+
width: hostWidth
|
|
1875
|
+
},
|
|
1876
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(jsx_native_bridge_default, { accessibilityElementsHidden: true, height: effTopPx, width: svgWidthPx, children: [
|
|
1877
|
+
/* @__PURE__ */ jsxRuntime.jsx(Defs, { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1878
|
+
LinearGradient,
|
|
1879
|
+
{
|
|
1880
|
+
gradientUnits: "objectBoundingBox",
|
|
1881
|
+
id: MOVIIE_SKIN_CHROME_SVG_GRADIENT_TOP_EDGE_ID,
|
|
1882
|
+
x1: "0",
|
|
1883
|
+
x2: "0",
|
|
1884
|
+
y1: "0",
|
|
1885
|
+
y2: "1",
|
|
1886
|
+
children: [
|
|
1887
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1888
|
+
Stop,
|
|
1889
|
+
{
|
|
1890
|
+
offset: "0",
|
|
1891
|
+
stopColor: MOVIIE_SKIN_CHROME_GRADIENT_BLACK_HEX,
|
|
1892
|
+
stopOpacity: MOVIIE_SKIN_CHROME_GRADIENT_EDGE_ALPHA
|
|
1893
|
+
}
|
|
1894
|
+
),
|
|
1895
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1896
|
+
Stop,
|
|
1897
|
+
{
|
|
1898
|
+
offset: fadeEndOffset,
|
|
1899
|
+
stopColor: MOVIIE_SKIN_CHROME_GRADIENT_BLACK_HEX,
|
|
1900
|
+
stopOpacity: 0
|
|
1901
|
+
}
|
|
1902
|
+
),
|
|
1903
|
+
/* @__PURE__ */ jsxRuntime.jsx(Stop, { offset: "1", stopColor: MOVIIE_SKIN_CHROME_GRADIENT_BLACK_HEX, stopOpacity: 0 })
|
|
1904
|
+
]
|
|
1905
|
+
}
|
|
1906
|
+
) }),
|
|
1907
|
+
/* @__PURE__ */ jsxRuntime.jsx(Rect, { fill: topFillUrl, height: effTopPx, width: svgWidthPx })
|
|
1908
|
+
] })
|
|
1909
|
+
}
|
|
1910
|
+
) : null,
|
|
1911
|
+
layoutReady && effBottomPx > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1912
|
+
reactNative.View,
|
|
1913
|
+
{
|
|
1914
|
+
accessibilityElementsHidden: true,
|
|
1915
|
+
importantForAccessibility: "no-hide-descendants",
|
|
1916
|
+
pointerEvents: "none",
|
|
1917
|
+
style: {
|
|
1918
|
+
bottom: 0,
|
|
1919
|
+
height: effBottomPx,
|
|
1920
|
+
left: 0,
|
|
1921
|
+
overflow: "hidden",
|
|
1922
|
+
position: "absolute",
|
|
1923
|
+
width: hostWidth
|
|
1924
|
+
},
|
|
1925
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(jsx_native_bridge_default, { accessibilityElementsHidden: true, height: effBottomPx, width: svgWidthPx, children: [
|
|
1926
|
+
/* @__PURE__ */ jsxRuntime.jsx(Defs, { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1927
|
+
LinearGradient,
|
|
1928
|
+
{
|
|
1929
|
+
gradientUnits: "objectBoundingBox",
|
|
1930
|
+
id: MOVIIE_SKIN_CHROME_SVG_GRADIENT_BOTTOM_EDGE_ID,
|
|
1931
|
+
x1: "0",
|
|
1932
|
+
x2: "0",
|
|
1933
|
+
y1: "1",
|
|
1934
|
+
y2: "0",
|
|
1935
|
+
children: [
|
|
1936
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1937
|
+
Stop,
|
|
1938
|
+
{
|
|
1939
|
+
offset: "0",
|
|
1940
|
+
stopColor: MOVIIE_SKIN_CHROME_GRADIENT_BLACK_HEX,
|
|
1941
|
+
stopOpacity: MOVIIE_SKIN_CHROME_GRADIENT_EDGE_ALPHA
|
|
1942
|
+
}
|
|
1943
|
+
),
|
|
1944
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1945
|
+
Stop,
|
|
1946
|
+
{
|
|
1947
|
+
offset: fadeEndOffset,
|
|
1948
|
+
stopColor: MOVIIE_SKIN_CHROME_GRADIENT_BLACK_HEX,
|
|
1949
|
+
stopOpacity: 0
|
|
1950
|
+
}
|
|
1951
|
+
),
|
|
1952
|
+
/* @__PURE__ */ jsxRuntime.jsx(Stop, { offset: "1", stopColor: MOVIIE_SKIN_CHROME_GRADIENT_BLACK_HEX, stopOpacity: 0 })
|
|
1953
|
+
]
|
|
1954
|
+
}
|
|
1955
|
+
) }),
|
|
1956
|
+
/* @__PURE__ */ jsxRuntime.jsx(Rect, { fill: bottomFillUrl, height: effBottomPx, width: svgWidthPx })
|
|
1957
|
+
] })
|
|
1958
|
+
}
|
|
1959
|
+
) : null
|
|
1960
|
+
]
|
|
1961
|
+
}
|
|
1962
|
+
);
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1965
|
+
// src/lib/clamp-unit-interval.ts
|
|
1966
|
+
function clampUnitInterval(value) {
|
|
1967
|
+
return Math.min(1, Math.max(0, value));
|
|
1968
|
+
}
|
|
1969
|
+
|
|
1970
|
+
// src/lib/compute-playback-progress-ratio.ts
|
|
1971
|
+
function computePlaybackProgressRatio(state) {
|
|
1972
|
+
if (!state.durationOk || !Number.isFinite(state.currentTime) || !Number.isFinite(state.duration) || state.duration <= 0) {
|
|
1973
|
+
return 0;
|
|
1974
|
+
}
|
|
1975
|
+
const raw = state.currentTime / state.duration;
|
|
1976
|
+
if (raw >= 1) {
|
|
1977
|
+
return 1;
|
|
1978
|
+
}
|
|
1979
|
+
const snapToEndWhilePaused = !state.playing && state.currentTime >= state.duration - MOVIIE_SKIN_TIMELINE_END_SNAP_EPSILON_SECONDS;
|
|
1980
|
+
const ratio = snapToEndWhilePaused ? 1 : raw;
|
|
1981
|
+
return clampUnitInterval(ratio);
|
|
1982
|
+
}
|
|
1983
|
+
|
|
1984
|
+
// src/lib/compute-timeline-scrub-commit-time.ts
|
|
1985
|
+
function computeTimelineScrubCommitTime(params) {
|
|
1986
|
+
const {
|
|
1987
|
+
ratio,
|
|
1988
|
+
durationSeconds,
|
|
1989
|
+
chapters,
|
|
1990
|
+
snapThresholdSeconds = MOVIIE_SKIN_TIMELINE_CHAPTER_SNAP_THRESHOLD_SECONDS
|
|
1991
|
+
} = params;
|
|
1992
|
+
const rawTime = ratio * durationSeconds;
|
|
1993
|
+
let nearest = null;
|
|
1994
|
+
let nearestDist = Infinity;
|
|
1995
|
+
for (const chapter of chapters) {
|
|
1996
|
+
const dist = Math.abs(chapter.startTimeSeconds - rawTime);
|
|
1997
|
+
if (dist < nearestDist) {
|
|
1998
|
+
nearestDist = dist;
|
|
1999
|
+
nearest = chapter.startTimeSeconds;
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
return nearest !== null && nearestDist <= snapThresholdSeconds ? nearest : rawTime;
|
|
2003
|
+
}
|
|
2004
|
+
|
|
2005
|
+
// src/lib/resolve-skin-accent-color.ts
|
|
2006
|
+
var HEX_COLOR_REGEX = /^#[0-9A-Fa-f]{6}$/;
|
|
2007
|
+
function resolveSkinAccentColor(primaryColor) {
|
|
2008
|
+
if (primaryColor != null && HEX_COLOR_REGEX.test(primaryColor)) {
|
|
2009
|
+
return primaryColor;
|
|
2010
|
+
}
|
|
2011
|
+
return MOVIIE_SKIN_DEFAULT_ACCENT_HEX;
|
|
2012
|
+
}
|
|
2013
|
+
function createMoviieSkinBottomTimelineStyles(layout) {
|
|
2014
|
+
return reactNative.StyleSheet.create({
|
|
2015
|
+
root: {
|
|
2016
|
+
bottom: 0,
|
|
2017
|
+
left: 0,
|
|
2018
|
+
overflow: "visible",
|
|
2019
|
+
pointerEvents: "box-none",
|
|
2020
|
+
position: "absolute",
|
|
2021
|
+
right: 0,
|
|
2022
|
+
zIndex: 24
|
|
2023
|
+
},
|
|
2024
|
+
touchExpansion: {
|
|
2025
|
+
overflow: "visible",
|
|
2026
|
+
paddingBottom: 0,
|
|
2027
|
+
paddingTop: layout.timelineTouchPaddingVerticalPx + MOVIIE_SKIN_TIMELINE_TOUCH_EXPANSION_VERTICAL_DP,
|
|
2028
|
+
position: "relative"
|
|
2029
|
+
},
|
|
2030
|
+
trackStack: {
|
|
2031
|
+
overflow: "visible",
|
|
2032
|
+
width: "100%"
|
|
2033
|
+
},
|
|
2034
|
+
thumbBase: {
|
|
2035
|
+
borderColor: MOVIIE_SKIN_TIMELINE_THUMB_BORDER_RGBA,
|
|
2036
|
+
borderWidth: 1,
|
|
2037
|
+
elevation: 8,
|
|
2038
|
+
position: "absolute",
|
|
2039
|
+
zIndex: 10
|
|
2040
|
+
},
|
|
2041
|
+
unifiedBarSlot: {
|
|
2042
|
+
overflow: "visible",
|
|
2043
|
+
position: "relative",
|
|
2044
|
+
width: "100%"
|
|
2045
|
+
},
|
|
2046
|
+
railLayer: {
|
|
2047
|
+
backgroundColor: MOVIIE_SKIN_TIMELINE_RAIL_BACKGROUND_RGBA,
|
|
2048
|
+
bottom: 0,
|
|
2049
|
+
height: layout.timelineBarHeightPx,
|
|
2050
|
+
left: 0,
|
|
2051
|
+
position: "absolute",
|
|
2052
|
+
right: 0,
|
|
2053
|
+
zIndex: 0
|
|
2054
|
+
},
|
|
2055
|
+
bufferLayer: {
|
|
2056
|
+
backgroundColor: MOVIIE_SKIN_TIMELINE_BUFFER_LAYER_RGBA,
|
|
2057
|
+
bottom: 0,
|
|
2058
|
+
height: layout.timelineBarHeightPx,
|
|
2059
|
+
left: 0,
|
|
2060
|
+
position: "absolute",
|
|
2061
|
+
zIndex: 1
|
|
2062
|
+
},
|
|
2063
|
+
progressLayer: {
|
|
2064
|
+
bottom: 0,
|
|
2065
|
+
height: layout.timelineBarHeightPx,
|
|
2066
|
+
left: 0,
|
|
2067
|
+
position: "absolute",
|
|
2068
|
+
zIndex: 2
|
|
2069
|
+
}
|
|
2070
|
+
});
|
|
2071
|
+
}
|
|
2072
|
+
function MoviieSkinBottomTimeline() {
|
|
2073
|
+
const {
|
|
2074
|
+
playback,
|
|
2075
|
+
chromeVisible,
|
|
2076
|
+
layout,
|
|
2077
|
+
player,
|
|
2078
|
+
setTimelineScrubClockSeconds,
|
|
2079
|
+
ui
|
|
2080
|
+
} = useMoviieSkinChrome();
|
|
2081
|
+
const styles6 = React.useMemo(
|
|
2082
|
+
() => createMoviieSkinBottomTimelineStyles(layout),
|
|
2083
|
+
[layout]
|
|
2084
|
+
);
|
|
2085
|
+
const { controls } = playback;
|
|
2086
|
+
const accent = resolveSkinAccentColor(playback.branding.primaryColor);
|
|
2087
|
+
const foreground = MOVIIE_SKIN_CHROME_FOREGROUND_HEX;
|
|
2088
|
+
const durationOk = controls.showProgress && Number.isFinite(ui.duration) && ui.duration > 0 && !player.isLive;
|
|
2089
|
+
const progressRatioLive = computePlaybackProgressRatio({
|
|
2090
|
+
currentTime: ui.currentTime,
|
|
2091
|
+
duration: ui.duration,
|
|
2092
|
+
durationOk,
|
|
2093
|
+
playing: ui.playing
|
|
2094
|
+
});
|
|
2095
|
+
const bufferRatioLive = durationOk && Number.isFinite(ui.bufferedPosition) && ui.bufferedPosition >= 0 ? clampUnitInterval(ui.bufferedPosition / ui.duration) : 0;
|
|
2096
|
+
const isDraggingSV = AnimatedReanimated.useSharedValue(false);
|
|
2097
|
+
const awaitingUnlockSV = AnimatedReanimated.useSharedValue(false);
|
|
2098
|
+
const scrubRatioSV = AnimatedReanimated.useSharedValue(0);
|
|
2099
|
+
const progressRatioSV = AnimatedReanimated.useSharedValue(progressRatioLive);
|
|
2100
|
+
const bufferRatioSV = AnimatedReanimated.useSharedValue(bufferRatioLive);
|
|
2101
|
+
const trackWidthSV = AnimatedReanimated.useSharedValue(0);
|
|
2102
|
+
const durationSV = AnimatedReanimated.useSharedValue(ui.duration);
|
|
2103
|
+
const chromeVisibleSV = AnimatedReanimated.useSharedValue(chromeVisible);
|
|
2104
|
+
const timelineAccentEngagedSV = AnimatedReanimated.useSharedValue(false);
|
|
2105
|
+
const thumbBaseDiamSV = AnimatedReanimated.useSharedValue(layout.timelineThumbDiameterPx);
|
|
2106
|
+
const barHeightSV = AnimatedReanimated.useSharedValue(layout.timelineBarHeightPx);
|
|
2107
|
+
const isDraggingRef = React.useRef(false);
|
|
2108
|
+
const shouldResumeRef = React.useRef(false);
|
|
2109
|
+
const progressRatioLiveRef = React.useRef(progressRatioLive);
|
|
2110
|
+
progressRatioLiveRef.current = progressRatioLive;
|
|
2111
|
+
const chaptersRef = React.useRef(playback.chapters);
|
|
2112
|
+
chaptersRef.current = playback.chapters;
|
|
2113
|
+
const chromeVisibleRef = React.useRef(chromeVisible);
|
|
2114
|
+
chromeVisibleRef.current = chromeVisible;
|
|
2115
|
+
React.useEffect(() => {
|
|
2116
|
+
if (!isDraggingRef.current) {
|
|
2117
|
+
progressRatioSV.value = progressRatioLive;
|
|
2118
|
+
}
|
|
2119
|
+
}, [progressRatioLive, progressRatioSV]);
|
|
2120
|
+
React.useEffect(() => {
|
|
2121
|
+
bufferRatioSV.value = bufferRatioLive;
|
|
2122
|
+
}, [bufferRatioLive, bufferRatioSV]);
|
|
2123
|
+
React.useEffect(() => {
|
|
2124
|
+
durationSV.value = ui.duration;
|
|
2125
|
+
}, [ui.duration, durationSV]);
|
|
2126
|
+
React.useEffect(() => {
|
|
2127
|
+
thumbBaseDiamSV.value = layout.timelineThumbDiameterPx;
|
|
2128
|
+
barHeightSV.value = layout.timelineBarHeightPx;
|
|
2129
|
+
}, [
|
|
2130
|
+
layout.timelineThumbDiameterPx,
|
|
2131
|
+
layout.timelineBarHeightPx,
|
|
2132
|
+
thumbBaseDiamSV,
|
|
2133
|
+
barHeightSV
|
|
2134
|
+
]);
|
|
2135
|
+
React.useEffect(() => {
|
|
2136
|
+
chromeVisibleSV.value = chromeVisible;
|
|
2137
|
+
if (chromeVisible) {
|
|
2138
|
+
timelineAccentEngagedSV.value = false;
|
|
2139
|
+
awaitingUnlockSV.value = false;
|
|
2140
|
+
}
|
|
2141
|
+
}, [
|
|
2142
|
+
chromeVisible,
|
|
2143
|
+
chromeVisibleSV,
|
|
2144
|
+
timelineAccentEngagedSV,
|
|
2145
|
+
awaitingUnlockSV
|
|
2146
|
+
]);
|
|
2147
|
+
React.useEffect(() => {
|
|
2148
|
+
const sub = player.addListener("statusChange", ({ status }) => {
|
|
2149
|
+
if (shouldResumeRef.current && status === "readyToPlay" && !isDraggingRef.current) {
|
|
2150
|
+
player.play();
|
|
2151
|
+
}
|
|
2152
|
+
});
|
|
2153
|
+
return () => sub.remove();
|
|
2154
|
+
}, [player]);
|
|
2155
|
+
React.useEffect(() => {
|
|
2156
|
+
const sub = player.addListener("playingChange", ({ isPlaying }) => {
|
|
2157
|
+
if (isPlaying && !isDraggingRef.current) {
|
|
2158
|
+
shouldResumeRef.current = false;
|
|
2159
|
+
}
|
|
2160
|
+
});
|
|
2161
|
+
return () => sub.remove();
|
|
2162
|
+
}, [player]);
|
|
2163
|
+
const effectiveRatioSV = AnimatedReanimated.useDerivedValue(
|
|
2164
|
+
() => isDraggingSV.value ? scrubRatioSV.value : progressRatioSV.value
|
|
2165
|
+
);
|
|
2166
|
+
const showAccentSV = AnimatedReanimated.useDerivedValue(
|
|
2167
|
+
() => chromeVisibleSV.value || isDraggingSV.value || timelineAccentEngagedSV.value
|
|
2168
|
+
);
|
|
2169
|
+
const showThumbSV = AnimatedReanimated.useDerivedValue(
|
|
2170
|
+
() => chromeVisibleSV.value || isDraggingSV.value || timelineAccentEngagedSV.value
|
|
2171
|
+
);
|
|
2172
|
+
const thumbDiamSV = AnimatedReanimated.useDerivedValue(
|
|
2173
|
+
() => isDraggingSV.value ? Math.round(
|
|
2174
|
+
thumbBaseDiamSV.value * MOVIIE_SKIN_TIMELINE_THUMB_DRAG_DIAMETER_MULTIPLIER
|
|
2175
|
+
) : thumbBaseDiamSV.value
|
|
2176
|
+
);
|
|
2177
|
+
const progressBarStyle = AnimatedReanimated.useAnimatedStyle(() => ({
|
|
2178
|
+
backgroundColor: showAccentSV.value ? accent : foreground,
|
|
2179
|
+
width: `${effectiveRatioSV.value * 100}%`
|
|
2180
|
+
}));
|
|
2181
|
+
const bufferBarStyle = AnimatedReanimated.useAnimatedStyle(() => ({
|
|
2182
|
+
width: `${bufferRatioSV.value * 100}%`
|
|
2183
|
+
}));
|
|
2184
|
+
const thumbStyle = AnimatedReanimated.useAnimatedStyle(() => {
|
|
2185
|
+
if (!showThumbSV.value) {
|
|
2186
|
+
return { opacity: 0 };
|
|
2187
|
+
}
|
|
2188
|
+
const diameter = thumbDiamSV.value;
|
|
2189
|
+
const radius = diameter / 2;
|
|
2190
|
+
const w = trackWidthSV.value;
|
|
2191
|
+
const left = w > 0 ? Math.min(w - diameter, Math.max(0, effectiveRatioSV.value * w - radius)) : 0;
|
|
2192
|
+
const bh = barHeightSV.value;
|
|
2193
|
+
return {
|
|
2194
|
+
opacity: 1,
|
|
2195
|
+
backgroundColor: showAccentSV.value ? accent : foreground,
|
|
2196
|
+
left,
|
|
2197
|
+
width: diameter,
|
|
2198
|
+
height: diameter,
|
|
2199
|
+
borderRadius: radius,
|
|
2200
|
+
bottom: bh / 2 - radius
|
|
2201
|
+
};
|
|
2202
|
+
});
|
|
2203
|
+
const onScrubBegin = React.useCallback(() => {
|
|
2204
|
+
isDraggingRef.current = true;
|
|
2205
|
+
if (!shouldResumeRef.current) {
|
|
2206
|
+
shouldResumeRef.current = player.playing;
|
|
2207
|
+
}
|
|
2208
|
+
}, [player]);
|
|
2209
|
+
const onScrubUpdate = React.useCallback(
|
|
2210
|
+
(ratio) => {
|
|
2211
|
+
setTimelineScrubClockSeconds(ratio * durationSV.value);
|
|
2212
|
+
},
|
|
2213
|
+
[setTimelineScrubClockSeconds, durationSV]
|
|
2214
|
+
);
|
|
2215
|
+
const onScrubCommit = React.useCallback(
|
|
2216
|
+
(ratio) => {
|
|
2217
|
+
isDraggingRef.current = false;
|
|
2218
|
+
setTimelineScrubClockSeconds(null);
|
|
2219
|
+
const dur = durationSV.value;
|
|
2220
|
+
if (!Number.isFinite(dur) || dur <= 0) return;
|
|
2221
|
+
const targetTime = computeTimelineScrubCommitTime({
|
|
2222
|
+
ratio,
|
|
2223
|
+
durationSeconds: dur,
|
|
2224
|
+
chapters: chaptersRef.current
|
|
2225
|
+
});
|
|
2226
|
+
player.currentTime = targetTime;
|
|
2227
|
+
if (shouldResumeRef.current) {
|
|
2228
|
+
player.play();
|
|
2229
|
+
}
|
|
2230
|
+
},
|
|
2231
|
+
[setTimelineScrubClockSeconds, player, durationSV]
|
|
2232
|
+
);
|
|
2233
|
+
const onScrubCancel = React.useCallback(() => {
|
|
2234
|
+
isDraggingRef.current = false;
|
|
2235
|
+
setTimelineScrubClockSeconds(null);
|
|
2236
|
+
progressRatioSV.value = progressRatioLiveRef.current;
|
|
2237
|
+
}, [setTimelineScrubClockSeconds, progressRatioSV]);
|
|
2238
|
+
const onAccentEngage = React.useCallback(() => {
|
|
2239
|
+
timelineAccentEngagedSV.value = true;
|
|
2240
|
+
}, [timelineAccentEngagedSV]);
|
|
2241
|
+
const onAccentDisengageCancel = React.useCallback(() => {
|
|
2242
|
+
timelineAccentEngagedSV.value = false;
|
|
2243
|
+
}, [timelineAccentEngagedSV]);
|
|
2244
|
+
const panGesture = React.useMemo(
|
|
2245
|
+
() => reactNativeGestureHandler.Gesture.Pan().activeOffsetX([-8, 8]).failOffsetY([-15, 15]).enabled(durationOk).onBegin(() => {
|
|
2246
|
+
"worklet";
|
|
2247
|
+
if (!chromeVisibleSV.value && !timelineAccentEngagedSV.value) {
|
|
2248
|
+
awaitingUnlockSV.value = true;
|
|
2249
|
+
AnimatedReanimated.runOnJS(onAccentEngage)();
|
|
2250
|
+
}
|
|
2251
|
+
}).onStart((e) => {
|
|
2252
|
+
"worklet";
|
|
2253
|
+
if (awaitingUnlockSV.value) {
|
|
2254
|
+
return;
|
|
2255
|
+
}
|
|
2256
|
+
isDraggingSV.value = true;
|
|
2257
|
+
AnimatedReanimated.runOnJS(onScrubBegin)();
|
|
2258
|
+
const w = trackWidthSV.value;
|
|
2259
|
+
if (w <= 0) return;
|
|
2260
|
+
const ratio = Math.max(0, Math.min(1, e.x / w));
|
|
2261
|
+
scrubRatioSV.value = ratio;
|
|
2262
|
+
AnimatedReanimated.runOnJS(onScrubUpdate)(ratio);
|
|
2263
|
+
}).onUpdate((e) => {
|
|
2264
|
+
"worklet";
|
|
2265
|
+
const w = trackWidthSV.value;
|
|
2266
|
+
if (w <= 0) return;
|
|
2267
|
+
const ratio = Math.max(0, Math.min(1, e.x / w));
|
|
2268
|
+
if (awaitingUnlockSV.value) {
|
|
2269
|
+
awaitingUnlockSV.value = false;
|
|
2270
|
+
isDraggingSV.value = true;
|
|
2271
|
+
AnimatedReanimated.runOnJS(onScrubBegin)();
|
|
2272
|
+
}
|
|
2273
|
+
if (!isDraggingSV.value) return;
|
|
2274
|
+
scrubRatioSV.value = ratio;
|
|
2275
|
+
AnimatedReanimated.runOnJS(onScrubUpdate)(ratio);
|
|
2276
|
+
}).onEnd(() => {
|
|
2277
|
+
"worklet";
|
|
2278
|
+
if (awaitingUnlockSV.value) {
|
|
2279
|
+
awaitingUnlockSV.value = false;
|
|
2280
|
+
AnimatedReanimated.runOnJS(onAccentDisengageCancel)();
|
|
2281
|
+
return;
|
|
2282
|
+
}
|
|
2283
|
+
if (!isDraggingSV.value) return;
|
|
2284
|
+
const committed = scrubRatioSV.value;
|
|
2285
|
+
progressRatioSV.value = committed;
|
|
2286
|
+
isDraggingSV.value = false;
|
|
2287
|
+
scrubRatioSV.value = 0;
|
|
2288
|
+
AnimatedReanimated.runOnJS(onScrubCommit)(committed);
|
|
2289
|
+
}).onFinalize(() => {
|
|
2290
|
+
"worklet";
|
|
2291
|
+
if (awaitingUnlockSV.value) {
|
|
2292
|
+
awaitingUnlockSV.value = false;
|
|
2293
|
+
AnimatedReanimated.runOnJS(onAccentDisengageCancel)();
|
|
2294
|
+
return;
|
|
2295
|
+
}
|
|
2296
|
+
if (isDraggingSV.value) {
|
|
2297
|
+
isDraggingSV.value = false;
|
|
2298
|
+
scrubRatioSV.value = 0;
|
|
2299
|
+
AnimatedReanimated.runOnJS(onScrubCancel)();
|
|
2300
|
+
}
|
|
2301
|
+
}),
|
|
2302
|
+
[
|
|
2303
|
+
durationOk,
|
|
2304
|
+
isDraggingSV,
|
|
2305
|
+
awaitingUnlockSV,
|
|
2306
|
+
scrubRatioSV,
|
|
2307
|
+
progressRatioSV,
|
|
2308
|
+
trackWidthSV,
|
|
2309
|
+
chromeVisibleSV,
|
|
2310
|
+
timelineAccentEngagedSV,
|
|
2311
|
+
onAccentEngage,
|
|
2312
|
+
onAccentDisengageCancel,
|
|
2313
|
+
onScrubBegin,
|
|
2314
|
+
onScrubUpdate,
|
|
2315
|
+
onScrubCommit,
|
|
2316
|
+
onScrubCancel
|
|
2317
|
+
]
|
|
2318
|
+
);
|
|
2319
|
+
const onTrackLayout = React.useCallback(
|
|
2320
|
+
(event) => {
|
|
2321
|
+
trackWidthSV.value = event.nativeEvent.layout.width;
|
|
2322
|
+
},
|
|
2323
|
+
[trackWidthSV]
|
|
2324
|
+
);
|
|
2325
|
+
if (!durationOk) {
|
|
2326
|
+
return null;
|
|
2327
|
+
}
|
|
2328
|
+
const unifiedSlotHeightPx = Math.max(
|
|
2329
|
+
layout.timelineThumbDiameterPx,
|
|
2330
|
+
Math.round(
|
|
2331
|
+
layout.timelineThumbDiameterPx * MOVIIE_SKIN_TIMELINE_THUMB_DRAG_DIAMETER_MULTIPLIER
|
|
2332
|
+
)
|
|
2333
|
+
);
|
|
2334
|
+
const scrubHitSlop = {
|
|
2335
|
+
top: MOVIIE_SKIN_TIMELINE_SCRUB_HIT_SLOP_TOP_DP,
|
|
2336
|
+
bottom: MOVIIE_SKIN_TIMELINE_SCRUB_HIT_SLOP_BOTTOM_DP,
|
|
2337
|
+
left: MOVIIE_SKIN_TIMELINE_SCRUB_HIT_SLOP_HORIZONTAL_DP,
|
|
2338
|
+
right: MOVIIE_SKIN_TIMELINE_SCRUB_HIT_SLOP_HORIZONTAL_DP
|
|
2339
|
+
};
|
|
2340
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { pointerEvents: "box-none", style: styles6.root, children: /* @__PURE__ */ jsxRuntime.jsx(reactNativeGestureHandler.GestureDetector, { gesture: panGesture, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { hitSlop: scrubHitSlop, pointerEvents: "auto", style: styles6.touchExpansion, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles6.trackStack, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2341
|
+
reactNative.View,
|
|
2342
|
+
{
|
|
2343
|
+
accessibilityRole: "progressbar",
|
|
2344
|
+
accessibilityValue: {
|
|
2345
|
+
max: 1,
|
|
2346
|
+
min: 0,
|
|
2347
|
+
now: progressRatioLive
|
|
2348
|
+
},
|
|
2349
|
+
collapsable: false,
|
|
2350
|
+
style: [styles6.unifiedBarSlot, { height: unifiedSlotHeightPx }],
|
|
2351
|
+
onLayout: onTrackLayout,
|
|
2352
|
+
children: [
|
|
2353
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles6.railLayer }),
|
|
2354
|
+
/* @__PURE__ */ jsxRuntime.jsx(ReanimatedView, { style: [styles6.bufferLayer, bufferBarStyle] }),
|
|
2355
|
+
/* @__PURE__ */ jsxRuntime.jsx(ReanimatedView, { style: [styles6.progressLayer, progressBarStyle] }),
|
|
2356
|
+
/* @__PURE__ */ jsxRuntime.jsx(ReanimatedView, { style: [styles6.thumbBase, thumbStyle] })
|
|
2357
|
+
]
|
|
2358
|
+
}
|
|
2359
|
+
) }) }) }) });
|
|
2360
|
+
}
|
|
2361
|
+
|
|
2362
|
+
// src/lib/map-smart-progress-display-ratio.ts
|
|
2363
|
+
function easeOutQuad(t) {
|
|
2364
|
+
return t * (2 - t);
|
|
2365
|
+
}
|
|
2366
|
+
function easeInQuad(t) {
|
|
2367
|
+
return t * t;
|
|
2368
|
+
}
|
|
2369
|
+
function mapSmartProgressRawRatio(realUnitInterval) {
|
|
2370
|
+
const r = Math.min(1, Math.max(0, realUnitInterval));
|
|
2371
|
+
const {
|
|
2372
|
+
R1,
|
|
2373
|
+
P1,
|
|
2374
|
+
R2,
|
|
2375
|
+
P2,
|
|
2376
|
+
P_MAX_BEFORE_END: pMax
|
|
2377
|
+
} = MOVIIE_SMART_PROGRESS_CONFIG;
|
|
2378
|
+
if (r <= 0) {
|
|
2379
|
+
return 0;
|
|
2380
|
+
}
|
|
2381
|
+
if (r >= 1) {
|
|
2382
|
+
return pMax;
|
|
2383
|
+
}
|
|
2384
|
+
if (r <= R1) {
|
|
2385
|
+
return P1 * easeOutQuad(r / R1);
|
|
2386
|
+
}
|
|
2387
|
+
if (r <= R2) {
|
|
2388
|
+
const t2 = (r - R1) / (R2 - R1);
|
|
2389
|
+
return P1 + (P2 - P1) * t2;
|
|
2390
|
+
}
|
|
2391
|
+
const t = (r - R2) / (1 - R2);
|
|
2392
|
+
return P2 + (pMax - P2) * easeInQuad(t);
|
|
2393
|
+
}
|
|
2394
|
+
var styles = reactNative.StyleSheet.create({
|
|
2395
|
+
container: {
|
|
2396
|
+
bottom: 0,
|
|
2397
|
+
height: MOVIIE_SMART_PROGRESS_BAR_HEIGHT_DP,
|
|
2398
|
+
left: 0,
|
|
2399
|
+
overflow: "hidden",
|
|
2400
|
+
position: "absolute",
|
|
2401
|
+
right: 0,
|
|
2402
|
+
zIndex: MOVIIE_SMART_PROGRESS_Z_INDEX
|
|
2403
|
+
},
|
|
2404
|
+
fill: {
|
|
2405
|
+
bottom: 0,
|
|
2406
|
+
height: "100%",
|
|
2407
|
+
left: 0,
|
|
2408
|
+
position: "absolute",
|
|
2409
|
+
top: 0
|
|
2410
|
+
}
|
|
2411
|
+
});
|
|
2412
|
+
function MoviieSkinSmartProgress() {
|
|
2413
|
+
const { playback, player, timelineScrubClockSeconds, ui } = useMoviieSkinChrome();
|
|
2414
|
+
const accent = resolveSkinAccentColor(playback.branding.primaryColor);
|
|
2415
|
+
const durationOk = playback.smartProgressEnabled && Number.isFinite(ui.duration) && ui.duration > 0 && !player.isLive;
|
|
2416
|
+
const [barVisible, setBarVisible] = React.useState(() => !player.muted);
|
|
2417
|
+
const hasUserInteractedRef = React.useRef(!player.muted);
|
|
2418
|
+
const lastDisplayedRef = React.useRef(0);
|
|
2419
|
+
const progressAnim = React.useRef(new reactNative.Animated.Value(0)).current;
|
|
2420
|
+
const syncMutedVisibility = React.useCallback(() => {
|
|
2421
|
+
const muted = player.muted;
|
|
2422
|
+
if (!muted) {
|
|
2423
|
+
hasUserInteractedRef.current = true;
|
|
2424
|
+
setBarVisible(true);
|
|
2425
|
+
return;
|
|
2426
|
+
}
|
|
2427
|
+
if (!hasUserInteractedRef.current) {
|
|
2428
|
+
setBarVisible(false);
|
|
2429
|
+
}
|
|
2430
|
+
}, [player]);
|
|
2431
|
+
React.useEffect(() => {
|
|
2432
|
+
syncMutedVisibility();
|
|
2433
|
+
const subMuted = player.addListener("mutedChange", syncMutedVisibility);
|
|
2434
|
+
const subVolume = player.addListener("volumeChange", syncMutedVisibility);
|
|
2435
|
+
return () => {
|
|
2436
|
+
subMuted.remove();
|
|
2437
|
+
subVolume.remove();
|
|
2438
|
+
};
|
|
2439
|
+
}, [player, syncMutedVisibility]);
|
|
2440
|
+
React.useEffect(() => {
|
|
2441
|
+
lastDisplayedRef.current = 0;
|
|
2442
|
+
progressAnim.setValue(0);
|
|
2443
|
+
}, [playback.embedId, progressAnim]);
|
|
2444
|
+
React.useEffect(() => {
|
|
2445
|
+
if (!durationOk || !barVisible) {
|
|
2446
|
+
return;
|
|
2447
|
+
}
|
|
2448
|
+
const scrubbing = timelineScrubClockSeconds != null;
|
|
2449
|
+
const clockSeconds = scrubbing ? timelineScrubClockSeconds : ui.currentTime;
|
|
2450
|
+
const realRatio = computePlaybackProgressRatio({
|
|
2451
|
+
currentTime: clockSeconds,
|
|
2452
|
+
duration: ui.duration,
|
|
2453
|
+
durationOk: true,
|
|
2454
|
+
playing: ui.playing
|
|
2455
|
+
});
|
|
2456
|
+
const mapped = mapSmartProgressRawRatio(realRatio);
|
|
2457
|
+
const next = scrubbing ? mapped : Math.max(mapped, lastDisplayedRef.current);
|
|
2458
|
+
lastDisplayedRef.current = next;
|
|
2459
|
+
reactNative.Animated.timing(progressAnim, {
|
|
2460
|
+
duration: MOVIIE_SMART_PROGRESS_FILL_TRANSITION_MS,
|
|
2461
|
+
toValue: next,
|
|
2462
|
+
useNativeDriver: false
|
|
2463
|
+
}).start();
|
|
2464
|
+
}, [
|
|
2465
|
+
barVisible,
|
|
2466
|
+
durationOk,
|
|
2467
|
+
progressAnim,
|
|
2468
|
+
timelineScrubClockSeconds,
|
|
2469
|
+
ui.currentTime,
|
|
2470
|
+
ui.duration,
|
|
2471
|
+
ui.playing
|
|
2472
|
+
]);
|
|
2473
|
+
React.useEffect(() => {
|
|
2474
|
+
if (!durationOk || !barVisible) {
|
|
2475
|
+
return;
|
|
2476
|
+
}
|
|
2477
|
+
const sub = player.addListener("playToEnd", () => {
|
|
2478
|
+
lastDisplayedRef.current = 1;
|
|
2479
|
+
reactNative.Animated.timing(progressAnim, {
|
|
2480
|
+
duration: MOVIIE_SMART_PROGRESS_FILL_TRANSITION_MS,
|
|
2481
|
+
toValue: 1,
|
|
2482
|
+
useNativeDriver: false
|
|
2483
|
+
}).start();
|
|
2484
|
+
});
|
|
2485
|
+
return () => sub.remove();
|
|
2486
|
+
}, [barVisible, durationOk, player, progressAnim]);
|
|
2487
|
+
if (!playback.smartProgressEnabled || !durationOk) {
|
|
2488
|
+
return null;
|
|
2489
|
+
}
|
|
2490
|
+
if (!barVisible) {
|
|
2491
|
+
return null;
|
|
2492
|
+
}
|
|
2493
|
+
const widthInterpolated = progressAnim.interpolate({
|
|
2494
|
+
extrapolate: "clamp",
|
|
2495
|
+
inputRange: [0, 1],
|
|
2496
|
+
outputRange: ["0%", "100%"]
|
|
2497
|
+
});
|
|
2498
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { pointerEvents: "none", style: styles.container, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2499
|
+
reactNative.Animated.View,
|
|
2500
|
+
{
|
|
2501
|
+
style: [
|
|
2502
|
+
styles.fill,
|
|
2503
|
+
{
|
|
2504
|
+
backgroundColor: accent,
|
|
2505
|
+
width: widthInterpolated
|
|
2506
|
+
}
|
|
2507
|
+
]
|
|
2508
|
+
}
|
|
2509
|
+
) });
|
|
2510
|
+
}
|
|
2511
|
+
function resolveChromeControlPressOpacityStyle(pressed) {
|
|
2512
|
+
return {
|
|
2513
|
+
opacity: pressed ? MOVIIE_SKIN_CHROME_CONTROL_PRESSED_OPACITY : MOVIIE_SKIN_CHROME_CONTROL_REST_OPACITY
|
|
2514
|
+
};
|
|
2515
|
+
}
|
|
2516
|
+
function createMoviieSkinOverlayStyles(layout) {
|
|
2517
|
+
return reactNative.StyleSheet.create({
|
|
2518
|
+
chromeScrimBase: {
|
|
2519
|
+
backgroundColor: MOVIIE_SKIN_CHROME_SCRIM_BLACK_RGBA
|
|
2520
|
+
},
|
|
2521
|
+
floatingHud: {
|
|
2522
|
+
bottom: 0,
|
|
2523
|
+
left: 0,
|
|
2524
|
+
pointerEvents: "box-none",
|
|
2525
|
+
position: "absolute",
|
|
2526
|
+
right: 0
|
|
2527
|
+
},
|
|
2528
|
+
floatingHudInner: {
|
|
2529
|
+
alignItems: "center",
|
|
2530
|
+
flexDirection: "row",
|
|
2531
|
+
justifyContent: "space-between",
|
|
2532
|
+
paddingBottom: layout.floatingHudAboveTimelineGapPx,
|
|
2533
|
+
paddingHorizontal: layout.hudEdgeInsetPx
|
|
2534
|
+
},
|
|
2535
|
+
floatingLeftSpacer: {
|
|
2536
|
+
flex: 1
|
|
2537
|
+
},
|
|
2538
|
+
floatingRight: {
|
|
2539
|
+
alignItems: "center",
|
|
2540
|
+
columnGap: layout.floatingHudButtonGapPx,
|
|
2541
|
+
flexDirection: "row",
|
|
2542
|
+
flexShrink: 0
|
|
2543
|
+
},
|
|
2544
|
+
clockScrim: {
|
|
2545
|
+
borderRadius: layout.hudClockCornerRadiusPx,
|
|
2546
|
+
overflow: "hidden",
|
|
2547
|
+
paddingHorizontal: layout.hudEdgeInsetPx,
|
|
2548
|
+
paddingVertical: layout.hudEdgeInsetPx
|
|
2549
|
+
},
|
|
2550
|
+
clockText: {
|
|
2551
|
+
color: MOVIIE_SKIN_CHROME_FOREGROUND_HEX,
|
|
2552
|
+
fontSize: layout.clockTextFontSizePx,
|
|
2553
|
+
fontVariant: ["tabular-nums"]
|
|
2554
|
+
},
|
|
2555
|
+
centerCluster: {
|
|
2556
|
+
...reactNative.StyleSheet.absoluteFillObject,
|
|
2557
|
+
alignItems: "center",
|
|
2558
|
+
justifyContent: "center",
|
|
2559
|
+
pointerEvents: "box-none"
|
|
2560
|
+
},
|
|
2561
|
+
centerClusterRow: {
|
|
2562
|
+
alignItems: "center",
|
|
2563
|
+
columnGap: layout.centerClusterColumnGapPx,
|
|
2564
|
+
flexDirection: "row",
|
|
2565
|
+
justifyContent: "center"
|
|
2566
|
+
},
|
|
2567
|
+
seekCircularScrim: {
|
|
2568
|
+
alignItems: "center",
|
|
2569
|
+
borderRadius: layout.seekScrimOuterDiameterPx / 2,
|
|
2570
|
+
height: layout.seekScrimOuterDiameterPx,
|
|
2571
|
+
justifyContent: "center",
|
|
2572
|
+
overflow: "hidden",
|
|
2573
|
+
width: layout.seekScrimOuterDiameterPx
|
|
2574
|
+
},
|
|
2575
|
+
playScrim: {
|
|
2576
|
+
alignItems: "center",
|
|
2577
|
+
borderRadius: layout.playScrimOuterDiameterPx / 2,
|
|
2578
|
+
height: layout.playScrimOuterDiameterPx,
|
|
2579
|
+
justifyContent: "center",
|
|
2580
|
+
overflow: "hidden",
|
|
2581
|
+
width: layout.playScrimOuterDiameterPx
|
|
2582
|
+
},
|
|
2583
|
+
playPlaceholder: {
|
|
2584
|
+
height: layout.playScrimOuterDiameterPx,
|
|
2585
|
+
width: layout.playScrimOuterDiameterPx
|
|
2586
|
+
},
|
|
2587
|
+
fullscreenHudCircleScrim: {
|
|
2588
|
+
alignItems: "center",
|
|
2589
|
+
borderRadius: layout.floatingHudFullscreenScrimDiameterPx / 2,
|
|
2590
|
+
height: layout.floatingHudFullscreenScrimDiameterPx,
|
|
2591
|
+
justifyContent: "center",
|
|
2592
|
+
overflow: "hidden",
|
|
2593
|
+
width: layout.floatingHudFullscreenScrimDiameterPx
|
|
2594
|
+
},
|
|
2595
|
+
topFullscreenCorner: {
|
|
2596
|
+
alignItems: "center",
|
|
2597
|
+
columnGap: layout.floatingHudButtonGapPx,
|
|
2598
|
+
flexDirection: "row",
|
|
2599
|
+
pointerEvents: "box-none",
|
|
2600
|
+
position: "absolute",
|
|
2601
|
+
right: layout.hudEdgeInsetPx,
|
|
2602
|
+
top: layout.hudEdgeInsetPx,
|
|
2603
|
+
zIndex: 8
|
|
2604
|
+
}
|
|
2605
|
+
});
|
|
2606
|
+
}
|
|
2607
|
+
function ChromeScrimPad(props) {
|
|
2608
|
+
const padStyle = [props.chromeScrimBaseStyle, props.style];
|
|
2609
|
+
if (props.onPress != null) {
|
|
2610
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2611
|
+
reactNative.Pressable,
|
|
2612
|
+
{
|
|
2613
|
+
accessibilityLabel: props.accessibilityLabel,
|
|
2614
|
+
accessibilityRole: props.accessibilityRole ?? "button",
|
|
2615
|
+
hitSlop: props.hitSlop,
|
|
2616
|
+
onPress: props.onPress,
|
|
2617
|
+
style: (state) => [
|
|
2618
|
+
props.chromeScrimBaseStyle,
|
|
2619
|
+
props.style,
|
|
2620
|
+
resolveChromeControlPressOpacityStyle(state.pressed)
|
|
2621
|
+
],
|
|
2622
|
+
children: props.children
|
|
2623
|
+
}
|
|
2624
|
+
);
|
|
2625
|
+
}
|
|
2626
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: padStyle, children: props.children });
|
|
2627
|
+
}
|
|
2628
|
+
function MoviieSkinPictureInPictureCircleButton(props) {
|
|
2629
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2630
|
+
ChromeScrimPad,
|
|
2631
|
+
{
|
|
2632
|
+
accessibilityLabel: props.pictureInPictureActive ? "Fechar imagem no imagem" : "Imagem no imagem",
|
|
2633
|
+
chromeScrimBaseStyle: props.styles.chromeScrimBase,
|
|
2634
|
+
hitSlop: MOVIIE_SKIN_FLOATING_HUD_TRAILING_HIT_SLOP_PX,
|
|
2635
|
+
onPress: props.onPress,
|
|
2636
|
+
style: props.styles.fullscreenHudCircleScrim,
|
|
2637
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2638
|
+
EmbedMediaIconPictureInPicture,
|
|
2639
|
+
{
|
|
2640
|
+
color: MOVIIE_SKIN_CHROME_FOREGROUND_HEX,
|
|
2641
|
+
size: props.layout.floatingHudFullscreenIconPx
|
|
2642
|
+
}
|
|
2643
|
+
)
|
|
2644
|
+
}
|
|
2645
|
+
);
|
|
2646
|
+
}
|
|
2647
|
+
function MoviieSkinPictureInPictureTopBareButton(props) {
|
|
2648
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2649
|
+
reactNative.Pressable,
|
|
2650
|
+
{
|
|
2651
|
+
accessibilityLabel: props.pictureInPictureActive ? "Fechar imagem no imagem" : "Imagem no imagem",
|
|
2652
|
+
accessibilityRole: "button",
|
|
2653
|
+
hitSlop: MOVIIE_SKIN_FLOATING_HUD_TRAILING_HIT_SLOP_PX,
|
|
2654
|
+
onPress: props.onPress,
|
|
2655
|
+
style: (state) => resolveChromeControlPressOpacityStyle(state.pressed),
|
|
2656
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2657
|
+
EmbedMediaIconPictureInPicture,
|
|
2658
|
+
{
|
|
2659
|
+
color: MOVIIE_SKIN_CHROME_FOREGROUND_HEX,
|
|
2660
|
+
size: props.layout.floatingHudFullscreenTopIconPx * MOVIIE_SKIN_TOP_ICON_PIP_VISUAL_SCALE
|
|
2661
|
+
}
|
|
2662
|
+
)
|
|
2663
|
+
}
|
|
2664
|
+
);
|
|
2665
|
+
}
|
|
2666
|
+
function MoviieSkinFullscreenCircleButton(props) {
|
|
2667
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2668
|
+
ChromeScrimPad,
|
|
2669
|
+
{
|
|
2670
|
+
accessibilityLabel: props.isFullscreen ? "Sair de ecr\xE3 inteiro" : "Ecr\xE3 inteiro",
|
|
2671
|
+
chromeScrimBaseStyle: props.styles.chromeScrimBase,
|
|
2672
|
+
hitSlop: MOVIIE_SKIN_FLOATING_HUD_TRAILING_HIT_SLOP_PX,
|
|
2673
|
+
onPress: props.onPress,
|
|
2674
|
+
style: props.styles.fullscreenHudCircleScrim,
|
|
2675
|
+
children: props.isFullscreen ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2676
|
+
EmbedMediaIconFullscreenExit,
|
|
2677
|
+
{
|
|
2678
|
+
color: MOVIIE_SKIN_CHROME_FOREGROUND_HEX,
|
|
2679
|
+
size: props.layout.floatingHudFullscreenIconPx
|
|
2680
|
+
}
|
|
2681
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
2682
|
+
EmbedMediaIconFullscreen,
|
|
2683
|
+
{
|
|
2684
|
+
color: MOVIIE_SKIN_CHROME_FOREGROUND_HEX,
|
|
2685
|
+
size: props.layout.floatingHudFullscreenIconPx
|
|
2686
|
+
}
|
|
2687
|
+
)
|
|
2688
|
+
}
|
|
2689
|
+
);
|
|
2690
|
+
}
|
|
2691
|
+
function MoviieSkinFullscreenTopBareButton(props) {
|
|
2692
|
+
const size = props.layout.floatingHudFullscreenTopIconPx * MOVIIE_SKIN_TOP_ICON_FULLSCREEN_VISUAL_SCALE;
|
|
2693
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2694
|
+
reactNative.Pressable,
|
|
2695
|
+
{
|
|
2696
|
+
accessibilityLabel: props.isFullscreen ? "Sair de ecr\xE3 inteiro" : "Ecr\xE3 inteiro",
|
|
2697
|
+
accessibilityRole: "button",
|
|
2698
|
+
hitSlop: MOVIIE_SKIN_FLOATING_HUD_TRAILING_HIT_SLOP_PX,
|
|
2699
|
+
onPress: props.onPress,
|
|
2700
|
+
style: (state) => resolveChromeControlPressOpacityStyle(state.pressed),
|
|
2701
|
+
children: props.isFullscreen ? /* @__PURE__ */ jsxRuntime.jsx(EmbedMediaIconFullscreenExit, { color: MOVIIE_SKIN_CHROME_FOREGROUND_HEX, size }) : /* @__PURE__ */ jsxRuntime.jsx(EmbedMediaIconFullscreen, { color: MOVIIE_SKIN_CHROME_FOREGROUND_HEX, size })
|
|
2702
|
+
}
|
|
2703
|
+
);
|
|
2704
|
+
}
|
|
2705
|
+
function MoviieSkinBufferingIndicator() {
|
|
2706
|
+
const { isBuffering, layout } = useMoviieSkinChrome();
|
|
2707
|
+
const bufferingHudStyle = React.useMemo(
|
|
2708
|
+
() => ({
|
|
2709
|
+
alignItems: "center",
|
|
2710
|
+
height: layout.bufferingIndicatorSlotPx,
|
|
2711
|
+
justifyContent: "center",
|
|
2712
|
+
left: layout.hudEdgeInsetPx,
|
|
2713
|
+
position: "absolute",
|
|
2714
|
+
top: layout.hudEdgeInsetPx,
|
|
2715
|
+
width: layout.bufferingIndicatorSlotPx,
|
|
2716
|
+
zIndex: 16
|
|
2717
|
+
}),
|
|
2718
|
+
[layout]
|
|
2719
|
+
);
|
|
2720
|
+
if (!isBuffering) {
|
|
2721
|
+
return null;
|
|
2722
|
+
}
|
|
2723
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { pointerEvents: "none", style: bufferingHudStyle, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2724
|
+
reactNative.ActivityIndicator,
|
|
2725
|
+
{
|
|
2726
|
+
accessibilityLabel: "A carregar v\xEDdeo",
|
|
2727
|
+
color: MOVIIE_SKIN_CHROME_FOREGROUND_HEX,
|
|
2728
|
+
size: "small"
|
|
2729
|
+
}
|
|
2730
|
+
) });
|
|
2731
|
+
}
|
|
2732
|
+
function MoviieSkinVideoOverlay() {
|
|
2733
|
+
const {
|
|
2734
|
+
chromeOpacity,
|
|
2735
|
+
chromeVisible,
|
|
2736
|
+
bumpChromeInteraction,
|
|
2737
|
+
castConnected,
|
|
2738
|
+
castControlEnabled,
|
|
2739
|
+
dismissChrome,
|
|
2740
|
+
isCustomFullscreen,
|
|
2741
|
+
openCastPicker,
|
|
2742
|
+
pictureInPictureActive,
|
|
2743
|
+
pictureInPictureControlEnabled,
|
|
2744
|
+
toggleFullscreen,
|
|
2745
|
+
togglePictureInPicture,
|
|
2746
|
+
layout,
|
|
2747
|
+
playback,
|
|
2748
|
+
player,
|
|
2749
|
+
seekBack,
|
|
2750
|
+
seekForward,
|
|
2751
|
+
timelineScrubClockSeconds,
|
|
2752
|
+
togglePlay,
|
|
2753
|
+
ui
|
|
2754
|
+
} = useMoviieSkinChrome();
|
|
2755
|
+
const handlePictureInPicturePress = React.useCallback(() => {
|
|
2756
|
+
togglePictureInPicture();
|
|
2757
|
+
dismissChrome();
|
|
2758
|
+
}, [togglePictureInPicture, dismissChrome]);
|
|
2759
|
+
const handleCastPress = React.useCallback(() => {
|
|
2760
|
+
dismissChrome();
|
|
2761
|
+
setTimeout(() => openCastPicker(), 150);
|
|
2762
|
+
}, [openCastPicker, dismissChrome]);
|
|
2763
|
+
const styles6 = React.useMemo(() => createMoviieSkinOverlayStyles(layout), [layout]);
|
|
2764
|
+
const { controls } = playback;
|
|
2765
|
+
const fg = MOVIIE_SKIN_CHROME_FOREGROUND_HEX;
|
|
2766
|
+
const clockDisplaySeconds = timelineScrubClockSeconds ?? ui.currentTime;
|
|
2767
|
+
const playbackEndedForUi = React.useMemo(
|
|
2768
|
+
() => computeMoviiePlaybackEnded({
|
|
2769
|
+
playing: ui.playing,
|
|
2770
|
+
currentTime: clockDisplaySeconds,
|
|
2771
|
+
duration: ui.duration,
|
|
2772
|
+
isLive: player.isLive,
|
|
2773
|
+
loop: player.loop
|
|
2774
|
+
}),
|
|
2775
|
+
[ui.playing, clockDisplaySeconds, ui.duration, player.isLive, player.loop]
|
|
2776
|
+
);
|
|
2777
|
+
const { centerSeekBackwardEnabled, centerSeekForwardEnabled } = React.useMemo(() => {
|
|
2778
|
+
const alignSeekButtonsWithPlay = controls.showPlay && !player.isLive;
|
|
2779
|
+
const hideSeekClusterAtEnd = playbackEndedForUi;
|
|
2780
|
+
return {
|
|
2781
|
+
centerSeekBackwardEnabled: !hideSeekClusterAtEnd && (controls.seekBackwardEnabled || alignSeekButtonsWithPlay),
|
|
2782
|
+
centerSeekForwardEnabled: !hideSeekClusterAtEnd && (controls.seekForwardEnabled || alignSeekButtonsWithPlay)
|
|
2783
|
+
};
|
|
2784
|
+
}, [
|
|
2785
|
+
controls.seekBackwardEnabled,
|
|
2786
|
+
controls.seekForwardEnabled,
|
|
2787
|
+
controls.showPlay,
|
|
2788
|
+
player.isLive,
|
|
2789
|
+
playbackEndedForUi
|
|
2790
|
+
]);
|
|
2791
|
+
const centerPlayShowsReplay = playbackEndedForUi;
|
|
2792
|
+
const centerPlayAccessibilityLabel = ui.playing ? "Pausar" : centerPlayShowsReplay ? "Come\xE7ar novamente" : "Reproduzir";
|
|
2793
|
+
const clockLabel = controls.showCurrentTime || controls.showDuration ? formatPlaybackClock(clockDisplaySeconds, ui.duration) : null;
|
|
2794
|
+
const showSeekCluster = centerSeekBackwardEnabled || centerSeekForwardEnabled || controls.showPlay;
|
|
2795
|
+
const seekSlot = layout.seekScrimOuterDiameterPx;
|
|
2796
|
+
const showPictureInPictureTrailing = pictureInPictureControlEnabled;
|
|
2797
|
+
const showCastTrailing = castControlEnabled;
|
|
2798
|
+
const hasFloatingHudTrailing = playback.branding.showWatermark || !playback.branding.showWatermark && (controls.showFullscreen || showPictureInPictureTrailing || showCastTrailing);
|
|
2799
|
+
const showFloatingHud = clockLabel != null || hasFloatingHudTrailing;
|
|
2800
|
+
const showFullscreenBottomTrailing = controls.showFullscreen && !playback.branding.showWatermark;
|
|
2801
|
+
const showTopCornerChrome = playback.branding.showWatermark && (controls.showFullscreen || showPictureInPictureTrailing || showCastTrailing);
|
|
2802
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { pointerEvents: "box-none", style: reactNative.StyleSheet.absoluteFillObject, children: [
|
|
2803
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2804
|
+
reactNative.Pressable,
|
|
2805
|
+
{
|
|
2806
|
+
accessibilityLabel: chromeVisible ? "\xC1rea do v\xEDdeo \u2014 toque para esconder os controles" : "Mostrar controles do v\xEDdeo",
|
|
2807
|
+
accessibilityRole: "button",
|
|
2808
|
+
onPress: chromeVisible ? dismissChrome : bumpChromeInteraction,
|
|
2809
|
+
style: [reactNative.StyleSheet.absoluteFillObject, { zIndex: 0 }]
|
|
2810
|
+
}
|
|
2811
|
+
),
|
|
2812
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2813
|
+
AnimatedView,
|
|
2814
|
+
{
|
|
2815
|
+
pointerEvents: !chromeVisible ? "none" : "box-none",
|
|
2816
|
+
style: [
|
|
2817
|
+
reactNative.StyleSheet.absoluteFillObject,
|
|
2818
|
+
{
|
|
2819
|
+
opacity: chromeOpacity,
|
|
2820
|
+
zIndex: 2
|
|
2821
|
+
}
|
|
2822
|
+
],
|
|
2823
|
+
children: [
|
|
2824
|
+
/* @__PURE__ */ jsxRuntime.jsx(MoviieSkinChromeEdgeGradients, { layout, showProgress: controls.showProgress }),
|
|
2825
|
+
showTopCornerChrome ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { pointerEvents: "box-none", style: styles6.topFullscreenCorner, children: [
|
|
2826
|
+
showCastTrailing ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2827
|
+
MoviieSkinCastTopBareButton,
|
|
2828
|
+
{
|
|
2829
|
+
castConnected,
|
|
2830
|
+
layout,
|
|
2831
|
+
onPress: handleCastPress
|
|
2832
|
+
}
|
|
2833
|
+
) : null,
|
|
2834
|
+
showPictureInPictureTrailing ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2835
|
+
MoviieSkinPictureInPictureTopBareButton,
|
|
2836
|
+
{
|
|
2837
|
+
layout,
|
|
2838
|
+
pictureInPictureActive,
|
|
2839
|
+
onPress: handlePictureInPicturePress
|
|
2840
|
+
}
|
|
2841
|
+
) : null,
|
|
2842
|
+
controls.showFullscreen ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2843
|
+
MoviieSkinFullscreenTopBareButton,
|
|
2844
|
+
{
|
|
2845
|
+
isFullscreen: isCustomFullscreen,
|
|
2846
|
+
layout,
|
|
2847
|
+
onPress: toggleFullscreen
|
|
2848
|
+
}
|
|
2849
|
+
) : null
|
|
2850
|
+
] }) : null,
|
|
2851
|
+
showFloatingHud ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2852
|
+
reactNative.View,
|
|
2853
|
+
{
|
|
2854
|
+
pointerEvents: "box-none",
|
|
2855
|
+
style: [
|
|
2856
|
+
styles6.floatingHud,
|
|
2857
|
+
controls.showProgress ? { bottom: layout.timelineStackHeightChromeVisiblePx } : null
|
|
2858
|
+
],
|
|
2859
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles6.floatingHudInner, children: [
|
|
2860
|
+
clockLabel ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2861
|
+
ChromeScrimPad,
|
|
2862
|
+
{
|
|
2863
|
+
chromeScrimBaseStyle: styles6.chromeScrimBase,
|
|
2864
|
+
style: styles6.clockScrim,
|
|
2865
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { accessibilityLabel: `Tempo ${clockLabel}`, style: styles6.clockText, children: clockLabel })
|
|
2866
|
+
}
|
|
2867
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles6.floatingLeftSpacer }),
|
|
2868
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles6.floatingRight, children: playback.branding.showWatermark ? /* @__PURE__ */ jsxRuntime.jsx(MoviieEmbedBrandMark, {}) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2869
|
+
showCastTrailing ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2870
|
+
MoviieSkinCastCircleButton,
|
|
2871
|
+
{
|
|
2872
|
+
castConnected,
|
|
2873
|
+
chromeScrimBaseStyle: styles6.chromeScrimBase,
|
|
2874
|
+
circleScrimStyle: styles6.fullscreenHudCircleScrim,
|
|
2875
|
+
layout,
|
|
2876
|
+
onPress: handleCastPress
|
|
2877
|
+
}
|
|
2878
|
+
) : null,
|
|
2879
|
+
showPictureInPictureTrailing ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2880
|
+
MoviieSkinPictureInPictureCircleButton,
|
|
2881
|
+
{
|
|
2882
|
+
layout,
|
|
2883
|
+
pictureInPictureActive,
|
|
2884
|
+
onPress: handlePictureInPicturePress,
|
|
2885
|
+
styles: styles6
|
|
2886
|
+
}
|
|
2887
|
+
) : null,
|
|
2888
|
+
showFullscreenBottomTrailing ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2889
|
+
MoviieSkinFullscreenCircleButton,
|
|
2890
|
+
{
|
|
2891
|
+
isFullscreen: isCustomFullscreen,
|
|
2892
|
+
layout,
|
|
2893
|
+
onPress: toggleFullscreen,
|
|
2894
|
+
styles: styles6
|
|
2895
|
+
}
|
|
2896
|
+
) : null
|
|
2897
|
+
] }) })
|
|
2898
|
+
] })
|
|
2899
|
+
}
|
|
2900
|
+
) : null,
|
|
2901
|
+
showSeekCluster ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { pointerEvents: "box-none", style: styles6.centerCluster, children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles6.centerClusterRow, children: [
|
|
2902
|
+
centerSeekBackwardEnabled ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2903
|
+
ChromeScrimPad,
|
|
2904
|
+
{
|
|
2905
|
+
accessibilityLabel: "Retroceder 10 segundos",
|
|
2906
|
+
chromeScrimBaseStyle: styles6.chromeScrimBase,
|
|
2907
|
+
onPress: seekBack,
|
|
2908
|
+
style: styles6.seekCircularScrim,
|
|
2909
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(EmbedMediaIconSeekBackward10, { color: fg, size: layout.seekIconPx })
|
|
2910
|
+
}
|
|
2911
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: { height: seekSlot, width: seekSlot } }),
|
|
2912
|
+
controls.showPlay ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2913
|
+
ChromeScrimPad,
|
|
2914
|
+
{
|
|
2915
|
+
accessibilityLabel: centerPlayAccessibilityLabel,
|
|
2916
|
+
chromeScrimBaseStyle: styles6.chromeScrimBase,
|
|
2917
|
+
onPress: togglePlay,
|
|
2918
|
+
style: styles6.playScrim,
|
|
2919
|
+
children: ui.playing ? /* @__PURE__ */ jsxRuntime.jsx(EmbedMediaIconPause, { color: fg, size: layout.centerPlayIconPx }) : centerPlayShowsReplay ? /* @__PURE__ */ jsxRuntime.jsx(EmbedMediaIconReplay, { color: fg, size: layout.centerPlayIconPx }) : /* @__PURE__ */ jsxRuntime.jsx(EmbedMediaIconPlay, { color: fg, size: layout.centerPlayIconPx })
|
|
2920
|
+
}
|
|
2921
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles6.playPlaceholder }),
|
|
2922
|
+
centerSeekForwardEnabled ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2923
|
+
ChromeScrimPad,
|
|
2924
|
+
{
|
|
2925
|
+
accessibilityLabel: "Avan\xE7ar 10 segundos",
|
|
2926
|
+
chromeScrimBaseStyle: styles6.chromeScrimBase,
|
|
2927
|
+
onPress: seekForward,
|
|
2928
|
+
style: styles6.seekCircularScrim,
|
|
2929
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(EmbedMediaIconSeekForward10, { color: fg, size: layout.seekIconPx })
|
|
2930
|
+
}
|
|
2931
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: { height: seekSlot, width: seekSlot } })
|
|
2932
|
+
] }) }) : null
|
|
2933
|
+
]
|
|
2934
|
+
}
|
|
2935
|
+
),
|
|
2936
|
+
/* @__PURE__ */ jsxRuntime.jsx(MoviieSkinBufferingIndicator, {}),
|
|
2937
|
+
/* @__PURE__ */ jsxRuntime.jsx(MoviieSkinSmartProgress, {}),
|
|
2938
|
+
/* @__PURE__ */ jsxRuntime.jsx(MoviieSkinBottomTimeline, {})
|
|
2939
|
+
] });
|
|
2940
|
+
}
|
|
2941
|
+
|
|
2942
|
+
// src/lib/optional-status-bar.ts
|
|
2943
|
+
var cachedModule;
|
|
2944
|
+
function loadModule() {
|
|
2945
|
+
if (cachedModule !== void 0) {
|
|
2946
|
+
return cachedModule;
|
|
2947
|
+
}
|
|
2948
|
+
try {
|
|
2949
|
+
cachedModule = __require("expo-status-bar");
|
|
2950
|
+
} catch {
|
|
2951
|
+
cachedModule = null;
|
|
2952
|
+
warnOnce(
|
|
2953
|
+
"moviie:expo-status-bar-missing",
|
|
2954
|
+
"[@moviie/player-expo] `expo-status-bar` n\xE3o est\xE1 instalado. Status bar n\xE3o ser\xE1 ocultada em fullscreen JS. Instala com `pnpm add expo-status-bar` se quiser este comportamento."
|
|
2955
|
+
);
|
|
2956
|
+
}
|
|
2957
|
+
return cachedModule;
|
|
2958
|
+
}
|
|
2959
|
+
function moviieSetStatusBarHidden(hidden, animation = "fade") {
|
|
2960
|
+
const mod = loadModule();
|
|
2961
|
+
if (mod == null) return;
|
|
2962
|
+
try {
|
|
2963
|
+
mod.setStatusBarHidden(hidden, animation);
|
|
2964
|
+
} catch {
|
|
2965
|
+
}
|
|
2966
|
+
}
|
|
2967
|
+
async function restoreOrientationLockPolicy(previousLock) {
|
|
2968
|
+
try {
|
|
2969
|
+
if (previousLock === void 0 || previousLock === expoScreenOrientation.OrientationLock.DEFAULT || previousLock === expoScreenOrientation.OrientationLock.UNKNOWN) {
|
|
2970
|
+
await expoScreenOrientation.unlockAsync();
|
|
2971
|
+
return;
|
|
2972
|
+
}
|
|
2973
|
+
await expoScreenOrientation.lockAsync(previousLock);
|
|
2974
|
+
} catch {
|
|
2975
|
+
try {
|
|
2976
|
+
await expoScreenOrientation.unlockAsync();
|
|
2977
|
+
} catch {
|
|
2978
|
+
}
|
|
2979
|
+
}
|
|
2980
|
+
}
|
|
2981
|
+
function subscribeCustomFullscreenNativeOrientation(targetLock) {
|
|
2982
|
+
if (reactNative.Platform.OS === "web") {
|
|
2983
|
+
return { finish: async () => {
|
|
2984
|
+
} };
|
|
2985
|
+
}
|
|
2986
|
+
let cancelled = false;
|
|
2987
|
+
let locked = false;
|
|
2988
|
+
let previousLock;
|
|
2989
|
+
const setup = (async () => {
|
|
2990
|
+
try {
|
|
2991
|
+
previousLock = await expoScreenOrientation.getOrientationLockAsync();
|
|
2992
|
+
if (cancelled) {
|
|
2993
|
+
return;
|
|
2994
|
+
}
|
|
2995
|
+
await expoScreenOrientation.lockAsync(targetLock);
|
|
2996
|
+
if (cancelled) {
|
|
2997
|
+
await restoreOrientationLockPolicy(previousLock);
|
|
2998
|
+
return;
|
|
2999
|
+
}
|
|
3000
|
+
locked = true;
|
|
3001
|
+
} catch {
|
|
3002
|
+
}
|
|
3003
|
+
})();
|
|
3004
|
+
let finishPromise = null;
|
|
3005
|
+
return {
|
|
3006
|
+
finish: () => {
|
|
3007
|
+
if (finishPromise != null) {
|
|
3008
|
+
return finishPromise;
|
|
3009
|
+
}
|
|
3010
|
+
cancelled = true;
|
|
3011
|
+
finishPromise = (async () => {
|
|
3012
|
+
await setup;
|
|
3013
|
+
if (locked) {
|
|
3014
|
+
locked = false;
|
|
3015
|
+
await restoreOrientationLockPolicy(previousLock);
|
|
3016
|
+
}
|
|
3017
|
+
})();
|
|
3018
|
+
return finishPromise;
|
|
3019
|
+
}
|
|
3020
|
+
};
|
|
3021
|
+
}
|
|
3022
|
+
|
|
3023
|
+
// src/lib/resolve-orientation-lock-for-rotate-z-deg.ts
|
|
3024
|
+
function resolveOrientationLockValueForRotateZDeg(rotateZDeg) {
|
|
3025
|
+
{
|
|
3026
|
+
return MOVIIE_EXPO_SCREEN_ORIENTATION_LOCK_VALUE.LANDSCAPE_RIGHT;
|
|
3027
|
+
}
|
|
3028
|
+
}
|
|
3029
|
+
var CUSTOM_FULLSCREEN_TIMING = {
|
|
3030
|
+
duration: MOVIIE_SKIN_CUSTOM_FULLSCREEN_TRANSITION_MS
|
|
3031
|
+
};
|
|
3032
|
+
var CUSTOM_FULLSCREEN_USE_JS_STAGE_ROTATION = reactNative.Platform.OS === "web";
|
|
3033
|
+
var MoviieSkinCustomFullscreenModalInner = React.forwardRef(function MoviieSkinCustomFullscreenModalInner2(props, ref) {
|
|
3034
|
+
const orientationFinishRef = React.useRef(null);
|
|
3035
|
+
const insets = reactNativeSafeAreaContext.useSafeAreaInsets();
|
|
3036
|
+
const { height: winH, width: winW } = reactNative.useWindowDimensions();
|
|
3037
|
+
const { longSide, shortSide } = React.useMemo(
|
|
3038
|
+
() => computeCustomFullscreenStageDimensions({
|
|
3039
|
+
windowHeight: winH,
|
|
3040
|
+
safeInsets: insets,
|
|
3041
|
+
stageOverscanPx: MOVIIE_SKIN_CUSTOM_FULLSCREEN_STAGE_OVERSCAN_PX,
|
|
3042
|
+
windowWidth: winW
|
|
3043
|
+
}),
|
|
3044
|
+
[winW, winH, insets.bottom, insets.left, insets.right, insets.top]
|
|
3045
|
+
);
|
|
3046
|
+
const rotateZDeg = AnimatedReanimated.useSharedValue(0);
|
|
3047
|
+
const scale = AnimatedReanimated.useSharedValue(1);
|
|
3048
|
+
const emitExitComplete = React.useCallback(() => {
|
|
3049
|
+
props.onExitComplete();
|
|
3050
|
+
}, [props.onExitComplete]);
|
|
3051
|
+
const completeExitAfterNativeOrientationRestore = React.useCallback(() => {
|
|
3052
|
+
void (async () => {
|
|
3053
|
+
await orientationFinishRef.current?.();
|
|
3054
|
+
emitExitComplete();
|
|
3055
|
+
})();
|
|
3056
|
+
}, [emitExitComplete]);
|
|
3057
|
+
const animateExit = React.useCallback(() => {
|
|
3058
|
+
scale.value = AnimatedReanimated.withTiming(
|
|
3059
|
+
MOVIIE_SKIN_CUSTOM_FULLSCREEN_ENTER_SCALE_START,
|
|
3060
|
+
CUSTOM_FULLSCREEN_TIMING,
|
|
3061
|
+
(finishedScale) => {
|
|
3062
|
+
if (!CUSTOM_FULLSCREEN_USE_JS_STAGE_ROTATION && finishedScale) {
|
|
3063
|
+
AnimatedReanimated.runOnJS(completeExitAfterNativeOrientationRestore)();
|
|
3064
|
+
}
|
|
3065
|
+
}
|
|
3066
|
+
);
|
|
3067
|
+
if (CUSTOM_FULLSCREEN_USE_JS_STAGE_ROTATION) {
|
|
3068
|
+
rotateZDeg.value = AnimatedReanimated.withTiming(0, CUSTOM_FULLSCREEN_TIMING, (finished) => {
|
|
3069
|
+
if (finished) {
|
|
3070
|
+
AnimatedReanimated.runOnJS(emitExitComplete)();
|
|
3071
|
+
}
|
|
3072
|
+
});
|
|
3073
|
+
return;
|
|
3074
|
+
}
|
|
3075
|
+
rotateZDeg.value = 0;
|
|
3076
|
+
}, [completeExitAfterNativeOrientationRestore, emitExitComplete, rotateZDeg, scale]);
|
|
3077
|
+
React.useImperativeHandle(ref, () => ({ animateExit }), [animateExit]);
|
|
3078
|
+
React.useEffect(() => {
|
|
3079
|
+
if (!props.visible) {
|
|
3080
|
+
return;
|
|
3081
|
+
}
|
|
3082
|
+
rotateZDeg.value = 0;
|
|
3083
|
+
scale.value = MOVIIE_SKIN_CUSTOM_FULLSCREEN_ENTER_SCALE_START;
|
|
3084
|
+
if (CUSTOM_FULLSCREEN_USE_JS_STAGE_ROTATION) {
|
|
3085
|
+
rotateZDeg.value = AnimatedReanimated.withTiming(
|
|
3086
|
+
MOVIIE_SKIN_CUSTOM_FULLSCREEN_ROTATE_Z_DEGREES,
|
|
3087
|
+
CUSTOM_FULLSCREEN_TIMING
|
|
3088
|
+
);
|
|
3089
|
+
}
|
|
3090
|
+
scale.value = AnimatedReanimated.withTiming(1, CUSTOM_FULLSCREEN_TIMING);
|
|
3091
|
+
}, [props.visible, rotateZDeg, scale]);
|
|
3092
|
+
React.useEffect(() => {
|
|
3093
|
+
if (!props.visible) {
|
|
3094
|
+
return;
|
|
3095
|
+
}
|
|
3096
|
+
moviieSetStatusBarHidden(true, "fade");
|
|
3097
|
+
return () => {
|
|
3098
|
+
moviieSetStatusBarHidden(false, "fade");
|
|
3099
|
+
};
|
|
3100
|
+
}, [props.visible]);
|
|
3101
|
+
React.useEffect(() => {
|
|
3102
|
+
if (!props.visible || CUSTOM_FULLSCREEN_USE_JS_STAGE_ROTATION) {
|
|
3103
|
+
orientationFinishRef.current = null;
|
|
3104
|
+
return;
|
|
3105
|
+
}
|
|
3106
|
+
const targetLock = resolveOrientationLockValueForRotateZDeg();
|
|
3107
|
+
const sub = subscribeCustomFullscreenNativeOrientation(targetLock);
|
|
3108
|
+
orientationFinishRef.current = () => sub.finish();
|
|
3109
|
+
return () => {
|
|
3110
|
+
orientationFinishRef.current = null;
|
|
3111
|
+
void sub.finish();
|
|
3112
|
+
};
|
|
3113
|
+
}, [props.visible]);
|
|
3114
|
+
const animatedStyle = AnimatedReanimated.useAnimatedStyle(() => {
|
|
3115
|
+
if (CUSTOM_FULLSCREEN_USE_JS_STAGE_ROTATION) {
|
|
3116
|
+
return {
|
|
3117
|
+
transform: [{ rotateZ: `${rotateZDeg.value}deg` }, { scale: scale.value }]
|
|
3118
|
+
};
|
|
3119
|
+
}
|
|
3120
|
+
return {
|
|
3121
|
+
transform: [{ scale: scale.value }]
|
|
3122
|
+
};
|
|
3123
|
+
});
|
|
3124
|
+
const stageStaticStyle = React.useMemo(
|
|
3125
|
+
() => ({
|
|
3126
|
+
height: shortSide,
|
|
3127
|
+
width: longSide
|
|
3128
|
+
}),
|
|
3129
|
+
[longSide, shortSide]
|
|
3130
|
+
);
|
|
3131
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3132
|
+
reactNative.View,
|
|
3133
|
+
{
|
|
3134
|
+
style: [styles2.root, { backgroundColor: MOVIIE_SKIN_CUSTOM_FULLSCREEN_STAGE_BACKGROUND_HEX }],
|
|
3135
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles2.centerSheet, children: /* @__PURE__ */ jsxRuntime.jsx(ReanimatedView, { style: [styles2.rotatingStage, stageStaticStyle, animatedStyle], children: props.children }) })
|
|
3136
|
+
}
|
|
3137
|
+
);
|
|
3138
|
+
});
|
|
3139
|
+
var MoviieSkinCustomFullscreenModal = React.forwardRef(function MoviieSkinCustomFullscreenModal2(props, ref) {
|
|
3140
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3141
|
+
reactNative.Modal,
|
|
3142
|
+
{
|
|
3143
|
+
animationType: "none",
|
|
3144
|
+
hardwareAccelerated: reactNative.Platform.OS === "android",
|
|
3145
|
+
onRequestClose: () => {
|
|
3146
|
+
if (ref != null && typeof ref !== "function") {
|
|
3147
|
+
ref.current?.animateExit();
|
|
3148
|
+
}
|
|
3149
|
+
},
|
|
3150
|
+
presentationStyle: "fullScreen",
|
|
3151
|
+
statusBarTranslucent: reactNative.Platform.OS === "android",
|
|
3152
|
+
supportedOrientations: [
|
|
3153
|
+
"portrait",
|
|
3154
|
+
"portrait-upside-down",
|
|
3155
|
+
"landscape",
|
|
3156
|
+
"landscape-left",
|
|
3157
|
+
"landscape-right"
|
|
3158
|
+
],
|
|
3159
|
+
visible: props.visible,
|
|
3160
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNativeSafeAreaContext.SafeAreaProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(MoviieSkinCustomFullscreenModalInner, { ref, ...props }) })
|
|
3161
|
+
}
|
|
3162
|
+
);
|
|
3163
|
+
});
|
|
3164
|
+
var styles2 = reactNative.StyleSheet.create({
|
|
3165
|
+
root: {
|
|
3166
|
+
flex: 1
|
|
3167
|
+
},
|
|
3168
|
+
centerSheet: {
|
|
3169
|
+
alignItems: "center",
|
|
3170
|
+
flex: 1,
|
|
3171
|
+
justifyContent: "center",
|
|
3172
|
+
overflow: "visible"
|
|
3173
|
+
},
|
|
3174
|
+
rotatingStage: {
|
|
3175
|
+
position: "relative"
|
|
3176
|
+
}
|
|
3177
|
+
});
|
|
3178
|
+
var ERROR_NUMERIC_CODE = {
|
|
3179
|
+
auth: "E1001",
|
|
3180
|
+
not_found: "E1002",
|
|
3181
|
+
bundle_blocked: "E1003",
|
|
3182
|
+
referrer_blocked: "E1004",
|
|
3183
|
+
subscription_inactive: "E1005",
|
|
3184
|
+
network: "E2001",
|
|
3185
|
+
rate_limit: "E2002",
|
|
3186
|
+
unknown: "E9999"
|
|
3187
|
+
};
|
|
3188
|
+
function resolveErrorCode(error) {
|
|
3189
|
+
if (error instanceof playerSdk.MoviieAuthError) return "auth";
|
|
3190
|
+
if (error instanceof playerSdk.MoviieNotFoundError) return "not_found";
|
|
3191
|
+
if (error instanceof playerSdk.MoviieBundleBlockedError) return "bundle_blocked";
|
|
3192
|
+
if (error instanceof playerSdk.MoviieReferrerBlockedError) return "referrer_blocked";
|
|
3193
|
+
if (error instanceof playerSdk.MoviieSubscriptionInactiveError) return "subscription_inactive";
|
|
3194
|
+
if (error instanceof playerSdk.MoviieNetworkError) return "network";
|
|
3195
|
+
if (error instanceof playerSdk.MoviieRateLimitError) return "rate_limit";
|
|
3196
|
+
const code = error.code;
|
|
3197
|
+
if (typeof code === "string") {
|
|
3198
|
+
const known = [
|
|
3199
|
+
"auth",
|
|
3200
|
+
"not_found",
|
|
3201
|
+
"bundle_blocked",
|
|
3202
|
+
"referrer_blocked",
|
|
3203
|
+
"subscription_inactive",
|
|
3204
|
+
"network",
|
|
3205
|
+
"rate_limit"
|
|
3206
|
+
];
|
|
3207
|
+
if (known.includes(code)) {
|
|
3208
|
+
return code;
|
|
3209
|
+
}
|
|
3210
|
+
}
|
|
3211
|
+
return "unknown";
|
|
3212
|
+
}
|
|
3213
|
+
function getErrorDisplay(error) {
|
|
3214
|
+
const code = resolveErrorCode(error);
|
|
3215
|
+
switch (code) {
|
|
3216
|
+
case "auth":
|
|
3217
|
+
return {
|
|
3218
|
+
code,
|
|
3219
|
+
numericCode: ERROR_NUMERIC_CODE[code],
|
|
3220
|
+
heading: "Configura\xE7\xE3o inv\xE1lida",
|
|
3221
|
+
description: "Verifique a chave public\xE1vel do SDK.",
|
|
3222
|
+
ctaLabel: "Acessar Moviie",
|
|
3223
|
+
ctaKind: "external",
|
|
3224
|
+
externalUrl: MOVIIE_DASHBOARD_URL
|
|
3225
|
+
};
|
|
3226
|
+
case "not_found":
|
|
3227
|
+
return {
|
|
3228
|
+
code,
|
|
3229
|
+
numericCode: ERROR_NUMERIC_CODE[code],
|
|
3230
|
+
heading: "Reprodu\xE7\xE3o indispon\xEDvel",
|
|
3231
|
+
description: "N\xE3o conseguimos encontrar este v\xEDdeo.",
|
|
3232
|
+
ctaLabel: "Acessar Moviie",
|
|
3233
|
+
ctaKind: "external",
|
|
3234
|
+
externalUrl: MOVIIE_DASHBOARD_URL
|
|
3235
|
+
};
|
|
3236
|
+
case "bundle_blocked":
|
|
3237
|
+
return {
|
|
3238
|
+
code,
|
|
3239
|
+
numericCode: ERROR_NUMERIC_CODE[code],
|
|
3240
|
+
heading: "Aplicativo n\xE3o autorizado",
|
|
3241
|
+
description: "Este aplicativo n\xE3o est\xE1 autorizado a reproduzir este v\xEDdeo.",
|
|
3242
|
+
ctaLabel: "Ajustar permiss\xF5es",
|
|
3243
|
+
ctaKind: "external",
|
|
3244
|
+
externalUrl: MOVIIE_DASHBOARD_URL
|
|
3245
|
+
};
|
|
3246
|
+
case "referrer_blocked":
|
|
3247
|
+
return {
|
|
3248
|
+
code,
|
|
3249
|
+
numericCode: ERROR_NUMERIC_CODE[code],
|
|
3250
|
+
heading: "Origem n\xE3o autorizada",
|
|
3251
|
+
description: "Origem n\xE3o autorizada para reprodu\xE7\xE3o.",
|
|
3252
|
+
ctaLabel: "Acessar Moviie",
|
|
3253
|
+
ctaKind: "external",
|
|
3254
|
+
externalUrl: MOVIIE_DASHBOARD_URL
|
|
3255
|
+
};
|
|
3256
|
+
case "subscription_inactive":
|
|
3257
|
+
return {
|
|
3258
|
+
code,
|
|
3259
|
+
numericCode: ERROR_NUMERIC_CODE[code],
|
|
3260
|
+
heading: "Reprodu\xE7\xE3o temporariamente indispon\xEDvel",
|
|
3261
|
+
description: "Acesse a Moviie para continuar assistindo.",
|
|
3262
|
+
ctaLabel: "Ir para a Moviie",
|
|
3263
|
+
ctaKind: "external",
|
|
3264
|
+
externalUrl: MOVIIE_DASHBOARD_URL
|
|
3265
|
+
};
|
|
3266
|
+
case "network":
|
|
3267
|
+
return {
|
|
3268
|
+
code,
|
|
3269
|
+
numericCode: ERROR_NUMERIC_CODE[code],
|
|
3270
|
+
heading: "Erro de conex\xE3o",
|
|
3271
|
+
description: "Verifique sua conex\xE3o e tente novamente.",
|
|
3272
|
+
ctaLabel: "Tentar de novo",
|
|
3273
|
+
ctaKind: "retry",
|
|
3274
|
+
externalUrl: null
|
|
3275
|
+
};
|
|
3276
|
+
case "rate_limit":
|
|
3277
|
+
return {
|
|
3278
|
+
code,
|
|
3279
|
+
numericCode: ERROR_NUMERIC_CODE[code],
|
|
3280
|
+
heading: "Muitas solicita\xE7\xF5es",
|
|
3281
|
+
description: "Aguarde alguns instantes e tente novamente.",
|
|
3282
|
+
ctaLabel: "Tentar de novo",
|
|
3283
|
+
ctaKind: "retry",
|
|
3284
|
+
externalUrl: null
|
|
3285
|
+
};
|
|
3286
|
+
case "unknown":
|
|
3287
|
+
default:
|
|
3288
|
+
return {
|
|
3289
|
+
code: "unknown",
|
|
3290
|
+
numericCode: ERROR_NUMERIC_CODE["unknown"],
|
|
3291
|
+
heading: "Erro tempor\xE1rio",
|
|
3292
|
+
description: "Tente novamente em instantes.",
|
|
3293
|
+
ctaLabel: "Tentar de novo",
|
|
3294
|
+
ctaKind: "retry",
|
|
3295
|
+
externalUrl: null
|
|
3296
|
+
};
|
|
3297
|
+
}
|
|
3298
|
+
}
|
|
3299
|
+
function MoviiePlayerErrorShell({
|
|
3300
|
+
error,
|
|
3301
|
+
onRetry
|
|
3302
|
+
}) {
|
|
3303
|
+
const display = getErrorDisplay(error);
|
|
3304
|
+
const handlePress = React.useCallback(() => {
|
|
3305
|
+
if (display.ctaKind === "retry") {
|
|
3306
|
+
onRetry?.();
|
|
3307
|
+
return;
|
|
3308
|
+
}
|
|
3309
|
+
if (display.ctaKind === "external" && display.externalUrl) {
|
|
3310
|
+
void reactNative.Linking.openURL(display.externalUrl).catch(() => {
|
|
3311
|
+
});
|
|
3312
|
+
}
|
|
3313
|
+
}, [display, onRetry]);
|
|
3314
|
+
const showCta = display.ctaLabel != null && display.ctaKind !== "none";
|
|
3315
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.root, accessibilityRole: "alert", children: [
|
|
3316
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.radialGlow }),
|
|
3317
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.errorCode, selectable: true, children: display.numericCode }),
|
|
3318
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.content, children: [
|
|
3319
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.heading, numberOfLines: 2, children: display.heading }),
|
|
3320
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.description, numberOfLines: 4, children: display.description }),
|
|
3321
|
+
showCta ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3322
|
+
reactNative.Pressable,
|
|
3323
|
+
{
|
|
3324
|
+
accessibilityRole: "button",
|
|
3325
|
+
accessibilityLabel: display.ctaLabel ?? void 0,
|
|
3326
|
+
onPress: handlePress,
|
|
3327
|
+
style: ({ pressed }) => [styles3.button, pressed ? styles3.buttonPressed : null],
|
|
3328
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles3.buttonLabel, children: display.ctaLabel })
|
|
3329
|
+
}
|
|
3330
|
+
) : null
|
|
3331
|
+
] })
|
|
3332
|
+
] });
|
|
3333
|
+
}
|
|
3334
|
+
var styles3 = reactNative.StyleSheet.create({
|
|
3335
|
+
root: {
|
|
3336
|
+
...reactNative.StyleSheet.absoluteFillObject,
|
|
3337
|
+
backgroundColor: MOVIIE_SHELL_BACKGROUND_HEX,
|
|
3338
|
+
overflow: "hidden",
|
|
3339
|
+
alignItems: "center",
|
|
3340
|
+
justifyContent: "center"
|
|
3341
|
+
},
|
|
3342
|
+
/** Simulates radial gradient: dark outer, lighter center. */
|
|
3343
|
+
radialGlow: {
|
|
3344
|
+
position: "absolute",
|
|
3345
|
+
width: "150%",
|
|
3346
|
+
aspectRatio: 1,
|
|
3347
|
+
borderRadius: 9999,
|
|
3348
|
+
backgroundColor: MOVIIE_SHELL_RADIAL_INNER_HEX
|
|
3349
|
+
},
|
|
3350
|
+
content: {
|
|
3351
|
+
...reactNative.StyleSheet.absoluteFillObject,
|
|
3352
|
+
alignItems: "center",
|
|
3353
|
+
justifyContent: "center",
|
|
3354
|
+
paddingHorizontal: 24,
|
|
3355
|
+
gap: 10
|
|
3356
|
+
},
|
|
3357
|
+
heading: {
|
|
3358
|
+
color: MOVIIE_SHELL_HEADING_HEX,
|
|
3359
|
+
fontSize: MOVIIE_SHELL_HEADING_FONT_SIZE_PX,
|
|
3360
|
+
fontWeight: "600",
|
|
3361
|
+
textAlign: "center",
|
|
3362
|
+
maxWidth: MOVIIE_SHELL_CONTENT_MAX_WIDTH_PX
|
|
3363
|
+
},
|
|
3364
|
+
description: {
|
|
3365
|
+
color: MOVIIE_SHELL_DESCRIPTION_HEX,
|
|
3366
|
+
fontSize: MOVIIE_SHELL_DESCRIPTION_FONT_SIZE_PX,
|
|
3367
|
+
lineHeight: 20,
|
|
3368
|
+
textAlign: "center",
|
|
3369
|
+
maxWidth: MOVIIE_SHELL_CONTENT_MAX_WIDTH_PX
|
|
3370
|
+
},
|
|
3371
|
+
errorCode: {
|
|
3372
|
+
position: "absolute",
|
|
3373
|
+
bottom: 8,
|
|
3374
|
+
right: 10,
|
|
3375
|
+
color: MOVIIE_SHELL_ERROR_CODE_HEX,
|
|
3376
|
+
fontSize: 10,
|
|
3377
|
+
fontFamily: "Menlo",
|
|
3378
|
+
opacity: 0.45,
|
|
3379
|
+
zIndex: 2
|
|
3380
|
+
},
|
|
3381
|
+
button: {
|
|
3382
|
+
marginTop: 6,
|
|
3383
|
+
paddingVertical: MOVIIE_SHELL_BUTTON_PADDING_V_PX,
|
|
3384
|
+
paddingHorizontal: MOVIIE_SHELL_BUTTON_PADDING_H_PX,
|
|
3385
|
+
backgroundColor: MOVIIE_SHELL_BUTTON_BG_HEX,
|
|
3386
|
+
borderColor: MOVIIE_SHELL_BUTTON_BORDER_RGBA,
|
|
3387
|
+
borderWidth: reactNative.StyleSheet.hairlineWidth * 2,
|
|
3388
|
+
borderRadius: MOVIIE_SHELL_BUTTON_RADIUS_PX
|
|
3389
|
+
},
|
|
3390
|
+
buttonPressed: {
|
|
3391
|
+
opacity: MOVIIE_SKIN_CHROME_CONTROL_PRESSED_OPACITY
|
|
3392
|
+
},
|
|
3393
|
+
buttonLabel: {
|
|
3394
|
+
color: MOVIIE_SHELL_BUTTON_LABEL_HEX,
|
|
3395
|
+
fontSize: MOVIIE_SHELL_BUTTON_LABEL_FONT_SIZE_PX,
|
|
3396
|
+
fontWeight: "600",
|
|
3397
|
+
textAlign: "center"
|
|
3398
|
+
}
|
|
3399
|
+
});
|
|
3400
|
+
function MoviiePlayerLoadingShell({
|
|
3401
|
+
posterUrl,
|
|
3402
|
+
primaryColor
|
|
3403
|
+
}) {
|
|
3404
|
+
const accent = resolveSkinAccentColor(primaryColor ?? null);
|
|
3405
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles4.root, accessibilityRole: "progressbar", accessibilityLabel: "Carregando v\xEDdeo", children: [
|
|
3406
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles4.radialGlow }),
|
|
3407
|
+
posterUrl ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Image, { source: { uri: posterUrl }, style: styles4.poster, resizeMode: "cover" }) : null,
|
|
3408
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles4.center, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { size: "large", color: accent }) })
|
|
3409
|
+
] });
|
|
3410
|
+
}
|
|
3411
|
+
var styles4 = reactNative.StyleSheet.create({
|
|
3412
|
+
root: {
|
|
3413
|
+
...reactNative.StyleSheet.absoluteFillObject,
|
|
3414
|
+
backgroundColor: MOVIIE_SHELL_BACKGROUND_HEX,
|
|
3415
|
+
overflow: "hidden",
|
|
3416
|
+
alignItems: "center",
|
|
3417
|
+
justifyContent: "center"
|
|
3418
|
+
},
|
|
3419
|
+
/** Simulates radial gradient: dark outer, lighter center. */
|
|
3420
|
+
radialGlow: {
|
|
3421
|
+
position: "absolute",
|
|
3422
|
+
width: "150%",
|
|
3423
|
+
aspectRatio: 1,
|
|
3424
|
+
borderRadius: 9999,
|
|
3425
|
+
backgroundColor: MOVIIE_SHELL_RADIAL_INNER_HEX
|
|
3426
|
+
},
|
|
3427
|
+
poster: {
|
|
3428
|
+
...reactNative.StyleSheet.absoluteFillObject,
|
|
3429
|
+
opacity: 0.35
|
|
3430
|
+
},
|
|
3431
|
+
center: {
|
|
3432
|
+
...reactNative.StyleSheet.absoluteFillObject,
|
|
3433
|
+
alignItems: "center",
|
|
3434
|
+
justifyContent: "center"
|
|
3435
|
+
}
|
|
3436
|
+
});
|
|
3437
|
+
function assignForwardedRef(forwarded, instance) {
|
|
3438
|
+
if (typeof forwarded === "function") {
|
|
3439
|
+
forwarded(instance);
|
|
3440
|
+
return;
|
|
3441
|
+
}
|
|
3442
|
+
if (forwarded) {
|
|
3443
|
+
forwarded.current = instance;
|
|
3444
|
+
}
|
|
3445
|
+
}
|
|
3446
|
+
var HostVideoView = expoVideo.VideoView;
|
|
3447
|
+
var CROSSFADE_TIMING = {
|
|
3448
|
+
duration: MOVIIE_SHELL_CROSSFADE_DURATION_MS,
|
|
3449
|
+
easing: AnimatedReanimated.Easing.out(AnimatedReanimated.Easing.quad)
|
|
3450
|
+
};
|
|
3451
|
+
var MoviieVideo = React.forwardRef(
|
|
3452
|
+
function MoviieVideo2(props, ref) {
|
|
3453
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNativeSafeAreaContext.SafeAreaProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(MoviieVideoImpl, { ref, ...props }) });
|
|
3454
|
+
}
|
|
3455
|
+
);
|
|
3456
|
+
var MoviieVideoImpl = React.forwardRef(
|
|
3457
|
+
function MoviieVideoImpl2(props, forwardedRef) {
|
|
3458
|
+
const {
|
|
3459
|
+
player,
|
|
3460
|
+
nativeControls,
|
|
3461
|
+
native = false,
|
|
3462
|
+
playback = null,
|
|
3463
|
+
controlsAutoHideMs,
|
|
3464
|
+
controlsVisibleByDefault,
|
|
3465
|
+
pictureInPicture,
|
|
3466
|
+
pictureInPictureAutoStart,
|
|
3467
|
+
allowsPictureInPicture: passthroughAllowsPictureInPicture,
|
|
3468
|
+
startsPictureInPictureAutomatically: passthroughStartsPictureInPictureAutomatically,
|
|
3469
|
+
requiresLinearPlayback: passthroughRequiresLinearPlayback,
|
|
3470
|
+
onPictureInPictureStart: userOnPictureInPictureStart,
|
|
3471
|
+
onPictureInPictureStop: userOnPictureInPictureStop,
|
|
3472
|
+
children,
|
|
3473
|
+
style,
|
|
3474
|
+
contentFit,
|
|
3475
|
+
error = null,
|
|
3476
|
+
isLoading = false,
|
|
3477
|
+
aspectRatio,
|
|
3478
|
+
onRetry,
|
|
3479
|
+
retry,
|
|
3480
|
+
castAdapter: castAdapterProp,
|
|
3481
|
+
cast,
|
|
3482
|
+
onTelemetryError,
|
|
3483
|
+
onTelemetryEvent,
|
|
3484
|
+
...videoRest
|
|
3485
|
+
} = props;
|
|
3486
|
+
const castAdapter = castAdapterProp ?? getRegisteredCastAdapter();
|
|
3487
|
+
const lastReportedErrorRef = React.useRef(null);
|
|
3488
|
+
React.useEffect(() => {
|
|
3489
|
+
if (error == null) {
|
|
3490
|
+
lastReportedErrorRef.current = null;
|
|
3491
|
+
return;
|
|
3492
|
+
}
|
|
3493
|
+
if (lastReportedErrorRef.current === error) {
|
|
3494
|
+
return;
|
|
3495
|
+
}
|
|
3496
|
+
lastReportedErrorRef.current = error;
|
|
3497
|
+
safeInvokeMoviieTelemetry(onTelemetryError, error, {
|
|
3498
|
+
phase: "playback_fetch"
|
|
3499
|
+
});
|
|
3500
|
+
}, [error, onTelemetryError]);
|
|
3501
|
+
const useMoviieChrome = !native;
|
|
3502
|
+
const shellState = playback != null ? "ready" : error != null ? "error" : "loading";
|
|
3503
|
+
const loadingOpacity = AnimatedReanimated.useSharedValue(shellState === "loading" ? 1 : 0);
|
|
3504
|
+
const errorOpacity = AnimatedReanimated.useSharedValue(shellState === "error" ? 1 : 0);
|
|
3505
|
+
const playerOpacity = AnimatedReanimated.useSharedValue(shellState === "ready" ? 1 : 0);
|
|
3506
|
+
React.useEffect(() => {
|
|
3507
|
+
loadingOpacity.value = AnimatedReanimated.withTiming(shellState === "loading" ? 1 : 0, CROSSFADE_TIMING);
|
|
3508
|
+
errorOpacity.value = AnimatedReanimated.withTiming(shellState === "error" ? 1 : 0, CROSSFADE_TIMING);
|
|
3509
|
+
playerOpacity.value = AnimatedReanimated.withTiming(shellState === "ready" ? 1 : 0, CROSSFADE_TIMING);
|
|
3510
|
+
}, [shellState, loadingOpacity, errorOpacity, playerOpacity]);
|
|
3511
|
+
const loadingAnimatedStyle = AnimatedReanimated.useAnimatedStyle(() => ({
|
|
3512
|
+
opacity: loadingOpacity.value
|
|
3513
|
+
}));
|
|
3514
|
+
const errorAnimatedStyle = AnimatedReanimated.useAnimatedStyle(() => ({
|
|
3515
|
+
opacity: errorOpacity.value
|
|
3516
|
+
}));
|
|
3517
|
+
const playerAnimatedStyle = AnimatedReanimated.useAnimatedStyle(() => ({
|
|
3518
|
+
opacity: playerOpacity.value
|
|
3519
|
+
}));
|
|
3520
|
+
const effectiveOnRetry = React.useMemo(() => {
|
|
3521
|
+
if (onRetry) return onRetry;
|
|
3522
|
+
if (retry) return retry;
|
|
3523
|
+
return void 0;
|
|
3524
|
+
}, [onRetry, retry]);
|
|
3525
|
+
const nativePresentationVideoProps = React.useMemo(() => {
|
|
3526
|
+
if (playback != null) {
|
|
3527
|
+
const embedBaseline = buildMoviieVideoPresentationProps({
|
|
3528
|
+
pictureInPicture,
|
|
3529
|
+
pictureInPictureAutoStart,
|
|
3530
|
+
profile: playback.profile,
|
|
3531
|
+
showPip: playback.controls.showPip
|
|
3532
|
+
});
|
|
3533
|
+
return {
|
|
3534
|
+
allowsPictureInPicture: passthroughAllowsPictureInPicture ?? embedBaseline.allowsPictureInPicture,
|
|
3535
|
+
startsPictureInPictureAutomatically: passthroughStartsPictureInPictureAutomatically ?? embedBaseline.startsPictureInPictureAutomatically,
|
|
3536
|
+
requiresLinearPlayback: passthroughRequiresLinearPlayback ?? embedBaseline.requiresLinearPlayback
|
|
3537
|
+
};
|
|
3538
|
+
}
|
|
3539
|
+
return {
|
|
3540
|
+
allowsPictureInPicture: passthroughAllowsPictureInPicture ?? false,
|
|
3541
|
+
startsPictureInPictureAutomatically: passthroughStartsPictureInPictureAutomatically ?? false,
|
|
3542
|
+
requiresLinearPlayback: passthroughRequiresLinearPlayback ?? false
|
|
3543
|
+
};
|
|
3544
|
+
}, [
|
|
3545
|
+
playback,
|
|
3546
|
+
pictureInPicture,
|
|
3547
|
+
pictureInPictureAutoStart,
|
|
3548
|
+
passthroughAllowsPictureInPicture,
|
|
3549
|
+
passthroughStartsPictureInPictureAutomatically,
|
|
3550
|
+
passthroughRequiresLinearPlayback
|
|
3551
|
+
]);
|
|
3552
|
+
const pipControlEnabled = React.useMemo(() => {
|
|
3553
|
+
if (!playback || !useMoviieChrome) {
|
|
3554
|
+
return false;
|
|
3555
|
+
}
|
|
3556
|
+
return expoVideo.isPictureInPictureSupported() && nativePresentationVideoProps.allowsPictureInPicture;
|
|
3557
|
+
}, [playback, useMoviieChrome, nativePresentationVideoProps.allowsPictureInPicture]);
|
|
3558
|
+
const innerRef = React.useRef(null);
|
|
3559
|
+
const fullscreenModalRef = React.useRef(null);
|
|
3560
|
+
const [customFullscreen, setCustomFullscreen] = React.useState(false);
|
|
3561
|
+
const [pipActive, setPipActive] = React.useState(false);
|
|
3562
|
+
const [castState, setCastState] = React.useState(
|
|
3563
|
+
() => castAdapter?.isAvailable() ? castAdapter.getState() : "unavailable"
|
|
3564
|
+
);
|
|
3565
|
+
const castDesired = React.useMemo(() => {
|
|
3566
|
+
if (!playback || !useMoviieChrome) return false;
|
|
3567
|
+
if (cast === false) return false;
|
|
3568
|
+
if (cast === true) return true;
|
|
3569
|
+
return playback.controls.chromecast === true;
|
|
3570
|
+
}, [cast, playback, useMoviieChrome]);
|
|
3571
|
+
const castControlEnabled = React.useMemo(() => {
|
|
3572
|
+
if (!castDesired) return false;
|
|
3573
|
+
return castAdapter?.isAvailable() === true;
|
|
3574
|
+
}, [castAdapter, castDesired]);
|
|
3575
|
+
const castConnected = castState === "connected";
|
|
3576
|
+
const openCastPicker = React.useCallback(() => {
|
|
3577
|
+
void castAdapter?.showDevicePicker().catch(() => {
|
|
3578
|
+
});
|
|
3579
|
+
}, [castAdapter]);
|
|
3580
|
+
React.useEffect(() => {
|
|
3581
|
+
if (!castAdapter?.isAvailable()) {
|
|
3582
|
+
setCastState("unavailable");
|
|
3583
|
+
return;
|
|
3584
|
+
}
|
|
3585
|
+
setCastState(castAdapter.getState());
|
|
3586
|
+
const unsubscribe = castAdapter.subscribe((next) => {
|
|
3587
|
+
setCastState(next);
|
|
3588
|
+
});
|
|
3589
|
+
return () => {
|
|
3590
|
+
unsubscribe();
|
|
3591
|
+
};
|
|
3592
|
+
}, [castAdapter]);
|
|
3593
|
+
React.useEffect(() => {
|
|
3594
|
+
if (castDesired && (!castAdapter || !castAdapter.isAvailable())) {
|
|
3595
|
+
warnOnce(
|
|
3596
|
+
"moviie-cast-missing-adapter",
|
|
3597
|
+
'[@moviie/player-expo] O embed habilita Chromecast mas a lib n\xE3o est\xE1 dispon\xEDvel. Instale `react-native-google-cast` e adicione `import "@moviie/player-expo/cast"` no seu _layout.tsx (ver docs/player-expo/cast). Para desligar explicitamente, passe `cast={false}` em <MoviieVideo />.'
|
|
3598
|
+
);
|
|
3599
|
+
}
|
|
3600
|
+
}, [castDesired, castAdapter]);
|
|
3601
|
+
React.useEffect(() => {
|
|
3602
|
+
if (!castAdapter?.isAvailable() || !playback || !player) return;
|
|
3603
|
+
if (castState !== "connected") return;
|
|
3604
|
+
const startSeconds = player.currentTime ?? 0;
|
|
3605
|
+
void castAdapter.loadMedia({
|
|
3606
|
+
uri: playback.playback.uri,
|
|
3607
|
+
title: playback.title,
|
|
3608
|
+
posterUrl: playback.posterUrl,
|
|
3609
|
+
durationSeconds: playback.durationSeconds ?? null,
|
|
3610
|
+
startSeconds
|
|
3611
|
+
}).then(() => {
|
|
3612
|
+
try {
|
|
3613
|
+
player.pause();
|
|
3614
|
+
} catch {
|
|
3615
|
+
}
|
|
3616
|
+
}).catch(() => {
|
|
3617
|
+
});
|
|
3618
|
+
}, [castAdapter, castState, playback, player]);
|
|
3619
|
+
const { width: winW, height: winH } = reactNative.useWindowDimensions();
|
|
3620
|
+
const safeAreaInsets = reactNativeSafeAreaContext.useSafeAreaInsets();
|
|
3621
|
+
const fullscreenStageLayout = React.useMemo(
|
|
3622
|
+
() => computeCustomFullscreenStageDimensions({
|
|
3623
|
+
windowHeight: winH,
|
|
3624
|
+
safeInsets: safeAreaInsets,
|
|
3625
|
+
stageOverscanPx: MOVIIE_SKIN_CUSTOM_FULLSCREEN_STAGE_OVERSCAN_PX,
|
|
3626
|
+
windowWidth: winW
|
|
3627
|
+
}),
|
|
3628
|
+
[
|
|
3629
|
+
winW,
|
|
3630
|
+
winH,
|
|
3631
|
+
safeAreaInsets.bottom,
|
|
3632
|
+
safeAreaInsets.left,
|
|
3633
|
+
safeAreaInsets.right,
|
|
3634
|
+
safeAreaInsets.top
|
|
3635
|
+
]
|
|
3636
|
+
);
|
|
3637
|
+
React.useEffect(() => {
|
|
3638
|
+
setPipActive(false);
|
|
3639
|
+
}, [playback?.embedId]);
|
|
3640
|
+
const handleNativePictureInPictureStart = React.useCallback(() => {
|
|
3641
|
+
if (useMoviieChrome && playback != null) {
|
|
3642
|
+
setPipActive(true);
|
|
3643
|
+
}
|
|
3644
|
+
userOnPictureInPictureStart?.();
|
|
3645
|
+
}, [playback, useMoviieChrome, userOnPictureInPictureStart]);
|
|
3646
|
+
const handleNativePictureInPictureStop = React.useCallback(() => {
|
|
3647
|
+
if (useMoviieChrome && playback != null) {
|
|
3648
|
+
setPipActive(false);
|
|
3649
|
+
}
|
|
3650
|
+
userOnPictureInPictureStop?.();
|
|
3651
|
+
}, [playback, useMoviieChrome, userOnPictureInPictureStop]);
|
|
3652
|
+
const togglePictureInPicture = React.useCallback(async () => {
|
|
3653
|
+
const surface = innerRef.current;
|
|
3654
|
+
if (!surface?.startPictureInPicture) {
|
|
3655
|
+
return;
|
|
3656
|
+
}
|
|
3657
|
+
try {
|
|
3658
|
+
if (pipActive) {
|
|
3659
|
+
await surface.stopPictureInPicture?.();
|
|
3660
|
+
} else {
|
|
3661
|
+
await surface.startPictureInPicture();
|
|
3662
|
+
}
|
|
3663
|
+
} catch {
|
|
3664
|
+
}
|
|
3665
|
+
}, [pipActive]);
|
|
3666
|
+
const requestExitCustomFullscreenAnimated = React.useCallback(() => {
|
|
3667
|
+
fullscreenModalRef.current?.animateExit();
|
|
3668
|
+
}, []);
|
|
3669
|
+
const setRefs = React.useCallback(
|
|
3670
|
+
(node) => {
|
|
3671
|
+
innerRef.current = node;
|
|
3672
|
+
assignForwardedRef(forwardedRef, node);
|
|
3673
|
+
},
|
|
3674
|
+
[forwardedRef]
|
|
3675
|
+
);
|
|
3676
|
+
const resolvedNativeControlsDefault = native ? playback?.profile === MOVIIE_PLAYBACK_PROFILE.VSL ? false : true : false;
|
|
3677
|
+
const effectiveNativeControls = nativeControls ?? resolvedNativeControlsDefault;
|
|
3678
|
+
const intrinsicAspectRatio = playback?.videoWidthPx != null && playback?.videoHeightPx != null && playback.videoWidthPx > 0 && playback.videoHeightPx > 0 ? playback.videoWidthPx / playback.videoHeightPx : null;
|
|
3679
|
+
const effectiveAspectRatio = intrinsicAspectRatio ?? aspectRatio ?? MOVIIE_SHELL_DEFAULT_ASPECT_RATIO;
|
|
3680
|
+
const effectiveContentFit = contentFit ?? (playback != null ? playback.isVertical ? MOVIIE_VIDEO_DEFAULT_CONTENT_FIT.VERTICAL : MOVIIE_VIDEO_DEFAULT_CONTENT_FIT.HORIZONTAL : void 0);
|
|
3681
|
+
const { columnStyle, surfaceStyle } = partitionMoviieVideoHostStyle(reactNative.StyleSheet.flatten(style));
|
|
3682
|
+
const stageContainerStyle = [
|
|
3683
|
+
styles5.videoStage,
|
|
3684
|
+
{
|
|
3685
|
+
width: "100%",
|
|
3686
|
+
aspectRatio: effectiveAspectRatio,
|
|
3687
|
+
alignSelf: "stretch",
|
|
3688
|
+
flex: 0
|
|
3689
|
+
},
|
|
3690
|
+
surfaceStyle,
|
|
3691
|
+
useMoviieChrome && playback ? styles5.videoStageClipNone : null
|
|
3692
|
+
];
|
|
3693
|
+
const inlineVideoAndOverlay = player != null ? useMoviieChrome && playback ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3694
|
+
React.createElement(HostVideoView, {
|
|
3695
|
+
...videoRest,
|
|
3696
|
+
...nativePresentationVideoProps,
|
|
3697
|
+
ref: setRefs,
|
|
3698
|
+
player,
|
|
3699
|
+
nativeControls: effectiveNativeControls,
|
|
3700
|
+
onPictureInPictureStart: handleNativePictureInPictureStart,
|
|
3701
|
+
onPictureInPictureStop: handleNativePictureInPictureStop,
|
|
3702
|
+
...effectiveContentFit != null ? { contentFit: effectiveContentFit } : {},
|
|
3703
|
+
style: styles5.videoFill
|
|
3704
|
+
}),
|
|
3705
|
+
/* @__PURE__ */ jsxRuntime.jsx(MoviieSkinVideoOverlay, {})
|
|
3706
|
+
] }) : React.createElement(HostVideoView, {
|
|
3707
|
+
...videoRest,
|
|
3708
|
+
...nativePresentationVideoProps,
|
|
3709
|
+
ref: setRefs,
|
|
3710
|
+
player,
|
|
3711
|
+
nativeControls: effectiveNativeControls,
|
|
3712
|
+
onPictureInPictureStart: handleNativePictureInPictureStart,
|
|
3713
|
+
onPictureInPictureStop: handleNativePictureInPictureStop,
|
|
3714
|
+
...effectiveContentFit != null ? { contentFit: effectiveContentFit } : {},
|
|
3715
|
+
style: styles5.videoFill
|
|
3716
|
+
}) : null;
|
|
3717
|
+
const renderInlineStage = (active) => {
|
|
3718
|
+
if (!playback || !useMoviieChrome) {
|
|
3719
|
+
return inlineVideoAndOverlay;
|
|
3720
|
+
}
|
|
3721
|
+
if (!customFullscreen) {
|
|
3722
|
+
return inlineVideoAndOverlay;
|
|
3723
|
+
}
|
|
3724
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3725
|
+
reactNative.View,
|
|
3726
|
+
{
|
|
3727
|
+
style: [
|
|
3728
|
+
styles5.videoFill,
|
|
3729
|
+
{
|
|
3730
|
+
backgroundColor: MOVIIE_SKIN_CUSTOM_FULLSCREEN_STAGE_BACKGROUND_HEX
|
|
3731
|
+
}
|
|
3732
|
+
]
|
|
3733
|
+
}
|
|
3734
|
+
);
|
|
3735
|
+
};
|
|
3736
|
+
const stageContent = /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: stageContainerStyle, children: [
|
|
3737
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3738
|
+
ReanimatedView,
|
|
3739
|
+
{
|
|
3740
|
+
style: [reactNative.StyleSheet.absoluteFillObject, loadingAnimatedStyle, styles5.shellLayer],
|
|
3741
|
+
pointerEvents: shellState === "loading" ? "auto" : "none",
|
|
3742
|
+
children: shellState === "loading" || loadingOpacity.value > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3743
|
+
MoviiePlayerLoadingShell,
|
|
3744
|
+
{
|
|
3745
|
+
posterUrl: playback?.posterUrl ?? null,
|
|
3746
|
+
primaryColor: playback?.branding.primaryColor ?? null
|
|
3747
|
+
}
|
|
3748
|
+
) : null
|
|
3749
|
+
}
|
|
3750
|
+
),
|
|
3751
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3752
|
+
ReanimatedView,
|
|
3753
|
+
{
|
|
3754
|
+
style: [reactNative.StyleSheet.absoluteFillObject, errorAnimatedStyle, styles5.shellLayer],
|
|
3755
|
+
pointerEvents: shellState === "error" ? "auto" : "none",
|
|
3756
|
+
children: error ? /* @__PURE__ */ jsxRuntime.jsx(MoviiePlayerErrorShell, { error, onRetry: effectiveOnRetry }) : null
|
|
3757
|
+
}
|
|
3758
|
+
),
|
|
3759
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3760
|
+
ReanimatedView,
|
|
3761
|
+
{
|
|
3762
|
+
style: [reactNative.StyleSheet.absoluteFillObject, playerAnimatedStyle],
|
|
3763
|
+
pointerEvents: shellState === "ready" ? "auto" : "none",
|
|
3764
|
+
children: renderInlineStage()
|
|
3765
|
+
}
|
|
3766
|
+
)
|
|
3767
|
+
] });
|
|
3768
|
+
if (useMoviieChrome && playback && player) {
|
|
3769
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3770
|
+
MoviieSkinChromeProvider,
|
|
3771
|
+
{
|
|
3772
|
+
autoHideMs: controlsAutoHideMs,
|
|
3773
|
+
customFullscreen,
|
|
3774
|
+
pictureInPictureActive: pipActive,
|
|
3775
|
+
pictureInPictureControlEnabled: pipControlEnabled,
|
|
3776
|
+
togglePictureInPicture,
|
|
3777
|
+
castControlEnabled,
|
|
3778
|
+
castConnected,
|
|
3779
|
+
openCastPicker,
|
|
3780
|
+
onRequestEnterCustomFullscreen: () => setCustomFullscreen(true),
|
|
3781
|
+
onRequestExitCustomFullscreenAnimated: requestExitCustomFullscreenAnimated,
|
|
3782
|
+
playback,
|
|
3783
|
+
player,
|
|
3784
|
+
skinLayoutMetricsWidth: customFullscreen ? fullscreenStageLayout.layoutMetricsBasisWidth : void 0,
|
|
3785
|
+
videoViewRef: innerRef,
|
|
3786
|
+
visibleByDefault: controlsVisibleByDefault,
|
|
3787
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3788
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles5.column, columnStyle], children: [
|
|
3789
|
+
stageContent,
|
|
3790
|
+
children
|
|
3791
|
+
] }),
|
|
3792
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3793
|
+
MoviieSkinCustomFullscreenModal,
|
|
3794
|
+
{
|
|
3795
|
+
ref: fullscreenModalRef,
|
|
3796
|
+
visible: customFullscreen,
|
|
3797
|
+
onExitComplete: () => setCustomFullscreen(false),
|
|
3798
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles5.fullscreenStage, children: [
|
|
3799
|
+
React.createElement(HostVideoView, {
|
|
3800
|
+
...videoRest,
|
|
3801
|
+
...nativePresentationVideoProps,
|
|
3802
|
+
ref: setRefs,
|
|
3803
|
+
player,
|
|
3804
|
+
nativeControls: effectiveNativeControls,
|
|
3805
|
+
onPictureInPictureStart: handleNativePictureInPictureStart,
|
|
3806
|
+
onPictureInPictureStop: handleNativePictureInPictureStop,
|
|
3807
|
+
contentFit: MOVIIE_SKIN_CUSTOM_FULLSCREEN_VIDEO_CONTENT_FIT,
|
|
3808
|
+
style: reactNative.StyleSheet.absoluteFillObject
|
|
3809
|
+
}),
|
|
3810
|
+
/* @__PURE__ */ jsxRuntime.jsx(MoviieSkinVideoOverlay, {})
|
|
3811
|
+
] })
|
|
3812
|
+
}
|
|
3813
|
+
)
|
|
3814
|
+
] })
|
|
3815
|
+
}
|
|
3816
|
+
);
|
|
3817
|
+
}
|
|
3818
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles5.column, columnStyle], children: [
|
|
3819
|
+
stageContent,
|
|
3820
|
+
children,
|
|
3821
|
+
castAdapter?.renderAndroidProxy?.()
|
|
3822
|
+
] });
|
|
3823
|
+
}
|
|
3824
|
+
);
|
|
3825
|
+
var styles5 = reactNative.StyleSheet.create({
|
|
3826
|
+
column: {
|
|
3827
|
+
alignSelf: "stretch",
|
|
3828
|
+
width: "100%"
|
|
3829
|
+
},
|
|
3830
|
+
videoStage: {
|
|
3831
|
+
overflow: "hidden",
|
|
3832
|
+
position: "relative",
|
|
3833
|
+
width: "100%"
|
|
3834
|
+
},
|
|
3835
|
+
videoStageClipNone: {
|
|
3836
|
+
overflow: "visible"
|
|
3837
|
+
},
|
|
3838
|
+
videoFill: {
|
|
3839
|
+
flex: 1,
|
|
3840
|
+
width: "100%",
|
|
3841
|
+
alignSelf: "stretch"
|
|
3842
|
+
},
|
|
3843
|
+
fullscreenStage: {
|
|
3844
|
+
flex: 1,
|
|
3845
|
+
position: "relative",
|
|
3846
|
+
width: "100%"
|
|
3847
|
+
},
|
|
3848
|
+
shellLayer: {
|
|
3849
|
+
zIndex: 1
|
|
3850
|
+
}
|
|
3851
|
+
});
|
|
3852
|
+
var MoviieErrorBoundary = class extends React__default.default.Component {
|
|
3853
|
+
state = { error: null };
|
|
3854
|
+
static getDerivedStateFromError(error) {
|
|
3855
|
+
return { error };
|
|
3856
|
+
}
|
|
3857
|
+
componentDidCatch(error, info) {
|
|
3858
|
+
if (this.props.onError != null) {
|
|
3859
|
+
try {
|
|
3860
|
+
this.props.onError(error, info);
|
|
3861
|
+
} catch {
|
|
3862
|
+
}
|
|
3863
|
+
}
|
|
3864
|
+
}
|
|
3865
|
+
reset = () => {
|
|
3866
|
+
this.setState({ error: null });
|
|
3867
|
+
};
|
|
3868
|
+
render() {
|
|
3869
|
+
if (this.state.error != null) {
|
|
3870
|
+
if (this.props.fallback != null) {
|
|
3871
|
+
return this.props.fallback({
|
|
3872
|
+
error: this.state.error,
|
|
3873
|
+
reset: this.reset
|
|
3874
|
+
});
|
|
3875
|
+
}
|
|
3876
|
+
return null;
|
|
3877
|
+
}
|
|
3878
|
+
return this.props.children;
|
|
3879
|
+
}
|
|
3880
|
+
};
|
|
3881
|
+
|
|
3882
|
+
Object.defineProperty(exports, "PLAYER_API_EVENTS", {
|
|
3883
|
+
enumerable: true,
|
|
3884
|
+
get: function () { return playerTypes.PLAYER_API_EVENTS; }
|
|
3885
|
+
});
|
|
3886
|
+
Object.defineProperty(exports, "PLAYER_API_METHODS", {
|
|
3887
|
+
enumerable: true,
|
|
3888
|
+
get: function () { return playerTypes.PLAYER_API_METHODS; }
|
|
3889
|
+
});
|
|
3890
|
+
Object.defineProperty(exports, "PLAYER_API_PROPERTIES", {
|
|
3891
|
+
enumerable: true,
|
|
3892
|
+
get: function () { return playerTypes.PLAYER_API_PROPERTIES; }
|
|
3893
|
+
});
|
|
3894
|
+
exports.EXPO_PUBLIC_MOVIIE_API_BASE_URL_ENV = EXPO_PUBLIC_MOVIIE_API_BASE_URL_ENV;
|
|
3895
|
+
exports.EXPO_PUBLIC_MOVIIE_EVENTS_BASE_URL_ENV = EXPO_PUBLIC_MOVIIE_EVENTS_BASE_URL_ENV;
|
|
3896
|
+
exports.EXPO_PUBLIC_MOVIIE_WATCH_ORIGIN_ENV = EXPO_PUBLIC_MOVIIE_WATCH_ORIGIN_ENV;
|
|
3897
|
+
exports.MOVIIE_PLAYBACK_MEMORY_CACHE_TTL_MS = MOVIIE_PLAYBACK_MEMORY_CACHE_TTL_MS;
|
|
3898
|
+
exports.MOVIIE_PLAYBACK_PROFILE = MOVIIE_PLAYBACK_PROFILE;
|
|
3899
|
+
exports.MOVIIE_PLAYER_EXPO_EMBED_JS_MARKER_ATTR = MOVIIE_PLAYER_EXPO_EMBED_JS_MARKER_ATTR;
|
|
3900
|
+
exports.MOVIIE_PLAYER_EXPO_PKG_VERSION = MOVIIE_PLAYER_EXPO_PKG_VERSION;
|
|
3901
|
+
exports.MOVIIE_REMEMBER_POSITION_DEBOUNCE_MS = MOVIIE_REMEMBER_POSITION_DEBOUNCE_MS;
|
|
3902
|
+
exports.MOVIIE_REMEMBER_POSITION_STORAGE_PREFIX = MOVIIE_REMEMBER_POSITION_STORAGE_PREFIX;
|
|
3903
|
+
exports.MOVIIE_SKIN_CONTROLS_AUTO_HIDE_MS = MOVIIE_SKIN_CONTROLS_AUTO_HIDE_MS;
|
|
3904
|
+
exports.MOVIIE_SKIN_CONTROL_ICON_PX = MOVIIE_SKIN_CONTROL_ICON_PX;
|
|
3905
|
+
exports.MOVIIE_SKIN_DEFAULT_ACCENT_HEX = MOVIIE_SKIN_DEFAULT_ACCENT_HEX;
|
|
3906
|
+
exports.MOVIIE_SKIN_TIMELINE_END_SNAP_EPSILON_SECONDS = MOVIIE_SKIN_TIMELINE_END_SNAP_EPSILON_SECONDS;
|
|
3907
|
+
exports.MOVIIE_SKIN_VOLUME_LOW_ICON_THRESHOLD = MOVIIE_SKIN_VOLUME_LOW_ICON_THRESHOLD;
|
|
3908
|
+
exports.MOVIIE_VIDEO_DEFAULT_CONTENT_FIT = MOVIIE_VIDEO_DEFAULT_CONTENT_FIT;
|
|
3909
|
+
exports.MOVIIE_VIEWER_TOKEN_SECURE_STORE_KEY = MOVIIE_VIEWER_TOKEN_SECURE_STORE_KEY;
|
|
3910
|
+
exports.MOVIIE_WATCH_EMBED_JS_PATH = MOVIIE_WATCH_EMBED_JS_PATH;
|
|
3911
|
+
exports.MOVIIE_WATCH_ORIGIN_DEFAULT = MOVIIE_WATCH_ORIGIN_DEFAULT;
|
|
3912
|
+
exports.MoviieErrorBoundary = MoviieErrorBoundary;
|
|
3913
|
+
exports.MoviieProvider = MoviieProvider;
|
|
3914
|
+
exports.MoviieVideo = MoviieVideo;
|
|
3915
|
+
exports.SecureStoreViewerTokenStore = SecureStoreViewerTokenStore;
|
|
3916
|
+
exports.addMoviiePlaybackEndedListener = addMoviiePlaybackEndedListener;
|
|
3917
|
+
exports.buildMoviieVideoPresentationProps = buildMoviieVideoPresentationProps;
|
|
3918
|
+
exports.buildMoviieWatchEmbedUrl = buildMoviieWatchEmbedUrl;
|
|
3919
|
+
exports.computeMoviiePlaybackEnded = computeMoviiePlaybackEnded;
|
|
3920
|
+
exports.normalizeWatchOrigin = normalizeWatchOrigin;
|
|
3921
|
+
exports.resolveMoviieWatchOrigin = resolveMoviieWatchOrigin;
|
|
3922
|
+
exports.useMoviieContext = useMoviieContext;
|
|
3923
|
+
exports.useMoviieEvent = useMoviieEvent;
|
|
3924
|
+
exports.useMoviiePlayback = useMoviiePlayback;
|
|
3925
|
+
exports.useMoviiePlaybackEnded = useMoviiePlaybackEnded;
|
|
3926
|
+
exports.useMoviiePlayer = useMoviiePlayer;
|
|
3927
|
+
Object.keys(playerSdk).forEach(function (k) {
|
|
3928
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
3929
|
+
enumerable: true,
|
|
3930
|
+
get: function () { return playerSdk[k]; }
|
|
3931
|
+
});
|
|
3932
|
+
});
|
|
3933
|
+
//# sourceMappingURL=index.cjs.map
|
|
3934
|
+
//# sourceMappingURL=index.cjs.map
|