@everframe/react-native 0.9.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.
Files changed (38) hide show
  1. package/EverframeRN.podspec +88 -0
  2. package/LICENSE +21 -0
  3. package/NOTICE +8 -0
  4. package/README.md +505 -0
  5. package/android/build.gradle.kts +209 -0
  6. package/android/settings.gradle.kts +8 -0
  7. package/android/src/main/AndroidManifest.xml +9 -0
  8. package/android/src/main/java/dev/everframe/rn/EverframeModule.kt +1670 -0
  9. package/android/src/main/java/dev/everframe/rn/EverframePackage.kt +40 -0
  10. package/android/src/main/java/dev/everframe/rn/EverframeSensitiveViewManager.kt +20 -0
  11. package/android/src/main/java/dev/everframe/rn/RnVideoPrivacyAdapter.kt +65 -0
  12. package/dist/NativeEverframe.d.ts +308 -0
  13. package/dist/NativeEverframe.js +1 -0
  14. package/dist/browser-ZQAY6B4M.js +1 -0
  15. package/dist/chunk-LPIKPZNX.js +1 -0
  16. package/dist/chunk-QRPINMCR.js +1 -0
  17. package/dist/chunk-QZRTTQRS.js +1 -0
  18. package/dist/chunk-XFLFA52R.js +1 -0
  19. package/dist/chunk-XUSV3KOD.js +1 -0
  20. package/dist/index.d.ts +1006 -0
  21. package/dist/index.js +51 -0
  22. package/dist/integrations/console.d.ts +8 -0
  23. package/dist/integrations/console.js +1 -0
  24. package/dist/integrations/react-native-video.d.ts +44 -0
  25. package/dist/integrations/react-native-video.js +1 -0
  26. package/dist/integrations/react-navigation.d.ts +21 -0
  27. package/dist/integrations/react-navigation.js +1 -0
  28. package/dist/integrations/theoplayer.d.ts +37 -0
  29. package/dist/integrations/theoplayer.js +1 -0
  30. package/dist/types-D5e4kWaw.d.ts +12 -0
  31. package/ios/Sources/EverframeBridge.swift +1043 -0
  32. package/ios/Sources/EverframeEventEmitter.swift +204 -0
  33. package/ios/Sources/EverframeModule.h +36 -0
  34. package/ios/Sources/EverframeModule.mm +489 -0
  35. package/ios/Sources/RemoteVitalsBridge.swift +99 -0
  36. package/package.json +121 -0
  37. package/src/NativeEverframe.ts +439 -0
  38. package/src/codegen-types.ts +11 -0
