novvy-ads-react-native 1.0.0-beta.1
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 +210 -0
- package/android/build.gradle +84 -0
- package/android/gradle.properties +4 -0
- package/android/src/main/AndroidManifest.xml +4 -0
- package/android/src/main/java/ai/novvy/reactnative/NovvyAdContainerView.kt +63 -0
- package/android/src/main/java/ai/novvy/reactnative/NovvyAdsModule.kt +390 -0
- package/android/src/main/java/ai/novvy/reactnative/NovvyAdsPackage.kt +46 -0
- package/android/src/main/java/ai/novvy/reactnative/NovvyPauseAdViewManager.kt +68 -0
- package/android/src/main/java/ai/novvy/reactnative/NovvyScrollAdViewManager.kt +72 -0
- package/android/src/main/java/ai/novvy/reactnative/RnPlayerAdapter.kt +18 -0
- package/android/src/main/java/ai/novvy/reactnative/ViewReadyEvent.kt +26 -0
- package/app.plugin.js +4 -0
- package/ios/NovvyAds.mm +168 -0
- package/ios/NovvyAdsImpl.swift +409 -0
- package/ios/NovvyPauseAdView.mm +79 -0
- package/ios/NovvyScrollAdView.mm +80 -0
- package/ios/RnPlayerAdapter.swift +14 -0
- package/lib/commonjs/NovvyAds.js +87 -0
- package/lib/commonjs/NovvyAds.js.map +1 -0
- package/lib/commonjs/ads/NovvyAd.js +121 -0
- package/lib/commonjs/ads/NovvyAd.js.map +1 -0
- package/lib/commonjs/ads/NovvyEndAd.js +19 -0
- package/lib/commonjs/ads/NovvyEndAd.js.map +1 -0
- package/lib/commonjs/ads/NovvyFullScreenAd.js +49 -0
- package/lib/commonjs/ads/NovvyFullScreenAd.js.map +1 -0
- package/lib/commonjs/ads/NovvyInterstitialAd.js +19 -0
- package/lib/commonjs/ads/NovvyInterstitialAd.js.map +1 -0
- package/lib/commonjs/ads/NovvyMidAd.js +19 -0
- package/lib/commonjs/ads/NovvyMidAd.js.map +1 -0
- package/lib/commonjs/ads/NovvyPauseAd.js +116 -0
- package/lib/commonjs/ads/NovvyPauseAd.js.map +1 -0
- package/lib/commonjs/ads/NovvyRewardedAd.js +53 -0
- package/lib/commonjs/ads/NovvyRewardedAd.js.map +1 -0
- package/lib/commonjs/ads/NovvyScrollAd.js +136 -0
- package/lib/commonjs/ads/NovvyScrollAd.js.map +1 -0
- package/lib/commonjs/eventBus.js +60 -0
- package/lib/commonjs/eventBus.js.map +1 -0
- package/lib/commonjs/index.js +90 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/spec/NativeNovvyAds.js +27 -0
- package/lib/commonjs/spec/NativeNovvyAds.js.map +1 -0
- package/lib/commonjs/spec/NovvyPauseAdViewNativeComponent.js +16 -0
- package/lib/commonjs/spec/NovvyPauseAdViewNativeComponent.js.map +1 -0
- package/lib/commonjs/spec/NovvyScrollAdViewNativeComponent.js +17 -0
- package/lib/commonjs/spec/NovvyScrollAdViewNativeComponent.js.map +1 -0
- package/lib/commonjs/spec/codegen-event-emitter.d.js +2 -0
- package/lib/commonjs/spec/codegen-event-emitter.d.js.map +1 -0
- package/lib/commonjs/types.js +54 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/commonjs/views/NovvyPauseAdView.js +76 -0
- package/lib/commonjs/views/NovvyPauseAdView.js.map +1 -0
- package/lib/commonjs/views/NovvyScrollAdView.js +63 -0
- package/lib/commonjs/views/NovvyScrollAdView.js.map +1 -0
- package/lib/module/NovvyAds.js +83 -0
- package/lib/module/NovvyAds.js.map +1 -0
- package/lib/module/ads/NovvyAd.js +117 -0
- package/lib/module/ads/NovvyAd.js.map +1 -0
- package/lib/module/ads/NovvyEndAd.js +15 -0
- package/lib/module/ads/NovvyEndAd.js.map +1 -0
- package/lib/module/ads/NovvyFullScreenAd.js +45 -0
- package/lib/module/ads/NovvyFullScreenAd.js.map +1 -0
- package/lib/module/ads/NovvyInterstitialAd.js +15 -0
- package/lib/module/ads/NovvyInterstitialAd.js.map +1 -0
- package/lib/module/ads/NovvyMidAd.js +15 -0
- package/lib/module/ads/NovvyMidAd.js.map +1 -0
- package/lib/module/ads/NovvyPauseAd.js +112 -0
- package/lib/module/ads/NovvyPauseAd.js.map +1 -0
- package/lib/module/ads/NovvyRewardedAd.js +49 -0
- package/lib/module/ads/NovvyRewardedAd.js.map +1 -0
- package/lib/module/ads/NovvyScrollAd.js +132 -0
- package/lib/module/ads/NovvyScrollAd.js.map +1 -0
- package/lib/module/eventBus.js +55 -0
- package/lib/module/eventBus.js.map +1 -0
- package/lib/module/index.js +22 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/spec/NativeNovvyAds.js +28 -0
- package/lib/module/spec/NativeNovvyAds.js.map +1 -0
- package/lib/module/spec/NovvyPauseAdViewNativeComponent.js +13 -0
- package/lib/module/spec/NovvyPauseAdViewNativeComponent.js.map +1 -0
- package/lib/module/spec/NovvyScrollAdViewNativeComponent.js +14 -0
- package/lib/module/spec/NovvyScrollAdViewNativeComponent.js.map +1 -0
- package/lib/module/spec/codegen-event-emitter.d.js +2 -0
- package/lib/module/spec/codegen-event-emitter.d.js.map +1 -0
- package/lib/module/types.js +56 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/views/NovvyPauseAdView.js +70 -0
- package/lib/module/views/NovvyPauseAdView.js.map +1 -0
- package/lib/module/views/NovvyScrollAdView.js +57 -0
- package/lib/module/views/NovvyScrollAdView.js.map +1 -0
- package/lib/typescript/NovvyAds.d.ts +69 -0
- package/lib/typescript/NovvyAds.d.ts.map +1 -0
- package/lib/typescript/ads/NovvyAd.d.ts +57 -0
- package/lib/typescript/ads/NovvyAd.d.ts.map +1 -0
- package/lib/typescript/ads/NovvyEndAd.d.ts +7 -0
- package/lib/typescript/ads/NovvyEndAd.d.ts.map +1 -0
- package/lib/typescript/ads/NovvyFullScreenAd.d.ts +19 -0
- package/lib/typescript/ads/NovvyFullScreenAd.d.ts.map +1 -0
- package/lib/typescript/ads/NovvyInterstitialAd.d.ts +7 -0
- package/lib/typescript/ads/NovvyInterstitialAd.d.ts.map +1 -0
- package/lib/typescript/ads/NovvyMidAd.d.ts +7 -0
- package/lib/typescript/ads/NovvyMidAd.d.ts.map +1 -0
- package/lib/typescript/ads/NovvyPauseAd.d.ts +45 -0
- package/lib/typescript/ads/NovvyPauseAd.d.ts.map +1 -0
- package/lib/typescript/ads/NovvyRewardedAd.d.ts +19 -0
- package/lib/typescript/ads/NovvyRewardedAd.d.ts.map +1 -0
- package/lib/typescript/ads/NovvyScrollAd.d.ts +57 -0
- package/lib/typescript/ads/NovvyScrollAd.d.ts.map +1 -0
- package/lib/typescript/eventBus.d.ts +15 -0
- package/lib/typescript/eventBus.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +15 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/spec/NativeNovvyAds.d.ts +73 -0
- package/lib/typescript/spec/NativeNovvyAds.d.ts.map +1 -0
- package/lib/typescript/spec/NovvyPauseAdViewNativeComponent.d.ts +18 -0
- package/lib/typescript/spec/NovvyPauseAdViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/spec/NovvyScrollAdViewNativeComponent.d.ts +19 -0
- package/lib/typescript/spec/NovvyScrollAdViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/types.d.ts +77 -0
- package/lib/typescript/types.d.ts.map +1 -0
- package/lib/typescript/views/NovvyPauseAdView.d.ts +21 -0
- package/lib/typescript/views/NovvyPauseAdView.d.ts.map +1 -0
- package/lib/typescript/views/NovvyScrollAdView.d.ts +22 -0
- package/lib/typescript/views/NovvyScrollAdView.d.ts.map +1 -0
- package/novvy-ads-react-native.podspec +71 -0
- package/package.json +84 -0
- package/plugin/build/index.d.ts +11 -0
- package/plugin/build/index.js +53 -0
- package/react-native.config.js +7 -0
- package/src/NovvyAds.ts +98 -0
- package/src/ads/NovvyAd.ts +125 -0
- package/src/ads/NovvyEndAd.ts +13 -0
- package/src/ads/NovvyFullScreenAd.ts +46 -0
- package/src/ads/NovvyInterstitialAd.ts +13 -0
- package/src/ads/NovvyMidAd.ts +13 -0
- package/src/ads/NovvyPauseAd.ts +125 -0
- package/src/ads/NovvyRewardedAd.ts +49 -0
- package/src/ads/NovvyScrollAd.ts +138 -0
- package/src/eventBus.ts +59 -0
- package/src/index.tsx +29 -0
- package/src/spec/NativeNovvyAds.ts +134 -0
- package/src/spec/NovvyPauseAdViewNativeComponent.ts +20 -0
- package/src/spec/NovvyScrollAdViewNativeComponent.ts +21 -0
- package/src/spec/codegen-event-emitter.d.ts +10 -0
- package/src/types.ts +82 -0
- package/src/views/NovvyPauseAdView.tsx +80 -0
- package/src/views/NovvyScrollAdView.tsx +71 -0
package/src/index.tsx
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Public entry point for the Novvy Ads React Native SDK.
|
|
2
|
+
|
|
3
|
+
export { NovvyAds } from './NovvyAds';
|
|
4
|
+
|
|
5
|
+
// Ad types
|
|
6
|
+
export { NovvyAd } from './ads/NovvyAd';
|
|
7
|
+
export { NovvyFullScreenAd } from './ads/NovvyFullScreenAd';
|
|
8
|
+
export { NovvyInterstitialAd } from './ads/NovvyInterstitialAd';
|
|
9
|
+
export { NovvyRewardedAd } from './ads/NovvyRewardedAd';
|
|
10
|
+
export { NovvyMidAd } from './ads/NovvyMidAd';
|
|
11
|
+
export { NovvyEndAd } from './ads/NovvyEndAd';
|
|
12
|
+
export { NovvyScrollAd } from './ads/NovvyScrollAd';
|
|
13
|
+
export { NovvyPauseAd } from './ads/NovvyPauseAd';
|
|
14
|
+
|
|
15
|
+
// Embedded views
|
|
16
|
+
export { NovvyScrollAdView } from './views/NovvyScrollAdView';
|
|
17
|
+
export type { NovvyScrollAdViewProps } from './views/NovvyScrollAdView';
|
|
18
|
+
export { NovvyPauseAdView } from './views/NovvyPauseAdView';
|
|
19
|
+
export type { NovvyPauseAdViewProps } from './views/NovvyPauseAdView';
|
|
20
|
+
|
|
21
|
+
// Data types
|
|
22
|
+
export {
|
|
23
|
+
NovvyAdEvent,
|
|
24
|
+
type NovvyUserContext,
|
|
25
|
+
type NovvyContentContext,
|
|
26
|
+
type NovvyDramaRecord,
|
|
27
|
+
type NovvyGender,
|
|
28
|
+
type NovvyPlayerAdapter,
|
|
29
|
+
} from './types';
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import type { TurboModule } from 'react-native';
|
|
2
|
+
import { TurboModuleRegistry } from 'react-native';
|
|
3
|
+
import type {
|
|
4
|
+
Int32,
|
|
5
|
+
Double,
|
|
6
|
+
EventEmitter,
|
|
7
|
+
UnsafeObject,
|
|
8
|
+
} from 'react-native/Libraries/Types/CodegenTypes';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Codegen-facing spec for the Novvy Ads TurboModule (new architecture only).
|
|
12
|
+
*
|
|
13
|
+
* Method surface mirrors the Flutter plugin's Pigeon `NovvyAdHostApi`
|
|
14
|
+
* (pigeons/novvy_ads_api.dart) one-to-one. The single `onAdEvent` emitter
|
|
15
|
+
* mirrors Pigeon's `NovvyAdsFlutterApi.onAdEvent`; each JS ad object filters
|
|
16
|
+
* this stream by its own `adObjectId`.
|
|
17
|
+
*
|
|
18
|
+
* NOTE: Codegen struct/event types must live in this file. The public,
|
|
19
|
+
* richly-documented aliases are re-exported from `../types`.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
// ── Data structs (codegen-facing) ───────────────────────────────────────────
|
|
23
|
+
|
|
24
|
+
export type NativeDramaRecord = {
|
|
25
|
+
seriesId: string;
|
|
26
|
+
lastWatchedEpisode: Int32;
|
|
27
|
+
unlockedEpisode: Int32;
|
|
28
|
+
dramaTitle?: string | null;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export type NativeUserContext = {
|
|
32
|
+
userId?: string | null;
|
|
33
|
+
hashedEmail?: string | null;
|
|
34
|
+
isPaidUser?: boolean | null;
|
|
35
|
+
age?: Int32 | null;
|
|
36
|
+
/** "male" / "female" / "unknown". */
|
|
37
|
+
gender?: string | null;
|
|
38
|
+
dramaWatchHistory?: Array<NativeDramaRecord> | null;
|
|
39
|
+
maximumAdsInOneDrama?: Int32 | null;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export type NativeContentContext = {
|
|
43
|
+
seriesName?: string | null;
|
|
44
|
+
episodeNumber?: Int32 | null;
|
|
45
|
+
url?: string | null;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Single native→JS ad lifecycle event. `event` is one of the NovvyAdEvent
|
|
50
|
+
* string values. `remainingSeconds` is only populated for `playbackTick`
|
|
51
|
+
* (flattened from Pigeon's `data` map for codegen compatibility).
|
|
52
|
+
*/
|
|
53
|
+
export type NativeAdEvent = {
|
|
54
|
+
adObjectId: string;
|
|
55
|
+
adUnitId: string;
|
|
56
|
+
event: string;
|
|
57
|
+
error?: string | null;
|
|
58
|
+
remainingSeconds?: Int32 | null;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// ── TurboModule ─────────────────────────────────────────────────────────────
|
|
62
|
+
|
|
63
|
+
export interface Spec extends TurboModule {
|
|
64
|
+
// SDK & context
|
|
65
|
+
//
|
|
66
|
+
// NOTE: context args are declared as UnsafeObject (not the typed
|
|
67
|
+
// NativeUserContext / NativeContentContext structs above) so iOS codegen
|
|
68
|
+
// produces NSDictionary * parameters instead of C++ struct references, to
|
|
69
|
+
// match the ObjC++ impl in ios/NovvyAds.mm. Android codegen already lowers
|
|
70
|
+
// typed structs to ReadableMap. The public API in NovvyAds.ts still exposes
|
|
71
|
+
// the strongly-typed NovvyUserContext / NovvyContentContext to JS callers.
|
|
72
|
+
initialize(
|
|
73
|
+
appId: string,
|
|
74
|
+
endpoint: string,
|
|
75
|
+
apiKey: string,
|
|
76
|
+
userContext?: UnsafeObject | null
|
|
77
|
+
): Promise<boolean>;
|
|
78
|
+
setUserContext(context: UnsafeObject): void;
|
|
79
|
+
updateUserContext(partial: UnsafeObject): void;
|
|
80
|
+
setContentContext(context: UnsafeObject): void;
|
|
81
|
+
updateContentContext(partial: UnsafeObject): void;
|
|
82
|
+
|
|
83
|
+
// Interstitial
|
|
84
|
+
loadInterstitialAd(adUnitId: string, adObjectId: string): void;
|
|
85
|
+
showInterstitialAd(adObjectId: string): void;
|
|
86
|
+
|
|
87
|
+
// Rewarded
|
|
88
|
+
loadRewardedAd(adUnitId: string, adObjectId: string): void;
|
|
89
|
+
showRewardedAd(adObjectId: string): void;
|
|
90
|
+
|
|
91
|
+
// Mid-roll
|
|
92
|
+
loadMidAd(adUnitId: string, adObjectId: string): void;
|
|
93
|
+
showMidAd(adObjectId: string): void;
|
|
94
|
+
|
|
95
|
+
// End-roll
|
|
96
|
+
loadEndAd(adUnitId: string, adObjectId: string): void;
|
|
97
|
+
showEndAd(adObjectId: string): void;
|
|
98
|
+
|
|
99
|
+
// Scroll (inline feed)
|
|
100
|
+
loadScrollAd(
|
|
101
|
+
adUnitId: string,
|
|
102
|
+
adObjectId: string,
|
|
103
|
+
episodeNumber?: Int32 | null
|
|
104
|
+
): void;
|
|
105
|
+
attachScrollAd(
|
|
106
|
+
adObjectId: string,
|
|
107
|
+
durationSeconds: Int32 | null,
|
|
108
|
+
useDefaultSwipeOverlay: boolean
|
|
109
|
+
): void;
|
|
110
|
+
setScrollAdPlaying(adObjectId: string, playing: boolean): void;
|
|
111
|
+
detachScrollAd(adObjectId: string): void;
|
|
112
|
+
|
|
113
|
+
// Pause (realtime pause card)
|
|
114
|
+
attachPauseAd(
|
|
115
|
+
adUnitId: string,
|
|
116
|
+
adObjectId: string,
|
|
117
|
+
positionMs: Double,
|
|
118
|
+
isPlaying: boolean
|
|
119
|
+
): void;
|
|
120
|
+
updatePauseAdPlayerState(
|
|
121
|
+
adObjectId: string,
|
|
122
|
+
positionMs: Double,
|
|
123
|
+
isPlaying: boolean
|
|
124
|
+
): void;
|
|
125
|
+
detachPauseAd(adObjectId: string): void;
|
|
126
|
+
|
|
127
|
+
// Common
|
|
128
|
+
disposeAd(adObjectId: string): void;
|
|
129
|
+
|
|
130
|
+
// Native → JS event stream (multiplexed by adObjectId)
|
|
131
|
+
readonly onAdEvent: EventEmitter<NativeAdEvent>;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export default TurboModuleRegistry.getEnforcing<Spec>('NovvyAds');
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { HostComponent, ViewProps } from 'react-native';
|
|
2
|
+
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
|
|
3
|
+
import type { DirectEventHandler } from 'react-native/Libraries/Types/CodegenTypes';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Fabric component for an inline realtime pause-card ad container
|
|
7
|
+
* (fixed 260×90). The native view registers its container in the TurboModule
|
|
8
|
+
* keyed by `adObjectId`, then fires `onViewReady`, at which point JS issues
|
|
9
|
+
* `attachPauseAd` (there is no load step for pause ads).
|
|
10
|
+
*/
|
|
11
|
+
type ViewReadyEvent = Readonly<{ adObjectId: string }>;
|
|
12
|
+
|
|
13
|
+
export interface NativeProps extends ViewProps {
|
|
14
|
+
adObjectId: string;
|
|
15
|
+
onViewReady?: DirectEventHandler<ViewReadyEvent>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default codegenNativeComponent<NativeProps>(
|
|
19
|
+
'NovvyPauseAdView'
|
|
20
|
+
) as HostComponent<NativeProps>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { HostComponent, ViewProps } from 'react-native';
|
|
2
|
+
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
|
|
3
|
+
import type { DirectEventHandler } from 'react-native/Libraries/Types/CodegenTypes';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Fabric component for an inline scroll (feed) ad container.
|
|
7
|
+
*
|
|
8
|
+
* The native view registers its container in the TurboModule keyed by
|
|
9
|
+
* `adObjectId`, then fires `onViewReady` (mirrors the Flutter plugin's
|
|
10
|
+
* `onPlatformViewCreated`), at which point JS issues `attachScrollAd`.
|
|
11
|
+
*/
|
|
12
|
+
type ViewReadyEvent = Readonly<{ adObjectId: string }>;
|
|
13
|
+
|
|
14
|
+
export interface NativeProps extends ViewProps {
|
|
15
|
+
adObjectId: string;
|
|
16
|
+
onViewReady?: DirectEventHandler<ViewReadyEvent>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default codegenNativeComponent<NativeProps>(
|
|
20
|
+
'NovvyScrollAdView'
|
|
21
|
+
) as HostComponent<NativeProps>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// RN 0.76.0 ships the codegen `EventEmitter` type in the Flow source
|
|
2
|
+
// (Libraries/Types/CodegenTypes.js) — the native codegen parser recognizes it
|
|
3
|
+
// — but omits it from the bundled TypeScript declarations. Augment the module
|
|
4
|
+
// so `tsc` type-checks the spec. Newer RN versions declare this themselves;
|
|
5
|
+
// declaration merging makes this a no-op there.
|
|
6
|
+
declare module 'react-native/Libraries/Types/CodegenTypes' {
|
|
7
|
+
export type EventEmitter<T> = (handler: (event: T) => void) => {
|
|
8
|
+
remove(): void;
|
|
9
|
+
};
|
|
10
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public types for the Novvy Ads React Native SDK.
|
|
3
|
+
*
|
|
4
|
+
* These mirror the Flutter plugin's Pigeon data classes
|
|
5
|
+
* (pigeons/novvy_ads_api.dart). At runtime they are structurally identical to
|
|
6
|
+
* the codegen structs in `spec/NativeNovvyAds.ts`, so instances pass straight
|
|
7
|
+
* through the TurboModule with no conversion.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** A single drama-watch history entry used for ad targeting. */
|
|
11
|
+
export interface NovvyDramaRecord {
|
|
12
|
+
seriesId: string;
|
|
13
|
+
lastWatchedEpisode: number;
|
|
14
|
+
unlockedEpisode: number;
|
|
15
|
+
dramaTitle?: string | null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** User gender values accepted by the SDK. */
|
|
19
|
+
export type NovvyGender = 'male' | 'female' | 'unknown';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* User identity and subscription context.
|
|
23
|
+
*
|
|
24
|
+
* Pass to {@link NovvyAds.setUserContext} (full replace) or
|
|
25
|
+
* {@link NovvyAds.updateUserContext} (incremental merge).
|
|
26
|
+
*/
|
|
27
|
+
export interface NovvyUserContext {
|
|
28
|
+
userId?: string | null;
|
|
29
|
+
/** SHA-256 of the trimmed/lowercased email. Use {@link NovvyAds.helperHashEmail}. */
|
|
30
|
+
hashedEmail?: string | null;
|
|
31
|
+
isPaidUser?: boolean | null;
|
|
32
|
+
age?: number | null;
|
|
33
|
+
gender?: NovvyGender | null;
|
|
34
|
+
/** Watched-drama records used for targeting. */
|
|
35
|
+
dramaWatchHistory?: NovvyDramaRecord[] | null;
|
|
36
|
+
/** Frequency cap: maximum ads shown within a single drama. */
|
|
37
|
+
maximumAdsInOneDrama?: number | null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Content and episode context used for ad targeting.
|
|
42
|
+
*
|
|
43
|
+
* Pass to {@link NovvyAds.setContentContext} (full replace) or
|
|
44
|
+
* {@link NovvyAds.updateContentContext} (incremental merge).
|
|
45
|
+
*/
|
|
46
|
+
export interface NovvyContentContext {
|
|
47
|
+
seriesName?: string | null;
|
|
48
|
+
episodeNumber?: number | null;
|
|
49
|
+
url?: string | null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Ad lifecycle event names (mirror Pigeon's `NovvyAdEvent` enum). */
|
|
53
|
+
export enum NovvyAdEvent {
|
|
54
|
+
/** Ad and creative are ready to show (not emitted for Pause — realtime). */
|
|
55
|
+
Loaded = 'loaded',
|
|
56
|
+
/** Ad failed to load / request. */
|
|
57
|
+
FailedToLoad = 'failedToLoad',
|
|
58
|
+
/** Ad was shown (full-screen) or became visible (Scroll / Pause). */
|
|
59
|
+
Showed = 'showed',
|
|
60
|
+
/** Full-screen ad was closed by the user (Rewarded / Interstitial / Mid / End). */
|
|
61
|
+
Dismissed = 'dismissed',
|
|
62
|
+
/** Inline ad was hidden / removed (Scroll onAdHidden, Pause hidden). */
|
|
63
|
+
Hidden = 'hidden',
|
|
64
|
+
/** Rewarded ad earned a reward. Carries no data payload. */
|
|
65
|
+
EarnedReward = 'earnedReward',
|
|
66
|
+
/** Scroll ad playback tick. Carries `remainingSeconds`. */
|
|
67
|
+
PlaybackTick = 'playbackTick',
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Interface for a media player that a {@link NovvyPauseAd} monitors.
|
|
72
|
+
*
|
|
73
|
+
* Implement this to bridge your video/audio player so the SDK can detect
|
|
74
|
+
* playback position and resumption. Mirrors the Flutter plugin's
|
|
75
|
+
* `NovvyPlayerAdapter`.
|
|
76
|
+
*/
|
|
77
|
+
export interface NovvyPlayerAdapter {
|
|
78
|
+
/** Current playback position in milliseconds. */
|
|
79
|
+
readonly currentPositionMs: number;
|
|
80
|
+
/** Whether the player is currently playing (not paused/buffering). */
|
|
81
|
+
readonly isPlaying: boolean;
|
|
82
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { StyleSheet, View, type ViewStyle, type StyleProp } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import { NovvyPauseAd } from '../ads/NovvyPauseAd';
|
|
5
|
+
import type { NovvyPlayerAdapter } from '../types';
|
|
6
|
+
import NativePauseView from '../spec/NovvyPauseAdViewNativeComponent';
|
|
7
|
+
|
|
8
|
+
export interface NovvyPauseAdViewProps {
|
|
9
|
+
/** The pause ad instance (no load step — attach happens on mount). */
|
|
10
|
+
ad: NovvyPauseAd;
|
|
11
|
+
/** Player adapter the SDK monitors to detect resumption. */
|
|
12
|
+
player: NovvyPlayerAdapter;
|
|
13
|
+
style?: StyleProp<ViewStyle>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Embeds a {@link NovvyPauseAd} as a native view. Fixed to
|
|
18
|
+
* {@link NovvyPauseAd.cardWidth} × {@link NovvyPauseAd.cardHeight}; position it
|
|
19
|
+
* within your own layout. Mirrors the Flutter plugin's `NovvyPauseAdView`.
|
|
20
|
+
*
|
|
21
|
+
* Touch passthrough / opacity follow the card's shown state so the view is
|
|
22
|
+
* transparent and non-interactive until the ad actually appears.
|
|
23
|
+
*/
|
|
24
|
+
export function NovvyPauseAdView({
|
|
25
|
+
ad,
|
|
26
|
+
player,
|
|
27
|
+
style,
|
|
28
|
+
}: NovvyPauseAdViewProps): React.ReactElement {
|
|
29
|
+
const attached = useRef(false);
|
|
30
|
+
const [shown, setShown] = useState(false);
|
|
31
|
+
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
const prev = ad.onShownChanged;
|
|
34
|
+
ad.onShownChanged = (isShown) => {
|
|
35
|
+
setShown(isShown);
|
|
36
|
+
prev?.(isShown);
|
|
37
|
+
};
|
|
38
|
+
return () => {
|
|
39
|
+
ad.onShownChanged = prev;
|
|
40
|
+
if (attached.current) {
|
|
41
|
+
ad.detach();
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
45
|
+
}, []);
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<View
|
|
49
|
+
style={[styles.container, style]}
|
|
50
|
+
pointerEvents={shown ? 'auto' : 'none'}
|
|
51
|
+
// Claim the RN JS responder while the card is shown so an outer
|
|
52
|
+
// Pressable/Touchable in the host layout can't also fire onPress on
|
|
53
|
+
// the same tap and race with the SDK's CTA (which would resume the
|
|
54
|
+
// video and destroy the ad before the browser opens). The SDK's
|
|
55
|
+
// native tap handling is unaffected: on Android JSTouchDispatcher
|
|
56
|
+
// runs in parallel to native dispatch, and on iOS RCTTouchHandler
|
|
57
|
+
// uses cancelsTouchesInView=NO so native touches still reach the
|
|
58
|
+
// ad view's own gesture recognizer.
|
|
59
|
+
onStartShouldSetResponder={shown ? () => true : undefined}
|
|
60
|
+
>
|
|
61
|
+
<NativePauseView
|
|
62
|
+
style={[StyleSheet.absoluteFill, { opacity: shown ? 1 : 0 }]}
|
|
63
|
+
adObjectId={ad.adObjectId}
|
|
64
|
+
onViewReady={() => {
|
|
65
|
+
if (!attached.current) {
|
|
66
|
+
attached.current = true;
|
|
67
|
+
ad.attach(player);
|
|
68
|
+
}
|
|
69
|
+
}}
|
|
70
|
+
/>
|
|
71
|
+
</View>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const styles = StyleSheet.create({
|
|
76
|
+
container: {
|
|
77
|
+
width: NovvyPauseAd.cardWidth,
|
|
78
|
+
height: NovvyPauseAd.cardHeight,
|
|
79
|
+
},
|
|
80
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import React, { useEffect, useRef } from 'react';
|
|
2
|
+
import { StyleSheet, View, type ViewStyle, type StyleProp } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import type { NovvyScrollAd } from '../ads/NovvyScrollAd';
|
|
5
|
+
import NativeScrollView from '../spec/NovvyScrollAdViewNativeComponent';
|
|
6
|
+
|
|
7
|
+
export interface NovvyScrollAdViewProps {
|
|
8
|
+
/** The scroll ad instance (load it first via `ad.load()`). */
|
|
9
|
+
ad: NovvyScrollAd;
|
|
10
|
+
/** Swipe-unlock wait time passed to the native attach call. */
|
|
11
|
+
durationSeconds?: number | null;
|
|
12
|
+
/** Whether the SDK renders its built-in "Swipe to skip" pill. */
|
|
13
|
+
useDefaultSwipeOverlay?: boolean;
|
|
14
|
+
style?: StyleProp<ViewStyle>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Embeds a {@link NovvyScrollAd} as a native view. Wrap it in a container with
|
|
19
|
+
* the desired height for your feed item. Mirrors the Flutter plugin's
|
|
20
|
+
* `NovvyScrollAdView`.
|
|
21
|
+
*
|
|
22
|
+
* A black backdrop paints immediately so the previous page can't show through
|
|
23
|
+
* the slot while the native view is created.
|
|
24
|
+
*/
|
|
25
|
+
export function NovvyScrollAdView({
|
|
26
|
+
ad,
|
|
27
|
+
durationSeconds,
|
|
28
|
+
useDefaultSwipeOverlay = true,
|
|
29
|
+
style,
|
|
30
|
+
}: NovvyScrollAdViewProps): React.ReactElement {
|
|
31
|
+
const attached = useRef(false);
|
|
32
|
+
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
return () => {
|
|
35
|
+
if (attached.current) {
|
|
36
|
+
ad.detach();
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
// Detach only on unmount; `ad` identity is stable for the view's lifetime.
|
|
40
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
41
|
+
}, []);
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<View
|
|
45
|
+
style={[styles.container, style]}
|
|
46
|
+
// Claim the RN JS responder for taps so an outer Pressable/Touchable
|
|
47
|
+
// in the host layout can't also fire onPress and race with the SDK's
|
|
48
|
+
// CTA. Only onStart is claimed — a subsequent move gesture can still
|
|
49
|
+
// migrate to an ancestor ScrollView/FlatList via the normal responder
|
|
50
|
+
// negotiation, so vertical feed swiping is preserved.
|
|
51
|
+
onStartShouldSetResponder={() => true}
|
|
52
|
+
>
|
|
53
|
+
<NativeScrollView
|
|
54
|
+
style={StyleSheet.absoluteFill}
|
|
55
|
+
adObjectId={ad.adObjectId}
|
|
56
|
+
onViewReady={() => {
|
|
57
|
+
if (!attached.current) {
|
|
58
|
+
attached.current = true;
|
|
59
|
+
ad.attach(durationSeconds, useDefaultSwipeOverlay);
|
|
60
|
+
}
|
|
61
|
+
}}
|
|
62
|
+
/>
|
|
63
|
+
</View>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const styles = StyleSheet.create({
|
|
68
|
+
container: {
|
|
69
|
+
backgroundColor: '#000000',
|
|
70
|
+
},
|
|
71
|
+
});
|