@hopeplayer/react-native 1.3.1 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -1
- package/dist/HopePlayer.d.ts +14 -2
- package/dist/HopePlayer.d.ts.map +1 -1
- package/dist/hope-player-react-native.js +50 -41
- package/dist/hope-player-react-native.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/player-html.js +34 -8
- package/dist/player-html.js.map +1 -1
- package/dist/playerHtml.d.ts +21 -2
- package/dist/playerHtml.d.ts.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -52,12 +52,51 @@ All [`HopePlayerOptions`](https://umutyaldiz.com/hopecoreplayer/install) are acc
|
|
|
52
52
|
| `css` | `string` | — | CSS added to the WebView page: `--hp-*` theme tokens and `hope-player::part(...)` rules that go in a global stylesheet on the web. Changing it reloads the WebView. |
|
|
53
53
|
| `webViewProps` | `WebViewProps` | — | Extra props for the underlying WebView. |
|
|
54
54
|
|
|
55
|
-
Callbacks: `onReady`, `onPlay`, `onPause`, `onEnded`, `onError(message)`, `onTimeUpdate({ currentTime, duration, paused })` (about every 250 ms), `onQualityChange(label)`, `onRateChange(rate)`, `onAdStart(type)`, `onAdEnd(type)`, `onAdError(message)`, `onItemChange(index, source)`, and `onEvent(type, data)` for every bridge event.
|
|
55
|
+
Callbacks: `onReady`, `onPlay`, `onPause`, `onEnded`, `onError(message)`, `onTimeUpdate({ currentTime, duration, paused })` (about every 250 ms), `onQualityChange(label)`, `onRateChange(rate)`, `onAdStart(type)`, `onAdEnd(type)`, `onAdError(message)`, `onItemChange(index, source)`, `onPluginEvent(event, detail)`, `onAnalytics({ event, metrics })` (with `analytics`), and `onEvent(type, data)` for every bridge event.
|
|
56
|
+
|
|
57
|
+
Ref methods: `play()`, `pause()`, `seek(time)`, `setMuted(muted)`, `toggleStats(force?)`, `postToPlugin(plugin, data)`.
|
|
58
|
+
|
|
59
|
+
## Plugins
|
|
60
|
+
|
|
61
|
+
[Plugins](https://github.com/umutyaldiz/hopecoreplayer/blob/main/docs/PLUGIN_API.md) run inside the WebView, so instead of plugin objects the `plugins` prop takes ES modules — a URL or the module code — that export the plugin as `default` or `plugin`:
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
const BADGE = `export default {
|
|
65
|
+
name: 'badge',
|
|
66
|
+
setup(player, options) {
|
|
67
|
+
const layer = player.ui.addLayer({ position: 'top-left' });
|
|
68
|
+
layer.el.textContent = options.text;
|
|
69
|
+
player.on('badge:native', (e) => (layer.el.textContent = e.detail.text)); // from React Native
|
|
70
|
+
player.ui.addButton({ label: 'Like', icon: 'play', onClick: () => player.emit('like', { at: player.currentTime }) });
|
|
71
|
+
},
|
|
72
|
+
};`;
|
|
73
|
+
|
|
74
|
+
const ref = useRef<HopePlayerHandle>(null);
|
|
75
|
+
|
|
76
|
+
<HopePlayer
|
|
77
|
+
ref={ref}
|
|
78
|
+
src="https://example.com/video.mp4"
|
|
79
|
+
plugins={[
|
|
80
|
+
'https://cdn.example.com/plugins/watermark.js', // URL
|
|
81
|
+
{ url: 'https://cdn.example.com/plugins/ads.js', options: { tag: '…' } },
|
|
82
|
+
{ code: BADGE, options: { text: 'LIVE' } }, // code bundled in the app
|
|
83
|
+
]}
|
|
84
|
+
onPluginEvent={(event, detail) => console.log(event, detail)} // 'badge:like', { at: 12.3 }
|
|
85
|
+
/>;
|
|
86
|
+
|
|
87
|
+
ref.current?.postToPlugin('badge', { text: 'REPLAY' });
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
- `player.emit('x', data)` in a plugin reaches `onPluginEvent('<plugin>:x', data)`; `data` must be JSON-serializable.
|
|
91
|
+
- `postToPlugin(name, data)` dispatches `<plugin>:native` on the player; listen with `player.on('<plugin>:native', (e) => e.detail)`.
|
|
92
|
+
- A plugin given as `code` keeps the same module while the code string is unchanged, so prop updates do not set it up again.
|
|
93
|
+
- Plugin modules cannot use bare imports (`import … from '@hopeplayer/core'`); `definePlugin` is optional — export a plain object.
|
|
56
94
|
|
|
57
95
|
## Notes
|
|
58
96
|
|
|
59
97
|
- **iOS:** inline playback and muted autoplay are enabled (`allowsInlineMediaPlayback`, `mediaPlaybackRequiresUserAction={false}`). The fullscreen button opens the native iOS video player.
|
|
60
98
|
- **Android:** `allowsFullscreenVideo` is enabled for the fullscreen button.
|
|
99
|
+
- **DRM / DASH:** `drm` and DASH sources work inside the WebView like on the web (Widevine on Android, FairPlay on iOS). Function options such as `drm.fairplay.prepareLicenseRequest` cannot cross into the WebView — use a license server that accepts the default binary format, or a plugin.
|
|
61
100
|
- **Offline / no CDN:** by default the WebView loads `@hopeplayer/core` from jsDelivr. To bundle it, serve `node_modules/@hopeplayer/core/dist/` from your own server or app assets and pass `coreUrl`.
|
|
62
101
|
- **Custom WebView setups:** `@hopeplayer/react-native/player-html` exports `buildPlayerHtml()` and `commandScript()` (no React Native dependency) if you want to build your own WebView integration.
|
|
63
102
|
|
package/dist/HopePlayer.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { StyleProp, ViewStyle } from 'react-native';
|
|
2
2
|
import type { WebViewProps } from 'react-native-webview';
|
|
3
|
-
import type { HopePlayerOptions } from '@hopeplayer/core';
|
|
3
|
+
import type { HopeAnalyticsEvent, HopePlayerOptions, HopeQoeMetrics } from '@hopeplayer/core';
|
|
4
|
+
import { type HopeNativePlugin } from './playerHtml';
|
|
4
5
|
export interface HopePlayerTimeUpdate {
|
|
5
6
|
currentTime: number;
|
|
6
7
|
/** Canlı yayında ya da süre henüz bilinmiyorsa null. */
|
|
@@ -11,7 +12,9 @@ export interface HopePlayerTimeUpdate {
|
|
|
11
12
|
* `<hope-player>`'ı bir WebView içinde çalıştırır — React sarmalayıcısıyla aynı seçenekler ve callback'ler.
|
|
12
13
|
* Seçenekler JSON'a çevrilebilir olmalı: fonksiyonlar (ör. `hls.config.xhrSetup`) WebView'a taşınamaz.
|
|
13
14
|
*/
|
|
14
|
-
export interface HopePlayerProps extends HopePlayerOptions {
|
|
15
|
+
export interface HopePlayerProps extends Omit<HopePlayerOptions, 'plugins'> {
|
|
16
|
+
/** WebView'da çalışan eklentiler: modül adresi ya da kodu (`{ url | code, options }`). */
|
|
17
|
+
plugins?: HopeNativePlugin[];
|
|
15
18
|
/** Player kutusu — 16:9 için `{ width: '100%', aspectRatio: 16 / 9 }`. */
|
|
16
19
|
style?: StyleProp<ViewStyle>;
|
|
17
20
|
/** @hopeplayer/core ESM giriş dosyası. Varsayılan: jsDelivr, bu paketle aynı sürüm. Kendi sunucunuzdan sunmak için verin. */
|
|
@@ -39,6 +42,13 @@ export interface HopePlayerProps extends HopePlayerOptions {
|
|
|
39
42
|
onAdEnd?: (type: 'preroll' | 'midroll' | 'postroll') => void;
|
|
40
43
|
onAdError?: (message: string) => void;
|
|
41
44
|
onItemChange?: (index: number, source: 'playlist' | 'story') => void;
|
|
45
|
+
/** `analytics` açıkken her izlenme olayı ve o anki QoE ölçümleri. */
|
|
46
|
+
onAnalytics?: (detail: {
|
|
47
|
+
event: HopeAnalyticsEvent;
|
|
48
|
+
metrics: HopeQoeMetrics;
|
|
49
|
+
}) => void;
|
|
50
|
+
/** Eklentinin `player.emit('x', data)` olayı → `('<eklenti>:x', data)`. */
|
|
51
|
+
onPluginEvent?: (event: string, detail: unknown) => void;
|
|
42
52
|
/** Köprüden gelen her olay (ham) — yukarıdaki callback'lerde olmayanlar için. */
|
|
43
53
|
onEvent?: (type: string, data: unknown) => void;
|
|
44
54
|
}
|
|
@@ -50,6 +60,8 @@ export interface HopePlayerHandle {
|
|
|
50
60
|
setMuted(muted: boolean): void;
|
|
51
61
|
/** Teknik istatistik paneli (`force`: true aç, false kapat). */
|
|
52
62
|
toggleStats(force?: boolean): void;
|
|
63
|
+
/** Eklentiye veri gönderir; eklentide `player.on('<eklenti>:native', (e) => e.detail)`. */
|
|
64
|
+
postToPlugin(plugin: string, data?: unknown): void;
|
|
53
65
|
}
|
|
54
66
|
export declare const HopePlayer: import("react").ForwardRefExoticComponent<HopePlayerProps & import("react").RefAttributes<HopePlayerHandle>>;
|
|
55
67
|
//# sourceMappingURL=HopePlayer.d.ts.map
|
package/dist/HopePlayer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HopePlayer.d.ts","sourceRoot":"","sources":["../src/HopePlayer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzD,OAAO,KAAK,EAAuB,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"HopePlayer.d.ts","sourceRoot":"","sources":["../src/HopePlayer.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { forwardRef as
|
|
3
|
-
import { WebView as
|
|
4
|
-
import { buildPlayerHtml as
|
|
5
|
-
import { DEFAULT_CORE_URL as
|
|
6
|
-
const
|
|
1
|
+
import { jsx as V } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as x, useRef as l, useMemo as J, useCallback as g, useEffect as H, useImperativeHandle as T } from "react";
|
|
3
|
+
import { WebView as j } from "react-native-webview";
|
|
4
|
+
import { buildPlayerHtml as L, commandScript as q } from "./player-html.js";
|
|
5
|
+
import { DEFAULT_CORE_URL as X, HOPE_PLAYER_RN_VERSION as Z } from "./player-html.js";
|
|
6
|
+
const F = [
|
|
7
7
|
"style",
|
|
8
8
|
"coreUrl",
|
|
9
9
|
"baseUrl",
|
|
@@ -22,43 +22,46 @@ const L = [
|
|
|
22
22
|
"onAdEnd",
|
|
23
23
|
"onAdError",
|
|
24
24
|
"onItemChange",
|
|
25
|
+
"onPluginEvent",
|
|
26
|
+
"onAnalytics",
|
|
25
27
|
"onEvent"
|
|
26
28
|
];
|
|
27
|
-
function
|
|
28
|
-
const r = { ...
|
|
29
|
-
for (const i of
|
|
29
|
+
function Q(k) {
|
|
30
|
+
const r = { ...k };
|
|
31
|
+
for (const i of F) delete r[i];
|
|
30
32
|
return r;
|
|
31
33
|
}
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
s.current =
|
|
35
|
-
const d = l(
|
|
34
|
+
const z = x(function(r, i) {
|
|
35
|
+
const m = l(null), u = JSON.stringify(Q(r)), s = l(u);
|
|
36
|
+
s.current = u;
|
|
37
|
+
const d = l(u), y = l(!1), f = l(r);
|
|
36
38
|
f.current = r;
|
|
37
|
-
const
|
|
39
|
+
const I = J(() => (y.current = !1, d.current = s.current, L({
|
|
38
40
|
options: JSON.parse(s.current),
|
|
39
41
|
coreUrl: r.coreUrl,
|
|
40
42
|
backgroundColor: r.backgroundColor,
|
|
41
43
|
css: r.css
|
|
42
44
|
})), [r.coreUrl, r.backgroundColor, r.css]), o = g((a) => {
|
|
43
45
|
var t;
|
|
44
|
-
(t =
|
|
45
|
-
}, []),
|
|
46
|
+
(t = m.current) == null || t.injectJavaScript(q(a));
|
|
47
|
+
}, []), c = g(() => {
|
|
46
48
|
!y.current || s.current === d.current || (d.current = s.current, o({ type: "options", options: JSON.parse(s.current) }));
|
|
47
49
|
}, [o]);
|
|
48
|
-
|
|
50
|
+
H(c, [u, c]), T(
|
|
49
51
|
i,
|
|
50
52
|
() => ({
|
|
51
53
|
play: () => o({ type: "play" }),
|
|
52
54
|
pause: () => o({ type: "pause" }),
|
|
53
55
|
seek: (a) => o({ type: "seek", time: a }),
|
|
54
56
|
setMuted: (a) => o({ type: "muted", value: a }),
|
|
55
|
-
toggleStats: (a) => o({ type: "toggleStats", force: a })
|
|
57
|
+
toggleStats: (a) => o({ type: "toggleStats", force: a }),
|
|
58
|
+
postToPlugin: (a, t) => o({ type: "pluginMessage", plugin: a, data: t })
|
|
56
59
|
}),
|
|
57
60
|
[o]
|
|
58
61
|
);
|
|
59
|
-
const
|
|
62
|
+
const M = g(
|
|
60
63
|
(a) => {
|
|
61
|
-
var
|
|
64
|
+
var p, E, P, S, C, h, R, b, v, w, A, U, O, N, _;
|
|
62
65
|
let t;
|
|
63
66
|
try {
|
|
64
67
|
t = JSON.parse(a.nativeEvent.data);
|
|
@@ -69,10 +72,10 @@ const D = V(function(r, i) {
|
|
|
69
72
|
const e = f.current, n = t.data ?? {};
|
|
70
73
|
switch (t.type) {
|
|
71
74
|
case "ready":
|
|
72
|
-
y.current = !0,
|
|
75
|
+
y.current = !0, c(), (p = e.onReady) == null || p.call(e);
|
|
73
76
|
break;
|
|
74
77
|
case "play":
|
|
75
|
-
(
|
|
78
|
+
(E = e.onPlay) == null || E.call(e);
|
|
76
79
|
break;
|
|
77
80
|
case "pause":
|
|
78
81
|
(P = e.onPause) == null || P.call(e);
|
|
@@ -84,38 +87,44 @@ const D = V(function(r, i) {
|
|
|
84
87
|
(C = e.onError) == null || C.call(e, String(n.message ?? "error"));
|
|
85
88
|
break;
|
|
86
89
|
case "timeupdate":
|
|
87
|
-
(
|
|
90
|
+
(h = e.onTimeUpdate) == null || h.call(e, n);
|
|
88
91
|
break;
|
|
89
92
|
case "qualitychange":
|
|
90
|
-
(
|
|
93
|
+
(R = e.onQualityChange) == null || R.call(e, String(n.label));
|
|
91
94
|
break;
|
|
92
95
|
case "ratechange":
|
|
93
|
-
(
|
|
96
|
+
(b = e.onRateChange) == null || b.call(e, Number(n.rate));
|
|
94
97
|
break;
|
|
95
98
|
case "adstart":
|
|
96
|
-
(
|
|
99
|
+
(v = e.onAdStart) == null || v.call(e, n.type);
|
|
97
100
|
break;
|
|
98
101
|
case "adend":
|
|
99
|
-
(
|
|
102
|
+
(w = e.onAdEnd) == null || w.call(e, n.type);
|
|
100
103
|
break;
|
|
101
104
|
case "aderror":
|
|
102
|
-
(
|
|
105
|
+
(A = e.onAdError) == null || A.call(e, String(n.message));
|
|
103
106
|
break;
|
|
104
107
|
case "itemchange":
|
|
105
|
-
(
|
|
108
|
+
(U = e.onItemChange) == null || U.call(e, Number(n.index), n.source);
|
|
109
|
+
break;
|
|
110
|
+
case "analytics":
|
|
111
|
+
(O = e.onAnalytics) == null || O.call(e, n);
|
|
112
|
+
break;
|
|
113
|
+
case "plugin":
|
|
114
|
+
(N = e.onPluginEvent) == null || N.call(e, String(n.event), n.detail);
|
|
106
115
|
break;
|
|
107
116
|
}
|
|
108
|
-
(
|
|
117
|
+
(_ = e.onEvent) == null || _.call(e, t.type, t.data);
|
|
109
118
|
},
|
|
110
|
-
[
|
|
119
|
+
[c]
|
|
111
120
|
);
|
|
112
|
-
return /* @__PURE__ */
|
|
113
|
-
|
|
121
|
+
return /* @__PURE__ */ V(
|
|
122
|
+
j,
|
|
114
123
|
{
|
|
115
|
-
ref:
|
|
124
|
+
ref: m,
|
|
116
125
|
originWhitelist: ["*"],
|
|
117
|
-
source: { html:
|
|
118
|
-
onMessage:
|
|
126
|
+
source: { html: I, baseUrl: r.baseUrl },
|
|
127
|
+
onMessage: M,
|
|
119
128
|
javaScriptEnabled: !0,
|
|
120
129
|
domStorageEnabled: !0,
|
|
121
130
|
allowsInlineMediaPlayback: !0,
|
|
@@ -132,10 +141,10 @@ const D = V(function(r, i) {
|
|
|
132
141
|
);
|
|
133
142
|
});
|
|
134
143
|
export {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
144
|
+
X as DEFAULT_CORE_URL,
|
|
145
|
+
Z as HOPE_PLAYER_RN_VERSION,
|
|
146
|
+
z as HopePlayer,
|
|
147
|
+
L as buildPlayerHtml,
|
|
148
|
+
q as commandScript
|
|
140
149
|
};
|
|
141
150
|
//# sourceMappingURL=hope-player-react-native.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hope-player-react-native.js","sources":["../src/HopePlayer.tsx"],"sourcesContent":["import { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef } from 'react';\nimport type { StyleProp, ViewStyle } from 'react-native';\nimport { WebView } from 'react-native-webview';\nimport type { WebViewMessageEvent, WebViewProps } from 'react-native-webview';\nimport type { HopePlayerOptions } from '@hopeplayer/core';\nimport { buildPlayerHtml, commandScript, type HopeBridgeCommand, type HopeBridgeMessage } from './playerHtml';\n\nexport interface HopePlayerTimeUpdate {\n currentTime: number;\n /** Canlı yayında ya da süre henüz bilinmiyorsa null. */\n duration: number | null;\n paused: boolean;\n}\n\n/**\n * `<hope-player>`'ı bir WebView içinde çalıştırır — React sarmalayıcısıyla aynı seçenekler ve callback'ler.\n * Seçenekler JSON'a çevrilebilir olmalı: fonksiyonlar (ör. `hls.config.xhrSetup`) WebView'a taşınamaz.\n */\nexport interface HopePlayerProps extends HopePlayerOptions {\n /** Player kutusu — 16:9 için `{ width: '100%', aspectRatio: 16 / 9 }`. */\n style?: StyleProp<ViewStyle>;\n /** @hopeplayer/core ESM giriş dosyası. Varsayılan: jsDelivr, bu paketle aynı sürüm. Kendi sunucunuzdan sunmak için verin. */\n coreUrl?: string;\n /** WebView sayfasının adresi — göreli medya/altyazı yolları buna göre çözülür, localStorage bu origin'de tutulur. */\n baseUrl?: string;\n /** Player yüklenene kadar görünen arka plan. Varsayılan #000. */\n backgroundColor?: string;\n /**\n * WebView sayfasına eklenen CSS: webde global stylesheet'e yazılan `--hp-*` token'ları ve\n * `hope-player::part(...)` kuralları buraya. Değişince sayfa yeniden yüklenir.\n */\n css?: string;\n /** WebView'a ek prop'lar (ör. `onShouldStartLoadWithRequest`). */\n webViewProps?: Omit<WebViewProps, 'source' | 'onMessage' | 'style' | 'containerStyle'>;\n onReady?: () => void;\n onPlay?: () => void;\n onPause?: () => void;\n onEnded?: () => void;\n onError?: (message: string) => void;\n onTimeUpdate?: (time: HopePlayerTimeUpdate) => void;\n onQualityChange?: (label: string) => void;\n onRateChange?: (rate: number) => void;\n onAdStart?: (type: 'preroll' | 'midroll' | 'postroll') => void;\n onAdEnd?: (type: 'preroll' | 'midroll' | 'postroll') => void;\n onAdError?: (message: string) => void;\n onItemChange?: (index: number, source: 'playlist' | 'story') => void;\n /** Köprüden gelen her olay (ham) — yukarıdaki callback'lerde olmayanlar için. */\n onEvent?: (type: string, data: unknown) => void;\n}\n\nexport interface HopePlayerHandle {\n play(): void;\n pause(): void;\n /** Saniye cinsinden konuma git. */\n seek(time: number): void;\n setMuted(muted: boolean): void;\n /** Teknik istatistik paneli (`force`: true aç, false kapat). */\n toggleStats(force?: boolean): void;\n}\n\nconst NATIVE_PROP_KEYS = [\n 'style',\n 'coreUrl',\n 'baseUrl',\n 'backgroundColor',\n 'css',\n 'webViewProps',\n 'onReady',\n 'onPlay',\n 'onPause',\n 'onEnded',\n 'onError',\n 'onTimeUpdate',\n 'onQualityChange',\n 'onRateChange',\n 'onAdStart',\n 'onAdEnd',\n 'onAdError',\n 'onItemChange',\n 'onEvent',\n] as const;\n\nfunction splitProps(props: HopePlayerProps): HopePlayerOptions {\n const options: Record<string, unknown> = { ...props };\n for (const key of NATIVE_PROP_KEYS) delete options[key];\n return options as HopePlayerOptions;\n}\n\nexport const HopePlayer = forwardRef<HopePlayerHandle, HopePlayerProps>(function HopePlayer(props, ref) {\n // react-native-webview `WebView<P = undefined>` — varsayılan P ile prop tipi `never`'a düşüyor (React 19 tiplerinde\n // ref verilince hata); açık `object` generic'i bunu önler.\n const webViewRef = useRef<WebView<object>>(null);\n const optionsJson = JSON.stringify(splitProps(props));\n // En güncel seçenekler / sayfaya son giden seçenekler. Sayfa yalnızca coreUrl/arka plan/css değişince yeniden\n // kurulur; seçenek değişiklikleri yeniden yüklemeden komutla gider.\n const latestOptions = useRef(optionsJson);\n latestOptions.current = optionsJson;\n const sentOptions = useRef(optionsJson);\n const ready = useRef(false);\n const callbacks = useRef(props);\n callbacks.current = props;\n\n const html = useMemo(() => {\n ready.current = false;\n sentOptions.current = latestOptions.current;\n return buildPlayerHtml({\n options: JSON.parse(latestOptions.current) as HopePlayerOptions,\n coreUrl: props.coreUrl,\n backgroundColor: props.backgroundColor,\n css: props.css,\n });\n }, [props.coreUrl, props.backgroundColor, props.css]);\n\n const send = useCallback((cmd: HopeBridgeCommand) => {\n webViewRef.current?.injectJavaScript(commandScript(cmd));\n }, []);\n\n const syncOptions = useCallback(() => {\n if (!ready.current || latestOptions.current === sentOptions.current) return;\n sentOptions.current = latestOptions.current;\n send({ type: 'options', options: JSON.parse(latestOptions.current) as HopePlayerOptions });\n }, [send]);\n\n useEffect(syncOptions, [optionsJson, syncOptions]);\n\n useImperativeHandle(\n ref,\n () => ({\n play: () => send({ type: 'play' }),\n pause: () => send({ type: 'pause' }),\n seek: (time) => send({ type: 'seek', time }),\n setMuted: (value) => send({ type: 'muted', value }),\n toggleStats: (force) => send({ type: 'toggleStats', force }),\n }),\n [send]\n );\n\n const onMessage = useCallback(\n (event: WebViewMessageEvent) => {\n let msg: HopeBridgeMessage;\n try {\n msg = JSON.parse(event.nativeEvent.data) as HopeBridgeMessage;\n } catch {\n return;\n }\n if (!msg || msg.__hope !== 1) return;\n const cb = callbacks.current;\n const data = (msg.data ?? {}) as Record<string, unknown>;\n switch (msg.type) {\n case 'ready':\n ready.current = true;\n // Sayfa kurulurken seçenekler değiştiyse son hâlini gönder.\n syncOptions();\n cb.onReady?.();\n break;\n case 'play':\n cb.onPlay?.();\n break;\n case 'pause':\n cb.onPause?.();\n break;\n case 'ended':\n cb.onEnded?.();\n break;\n case 'error':\n cb.onError?.(String(data.message ?? 'error'));\n break;\n case 'timeupdate':\n cb.onTimeUpdate?.(data as unknown as HopePlayerTimeUpdate);\n break;\n case 'qualitychange':\n cb.onQualityChange?.(String(data.label));\n break;\n case 'ratechange':\n cb.onRateChange?.(Number(data.rate));\n break;\n case 'adstart':\n cb.onAdStart?.(data.type as 'preroll' | 'midroll' | 'postroll');\n break;\n case 'adend':\n cb.onAdEnd?.(data.type as 'preroll' | 'midroll' | 'postroll');\n break;\n case 'aderror':\n cb.onAdError?.(String(data.message));\n break;\n case 'itemchange':\n cb.onItemChange?.(Number(data.index), data.source as 'playlist' | 'story');\n break;\n }\n cb.onEvent?.(msg.type, msg.data);\n },\n [syncOptions]\n );\n\n return (\n <WebView<object>\n ref={webViewRef}\n originWhitelist={['*']}\n source={{ html, baseUrl: props.baseUrl }}\n onMessage={onMessage}\n javaScriptEnabled\n domStorageEnabled\n // iOS: video sayfa içinde oynasın (tam ekrana zorlanmasın); otomatik oynatma muted iken çalışsın.\n allowsInlineMediaPlayback\n mediaPlaybackRequiresUserAction={false}\n allowsPictureInPictureMediaPlayback\n // Android: player'ın tam ekran butonu için.\n allowsFullscreenVideo\n scrollEnabled={false}\n bounces={false}\n overScrollMode=\"never\"\n {...props.webViewProps}\n // Kutu boyutu WebView'ın dış sarmalayıcısına verilir. Sarmalayıcı varsayılan olarak `flex: 1` olduğundan\n // boş alanı doldurmak için uzuyordu; `aspectRatio` içteki WebView'a gidince genişlik bu uzamış yükseklikten\n // hesaplanıyor, player ekrandan taşıp sağdan kesiliyordu. `flex: 0` + kullanıcının style'ı, WebView da kutuyu doldurur.\n containerStyle={[{ flex: 0, backgroundColor: props.backgroundColor ?? '#000' }, props.style]}\n style={{ flex: 1, backgroundColor: props.backgroundColor ?? '#000' }}\n />\n );\n});\n"],"names":["NATIVE_PROP_KEYS","splitProps","props","options","key","HopePlayer","forwardRef","ref","webViewRef","useRef","optionsJson","latestOptions","sentOptions","ready","callbacks","html","useMemo","buildPlayerHtml","send","useCallback","cmd","_a","commandScript","syncOptions","useEffect","useImperativeHandle","time","value","force","onMessage","event","msg","cb","data","_b","_c","_d","_e","_f","_g","_h","_i","_j","_k","_l","_m","jsx","WebView"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"hope-player-react-native.js","sources":["../src/HopePlayer.tsx"],"sourcesContent":["import { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef } from 'react';\nimport type { StyleProp, ViewStyle } from 'react-native';\nimport { WebView } from 'react-native-webview';\nimport type { WebViewMessageEvent, WebViewProps } from 'react-native-webview';\nimport type { HopeAnalyticsEvent, HopePlayerOptions, HopeQoeMetrics } from '@hopeplayer/core';\nimport { buildPlayerHtml, commandScript, type HopeBridgeCommand, type HopeBridgeMessage, type HopeNativeOptions, type HopeNativePlugin } from './playerHtml';\n\nexport interface HopePlayerTimeUpdate {\n currentTime: number;\n /** Canlı yayında ya da süre henüz bilinmiyorsa null. */\n duration: number | null;\n paused: boolean;\n}\n\n/**\n * `<hope-player>`'ı bir WebView içinde çalıştırır — React sarmalayıcısıyla aynı seçenekler ve callback'ler.\n * Seçenekler JSON'a çevrilebilir olmalı: fonksiyonlar (ör. `hls.config.xhrSetup`) WebView'a taşınamaz.\n */\nexport interface HopePlayerProps extends Omit<HopePlayerOptions, 'plugins'> {\n /** WebView'da çalışan eklentiler: modül adresi ya da kodu (`{ url | code, options }`). */\n plugins?: HopeNativePlugin[];\n /** Player kutusu — 16:9 için `{ width: '100%', aspectRatio: 16 / 9 }`. */\n style?: StyleProp<ViewStyle>;\n /** @hopeplayer/core ESM giriş dosyası. Varsayılan: jsDelivr, bu paketle aynı sürüm. Kendi sunucunuzdan sunmak için verin. */\n coreUrl?: string;\n /** WebView sayfasının adresi — göreli medya/altyazı yolları buna göre çözülür, localStorage bu origin'de tutulur. */\n baseUrl?: string;\n /** Player yüklenene kadar görünen arka plan. Varsayılan #000. */\n backgroundColor?: string;\n /**\n * WebView sayfasına eklenen CSS: webde global stylesheet'e yazılan `--hp-*` token'ları ve\n * `hope-player::part(...)` kuralları buraya. Değişince sayfa yeniden yüklenir.\n */\n css?: string;\n /** WebView'a ek prop'lar (ör. `onShouldStartLoadWithRequest`). */\n webViewProps?: Omit<WebViewProps, 'source' | 'onMessage' | 'style' | 'containerStyle'>;\n onReady?: () => void;\n onPlay?: () => void;\n onPause?: () => void;\n onEnded?: () => void;\n onError?: (message: string) => void;\n onTimeUpdate?: (time: HopePlayerTimeUpdate) => void;\n onQualityChange?: (label: string) => void;\n onRateChange?: (rate: number) => void;\n onAdStart?: (type: 'preroll' | 'midroll' | 'postroll') => void;\n onAdEnd?: (type: 'preroll' | 'midroll' | 'postroll') => void;\n onAdError?: (message: string) => void;\n onItemChange?: (index: number, source: 'playlist' | 'story') => void;\n /** `analytics` açıkken her izlenme olayı ve o anki QoE ölçümleri. */\n onAnalytics?: (detail: { event: HopeAnalyticsEvent; metrics: HopeQoeMetrics }) => void;\n /** Eklentinin `player.emit('x', data)` olayı → `('<eklenti>:x', data)`. */\n onPluginEvent?: (event: string, detail: unknown) => void;\n /** Köprüden gelen her olay (ham) — yukarıdaki callback'lerde olmayanlar için. */\n onEvent?: (type: string, data: unknown) => void;\n}\n\nexport interface HopePlayerHandle {\n play(): void;\n pause(): void;\n /** Saniye cinsinden konuma git. */\n seek(time: number): void;\n setMuted(muted: boolean): void;\n /** Teknik istatistik paneli (`force`: true aç, false kapat). */\n toggleStats(force?: boolean): void;\n /** Eklentiye veri gönderir; eklentide `player.on('<eklenti>:native', (e) => e.detail)`. */\n postToPlugin(plugin: string, data?: unknown): void;\n}\n\nconst NATIVE_PROP_KEYS = [\n 'style',\n 'coreUrl',\n 'baseUrl',\n 'backgroundColor',\n 'css',\n 'webViewProps',\n 'onReady',\n 'onPlay',\n 'onPause',\n 'onEnded',\n 'onError',\n 'onTimeUpdate',\n 'onQualityChange',\n 'onRateChange',\n 'onAdStart',\n 'onAdEnd',\n 'onAdError',\n 'onItemChange',\n 'onPluginEvent',\n 'onAnalytics',\n 'onEvent',\n] as const;\n\nfunction splitProps(props: HopePlayerProps): HopeNativeOptions {\n const options: Record<string, unknown> = { ...props };\n for (const key of NATIVE_PROP_KEYS) delete options[key];\n return options as HopeNativeOptions;\n}\n\nexport const HopePlayer = forwardRef<HopePlayerHandle, HopePlayerProps>(function HopePlayer(props, ref) {\n // react-native-webview `WebView<P = undefined>` — varsayılan P ile prop tipi `never`'a düşüyor (React 19 tiplerinde\n // ref verilince hata); açık `object` generic'i bunu önler.\n const webViewRef = useRef<WebView<object>>(null);\n const optionsJson = JSON.stringify(splitProps(props));\n // En güncel seçenekler / sayfaya son giden seçenekler. Sayfa yalnızca coreUrl/arka plan/css değişince yeniden\n // kurulur; seçenek değişiklikleri yeniden yüklemeden komutla gider.\n const latestOptions = useRef(optionsJson);\n latestOptions.current = optionsJson;\n const sentOptions = useRef(optionsJson);\n const ready = useRef(false);\n const callbacks = useRef(props);\n callbacks.current = props;\n\n const html = useMemo(() => {\n ready.current = false;\n sentOptions.current = latestOptions.current;\n return buildPlayerHtml({\n options: JSON.parse(latestOptions.current) as HopeNativeOptions,\n coreUrl: props.coreUrl,\n backgroundColor: props.backgroundColor,\n css: props.css,\n });\n }, [props.coreUrl, props.backgroundColor, props.css]);\n\n const send = useCallback((cmd: HopeBridgeCommand) => {\n webViewRef.current?.injectJavaScript(commandScript(cmd));\n }, []);\n\n const syncOptions = useCallback(() => {\n if (!ready.current || latestOptions.current === sentOptions.current) return;\n sentOptions.current = latestOptions.current;\n send({ type: 'options', options: JSON.parse(latestOptions.current) as HopeNativeOptions });\n }, [send]);\n\n useEffect(syncOptions, [optionsJson, syncOptions]);\n\n useImperativeHandle(\n ref,\n () => ({\n play: () => send({ type: 'play' }),\n pause: () => send({ type: 'pause' }),\n seek: (time) => send({ type: 'seek', time }),\n setMuted: (value) => send({ type: 'muted', value }),\n toggleStats: (force) => send({ type: 'toggleStats', force }),\n postToPlugin: (plugin, data) => send({ type: 'pluginMessage', plugin, data }),\n }),\n [send]\n );\n\n const onMessage = useCallback(\n (event: WebViewMessageEvent) => {\n let msg: HopeBridgeMessage;\n try {\n msg = JSON.parse(event.nativeEvent.data) as HopeBridgeMessage;\n } catch {\n return;\n }\n if (!msg || msg.__hope !== 1) return;\n const cb = callbacks.current;\n const data = (msg.data ?? {}) as Record<string, unknown>;\n switch (msg.type) {\n case 'ready':\n ready.current = true;\n // Sayfa kurulurken seçenekler değiştiyse son hâlini gönder.\n syncOptions();\n cb.onReady?.();\n break;\n case 'play':\n cb.onPlay?.();\n break;\n case 'pause':\n cb.onPause?.();\n break;\n case 'ended':\n cb.onEnded?.();\n break;\n case 'error':\n cb.onError?.(String(data.message ?? 'error'));\n break;\n case 'timeupdate':\n cb.onTimeUpdate?.(data as unknown as HopePlayerTimeUpdate);\n break;\n case 'qualitychange':\n cb.onQualityChange?.(String(data.label));\n break;\n case 'ratechange':\n cb.onRateChange?.(Number(data.rate));\n break;\n case 'adstart':\n cb.onAdStart?.(data.type as 'preroll' | 'midroll' | 'postroll');\n break;\n case 'adend':\n cb.onAdEnd?.(data.type as 'preroll' | 'midroll' | 'postroll');\n break;\n case 'aderror':\n cb.onAdError?.(String(data.message));\n break;\n case 'itemchange':\n cb.onItemChange?.(Number(data.index), data.source as 'playlist' | 'story');\n break;\n case 'analytics':\n cb.onAnalytics?.(data as unknown as { event: HopeAnalyticsEvent; metrics: HopeQoeMetrics });\n break;\n case 'plugin':\n cb.onPluginEvent?.(String(data.event), data.detail);\n break;\n }\n cb.onEvent?.(msg.type, msg.data);\n },\n [syncOptions]\n );\n\n return (\n <WebView<object>\n ref={webViewRef}\n originWhitelist={['*']}\n source={{ html, baseUrl: props.baseUrl }}\n onMessage={onMessage}\n javaScriptEnabled\n domStorageEnabled\n // iOS: video sayfa içinde oynasın (tam ekrana zorlanmasın); otomatik oynatma muted iken çalışsın.\n allowsInlineMediaPlayback\n mediaPlaybackRequiresUserAction={false}\n allowsPictureInPictureMediaPlayback\n // Android: player'ın tam ekran butonu için.\n allowsFullscreenVideo\n scrollEnabled={false}\n bounces={false}\n overScrollMode=\"never\"\n {...props.webViewProps}\n // Kutu boyutu WebView'ın dış sarmalayıcısına verilir. Sarmalayıcı varsayılan olarak `flex: 1` olduğundan\n // boş alanı doldurmak için uzuyordu; `aspectRatio` içteki WebView'a gidince genişlik bu uzamış yükseklikten\n // hesaplanıyor, player ekrandan taşıp sağdan kesiliyordu. `flex: 0` + kullanıcının style'ı, WebView da kutuyu doldurur.\n containerStyle={[{ flex: 0, backgroundColor: props.backgroundColor ?? '#000' }, props.style]}\n style={{ flex: 1, backgroundColor: props.backgroundColor ?? '#000' }}\n />\n );\n});\n"],"names":["NATIVE_PROP_KEYS","splitProps","props","options","key","HopePlayer","forwardRef","ref","webViewRef","useRef","optionsJson","latestOptions","sentOptions","ready","callbacks","html","useMemo","buildPlayerHtml","send","useCallback","cmd","_a","commandScript","syncOptions","useEffect","useImperativeHandle","time","value","force","plugin","data","onMessage","event","msg","cb","_b","_c","_d","_e","_f","_g","_h","_i","_j","_k","_l","_m","_n","_o","jsx","WebView"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { HopePlayer } from './HopePlayer';
|
|
2
2
|
export type { HopePlayerProps, HopePlayerHandle, HopePlayerTimeUpdate } from './HopePlayer';
|
|
3
3
|
export { buildPlayerHtml, commandScript, DEFAULT_CORE_URL, HOPE_PLAYER_RN_VERSION } from './playerHtml';
|
|
4
|
-
export type { PlayerHtmlConfig, HopeBridgeCommand, HopeBridgeMessage } from './playerHtml';
|
|
4
|
+
export type { PlayerHtmlConfig, HopeBridgeCommand, HopeBridgeMessage, HopeNativePlugin, HopeNativeOptions } from './playerHtml';
|
|
5
5
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAC5F,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACxG,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAC5F,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACxG,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/player-html.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const o = "1.5.0", d = `https://cdn.jsdelivr.net/npm/@hopeplayer/core@${o}/dist/hope-player.js`, s = [
|
|
2
2
|
"hp:play",
|
|
3
3
|
"hp:pause",
|
|
4
4
|
"hp:ended",
|
|
@@ -9,13 +9,14 @@ const i = "1.3.1", d = `https://cdn.jsdelivr.net/npm/@hopeplayer/core@${i}/dist/
|
|
|
9
9
|
"hp:adend",
|
|
10
10
|
"hp:aderror",
|
|
11
11
|
"hp:itemchange",
|
|
12
|
-
"hp:pausead"
|
|
12
|
+
"hp:pausead",
|
|
13
|
+
"hp:analytics"
|
|
13
14
|
], l = "\u2028", p = "\u2029";
|
|
14
15
|
function t(e) {
|
|
15
16
|
return JSON.stringify(e).split("<").join("\\u003c").split(l).join("\\u2028").split(p).join("\\u2029");
|
|
16
17
|
}
|
|
17
18
|
function c(e) {
|
|
18
|
-
const a = e.coreUrl ?? d, r = e.backgroundColor ?? "#000",
|
|
19
|
+
const a = e.coreUrl ?? d, r = e.backgroundColor ?? "#000", n = e.timeUpdateIntervalMs ?? 250, i = (e.css ?? "").split("</").join("<\\/");
|
|
19
20
|
return `<!DOCTYPE html>
|
|
20
21
|
<html>
|
|
21
22
|
<head>
|
|
@@ -24,7 +25,7 @@ function c(e) {
|
|
|
24
25
|
<style>
|
|
25
26
|
html, body { margin: 0; padding: 0; width: 100%; height: 100%; overflow: hidden; background: ${r}; }
|
|
26
27
|
hope-player { display: block; width: 100%; }
|
|
27
|
-
${
|
|
28
|
+
${i}
|
|
28
29
|
</style>
|
|
29
30
|
</head>
|
|
30
31
|
<body>
|
|
@@ -48,7 +49,31 @@ try {
|
|
|
48
49
|
}
|
|
49
50
|
await customElements.whenDefined('hope-player');
|
|
50
51
|
const el = document.getElementById('hope-player');
|
|
51
|
-
|
|
52
|
+
|
|
53
|
+
// Eklentiler: adres → import(); kod → Blob URL (aynı kod aynı modül, yeniden kurulmaz).
|
|
54
|
+
const blobUrls = new Map();
|
|
55
|
+
const pluginEntries = (list) => (Array.isArray(list) ? list : []).map((p) => {
|
|
56
|
+
const d = typeof p === 'string' ? { url: p } : p || {};
|
|
57
|
+
let url = d.url;
|
|
58
|
+
if (!url && typeof d.code === 'string') {
|
|
59
|
+
url = blobUrls.get(d.code);
|
|
60
|
+
if (!url) blobUrls.set(d.code, (url = URL.createObjectURL(new Blob([d.code], { type: 'text/javascript' }))));
|
|
61
|
+
}
|
|
62
|
+
return [() => import(url), d.options];
|
|
63
|
+
});
|
|
64
|
+
const setOptions = (o) => { el.options = { ...o, plugins: pluginEntries(o && o.plugins) }; };
|
|
65
|
+
|
|
66
|
+
// Eklenti olayları (<ad>:<olay>) React Native'e; '<ad>:native' ondan gelir, geri gönderilmez.
|
|
67
|
+
const dispatch = el.dispatchEvent.bind(el);
|
|
68
|
+
el.dispatchEvent = (ev) => {
|
|
69
|
+
const t = ev.type;
|
|
70
|
+
if (t.includes(':') && !t.startsWith('hp:') && !t.endsWith(':native')) {
|
|
71
|
+
try { post('plugin', { event: t, detail: ev.detail === undefined ? null : ev.detail }); } catch (_) { post('plugin', { event: t, detail: null }); }
|
|
72
|
+
}
|
|
73
|
+
return dispatch(ev);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
setOptions(${t(e.options)});
|
|
52
77
|
const video = el.shadowRoot.querySelector('video');
|
|
53
78
|
|
|
54
79
|
for (const name of ${t(s)}) {
|
|
@@ -57,7 +82,7 @@ for (const name of ${t(s)}) {
|
|
|
57
82
|
let lastTimeUpdate = 0;
|
|
58
83
|
const sendTime = (force) => {
|
|
59
84
|
const now = Date.now();
|
|
60
|
-
if (!force && now - lastTimeUpdate < ${
|
|
85
|
+
if (!force && now - lastTimeUpdate < ${n}) return;
|
|
61
86
|
lastTimeUpdate = now;
|
|
62
87
|
post('timeupdate', { currentTime: video.currentTime, duration: Number.isFinite(video.duration) ? video.duration : null, paused: video.paused });
|
|
63
88
|
};
|
|
@@ -87,7 +112,8 @@ const seekTo = (time) => {
|
|
|
87
112
|
|
|
88
113
|
run = (cmd) => {
|
|
89
114
|
switch (cmd && cmd.type) {
|
|
90
|
-
case 'options':
|
|
115
|
+
case 'options': setOptions(cmd.options); break;
|
|
116
|
+
case 'pluginMessage': dispatch(new CustomEvent(cmd.plugin + ':native', { detail: cmd.data === undefined ? null : cmd.data })); break;
|
|
91
117
|
case 'play': video.play().catch((err) => post('error', { message: String(err && err.message ? err.message : err), code: 'play' })); break;
|
|
92
118
|
case 'pause': video.pause(); break;
|
|
93
119
|
case 'seek': seekTo(cmd.time); break;
|
|
@@ -106,7 +132,7 @@ function u(e) {
|
|
|
106
132
|
}
|
|
107
133
|
export {
|
|
108
134
|
d as DEFAULT_CORE_URL,
|
|
109
|
-
|
|
135
|
+
o as HOPE_PLAYER_RN_VERSION,
|
|
110
136
|
c as buildPlayerHtml,
|
|
111
137
|
u as commandScript
|
|
112
138
|
};
|
package/dist/player-html.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"player-html.js","sources":["../src/playerHtml.ts"],"sourcesContent":["import type { HopePlayerOptions } from '@hopeplayer/core';\n\n/** Paket sürümü — build sırasında package.json'dan gömülür; varsayılan core adresi aynı sürüme sabitlenir. */\nexport const HOPE_PLAYER_RN_VERSION: string = __HOPE_VERSION__;\n\n/** Varsayılan core adresi: jsDelivr üzerinden bu paketle aynı sürümdeki @hopeplayer/core. */\nexport const DEFAULT_CORE_URL = `https://cdn.jsdelivr.net/npm/@hopeplayer/core@${HOPE_PLAYER_RN_VERSION}/dist/hope-player.js`;\n\n/** WebView → React Native mesajı. `type`: köprü olayı (ready/timeupdate/error) ya da `hp:` öneki atılmış player olayı. */\nexport interface HopeBridgeMessage {\n __hope: 1;\n type: string;\n data: unknown;\n}\n\n/** React Native → WebView komutu (`window.__hopeCommand`). */\nexport type HopeBridgeCommand =\n | { type: 'options'; options: HopePlayerOptions }\n | { type: 'play' }\n | { type: 'pause' }\n | { type: 'seek'; time: number }\n | { type: 'muted'; value: boolean }\n | { type: 'toggleStats'; force?: boolean };\n\nexport interface PlayerHtmlConfig {\n /** Başlangıç seçenekleri — JSON'a çevrilebilir olmalı (fonksiyonlar WebView'a taşınamaz). */\n options: HopePlayerOptions;\n /** @hopeplayer/core ESM giriş dosyası. Varsayılan: jsDelivr, aynı sürüm. */\n coreUrl?: string;\n /** Sayfa arka planı (player yüklenene kadar görünen). Varsayılan #000. */\n backgroundColor?: string;\n /** WebView sayfasına eklenen CSS — `--hp-*` token'ları ve `hope-player::part(...)` kuralları için. */\n css?: string;\n /** `timeupdate` köprü olayının en sık gönderilme aralığı (ms). Varsayılan 250. */\n timeUpdateIntervalMs?: number;\n}\n\n/** Player'ın yaydığı ve React Native'e aktarılan olaylar (`hp:` öneki atılarak). */\nconst FORWARDED_EVENTS = [\n 'hp:play',\n 'hp:pause',\n 'hp:ended',\n 'hp:error',\n 'hp:qualitychange',\n 'hp:ratechange',\n 'hp:adstart',\n 'hp:adend',\n 'hp:aderror',\n 'hp:itemchange',\n 'hp:pausead',\n];\n\n/** Satır/paragraf ayırıcı — JSON'da geçerli, JS string'inde (eski motorlarda) değil. */\nconst LINE_SEP = String.fromCharCode(0x2028);\nconst PARA_SEP = String.fromCharCode(0x2029);\n\n/** JSON'u <script> içine güvenle gömer (`</script>` ve satır ayırıcıları kaçırılır). */\nfunction inlineJson(value: unknown): string {\n return JSON.stringify(value).split('<').join('\\\\u003c').split(LINE_SEP).join('\\\\u2028').split(PARA_SEP).join('\\\\u2029');\n}\n\n/**\n * WebView'da çalışan sayfa: <hope-player> + köprü. React Native `window.__hopeCommand(...)` ile komut verir\n * (injectJavaScript), sayfa olayları `window.ReactNativeWebView.postMessage` ile geri gönderir.\n */\nexport function buildPlayerHtml(config: PlayerHtmlConfig): string {\n const coreUrl = config.coreUrl ?? DEFAULT_CORE_URL;\n const background = config.backgroundColor ?? '#000';\n const interval = config.timeUpdateIntervalMs ?? 250;\n // `</style` CSS'in içinden <style> etiketini kapatamasın.\n const css = (config.css ?? '').split('</').join('<\\\\/');\n return `<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no\">\n<style>\nhtml, body { margin: 0; padding: 0; width: 100%; height: 100%; overflow: hidden; background: ${background}; }\nhope-player { display: block; width: 100%; }\n${css}\n</style>\n</head>\n<body>\n<hope-player id=\"hope-player\"></hope-player>\n<script type=\"module\">\nconst post = (type, data) => {\n const message = JSON.stringify({ __hope: 1, type, data: data === undefined ? null : data });\n if (window.ReactNativeWebView) window.ReactNativeWebView.postMessage(message);\n else if (window.parent !== window) window.parent.postMessage(message, '*');\n};\n// Player hazır olana kadar gelen komutlar sıraya alınır.\nconst queue = [];\nlet run = null;\nwindow.__hopeCommand = (cmd) => (run ? run(cmd) : queue.push(cmd));\n\ntry {\n await import(${inlineJson(coreUrl)});\n} catch (err) {\n post('error', { message: 'HopePlayer core could not be loaded: ' + (err && err.message ? err.message : String(err)), code: 'core-load' });\n throw err;\n}\nawait customElements.whenDefined('hope-player');\nconst el = document.getElementById('hope-player');\nel.options = ${inlineJson(config.options)};\nconst video = el.shadowRoot.querySelector('video');\n\nfor (const name of ${inlineJson(FORWARDED_EVENTS)}) {\n el.addEventListener(name, (e) => post(name.slice(3), e.detail === undefined ? null : e.detail));\n}\nlet lastTimeUpdate = 0;\nconst sendTime = (force) => {\n const now = Date.now();\n if (!force && now - lastTimeUpdate < ${interval}) return;\n lastTimeUpdate = now;\n post('timeupdate', { currentTime: video.currentTime, duration: Number.isFinite(video.duration) ? video.duration : null, paused: video.paused });\n};\nvideo.addEventListener('timeupdate', () => sendTime(false));\nvideo.addEventListener('seeked', () => sendTime(true));\nvideo.addEventListener('loadedmetadata', () => post('loadedmetadata', { duration: Number.isFinite(video.duration) ? video.duration : null, width: video.videoWidth, height: video.videoHeight }));\n\n// Sarma: meta veri yoksa beklenir; WebKit (iOS WKWebView) meta veri işlenirken yapılan sarmayı sıfırlayabildiği için\n// sonucu (seeked) doğrulanır, kaydıysa yeniden uygulanır. Art arda gelen sarmalarda son hedef geçerli.\nlet seekTarget = null;\nlet seekRetries = 0;\nconst applySeek = () => {\n if (seekTarget === null) return;\n if (Math.abs(video.currentTime - seekTarget) <= 0.5 || seekRetries-- <= 0) {\n seekTarget = null;\n return;\n }\n video.addEventListener('seeked', applySeek, { once: true });\n video.currentTime = seekTarget;\n};\nconst seekTo = (time) => {\n seekTarget = Number(time) || 0;\n seekRetries = 3;\n if (video.readyState >= 1) applySeek();\n else video.addEventListener('loadedmetadata', applySeek, { once: true });\n};\n\nrun = (cmd) => {\n switch (cmd && cmd.type) {\n case 'options': el.options = cmd.options; break;\n case 'play': video.play().catch((err) => post('error', { message: String(err && err.message ? err.message : err), code: 'play' })); break;\n case 'pause': video.pause(); break;\n case 'seek': seekTo(cmd.time); break;\n case 'muted': video.muted = !!cmd.value; break;\n case 'toggleStats': el.toggleStats(cmd.force); break;\n }\n};\nqueue.splice(0).forEach(run);\npost('ready', { version: el.constructor.version || null });\n</script>\n</body>\n</html>`;\n}\n\n/** `window.__hopeCommand(...)` çağrısı — WebView `injectJavaScript`'e verilir (sondaki `true` iOS uyarısını önler). */\nexport function commandScript(cmd: HopeBridgeCommand): string {\n return `window.__hopeCommand && window.__hopeCommand(${inlineJson(cmd)}); true;`;\n}\n"],"names":["HOPE_PLAYER_RN_VERSION","DEFAULT_CORE_URL","FORWARDED_EVENTS","LINE_SEP","PARA_SEP","inlineJson","value","buildPlayerHtml","config","coreUrl","background","interval","css","commandScript","cmd"],"mappings":"AAGO,MAAMA,IAAiC,SAGjCC,IAAmB,iDAAiDD,CAAsB,wBAgCjGE,IAAmB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,GAGMC,IAAW,UACXC,IAAW;AAGjB,SAASC,EAAWC,GAAwB;AACxC,SAAO,KAAK,UAAUA,CAAK,EAAE,MAAM,GAAG,EAAE,KAAK,SAAS,EAAE,MAAMH,CAAQ,EAAE,KAAK,SAAS,EAAE,MAAMC,CAAQ,EAAE,KAAK,SAAS;AAC1H;AAMO,SAASG,EAAgBC,GAAkC;AAC9D,QAAMC,IAAUD,EAAO,WAAWP,GAC5BS,IAAaF,EAAO,mBAAmB,QACvCG,IAAWH,EAAO,wBAAwB,KAE1CI,KAAOJ,EAAO,OAAO,IAAI,MAAM,IAAI,EAAE,KAAK,MAAM;AACtD,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,+FAMoFE,CAAU;AAAA;AAAA,EAEvGE,CAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAiBcP,EAAWI,CAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAOvBJ,EAAWG,EAAO,OAAO,CAAC;AAAA;AAAA;AAAA,qBAGpBH,EAAWH,CAAgB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2CAMNS,CAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2CnD;AAGO,SAASE,EAAcC,GAAgC;AAC1D,SAAO,gDAAgDT,EAAWS,CAAG,CAAC;AAC1E;"}
|
|
1
|
+
{"version":3,"file":"player-html.js","sources":["../src/playerHtml.ts"],"sourcesContent":["import type { HopePlayerOptions } from '@hopeplayer/core';\n\n/** Paket sürümü — build sırasında package.json'dan gömülür; varsayılan core adresi aynı sürüme sabitlenir. */\nexport const HOPE_PLAYER_RN_VERSION: string = __HOPE_VERSION__;\n\n/** Varsayılan core adresi: jsDelivr üzerinden bu paketle aynı sürümdeki @hopeplayer/core. */\nexport const DEFAULT_CORE_URL = `https://cdn.jsdelivr.net/npm/@hopeplayer/core@${HOPE_PLAYER_RN_VERSION}/dist/hope-player.js`;\n\n/** WebView → React Native mesajı. `type`: köprü olayı (ready/timeupdate/error) ya da `hp:` öneki atılmış player olayı. */\nexport interface HopeBridgeMessage {\n __hope: 1;\n type: string;\n data: unknown;\n}\n\n/**\n * WebView'da çalışan eklenti: ES modül adresi ya da kodu (default / `plugin` export'u).\n * `'https://…/watermark.js'`, `{ url, options }` ya da `{ code, options }`.\n */\nexport type HopeNativePlugin = string | { url: string; options?: unknown } | { code: string; options?: unknown };\n\n/** WebView'a giden seçenekler: `plugins` fonksiyon yerine adres / kod alır. */\nexport type HopeNativeOptions = Omit<HopePlayerOptions, 'plugins'> & { plugins?: HopeNativePlugin[] };\n\n/** React Native → WebView komutu (`window.__hopeCommand`). */\nexport type HopeBridgeCommand =\n | { type: 'options'; options: HopeNativeOptions }\n | { type: 'pluginMessage'; plugin: string; data?: unknown }\n | { type: 'play' }\n | { type: 'pause' }\n | { type: 'seek'; time: number }\n | { type: 'muted'; value: boolean }\n | { type: 'toggleStats'; force?: boolean };\n\nexport interface PlayerHtmlConfig {\n /** Başlangıç seçenekleri — JSON'a çevrilebilir olmalı (fonksiyonlar WebView'a taşınamaz). */\n options: HopeNativeOptions;\n /** @hopeplayer/core ESM giriş dosyası. Varsayılan: jsDelivr, aynı sürüm. */\n coreUrl?: string;\n /** Sayfa arka planı (player yüklenene kadar görünen). Varsayılan #000. */\n backgroundColor?: string;\n /** WebView sayfasına eklenen CSS — `--hp-*` token'ları ve `hope-player::part(...)` kuralları için. */\n css?: string;\n /** `timeupdate` köprü olayının en sık gönderilme aralığı (ms). Varsayılan 250. */\n timeUpdateIntervalMs?: number;\n}\n\n/** Player'ın yaydığı ve React Native'e aktarılan olaylar (`hp:` öneki atılarak). */\nconst FORWARDED_EVENTS = [\n 'hp:play',\n 'hp:pause',\n 'hp:ended',\n 'hp:error',\n 'hp:qualitychange',\n 'hp:ratechange',\n 'hp:adstart',\n 'hp:adend',\n 'hp:aderror',\n 'hp:itemchange',\n 'hp:pausead',\n 'hp:analytics',\n];\n\n/** Satır/paragraf ayırıcı — JSON'da geçerli, JS string'inde (eski motorlarda) değil. */\nconst LINE_SEP = String.fromCharCode(0x2028);\nconst PARA_SEP = String.fromCharCode(0x2029);\n\n/** JSON'u <script> içine güvenle gömer (`</script>` ve satır ayırıcıları kaçırılır). */\nfunction inlineJson(value: unknown): string {\n return JSON.stringify(value).split('<').join('\\\\u003c').split(LINE_SEP).join('\\\\u2028').split(PARA_SEP).join('\\\\u2029');\n}\n\n/**\n * WebView'da çalışan sayfa: <hope-player> + köprü. React Native `window.__hopeCommand(...)` ile komut verir\n * (injectJavaScript), sayfa olayları `window.ReactNativeWebView.postMessage` ile geri gönderir.\n */\nexport function buildPlayerHtml(config: PlayerHtmlConfig): string {\n const coreUrl = config.coreUrl ?? DEFAULT_CORE_URL;\n const background = config.backgroundColor ?? '#000';\n const interval = config.timeUpdateIntervalMs ?? 250;\n // `</style` CSS'in içinden <style> etiketini kapatamasın.\n const css = (config.css ?? '').split('</').join('<\\\\/');\n return `<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no\">\n<style>\nhtml, body { margin: 0; padding: 0; width: 100%; height: 100%; overflow: hidden; background: ${background}; }\nhope-player { display: block; width: 100%; }\n${css}\n</style>\n</head>\n<body>\n<hope-player id=\"hope-player\"></hope-player>\n<script type=\"module\">\nconst post = (type, data) => {\n const message = JSON.stringify({ __hope: 1, type, data: data === undefined ? null : data });\n if (window.ReactNativeWebView) window.ReactNativeWebView.postMessage(message);\n else if (window.parent !== window) window.parent.postMessage(message, '*');\n};\n// Player hazır olana kadar gelen komutlar sıraya alınır.\nconst queue = [];\nlet run = null;\nwindow.__hopeCommand = (cmd) => (run ? run(cmd) : queue.push(cmd));\n\ntry {\n await import(${inlineJson(coreUrl)});\n} catch (err) {\n post('error', { message: 'HopePlayer core could not be loaded: ' + (err && err.message ? err.message : String(err)), code: 'core-load' });\n throw err;\n}\nawait customElements.whenDefined('hope-player');\nconst el = document.getElementById('hope-player');\n\n// Eklentiler: adres → import(); kod → Blob URL (aynı kod aynı modül, yeniden kurulmaz).\nconst blobUrls = new Map();\nconst pluginEntries = (list) => (Array.isArray(list) ? list : []).map((p) => {\n const d = typeof p === 'string' ? { url: p } : p || {};\n let url = d.url;\n if (!url && typeof d.code === 'string') {\n url = blobUrls.get(d.code);\n if (!url) blobUrls.set(d.code, (url = URL.createObjectURL(new Blob([d.code], { type: 'text/javascript' }))));\n }\n return [() => import(url), d.options];\n});\nconst setOptions = (o) => { el.options = { ...o, plugins: pluginEntries(o && o.plugins) }; };\n\n// Eklenti olayları (<ad>:<olay>) React Native'e; '<ad>:native' ondan gelir, geri gönderilmez.\nconst dispatch = el.dispatchEvent.bind(el);\nel.dispatchEvent = (ev) => {\n const t = ev.type;\n if (t.includes(':') && !t.startsWith('hp:') && !t.endsWith(':native')) {\n try { post('plugin', { event: t, detail: ev.detail === undefined ? null : ev.detail }); } catch (_) { post('plugin', { event: t, detail: null }); }\n }\n return dispatch(ev);\n};\n\nsetOptions(${inlineJson(config.options)});\nconst video = el.shadowRoot.querySelector('video');\n\nfor (const name of ${inlineJson(FORWARDED_EVENTS)}) {\n el.addEventListener(name, (e) => post(name.slice(3), e.detail === undefined ? null : e.detail));\n}\nlet lastTimeUpdate = 0;\nconst sendTime = (force) => {\n const now = Date.now();\n if (!force && now - lastTimeUpdate < ${interval}) return;\n lastTimeUpdate = now;\n post('timeupdate', { currentTime: video.currentTime, duration: Number.isFinite(video.duration) ? video.duration : null, paused: video.paused });\n};\nvideo.addEventListener('timeupdate', () => sendTime(false));\nvideo.addEventListener('seeked', () => sendTime(true));\nvideo.addEventListener('loadedmetadata', () => post('loadedmetadata', { duration: Number.isFinite(video.duration) ? video.duration : null, width: video.videoWidth, height: video.videoHeight }));\n\n// Sarma: meta veri yoksa beklenir; WebKit (iOS WKWebView) meta veri işlenirken yapılan sarmayı sıfırlayabildiği için\n// sonucu (seeked) doğrulanır, kaydıysa yeniden uygulanır. Art arda gelen sarmalarda son hedef geçerli.\nlet seekTarget = null;\nlet seekRetries = 0;\nconst applySeek = () => {\n if (seekTarget === null) return;\n if (Math.abs(video.currentTime - seekTarget) <= 0.5 || seekRetries-- <= 0) {\n seekTarget = null;\n return;\n }\n video.addEventListener('seeked', applySeek, { once: true });\n video.currentTime = seekTarget;\n};\nconst seekTo = (time) => {\n seekTarget = Number(time) || 0;\n seekRetries = 3;\n if (video.readyState >= 1) applySeek();\n else video.addEventListener('loadedmetadata', applySeek, { once: true });\n};\n\nrun = (cmd) => {\n switch (cmd && cmd.type) {\n case 'options': setOptions(cmd.options); break;\n case 'pluginMessage': dispatch(new CustomEvent(cmd.plugin + ':native', { detail: cmd.data === undefined ? null : cmd.data })); break;\n case 'play': video.play().catch((err) => post('error', { message: String(err && err.message ? err.message : err), code: 'play' })); break;\n case 'pause': video.pause(); break;\n case 'seek': seekTo(cmd.time); break;\n case 'muted': video.muted = !!cmd.value; break;\n case 'toggleStats': el.toggleStats(cmd.force); break;\n }\n};\nqueue.splice(0).forEach(run);\npost('ready', { version: el.constructor.version || null });\n</script>\n</body>\n</html>`;\n}\n\n/** `window.__hopeCommand(...)` çağrısı — WebView `injectJavaScript`'e verilir (sondaki `true` iOS uyarısını önler). */\nexport function commandScript(cmd: HopeBridgeCommand): string {\n return `window.__hopeCommand && window.__hopeCommand(${inlineJson(cmd)}); true;`;\n}\n"],"names":["HOPE_PLAYER_RN_VERSION","DEFAULT_CORE_URL","FORWARDED_EVENTS","LINE_SEP","PARA_SEP","inlineJson","value","buildPlayerHtml","config","coreUrl","background","interval","css","commandScript","cmd"],"mappings":"AAGO,MAAMA,IAAiC,SAGjCC,IAAmB,iDAAiDD,CAAsB,wBA0CjGE,IAAmB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,GAGMC,IAAW,UACXC,IAAW;AAGjB,SAASC,EAAWC,GAAwB;AACxC,SAAO,KAAK,UAAUA,CAAK,EAAE,MAAM,GAAG,EAAE,KAAK,SAAS,EAAE,MAAMH,CAAQ,EAAE,KAAK,SAAS,EAAE,MAAMC,CAAQ,EAAE,KAAK,SAAS;AAC1H;AAMO,SAASG,EAAgBC,GAAkC;AAC9D,QAAMC,IAAUD,EAAO,WAAWP,GAC5BS,IAAaF,EAAO,mBAAmB,QACvCG,IAAWH,EAAO,wBAAwB,KAE1CI,KAAOJ,EAAO,OAAO,IAAI,MAAM,IAAI,EAAE,KAAK,MAAM;AACtD,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,+FAMoFE,CAAU;AAAA;AAAA,EAEvGE,CAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAiBcP,EAAWI,CAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,aA+BzBJ,EAAWG,EAAO,OAAO,CAAC;AAAA;AAAA;AAAA,qBAGlBH,EAAWH,CAAgB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2CAMNS,CAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA4CnD;AAGO,SAASE,EAAcC,GAAgC;AAC1D,SAAO,gDAAgDT,EAAWS,CAAG,CAAC;AAC1E;"}
|
package/dist/playerHtml.d.ts
CHANGED
|
@@ -9,10 +9,29 @@ export interface HopeBridgeMessage {
|
|
|
9
9
|
type: string;
|
|
10
10
|
data: unknown;
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* WebView'da çalışan eklenti: ES modül adresi ya da kodu (default / `plugin` export'u).
|
|
14
|
+
* `'https://…/watermark.js'`, `{ url, options }` ya da `{ code, options }`.
|
|
15
|
+
*/
|
|
16
|
+
export type HopeNativePlugin = string | {
|
|
17
|
+
url: string;
|
|
18
|
+
options?: unknown;
|
|
19
|
+
} | {
|
|
20
|
+
code: string;
|
|
21
|
+
options?: unknown;
|
|
22
|
+
};
|
|
23
|
+
/** WebView'a giden seçenekler: `plugins` fonksiyon yerine adres / kod alır. */
|
|
24
|
+
export type HopeNativeOptions = Omit<HopePlayerOptions, 'plugins'> & {
|
|
25
|
+
plugins?: HopeNativePlugin[];
|
|
26
|
+
};
|
|
12
27
|
/** React Native → WebView komutu (`window.__hopeCommand`). */
|
|
13
28
|
export type HopeBridgeCommand = {
|
|
14
29
|
type: 'options';
|
|
15
|
-
options:
|
|
30
|
+
options: HopeNativeOptions;
|
|
31
|
+
} | {
|
|
32
|
+
type: 'pluginMessage';
|
|
33
|
+
plugin: string;
|
|
34
|
+
data?: unknown;
|
|
16
35
|
} | {
|
|
17
36
|
type: 'play';
|
|
18
37
|
} | {
|
|
@@ -29,7 +48,7 @@ export type HopeBridgeCommand = {
|
|
|
29
48
|
};
|
|
30
49
|
export interface PlayerHtmlConfig {
|
|
31
50
|
/** Başlangıç seçenekleri — JSON'a çevrilebilir olmalı (fonksiyonlar WebView'a taşınamaz). */
|
|
32
|
-
options:
|
|
51
|
+
options: HopeNativeOptions;
|
|
33
52
|
/** @hopeplayer/core ESM giriş dosyası. Varsayılan: jsDelivr, aynı sürüm. */
|
|
34
53
|
coreUrl?: string;
|
|
35
54
|
/** Sayfa arka planı (player yüklenene kadar görünen). Varsayılan #000. */
|
package/dist/playerHtml.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"playerHtml.d.ts","sourceRoot":"","sources":["../src/playerHtml.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,8GAA8G;AAC9G,eAAO,MAAM,sBAAsB,EAAE,MAAyB,CAAC;AAE/D,6FAA6F;AAC7F,eAAO,MAAM,gBAAgB,QAAgG,CAAC;AAE9H,0HAA0H;AAC1H,MAAM,WAAW,iBAAiB;IAC9B,MAAM,EAAE,CAAC,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;CACjB;AAED,8DAA8D;AAC9D,MAAM,MAAM,iBAAiB,GACvB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,iBAAiB,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAE/C,MAAM,WAAW,gBAAgB;IAC7B,6FAA6F;IAC7F,OAAO,EAAE,iBAAiB,CAAC;IAC3B,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sGAAsG;IACtG,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kFAAkF;IAClF,oBAAoB,CAAC,EAAE,MAAM,CAAC;CACjC;
|
|
1
|
+
{"version":3,"file":"playerHtml.d.ts","sourceRoot":"","sources":["../src/playerHtml.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,8GAA8G;AAC9G,eAAO,MAAM,sBAAsB,EAAE,MAAyB,CAAC;AAE/D,6FAA6F;AAC7F,eAAO,MAAM,gBAAgB,QAAgG,CAAC;AAE9H,0HAA0H;AAC1H,MAAM,WAAW,iBAAiB;IAC9B,MAAM,EAAE,CAAC,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEjH,+EAA+E;AAC/E,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,EAAE,SAAS,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAA;CAAE,CAAC;AAEtG,8DAA8D;AAC9D,MAAM,MAAM,iBAAiB,GACvB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,iBAAiB,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAE/C,MAAM,WAAW,gBAAgB;IAC7B,6FAA6F;IAC7F,OAAO,EAAE,iBAAiB,CAAC;IAC3B,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sGAAsG;IACtG,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kFAAkF;IAClF,oBAAoB,CAAC,EAAE,MAAM,CAAC;CACjC;AA2BD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAmHhE;AAED,uHAAuH;AACvH,wBAAgB,aAAa,CAAC,GAAG,EAAE,iBAAiB,GAAG,MAAM,CAE5D"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hopeplayer/react-native",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "React Native wrapper for HopeCorePlayer — runs <hope-player> in a WebView with a prop/event bridge (same options and callbacks as @hopeplayer/react)",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"test": "node test/bridge.e2e.mjs"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@hopeplayer/core": "^1.
|
|
45
|
+
"@hopeplayer/core": "^1.5.0"
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
48
|
"react": ">=18",
|