@@ -0,0 +1,8 @@
1
+ import { E as EverframeIntegration } from '../types-D5e4kWaw.js';
2
+
3
+ type ConsoleLevel = 'log' | 'info' | 'warn' | 'error' | 'debug';
4
+ declare function consoleIntegration(opts?: {
5
+ levels?: ConsoleLevel[];
6
+ }): EverframeIntegration;
7
+
8
+ export { type ConsoleLevel, consoleIntegration };
@@ -0,0 +1 @@
1
+ import{f as c}from"../chunk-QRPINMCR.js";import{a as i}from"../chunk-XUSV3KOD.js";var g={log:"info",info:"info",warn:"warn",error:"error",debug:"debug"},a=2048;function p(t){let l=[...new Set(t?.levels??["log","info","warn","error"])];return{name:"console",setup(){let n=!1,e=[];for(let o of l){let r=console[o];if(typeof r!="function")continue;e.push({level:o,fn:r});let u=r.bind(console);console[o]=(...f)=>{if(u(...f),!n){n=!0;try{let s=v(f);s&&!s.startsWith("[everframe]")&&c({message:s,kind:"console",level:g[o]})}catch{}finally{n=!1}}}}return()=>{for(let{level:o,fn:r}of e)console[o]=r}}}}i(p,"consoleIntegration");function v(t){let n=t.map(e=>{if(typeof e=="string")return e;if(e instanceof Error)return e.message;try{return JSON.stringify(e)??String(e)}catch{return String(e)}}).join(" ");return n.length>a?n.slice(0,a):n}i(v,"serializeArgs");export{p as consoleIntegration};
@@ -0,0 +1,44 @@
1
+ interface VideoPlayerLike {
2
+ addEventListener(event: string, cb: (...args: any[]) => void): {
3
+ remove(): void;
4
+ };
5
+ readonly isPlaying?: boolean;
6
+ readonly source?: {
7
+ uri?: string;
8
+ config?: {
9
+ drm?: {
10
+ type?: string;
11
+ };
12
+ };
13
+ } | null;
14
+ /** Playhead position in seconds; > 0 means this source has already produced frames. */
15
+ readonly currentTime?: number;
16
+ /** `'idle' | 'loading' | 'readyToPlay' | 'error'` — `'readyToPlay'` also means past startup. */
17
+ readonly status?: string;
18
+ }
19
+ interface VideoPlayerVitalsOptions {
20
+ name?: string;
21
+ libraryVersion?: string;
22
+ /**
23
+ * Subscribe to `onError` so errors carry the library's `code`. OFF by
24
+ * default: registering an `onError` listener makes react-native-video stop
25
+ * throwing synchronously from `play()`/`pause()`/`seek*()` for the entire
26
+ * host app, which is a behaviour change Everframe must not make silently.
27
+ * Without it, a fatal error is still reported via `onStatusChange('error')`
28
+ * — just without a `code`.
29
+ */
30
+ captureErrors?: boolean;
31
+ /**
32
+ * TEST-ONLY override for the platform split on `onBandwidthUpdate`
33
+ * (iOS reports the rendition's declared bitrate, Android reports
34
+ * ExoPlayer's bandwidth estimate). Defaults to `Platform.OS`; hosts should
35
+ * never set it.
36
+ * @internal
37
+ */
38
+ platform?: 'ios' | 'android';
39
+ }
40
+ declare function attachVideoPlayerVitals(player: VideoPlayerLike, opts?: VideoPlayerVitalsOptions): () => void;
41
+ /** Effect-bound form: attaches per player INSTANCE, detaches on unmount or change. */
42
+ declare function useVideoPlayerVitals(player: VideoPlayerLike | null | undefined, opts?: VideoPlayerVitalsOptions): void;
43
+
44
+ export { type VideoPlayerLike, type VideoPlayerVitalsOptions, attachVideoPlayerVitals, useVideoPlayerVitals };
@@ -0,0 +1 @@
1
+ import{a as v}from"../chunk-QZRTTQRS.js";import{a as V}from"../chunk-LPIKPZNX.js";import"../chunk-XFLFA52R.js";import{a as d}from"../chunk-XUSV3KOD.js";import{useEffect as C}from"react";import{Platform as O}from"react-native";var T="react-native-video";function L(n){return typeof n=="string"&&(n.startsWith("player/")||n.startsWith("source/"))}d(L,"isFatal");function E(n){return n!==void 0?{keySystem:n}:void 0}d(E,"drmExtra");function x(n,o={}){let s,u,f=!1,l=!1;try{let e=n.source;s=e?.uri,u=e?.config?.drm?.type,f=!!n.isPlaying;let t=n.currentTime;l=typeof t=="number"&&t>0||n.status==="readyToPlay"}catch{return()=>{}}let a=[],i=d((e,t)=>{a.push(n.addEventListener(e,t))},"on"),y={library:T};o.libraryVersion!==void 0&&(y.libraryVersion=o.libraryVersion),o.name!==void 0&&(y.name=o.name);let r=v(V(y)),g=o.platform??(O.OS==="android"?"android":"ios"),b,p,c,h,m=!1,k=d(()=>{b=void 0,p=void 0,c=void 0,h=void 0},"resetSourceCache"),S=d(e=>{let t={bufferAheadMs:e},w=g==="android"?p:b;w!==void 0&&(g==="android"?t.bandwidthEstimate=w:t.bitrate=w),c!==void 0&&(t.width=c),h!==void 0&&(t.height=h),r.stats(t)},"push");try{i("onLoadStart",r.wrap(e=>{m=!1,k(),r.loadStart(e?.source?.uri,E(e?.source?.config?.drm?.type))})),i("onLoad",r.wrap(e=>{e?.width&&e?.height&&(c=e.width,h=e.height,r.sizeChanged(e.width,e.height))})),i("onPlaybackStateChange",r.wrap(e=>{if(e?.isPlaying){r.playing();return}if(e?.isBuffering){r.bufferingChanged(!0);return}r.paused()})),i("onBuffer",r.wrap(e=>r.bufferingChanged(!!e))),i("onProgress",r.wrap(e=>{if(typeof e?.bufferDuration!="number")return;let t=g==="android"?e.bufferDuration:e.bufferDuration-(typeof e.currentTime=="number"?e.currentTime:0);S(Math.round(Math.max(0,t)*1e3))})),i("onBandwidthUpdate",r.wrap(e=>{if(typeof e?.bitrate=="number"){if(e.width!==void 0&&(c=e.width),e.height!==void 0&&(h=e.height),g==="android"){p=e.bitrate,e.width!==void 0&&e.height!==void 0&&r.sizeChanged(e.width,e.height);return}e.bitrate!==b&&(b=e.bitrate,r.bitrateChanged(e.bitrate,e.width,e.height))}})),i("onPlaybackRateChange",r.wrap(e=>r.rateChanged(e))),i("onSeek",r.wrap(()=>r.seek())),i("onEnd",r.wrap(()=>r.ended())),o.captureErrors&&i("onError",r.wrap(e=>{let t=L(e?.code);if(t){if(m)return;m=!0}r.error(String(e?.message??"error"),e?.code,t)})),i("onStatusChange",r.wrap(e=>{e!=="error"||m||(m=!0,r.error("player status error",void 0,!0))}))}catch{return a.forEach(e=>{try{e.remove()}catch{}}),r.close(),()=>{}}s&&r.seedSource(s,E(u)),f?r.seedPlaying():l&&r.seedStarted();let P=!1;return()=>{P||(P=!0,a.forEach(e=>{try{e.remove()}catch{}}),r.close())}}d(x,"attachVideoPlayerVitals");function M(n,o={}){let{name:s,libraryVersion:u,captureErrors:f,platform:l}=o;C(()=>{if(!n)return;let a={};return s!==void 0&&(a.name=s),u!==void 0&&(a.libraryVersion=u),f!==void 0&&(a.captureErrors=f),l!==void 0&&(a.platform=l),x(n,a)},[n,s,u,f])}d(M,"useVideoPlayerVitals");export{x as attachVideoPlayerVitals,M as useVideoPlayerVitals};
@@ -0,0 +1,21 @@
1
+ import { E as EverframeIntegration } from '../types-D5e4kWaw.js';
2
+
3
+ /** Duck-typed subset of react-navigation's NavigationContainerRef. */
4
+ interface NavigationRefLike {
5
+ isReady(): boolean;
6
+ getCurrentRoute(): {
7
+ name?: string;
8
+ } | undefined;
9
+ addListener(type: 'state', callback: () => void): () => void;
10
+ }
11
+ interface ReactNavigationIntegration extends EverframeIntegration {
12
+ /** Pass to <NavigationContainer onReady> to record the initial route. */
13
+ onReady(): void;
14
+ /** Pass to <NavigationContainer onStateChange> as a listener fallback. */
15
+ onStateChange(): void;
16
+ }
17
+ declare function reactNavigationIntegration(opts: {
18
+ navigationRef: NavigationRefLike;
19
+ }): ReactNavigationIntegration;
20
+
21
+ export { type NavigationRefLike, type ReactNavigationIntegration, reactNavigationIntegration };
@@ -0,0 +1 @@
1
+ import{g as i}from"../chunk-QRPINMCR.js";import{a as n}from"../chunk-XUSV3KOD.js";function o(t){let e=n(()=>{try{let a=t.navigationRef.getCurrentRoute?.()?.name;a&&i(a)}catch{}},"emit");return{name:"react-navigation",onReady:e,onStateChange:e,setup(){try{t.navigationRef.isReady()&&e()}catch{}try{return t.navigationRef.addListener("state",e)}catch{return}}}}n(o,"reactNavigationIntegration");export{o as reactNavigationIntegration};
@@ -0,0 +1,37 @@
1
+ interface TheoTypedSource {
2
+ src?: string;
3
+ type?: string;
4
+ contentProtection?: Record<string, unknown>;
5
+ }
6
+ interface TheoPlayerLike {
7
+ addEventListener(type: string, listener: (event: any) => void): void;
8
+ removeEventListener(type: string, listener: (event: any) => void): void;
9
+ readonly source?: {
10
+ sources?: TheoTypedSource | TheoTypedSource[];
11
+ } | undefined;
12
+ readonly buffered?: Array<{
13
+ start: number;
14
+ end: number;
15
+ }>;
16
+ readonly currentTime?: number;
17
+ readonly paused?: boolean;
18
+ readonly version?: {
19
+ version?: string;
20
+ };
21
+ readonly videoTracks?: Array<{
22
+ uid: number;
23
+ activeQuality?: {
24
+ bandwidth?: number;
25
+ width?: number;
26
+ height?: number;
27
+ };
28
+ }>;
29
+ }
30
+ interface TheoPlayerVitalsOptions {
31
+ name?: string;
32
+ }
33
+ declare function attachTheoPlayerVitals(player: TheoPlayerLike, opts?: TheoPlayerVitalsOptions): () => void;
34
+ /** Effect-bound form: attaches per player INSTANCE, detaches on unmount or change. */
35
+ declare function useTheoPlayerVitals(player: TheoPlayerLike | null | undefined, opts?: TheoPlayerVitalsOptions): void;
36
+
37
+ export { type TheoPlayerLike, type TheoPlayerVitalsOptions, type TheoTypedSource, attachTheoPlayerVitals, useTheoPlayerVitals };
@@ -0,0 +1 @@
1
+ import{a as w}from"../chunk-QZRTTQRS.js";import{a as k}from"../chunk-LPIKPZNX.js";import"../chunk-XFLFA52R.js";import{a as s}from"../chunk-XUSV3KOD.js";import{useEffect as P}from"react";var A="theoplayer",L=["widevine","fairplay","playready","clearkey"];function x(t){let i=t?.sources;return Array.isArray(i)?i[0]:i}s(x,"firstSource");function O(t){let i=t?.contentProtection;if(i)return L.find(a=>a in i)??(typeof i.integration=="string"?i.integration:"unknown")}s(O,"keySystemOf");function E(t){let i=t.currentTime,a=t.buffered;if(typeof i!="number"||!Array.isArray(a))return;let d=a.find(n=>n.start<=i&&i<=n.end);return d?Math.round(Math.max(0,(d.end-i)*1e3)):0}s(E,"bufferAheadMs");function M(t,i={}){let a={library:A},d=t.version?.version;d!==void 0&&(a.libraryVersion=d),i.name!==void 0&&(a.name=i.name);let n=w(k(a)),g=[],o=s((r,e)=>{let u=n.wrap(e);g.push([r,u]),t.addEventListener(r,u)},"on"),c,f,y,h=!1,S=s(()=>{let r=E(t);if(r===void 0)return;let e={bufferAheadMs:r};c!==void 0&&(e.bitrate=c,f!==void 0&&(e.width=f),y!==void 0&&(e.height=y)),n.stats(e)},"push"),b=s(()=>{let r=x(t.source),e=r?.type,u=O(r),m={};return e!==void 0&&(m.mime=e),u!==void 0&&(m.keySystem=u),{src:r?.src,extra:m}},"readSource"),p=s(()=>{c=void 0,f=void 0,y=void 0;let{src:r,extra:e}=b();n.loadStart(r,e)},"load"),T=s(r=>{r&&(typeof r.bandwidth=="number"&&(c=r.bandwidth,f=r.width,y=r.height,n.bitrateChanged(r.bandwidth,r.width,r.height)),r.width&&r.height&&n.sizeChanged(r.width,r.height))},"quality"),v=!1,l=s(()=>{v||(v=!0,g.forEach(([r,e])=>{try{t.removeEventListener(r,e)}catch{}}),n.close())},"detach");try{o("sourcechange",()=>{h=!0,p()}),o("loadstart",()=>{let e=h;h=!1,e||p()}),o("playing",()=>{n.bufferingChanged(!1),n.playing()}),o("pause",()=>n.paused()),o("ended",()=>n.ended()),o("waiting",()=>n.bufferingChanged(!0)),o("seeked",()=>n.seek()),o("ratechange",e=>{typeof e?.playbackRate=="number"&&n.rateChanged(e.playbackRate)}),o("error",e=>n.error(String(e?.error?.errorMessage??"error"),e?.error?.errorCode,!0)),o("contentprotectionerror",e=>n.error(String(e?.error?.errorMessage??"content protection error"),e?.error?.errorCode,!1)),o("timeupdate",S),o("mediatrack",e=>{e?.subType!=="activequalitychanged"||e?.trackType!=="video"||T(Array.isArray(e.qualities)?e.qualities[0]:e.qualities)}),o("destroy",l);let r=b();r.src&&n.seedSource(r.src,r.extra),t.paused===!1&&n.seedPlaying(),T(t.videoTracks?.find(e=>e.activeQuality)?.activeQuality)}catch{return l(),()=>{}}return l}s(M,"attachTheoPlayerVitals");function Q(t,i={}){let{name:a}=i;P(()=>{if(!t)return;let d={};return a!==void 0&&(d.name=a),M(t,d)},[t,a])}s(Q,"useTheoPlayerVitals");export{M as attachTheoPlayerVitals,Q as useTheoPlayerVitals};
@@ -0,0 +1,12 @@
1
+ /** A host-opt-in capture integration. */
2
+ interface EverframeIntegration {
3
+ /** Diagnostic name used in warn messages, e.g. 'console'. */
4
+ name: string;
5
+ /**
6
+ * Called at the end of runtime mount (context is published — top-level
7
+ * seam functions work). Return a teardown to run on unmount.
8
+ */
9
+ setup(): (() => void) | void;
10
+ }
11
+
12
+ export type { EverframeIntegration as E };