react-native-buzzvil-ad 0.1.0 → 0.2.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/CHANGELOG.md +58 -0
- package/android/src/main/java/com/buzzvil/BuzzvilModule.kt +83 -0
- package/ios/Buzzvil.h +4 -1
- package/ios/Buzzvil.mm +142 -1
- package/lib/module/NativeBuzzvil.js +6 -0
- package/lib/module/NativeBuzzvil.js.map +1 -1
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/interstitial.js +23 -0
- package/lib/module/interstitial.js.map +1 -0
- package/lib/module/interstitial.native.js +47 -0
- package/lib/module/interstitial.native.js.map +1 -0
- package/lib/typescript/src/NativeBuzzvil.d.ts +47 -0
- package/lib/typescript/src/NativeBuzzvil.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +2 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/interstitial.d.ts +8 -0
- package/lib/typescript/src/interstitial.d.ts.map +1 -0
- package/lib/typescript/src/interstitial.native.d.ts +29 -0
- package/lib/typescript/src/interstitial.native.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +5 -0
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/package.json +3 -1
- package/src/NativeBuzzvil.ts +49 -0
- package/src/index.tsx +6 -0
- package/src/interstitial.native.tsx +52 -0
- package/src/interstitial.tsx +30 -0
- package/src/types.ts +6 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format follows
|
|
4
|
+
[Conventional Commits](https://www.conventionalcommits.org/) and
|
|
5
|
+
[Keep a Changelog](https://keepachangelog.com/); this project adheres to
|
|
6
|
+
[Semantic Versioning](https://semver.org/).
|
|
7
|
+
|
|
8
|
+
> **Unofficial package.** `react-native-buzzvil-ad` is community-maintained and
|
|
9
|
+
> is **not** affiliated with, endorsed by, or supported by Buzzvil.
|
|
10
|
+
|
|
11
|
+
## 0.2.0 (2026-06-13)
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
- **interstitial:** add Buzzvil BuzzBenefit v6 interstitial ads (full-screen
|
|
16
|
+
`dialog` / `bottomSheet`) on Android & iOS — `loadInterstitial(unitId, type?)`
|
|
17
|
+
(resolves on load, rejects on failure), `showInterstitial(unitId)`, and the
|
|
18
|
+
`onInterstitialClosed` event via `addInterstitialClosedListener(unitId, cb)`.
|
|
19
|
+
Built on the existing `Buzzvil` TurboModule using a New-Architecture typed
|
|
20
|
+
`EventEmitter`; native instances are tracked per `unitId`. (#5)
|
|
21
|
+
- **example:** add interstitial smoke-test controls (type toggle, load/show,
|
|
22
|
+
close-event log) to the example app. (#5)
|
|
23
|
+
|
|
24
|
+
### Bug Fixes
|
|
25
|
+
|
|
26
|
+
- **interstitial:** reject a new `loadInterstitial` while an instance for the
|
|
27
|
+
same `unitId` is still loaded or showing, so the previous ad's close can no
|
|
28
|
+
longer remove a newer instance (and, on iOS, can no longer deallocate a
|
|
29
|
+
currently-visible ad). (#5)
|
|
30
|
+
|
|
31
|
+
### Build / Dependencies
|
|
32
|
+
|
|
33
|
+
- **deps:** resolve OSV-Scanner advisories (all dev-only, not shipped) — bump
|
|
34
|
+
`joi` to 17.13.4 (#2), pin `esbuild` `^0.28.1` via `resolutions`, and document
|
|
35
|
+
the `fast-xml-parser` suppression in `osv-scanner.toml`. (#4)
|
|
36
|
+
|
|
37
|
+
## 0.1.0 (2026-06-13)
|
|
38
|
+
|
|
39
|
+
Initial public release as the unofficial `react-native-buzzvil-ad` package
|
|
40
|
+
(renamed from the scoped `@dongminyu/react-native-buzzvil`).
|
|
41
|
+
|
|
42
|
+
### Features
|
|
43
|
+
|
|
44
|
+
- **session:** BuzzBenefit v6 session API via the `Buzzvil` TurboModule —
|
|
45
|
+
`initialize`, `login`, `logout`, `isLoggedIn`, and `showBenefitHub` (the
|
|
46
|
+
BenefitHub offerwall), with a primitives-only spec + sentinel contract.
|
|
47
|
+
- **native-ad:** `BuzzvilNativeAdView` Fabric component for in-feed native ads
|
|
48
|
+
on Android & iOS — inventory-size layout variants (banner / card), self-sizing
|
|
49
|
+
wrapper, and `onAdLoaded` / `onAdFailed` / `onAdClicked` / `onImpressed` /
|
|
50
|
+
`onRewarded` events. iOS calls the Swift SDK directly from Objective-C++
|
|
51
|
+
(no shim).
|
|
52
|
+
- **login:** dev-mode warnings for non-PII / malformed `userId` values (Buzzvil
|
|
53
|
+
rejects emails and other identifiable ids).
|
|
54
|
+
|
|
55
|
+
### Documentation
|
|
56
|
+
|
|
57
|
+
- Add the SDK API-mapping spec, the ad-format expansion design, and project
|
|
58
|
+
guidance (`CLAUDE.md`) covering the two native surfaces.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
package com.buzzvil
|
|
2
2
|
|
|
3
3
|
import android.app.Application
|
|
4
|
+
import com.facebook.react.bridge.Arguments
|
|
4
5
|
import com.facebook.react.bridge.Promise
|
|
5
6
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
7
|
import com.facebook.react.bridge.UiThreadUtil
|
|
@@ -12,6 +13,9 @@ import com.buzzvil.buzzbenefit.BuzzBenefitConfig
|
|
|
12
13
|
import com.buzzvil.buzzbenefit.benefithub.BuzzBenefitHub
|
|
13
14
|
import com.buzzvil.buzzbenefit.benefithub.BuzzBenefitHubConfig
|
|
14
15
|
import com.buzzvil.buzzbenefit.benefithub.BuzzBenefitHubPage
|
|
16
|
+
import com.buzzvil.buzzbenefit.BuzzAdError
|
|
17
|
+
import com.buzzvil.buzzbenefit.interstitial.BuzzInterstitial
|
|
18
|
+
import com.buzzvil.buzzbenefit.interstitial.BuzzInterstitialListener
|
|
15
19
|
import com.buzzvil.sdk.BuzzvilSdk
|
|
16
20
|
import com.buzzvil.sdk.BuzzvilSdkLoginListener
|
|
17
21
|
import com.buzzvil.sdk.BuzzvilSdkUser
|
|
@@ -84,6 +88,85 @@ class BuzzvilModule(
|
|
|
84
88
|
}
|
|
85
89
|
}
|
|
86
90
|
|
|
91
|
+
// --- Interstitial ---
|
|
92
|
+
|
|
93
|
+
// Design Decision 1: one BuzzInterstitial instance per unitId, so a later
|
|
94
|
+
// showInterstitial(unitId) presents the instance loaded by loadInterstitial.
|
|
95
|
+
private val interstitials = mutableMapOf<String, BuzzInterstitial>()
|
|
96
|
+
|
|
97
|
+
override fun loadInterstitial(
|
|
98
|
+
unitId: String,
|
|
99
|
+
type: String,
|
|
100
|
+
promise: Promise,
|
|
101
|
+
) {
|
|
102
|
+
// Reject a new load while an instance for this unitId already exists — in
|
|
103
|
+
// flight, loaded-and-waiting-to-show, or currently showing (parity with iOS).
|
|
104
|
+
// Overwriting interstitials[unitId] would let the OLD instance's onAdClosed
|
|
105
|
+
// remove the NEW one by unitId, no-op'ing the next show(). The entry is
|
|
106
|
+
// cleared on close/failure, after which a fresh load is allowed.
|
|
107
|
+
if (interstitials.containsKey(unitId)) {
|
|
108
|
+
promise.reject(
|
|
109
|
+
"buzzvil_interstitial_load_failed",
|
|
110
|
+
"An interstitial for this unitId is already loaded or loading; wait for onInterstitialClosed before loading again.",
|
|
111
|
+
)
|
|
112
|
+
return
|
|
113
|
+
}
|
|
114
|
+
// type sentinel: "bottomSheet" → bottom sheet; "dialog"/""/unknown → dialog.
|
|
115
|
+
val builder = BuzzInterstitial.Builder(unitId)
|
|
116
|
+
val interstitial =
|
|
117
|
+
if (type == "bottomSheet") builder.buildBottomSheet() else builder.buildDialog()
|
|
118
|
+
if (interstitial == null) {
|
|
119
|
+
promise.reject(
|
|
120
|
+
"buzzvil_interstitial_load_failed",
|
|
121
|
+
"Failed to build a BuzzInterstitial for unitId=$unitId.",
|
|
122
|
+
)
|
|
123
|
+
return
|
|
124
|
+
}
|
|
125
|
+
// Store from load-start; the guard above keys off its presence, and it's
|
|
126
|
+
// removed on close/failure.
|
|
127
|
+
interstitials[unitId] = interstitial
|
|
128
|
+
|
|
129
|
+
// The SDK listener can fire repeatedly; settle the promise exactly once.
|
|
130
|
+
var settled = false
|
|
131
|
+
interstitial.load(
|
|
132
|
+
object : BuzzInterstitialListener() {
|
|
133
|
+
override fun onAdLoaded() {
|
|
134
|
+
if (settled) return
|
|
135
|
+
settled = true
|
|
136
|
+
// Keep the instance in `interstitials` for the later show().
|
|
137
|
+
promise.resolve(null)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
override fun onAdLoadFailed(error: BuzzAdError?) {
|
|
141
|
+
if (settled) return
|
|
142
|
+
settled = true
|
|
143
|
+
interstitials.remove(unitId)
|
|
144
|
+
promise.reject(
|
|
145
|
+
"buzzvil_interstitial_load_failed",
|
|
146
|
+
error?.message ?: error?.type?.toString() ?: "Interstitial load failed.",
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
override fun onAdClosed() {
|
|
151
|
+
// New-Arch typed EventEmitter: codegen generates this concrete emit
|
|
152
|
+
// method on the spec base; payload is a flat primitive map.
|
|
153
|
+
emitOnInterstitialClosed(Arguments.createMap().apply { putString("unitId", unitId) })
|
|
154
|
+
// Lifecycle: drop the dismissed instance so the map doesn't retain it
|
|
155
|
+
// (and so a fresh loadInterstitial for this unitId is allowed again).
|
|
156
|
+
interstitials.remove(unitId)
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
override fun showInterstitial(unitId: String) {
|
|
163
|
+
// show() presents UI — must run on the main thread (parity with BenefitHub).
|
|
164
|
+
UiThreadUtil.runOnUiThread {
|
|
165
|
+
val activity = currentActivity ?: return@runOnUiThread
|
|
166
|
+
interstitials[unitId]?.show(activity)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
87
170
|
companion object {
|
|
88
171
|
const val NAME = NativeBuzzvilSpec.NAME
|
|
89
172
|
}
|
package/ios/Buzzvil.h
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
#import <BuzzvilSpec/BuzzvilSpec.h>
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// Subclass the codegen base (not bare NSObject): NativeBuzzvilSpecBase provides
|
|
4
|
+
// setEventEmitterCallback: and the generated emitOnInterstitialClosed:, which
|
|
5
|
+
// the interstitial "closed" event is dispatched through.
|
|
6
|
+
@interface Buzzvil : NativeBuzzvilSpecBase <NativeBuzzvilSpec>
|
|
4
7
|
|
|
5
8
|
@end
|
package/ios/Buzzvil.mm
CHANGED
|
@@ -8,7 +8,52 @@
|
|
|
8
8
|
#import <BuzzvilSDK/BuzzvilSDK-Swift.h>
|
|
9
9
|
#import <BuzzAdBenefitSDK/BuzzAdBenefitSDK-Swift.h>
|
|
10
10
|
|
|
11
|
-
@
|
|
11
|
+
@class BuzzInterstitialLoader;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Per-load helper that conforms to `BuzzInterstitialDelegate` and captures the
|
|
15
|
+
* promise blocks + `unitId` for one `loadInterstitial` call.
|
|
16
|
+
*
|
|
17
|
+
* Why a helper at all: `BuzzInterstitial.delegate` is a **weak** property and
|
|
18
|
+
* its delegate callbacks pass back the `BuzzInterstitial` (not the unitId). A
|
|
19
|
+
* dedicated loader (a) owns the `BuzzInterstitial` strongly so a later
|
|
20
|
+
* `showInterstitial` can present it, (b) carries the `unitId` directly so no
|
|
21
|
+
* instance→unitId reverse lookup is needed, and (c) is retained by the module's
|
|
22
|
+
* `_loaders` map so ARC doesn't dealloc it the moment `loadInterstitial`
|
|
23
|
+
* returns (which would silently drop every callback and hang the promise).
|
|
24
|
+
*
|
|
25
|
+
* The back-ref to the module is **weak** to avoid a retain cycle (the module is
|
|
26
|
+
* a long-lived TurboModule singleton). The module owns loader removal so a
|
|
27
|
+
* loader's final act is `[module removeLoaderForUnitId:]` — after which `self`
|
|
28
|
+
* may be deallocated, so callbacks touch nothing on `self` afterwards.
|
|
29
|
+
*/
|
|
30
|
+
@interface BuzzInterstitialLoader : NSObject <BuzzInterstitialDelegate>
|
|
31
|
+
@property (nonatomic, strong) BuzzInterstitial *interstitial;
|
|
32
|
+
@property (nonatomic, copy) NSString *unitId;
|
|
33
|
+
@property (nonatomic, copy) RCTPromiseResolveBlock resolve;
|
|
34
|
+
@property (nonatomic, copy) RCTPromiseRejectBlock reject;
|
|
35
|
+
@property (nonatomic, assign) BOOL settled; // settle the promise exactly once
|
|
36
|
+
@property (nonatomic, weak) Buzzvil *module;
|
|
37
|
+
@end
|
|
38
|
+
|
|
39
|
+
@implementation Buzzvil {
|
|
40
|
+
// unitId → loader. Retains each loader (and its BuzzInterstitial) from load
|
|
41
|
+
// until did-fail / did-dismiss removes it (parity with Android's map cleanup).
|
|
42
|
+
NSMutableDictionary<NSString *, BuzzInterstitialLoader *> *_loaders;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
- (NSMutableDictionary<NSString *, BuzzInterstitialLoader *> *)loaders
|
|
46
|
+
{
|
|
47
|
+
if (_loaders == nil) {
|
|
48
|
+
_loaders = [NSMutableDictionary new];
|
|
49
|
+
}
|
|
50
|
+
return _loaders;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
- (void)removeLoaderForUnitId:(NSString *)unitId
|
|
54
|
+
{
|
|
55
|
+
[self.loaders removeObjectForKey:unitId];
|
|
56
|
+
}
|
|
12
57
|
|
|
13
58
|
- (void)initialize:(NSString *)appId
|
|
14
59
|
{
|
|
@@ -86,6 +131,61 @@
|
|
|
86
131
|
});
|
|
87
132
|
}
|
|
88
133
|
|
|
134
|
+
#pragma mark - Interstitial
|
|
135
|
+
|
|
136
|
+
- (void)loadInterstitial:(NSString *)unitId
|
|
137
|
+
type:(NSString *)type
|
|
138
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
139
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
140
|
+
{
|
|
141
|
+
// type sentinel: "bottomSheet" → bottom sheet; "dialog"/""/unknown → dialog
|
|
142
|
+
// (parity with Android's buildBottomSheet()/buildDialog()).
|
|
143
|
+
BuzzInterstitialType interstitialType =
|
|
144
|
+
[type isEqualToString:@"bottomSheet"] ? BuzzInterstitialTypeBottomSheet : BuzzInterstitialTypeDialog;
|
|
145
|
+
|
|
146
|
+
// Reject a new load while a loader for this unitId already exists — in flight,
|
|
147
|
+
// loaded-and-waiting-to-show, or currently showing (parity with Android).
|
|
148
|
+
// Overwriting self.loaders[unitId] would (a) let the OLD loader's didDismiss
|
|
149
|
+
// remove the NEW loader by unitId, and (b) dealloc the existing loader — and,
|
|
150
|
+
// as the sole strong owner of its BuzzInterstitial, dealloc a currently-visible
|
|
151
|
+
// interstitial. The entry is cleared on dismiss/failure, then a fresh load is OK.
|
|
152
|
+
BuzzInterstitialLoader *existing = self.loaders[unitId];
|
|
153
|
+
if (existing != nil) {
|
|
154
|
+
reject(@"buzzvil_interstitial_load_failed",
|
|
155
|
+
@"An interstitial for this unitId is already loaded or loading; wait for onInterstitialClosed before loading again.", nil);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
BuzzInterstitialLoader *loader = [BuzzInterstitialLoader new];
|
|
160
|
+
loader.unitId = unitId;
|
|
161
|
+
loader.resolve = resolve;
|
|
162
|
+
loader.reject = reject;
|
|
163
|
+
loader.module = self;
|
|
164
|
+
loader.interstitial = [[BuzzInterstitial alloc] initWithUnitId:unitId type:interstitialType];
|
|
165
|
+
loader.interstitial.delegate = loader; // delegate is weak — loader must outlive this call
|
|
166
|
+
|
|
167
|
+
// Retain the loader (and its BuzzInterstitial) until did-fail / did-dismiss.
|
|
168
|
+
self.loaders[unitId] = loader;
|
|
169
|
+
|
|
170
|
+
[loader.interstitial load];
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
- (void)showInterstitial:(NSString *)unitId
|
|
174
|
+
{
|
|
175
|
+
// present presents UI — must run on the main thread (parity with BenefitHub).
|
|
176
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
177
|
+
UIViewController *presenter = RCTPresentedViewController();
|
|
178
|
+
if (presenter == nil) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
BuzzInterstitialLoader *loader = self.loaders[unitId];
|
|
182
|
+
if (loader == nil) {
|
|
183
|
+
return; // nothing loaded for this unitId — no-op
|
|
184
|
+
}
|
|
185
|
+
[loader.interstitial presentOnViewController:presenter];
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
89
189
|
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
90
190
|
(const facebook::react::ObjCTurboModule::InitParams &)params
|
|
91
191
|
{
|
|
@@ -98,3 +198,44 @@
|
|
|
98
198
|
}
|
|
99
199
|
|
|
100
200
|
@end
|
|
201
|
+
|
|
202
|
+
#pragma mark - BuzzInterstitialLoader
|
|
203
|
+
|
|
204
|
+
@implementation BuzzInterstitialLoader
|
|
205
|
+
|
|
206
|
+
- (void)buzzInterstitialDidLoadAd:(BuzzInterstitial *)interstitial
|
|
207
|
+
{
|
|
208
|
+
if (self.settled) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
self.settled = YES;
|
|
212
|
+
self.resolve(nil);
|
|
213
|
+
// Keep the loader in the map — showInterstitial needs it until dismiss.
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
- (void)buzzInterstitialDidFailToLoadAd:(BuzzInterstitial *)interstitial withError:(NSError *)error
|
|
217
|
+
{
|
|
218
|
+
if (self.settled) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
self.settled = YES;
|
|
222
|
+
// Capture before removal: removing from the map may dealloc self.
|
|
223
|
+
NSString *unitId = self.unitId;
|
|
224
|
+
RCTPromiseRejectBlock reject = self.reject;
|
|
225
|
+
Buzzvil *module = self.module;
|
|
226
|
+
reject(@"buzzvil_interstitial_load_failed", error.localizedDescription ?: @"Interstitial load failed.", error);
|
|
227
|
+
[module removeLoaderForUnitId:unitId]; // final act — touch nothing on self after this
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
- (void)buzzInterstitialDidDismiss:(UIViewController *)viewController
|
|
231
|
+
{
|
|
232
|
+
// Capture before removal: removing from the map may dealloc self.
|
|
233
|
+
NSString *unitId = self.unitId;
|
|
234
|
+
Buzzvil *module = self.module;
|
|
235
|
+
// New-Arch typed EventEmitter: codegen generates emitOnInterstitialClosed on
|
|
236
|
+
// the spec base; payload is a flat NSDictionary { unitId } (parity with Android).
|
|
237
|
+
[module emitOnInterstitialClosed:@{@"unitId" : unitId}];
|
|
238
|
+
[module removeLoaderForUnitId:unitId]; // final act — touch nothing on self after this
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
@end
|
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
import { TurboModuleRegistry } from 'react-native';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Payload for the interstitial "closed" event. Flat primitive (codegen events
|
|
7
|
+
* cannot carry nested objects); `unitId` identifies which placement closed so
|
|
8
|
+
* the JS wrapper can route the callback to the right listener.
|
|
9
|
+
*/
|
|
10
|
+
|
|
5
11
|
/**
|
|
6
12
|
* TurboModule spec for the native `Buzzvil` module — a thin bridge over
|
|
7
13
|
* Buzzvil's BuzzBenefit v6 SDKs (Android / iOS).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeBuzzvil.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAA0B,cAAc;;
|
|
1
|
+
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeBuzzvil.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAA0B,cAAc;;AAGpE;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AA0FA,eAAeA,mBAAmB,CAACC,YAAY,CAAO,SAAS,CAAC","ignoreList":[]}
|
package/lib/module/index.js
CHANGED
|
@@ -2,4 +2,5 @@
|
|
|
2
2
|
|
|
3
3
|
export { initialize, login, logout, isLoggedIn, showBenefitHub } from './buzzvil';
|
|
4
4
|
export { BuzzvilNativeAdView } from './BuzzvilNativeAdView';
|
|
5
|
+
export { loadInterstitial, showInterstitial, addInterstitialClosedListener } from './interstitial';
|
|
5
6
|
//# sourceMappingURL=index.js.map
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["initialize","login","logout","isLoggedIn","showBenefitHub","BuzzvilNativeAdView"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SACEA,UAAU,EACVC,KAAK,EACLC,MAAM,EACNC,UAAU,EACVC,cAAc,QACT,WAAW;AAElB,SAASC,mBAAmB,QAAQ,uBAAuB","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["initialize","login","logout","isLoggedIn","showBenefitHub","BuzzvilNativeAdView","loadInterstitial","showInterstitial","addInterstitialClosedListener"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SACEA,UAAU,EACVC,KAAK,EACLC,MAAM,EACNC,UAAU,EACVC,cAAc,QACT,WAAW;AAElB,SAASC,mBAAmB,QAAQ,uBAAuB;AAE3D,SACEC,gBAAgB,EAChBC,gBAAgB,EAChBC,6BAA6B,QACxB,gBAAgB","ignoreList":[]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Web fallback. Buzzvil's interstitial is mobile-only, so the imperative
|
|
5
|
+
* methods fail **at call time** (never at import time). `.native.tsx` is used
|
|
6
|
+
* on iOS/Android.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const UNSUPPORTED = 'react-native-buzzvil is not supported on web.';
|
|
10
|
+
export function loadInterstitial(_unitId, _type = 'dialog') {
|
|
11
|
+
return Promise.reject(new Error(UNSUPPORTED));
|
|
12
|
+
}
|
|
13
|
+
export function showInterstitial(_unitId) {
|
|
14
|
+
throw new Error(UNSUPPORTED);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** No-op on web: the close event never fires, so `remove()` does nothing. */
|
|
18
|
+
export function addInterstitialClosedListener(_unitId, _cb) {
|
|
19
|
+
return {
|
|
20
|
+
remove() {}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=interstitial.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["UNSUPPORTED","loadInterstitial","_unitId","_type","Promise","reject","Error","showInterstitial","addInterstitialClosedListener","_cb","remove"],"sourceRoot":"../../src","sources":["interstitial.tsx"],"mappings":";;AAEA;AACA;AACA;AACA;AACA;;AAEA,MAAMA,WAAW,GAAG,+CAA+C;AAEnE,OAAO,SAASC,gBAAgBA,CAC9BC,OAAe,EACfC,KAAuB,GAAG,QAAQ,EACnB;EACf,OAAOC,OAAO,CAACC,MAAM,CAAC,IAAIC,KAAK,CAACN,WAAW,CAAC,CAAC;AAC/C;AAEA,OAAO,SAASO,gBAAgBA,CAACL,OAAe,EAAQ;EACtD,MAAM,IAAII,KAAK,CAACN,WAAW,CAAC;AAC9B;;AAEA;AACA,OAAO,SAASQ,6BAA6BA,CAC3CN,OAAe,EACfO,GAAe,EACK;EACpB,OAAO;IACLC,MAAMA,CAAA,EAAG,CAAC;EACZ,CAAC;AACH","ignoreList":[]}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import Buzzvil from "./NativeBuzzvil.js";
|
|
4
|
+
/**
|
|
5
|
+
* Native (iOS/Android) implementation of the public Interstitial API. Wraps the
|
|
6
|
+
* primitive-only native spec (`./NativeBuzzvil`) in friendly functions; raw
|
|
7
|
+
* `NativeBuzzvil` calls stay out of the public surface.
|
|
8
|
+
*
|
|
9
|
+
* The native side holds one interstitial instance per `unitId` (design
|
|
10
|
+
* Decision 1), so `loadInterstitial` then `showInterstitial` operate on the
|
|
11
|
+
* same placement.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Load an interstitial for `unitId`. Resolves once loaded, rejects on
|
|
16
|
+
* load failure.
|
|
17
|
+
*
|
|
18
|
+
* @param type `'dialog'` (default) or `'bottomSheet'`.
|
|
19
|
+
*/
|
|
20
|
+
export function loadInterstitial(unitId, type = 'dialog') {
|
|
21
|
+
return Buzzvil.loadInterstitial(unitId, type);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Present the interstitial previously loaded for `unitId`. */
|
|
25
|
+
export function showInterstitial(unitId) {
|
|
26
|
+
Buzzvil.showInterstitial(unitId);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Subscribe to the "interstitial closed" event for a specific `unitId`. The
|
|
31
|
+
* native emitter is module-wide (one event for all placements), so the
|
|
32
|
+
* callback is gated on `event.unitId === unitId` — listeners for other units
|
|
33
|
+
* never fire. Returns a handle whose `remove()` unsubscribes.
|
|
34
|
+
*/
|
|
35
|
+
export function addInterstitialClosedListener(unitId, cb) {
|
|
36
|
+
const subscription = Buzzvil.onInterstitialClosed(event => {
|
|
37
|
+
if (event.unitId === unitId) {
|
|
38
|
+
cb();
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
return {
|
|
42
|
+
remove() {
|
|
43
|
+
subscription.remove();
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=interstitial.native.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["Buzzvil","loadInterstitial","unitId","type","showInterstitial","addInterstitialClosedListener","cb","subscription","onInterstitialClosed","event","remove"],"sourceRoot":"../../src","sources":["interstitial.native.tsx"],"mappings":";;AAAA,OAAOA,OAAO,MAAM,oBAAiB;AAGrC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,gBAAgBA,CAC9BC,MAAc,EACdC,IAAsB,GAAG,QAAQ,EAClB;EACf,OAAOH,OAAO,CAACC,gBAAgB,CAACC,MAAM,EAAEC,IAAI,CAAC;AAC/C;;AAEA;AACA,OAAO,SAASC,gBAAgBA,CAACF,MAAc,EAAQ;EACrDF,OAAO,CAACI,gBAAgB,CAACF,MAAM,CAAC;AAClC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASG,6BAA6BA,CAC3CH,MAAc,EACdI,EAAc,EACM;EACpB,MAAMC,YAAY,GAAGP,OAAO,CAACQ,oBAAoB,CAAEC,KAAK,IAAK;IAC3D,IAAIA,KAAK,CAACP,MAAM,KAAKA,MAAM,EAAE;MAC3BI,EAAE,CAAC,CAAC;IACN;EACF,CAAC,CAAC;EACF,OAAO;IACLI,MAAMA,CAAA,EAAG;MACPH,YAAY,CAACG,MAAM,CAAC,CAAC;IACvB;EACF,CAAC;AACH","ignoreList":[]}
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import { type TurboModule } from 'react-native';
|
|
2
|
+
import type { CodegenTypes } from 'react-native';
|
|
3
|
+
/**
|
|
4
|
+
* Payload for the interstitial "closed" event. Flat primitive (codegen events
|
|
5
|
+
* cannot carry nested objects); `unitId` identifies which placement closed so
|
|
6
|
+
* the JS wrapper can route the callback to the right listener.
|
|
7
|
+
*/
|
|
8
|
+
type InterstitialClosedEvent = Readonly<{
|
|
9
|
+
unitId: string;
|
|
10
|
+
}>;
|
|
2
11
|
/**
|
|
3
12
|
* TurboModule spec for the native `Buzzvil` module — a thin bridge over
|
|
4
13
|
* Buzzvil's BuzzBenefit v6 SDKs (Android / iOS).
|
|
@@ -66,6 +75,44 @@ export interface Spec extends TurboModule {
|
|
|
66
75
|
* See the sentinel contract above for `routePath` / `showHistory`.
|
|
67
76
|
*/
|
|
68
77
|
showBenefitHub(routePath: string, showHistory: boolean): void;
|
|
78
|
+
/**
|
|
79
|
+
* Load an interstitial ad for `unitId`. Resolves when the ad has loaded
|
|
80
|
+
* (Android `onAdLoaded` / iOS `BuzzInterstitialDidLoadAd`), rejects on
|
|
81
|
+
* load failure (`onAdLoadFailed` / `DidFail(toLoadAd:)`).
|
|
82
|
+
*
|
|
83
|
+
* The native side holds one `BuzzInterstitial` instance per `unitId` (see
|
|
84
|
+
* design Decision 1: a `unitId`-keyed map), so a later `showInterstitial`
|
|
85
|
+
* presents this loaded instance.
|
|
86
|
+
*
|
|
87
|
+
* @param unitId Interstitial ad unit id from the Buzzvil admin.
|
|
88
|
+
* @param type `'dialog'` or `'bottomSheet'` — selects the native build
|
|
89
|
+
* variant (`buildDialog()` / `buildBottomSheet()`). Carried as a plain
|
|
90
|
+
* string (no codegen enums); the friendly `InterstitialType` union and the
|
|
91
|
+
* `'dialog'` default live in the JS wrapper (`./interstitial.native.tsx`).
|
|
92
|
+
*/
|
|
93
|
+
loadInterstitial(unitId: string, type: string): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Present the interstitial instance previously loaded for `unitId`. No-op if
|
|
96
|
+
* nothing is loaded. UI work — runs on the main thread (parity with
|
|
97
|
+
* `showBenefitHub`).
|
|
98
|
+
*/
|
|
99
|
+
showInterstitial(unitId: string): void;
|
|
100
|
+
/**
|
|
101
|
+
* Fires when an interstitial is dismissed (Android `onAdClosed` / iOS
|
|
102
|
+
* `BuzzInterstitialDidDismiss`). The payload's `unitId` identifies which
|
|
103
|
+
* placement closed; the JS wrapper filters by it so each
|
|
104
|
+
* `addInterstitialClosedListener(unitId, …)` only fires for its own unit.
|
|
105
|
+
*
|
|
106
|
+
* Uses a codegen typed `EventEmitter` (RN New-Architecture event member):
|
|
107
|
+
* codegen generates a concrete `emitOnInterstitialClosed` on the native spec
|
|
108
|
+
* base class, so the native impl emits via that — no manual
|
|
109
|
+
* `addListener`/`removeListeners` plumbing. Imported as
|
|
110
|
+
* `CodegenTypes.EventEmitter` (the runtime `EventEmitter` exported from
|
|
111
|
+
* `react-native` is a class, not this type); codegen matches by the bare
|
|
112
|
+
* type name `EventEmitter`, so the `CodegenTypes.`-qualified form is
|
|
113
|
+
* recognized identically.
|
|
114
|
+
*/
|
|
115
|
+
readonly onInterstitialClosed: CodegenTypes.EventEmitter<InterstitialClosedEvent>;
|
|
69
116
|
}
|
|
70
117
|
declare const _default: Spec;
|
|
71
118
|
export default _default;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeBuzzvil.d.ts","sourceRoot":"","sources":["../../../src/NativeBuzzvil.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"NativeBuzzvil.d.ts","sourceRoot":"","sources":["../../../src/NativeBuzzvil.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD;;;;GAIG;AACH,KAAK,uBAAuB,GAAG,QAAQ,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE5D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAEhC;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExE,yDAAyD;IACzD,MAAM,IAAI,IAAI,CAAC;IAEf,wFAAwF;IACxF,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAE/B;;;;;;;OAOG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,GAAG,IAAI,CAAC;IAE9D;;;;;;;;;;;;;;OAcG;IACH,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9D;;;;OAIG;IACH,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAEvC;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,oBAAoB,EAAE,YAAY,CAAC,YAAY,CAAC,uBAAuB,CAAC,CAAC;CACnF;;AAED,wBAAiE"}
|
|
@@ -2,4 +2,6 @@ export { initialize, login, logout, isLoggedIn, showBenefitHub, } from './buzzvi
|
|
|
2
2
|
export type { BuzzvilUser, BuzzvilGender, BenefitHubOptions } from './types.js';
|
|
3
3
|
export { BuzzvilNativeAdView } from './BuzzvilNativeAdView';
|
|
4
4
|
export type { BuzzvilNativeAdLayout, BuzzvilNativeAdViewProps } from './types.js';
|
|
5
|
+
export { loadInterstitial, showInterstitial, addInterstitialClosedListener, } from './interstitial';
|
|
6
|
+
export type { InterstitialType } from './types.js';
|
|
5
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,KAAK,EACL,MAAM,EACN,UAAU,EACV,cAAc,GACf,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAS,CAAC;AAC7E,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,YAAY,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,MAAM,YAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,KAAK,EACL,MAAM,EACN,UAAU,EACV,cAAc,GACf,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAS,CAAC;AAC7E,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,YAAY,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,MAAM,YAAS,CAAC;AAC/E,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,6BAA6B,GAC9B,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAS,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { InterstitialType } from './types.js';
|
|
2
|
+
export declare function loadInterstitial(_unitId: string, _type?: InterstitialType): Promise<void>;
|
|
3
|
+
export declare function showInterstitial(_unitId: string): void;
|
|
4
|
+
/** No-op on web: the close event never fires, so `remove()` does nothing. */
|
|
5
|
+
export declare function addInterstitialClosedListener(_unitId: string, _cb: () => void): {
|
|
6
|
+
remove(): void;
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=interstitial.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interstitial.d.ts","sourceRoot":"","sources":["../../../src/interstitial.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAS,CAAC;AAUhD,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,KAAK,GAAE,gBAA2B,GACjC,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEtD;AAED,6EAA6E;AAC7E,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,IAAI,GACd;IAAE,MAAM,IAAI,IAAI,CAAA;CAAE,CAIpB"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { InterstitialType } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Native (iOS/Android) implementation of the public Interstitial API. Wraps the
|
|
4
|
+
* primitive-only native spec (`./NativeBuzzvil`) in friendly functions; raw
|
|
5
|
+
* `NativeBuzzvil` calls stay out of the public surface.
|
|
6
|
+
*
|
|
7
|
+
* The native side holds one interstitial instance per `unitId` (design
|
|
8
|
+
* Decision 1), so `loadInterstitial` then `showInterstitial` operate on the
|
|
9
|
+
* same placement.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Load an interstitial for `unitId`. Resolves once loaded, rejects on
|
|
13
|
+
* load failure.
|
|
14
|
+
*
|
|
15
|
+
* @param type `'dialog'` (default) or `'bottomSheet'`.
|
|
16
|
+
*/
|
|
17
|
+
export declare function loadInterstitial(unitId: string, type?: InterstitialType): Promise<void>;
|
|
18
|
+
/** Present the interstitial previously loaded for `unitId`. */
|
|
19
|
+
export declare function showInterstitial(unitId: string): void;
|
|
20
|
+
/**
|
|
21
|
+
* Subscribe to the "interstitial closed" event for a specific `unitId`. The
|
|
22
|
+
* native emitter is module-wide (one event for all placements), so the
|
|
23
|
+
* callback is gated on `event.unitId === unitId` — listeners for other units
|
|
24
|
+
* never fire. Returns a handle whose `remove()` unsubscribes.
|
|
25
|
+
*/
|
|
26
|
+
export declare function addInterstitialClosedListener(unitId: string, cb: () => void): {
|
|
27
|
+
remove(): void;
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=interstitial.native.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interstitial.native.d.ts","sourceRoot":"","sources":["../../../src/interstitial.native.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAS,CAAC;AAEhD;;;;;;;;GAQG;AAEH;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,gBAA2B,GAChC,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,+DAA+D;AAC/D,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAErD;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,IAAI,GACb;IAAE,MAAM,IAAI,IAAI,CAAA;CAAE,CAWpB"}
|
|
@@ -13,6 +13,11 @@ export interface BuzzvilUser {
|
|
|
13
13
|
/** 4-digit birth year, e.g. `1990`. */
|
|
14
14
|
birthYear?: number;
|
|
15
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Interstitial presentation style. `'dialog'` → `BuzzInterstitial.buildDialog()`;
|
|
18
|
+
* `'bottomSheet'` → `.buildBottomSheet()`. Carried to native as a plain string.
|
|
19
|
+
*/
|
|
20
|
+
export type InterstitialType = 'dialog' | 'bottomSheet';
|
|
16
21
|
/** Options for presenting the BenefitHub (offerwall). */
|
|
17
22
|
export interface BenefitHubOptions {
|
|
18
23
|
/** BenefitHub page number from the Buzzvil admin (advanced routing). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,kEAAkE;AAClE,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE9C,6EAA6E;AAC7E,MAAM,WAAW,WAAW;IAC1B,kEAAkE;IAClE,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,yDAAyD;AACzD,MAAM,WAAW,iBAAiB;IAChC,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,+DAA+D;AAC/D,MAAM,MAAM,qBAAqB,GAC7B,QAAQ,GACR,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,CAAC;AAEd,qEAAqE;AACrE,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAC/B,KAAK,CAAC,EAAE,OAAO,cAAc,EAAE,SAAS,CAAC,OAAO,cAAc,EAAE,SAAS,CAAC,CAAC;IAC3E,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC5D,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC5D,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;CAChD"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,kEAAkE;AAClE,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE9C,6EAA6E;AAC7E,MAAM,WAAW,WAAW;IAC1B,kEAAkE;IAClE,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,aAAa,CAAC;AAExD,yDAAyD;AACzD,MAAM,WAAW,iBAAiB;IAChC,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,+DAA+D;AAC/D,MAAM,MAAM,qBAAqB,GAC7B,QAAQ,GACR,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,CAAC;AAEd,qEAAqE;AACrE,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAC/B,KAAK,CAAC,EAAE,OAAO,cAAc,EAAE,SAAS,CAAC,OAAO,cAAc,EAAE,SAAS,CAAC,CAAC;IAC3E,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC5D,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC5D,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;CAChD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-buzzvil-ad",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Unofficial, community-maintained React Native wrapper for the Buzzvil BuzzBenefit SDK (Android & iOS). Not affiliated with, endorsed by, or supported by Buzzvil.",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"cpp",
|
|
21
21
|
"*.podspec",
|
|
22
22
|
"react-native.config.js",
|
|
23
|
+
"CHANGELOG.md",
|
|
23
24
|
"!ios/build",
|
|
24
25
|
"!android/build",
|
|
25
26
|
"!android/gradle",
|
|
@@ -88,6 +89,7 @@
|
|
|
88
89
|
"react-native": "*"
|
|
89
90
|
},
|
|
90
91
|
"resolutions": {
|
|
92
|
+
"esbuild": "^0.28.1",
|
|
91
93
|
"jest": "30.4.1",
|
|
92
94
|
"jest-cli": "30.4.1",
|
|
93
95
|
"@jest/core": "30.4.1",
|
package/src/NativeBuzzvil.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import { TurboModuleRegistry, type TurboModule } from 'react-native';
|
|
2
|
+
import type { CodegenTypes } from 'react-native';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Payload for the interstitial "closed" event. Flat primitive (codegen events
|
|
6
|
+
* cannot carry nested objects); `unitId` identifies which placement closed so
|
|
7
|
+
* the JS wrapper can route the callback to the right listener.
|
|
8
|
+
*/
|
|
9
|
+
type InterstitialClosedEvent = Readonly<{ unitId: string }>;
|
|
2
10
|
|
|
3
11
|
/**
|
|
4
12
|
* TurboModule spec for the native `Buzzvil` module — a thin bridge over
|
|
@@ -71,6 +79,47 @@ export interface Spec extends TurboModule {
|
|
|
71
79
|
* See the sentinel contract above for `routePath` / `showHistory`.
|
|
72
80
|
*/
|
|
73
81
|
showBenefitHub(routePath: string, showHistory: boolean): void;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Load an interstitial ad for `unitId`. Resolves when the ad has loaded
|
|
85
|
+
* (Android `onAdLoaded` / iOS `BuzzInterstitialDidLoadAd`), rejects on
|
|
86
|
+
* load failure (`onAdLoadFailed` / `DidFail(toLoadAd:)`).
|
|
87
|
+
*
|
|
88
|
+
* The native side holds one `BuzzInterstitial` instance per `unitId` (see
|
|
89
|
+
* design Decision 1: a `unitId`-keyed map), so a later `showInterstitial`
|
|
90
|
+
* presents this loaded instance.
|
|
91
|
+
*
|
|
92
|
+
* @param unitId Interstitial ad unit id from the Buzzvil admin.
|
|
93
|
+
* @param type `'dialog'` or `'bottomSheet'` — selects the native build
|
|
94
|
+
* variant (`buildDialog()` / `buildBottomSheet()`). Carried as a plain
|
|
95
|
+
* string (no codegen enums); the friendly `InterstitialType` union and the
|
|
96
|
+
* `'dialog'` default live in the JS wrapper (`./interstitial.native.tsx`).
|
|
97
|
+
*/
|
|
98
|
+
loadInterstitial(unitId: string, type: string): Promise<void>;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Present the interstitial instance previously loaded for `unitId`. No-op if
|
|
102
|
+
* nothing is loaded. UI work — runs on the main thread (parity with
|
|
103
|
+
* `showBenefitHub`).
|
|
104
|
+
*/
|
|
105
|
+
showInterstitial(unitId: string): void;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Fires when an interstitial is dismissed (Android `onAdClosed` / iOS
|
|
109
|
+
* `BuzzInterstitialDidDismiss`). The payload's `unitId` identifies which
|
|
110
|
+
* placement closed; the JS wrapper filters by it so each
|
|
111
|
+
* `addInterstitialClosedListener(unitId, …)` only fires for its own unit.
|
|
112
|
+
*
|
|
113
|
+
* Uses a codegen typed `EventEmitter` (RN New-Architecture event member):
|
|
114
|
+
* codegen generates a concrete `emitOnInterstitialClosed` on the native spec
|
|
115
|
+
* base class, so the native impl emits via that — no manual
|
|
116
|
+
* `addListener`/`removeListeners` plumbing. Imported as
|
|
117
|
+
* `CodegenTypes.EventEmitter` (the runtime `EventEmitter` exported from
|
|
118
|
+
* `react-native` is a class, not this type); codegen matches by the bare
|
|
119
|
+
* type name `EventEmitter`, so the `CodegenTypes.`-qualified form is
|
|
120
|
+
* recognized identically.
|
|
121
|
+
*/
|
|
122
|
+
readonly onInterstitialClosed: CodegenTypes.EventEmitter<InterstitialClosedEvent>;
|
|
74
123
|
}
|
|
75
124
|
|
|
76
125
|
export default TurboModuleRegistry.getEnforcing<Spec>('Buzzvil');
|
package/src/index.tsx
CHANGED
|
@@ -8,3 +8,9 @@ export {
|
|
|
8
8
|
export type { BuzzvilUser, BuzzvilGender, BenefitHubOptions } from './types';
|
|
9
9
|
export { BuzzvilNativeAdView } from './BuzzvilNativeAdView';
|
|
10
10
|
export type { BuzzvilNativeAdLayout, BuzzvilNativeAdViewProps } from './types';
|
|
11
|
+
export {
|
|
12
|
+
loadInterstitial,
|
|
13
|
+
showInterstitial,
|
|
14
|
+
addInterstitialClosedListener,
|
|
15
|
+
} from './interstitial';
|
|
16
|
+
export type { InterstitialType } from './types';
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import Buzzvil from './NativeBuzzvil';
|
|
2
|
+
import type { InterstitialType } from './types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Native (iOS/Android) implementation of the public Interstitial API. Wraps the
|
|
6
|
+
* primitive-only native spec (`./NativeBuzzvil`) in friendly functions; raw
|
|
7
|
+
* `NativeBuzzvil` calls stay out of the public surface.
|
|
8
|
+
*
|
|
9
|
+
* The native side holds one interstitial instance per `unitId` (design
|
|
10
|
+
* Decision 1), so `loadInterstitial` then `showInterstitial` operate on the
|
|
11
|
+
* same placement.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Load an interstitial for `unitId`. Resolves once loaded, rejects on
|
|
16
|
+
* load failure.
|
|
17
|
+
*
|
|
18
|
+
* @param type `'dialog'` (default) or `'bottomSheet'`.
|
|
19
|
+
*/
|
|
20
|
+
export function loadInterstitial(
|
|
21
|
+
unitId: string,
|
|
22
|
+
type: InterstitialType = 'dialog'
|
|
23
|
+
): Promise<void> {
|
|
24
|
+
return Buzzvil.loadInterstitial(unitId, type);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Present the interstitial previously loaded for `unitId`. */
|
|
28
|
+
export function showInterstitial(unitId: string): void {
|
|
29
|
+
Buzzvil.showInterstitial(unitId);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Subscribe to the "interstitial closed" event for a specific `unitId`. The
|
|
34
|
+
* native emitter is module-wide (one event for all placements), so the
|
|
35
|
+
* callback is gated on `event.unitId === unitId` — listeners for other units
|
|
36
|
+
* never fire. Returns a handle whose `remove()` unsubscribes.
|
|
37
|
+
*/
|
|
38
|
+
export function addInterstitialClosedListener(
|
|
39
|
+
unitId: string,
|
|
40
|
+
cb: () => void
|
|
41
|
+
): { remove(): void } {
|
|
42
|
+
const subscription = Buzzvil.onInterstitialClosed((event) => {
|
|
43
|
+
if (event.unitId === unitId) {
|
|
44
|
+
cb();
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
return {
|
|
48
|
+
remove() {
|
|
49
|
+
subscription.remove();
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { InterstitialType } from './types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Web fallback. Buzzvil's interstitial is mobile-only, so the imperative
|
|
5
|
+
* methods fail **at call time** (never at import time). `.native.tsx` is used
|
|
6
|
+
* on iOS/Android.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const UNSUPPORTED = 'react-native-buzzvil is not supported on web.';
|
|
10
|
+
|
|
11
|
+
export function loadInterstitial(
|
|
12
|
+
_unitId: string,
|
|
13
|
+
_type: InterstitialType = 'dialog'
|
|
14
|
+
): Promise<void> {
|
|
15
|
+
return Promise.reject(new Error(UNSUPPORTED));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function showInterstitial(_unitId: string): void {
|
|
19
|
+
throw new Error(UNSUPPORTED);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** No-op on web: the close event never fires, so `remove()` does nothing. */
|
|
23
|
+
export function addInterstitialClosedListener(
|
|
24
|
+
_unitId: string,
|
|
25
|
+
_cb: () => void
|
|
26
|
+
): { remove(): void } {
|
|
27
|
+
return {
|
|
28
|
+
remove() {},
|
|
29
|
+
};
|
|
30
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -16,6 +16,12 @@ export interface BuzzvilUser {
|
|
|
16
16
|
birthYear?: number;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Interstitial presentation style. `'dialog'` → `BuzzInterstitial.buildDialog()`;
|
|
21
|
+
* `'bottomSheet'` → `.buildBottomSheet()`. Carried to native as a plain string.
|
|
22
|
+
*/
|
|
23
|
+
export type InterstitialType = 'dialog' | 'bottomSheet';
|
|
24
|
+
|
|
19
25
|
/** Options for presenting the BenefitHub (offerwall). */
|
|
20
26
|
export interface BenefitHubOptions {
|
|
21
27
|
/** BenefitHub page number from the Buzzvil admin (advanced routing). */
|