提交 24cce19a 编写于 作者: d-u-a's avatar d-u-a

feat(App): createRewardedVideoAd、createFullScreenVideoAd、createInterstitialAd、createInteractiveAd

上级 b4c30451
......@@ -40,7 +40,7 @@
"node": ">=10.0.0"
},
"devDependencies": {
"@dcloudio/types": "^2.2.16",
"@dcloudio/types": "^2.2.18",
"@jest/types": "^27.0.2",
"@microsoft/api-extractor": "^7.13.2",
"@rollup/plugin-alias": "^3.1.1",
......
......@@ -83,6 +83,13 @@ export * from './protocols/plugin/getProvider'
export * from './protocols/plugin/oauth'
export * from './protocols/plugin/share'
export * from './protocols/plugin/requestPayment'
// ad
export * from './protocols/ad/rewardedVideoAd'
export * from './protocols/ad/fullScreenVideoAd'
export * from './protocols/ad/interstitialAd'
export * from './protocols/ad/interactiveAd'
// helpers
export {
defineOnApi,
......
export const API_CREATE_FULL_SCREEN_VIDEO_AD = 'createFullScreenVideoAd'
export type API_TYPE_CREATE_FULL_SCREEN_VIDEO_AD =
typeof uni.createFullScreenVideoAd
export const CreateFullScreenVideoAdOptions: ApiOptions<API_TYPE_CREATE_FULL_SCREEN_VIDEO_AD> =
{
formatArgs: {
adpid: '',
},
}
export const CreateFullScreenVideoAdProtocol: ApiProtocol<API_TYPE_CREATE_FULL_SCREEN_VIDEO_AD> =
{
adpid: String,
}
export const API_CREATE_INTERACTIVE_AD = 'createInteractiveAd'
export type API_TYPE_CREATE_INTERACTIVE_AD = typeof uni.createInteractiveAd
export const CreateInteractiveAdOptions: ApiOptions<API_TYPE_CREATE_INTERACTIVE_AD> =
{
formatArgs: {
adpid(value, params) {
if (!value) {
return 'adpid should not be empty.'
}
if (value) params.adpid = value
},
provider(value, params) {
if (!value) {
return 'provider should not be empty.'
}
if (value) params.provider = value
},
},
}
export const CreateInteractiveAdProtocol: ApiProtocol<API_TYPE_CREATE_INTERACTIVE_AD> =
{
adpid: {
type: String,
required: true,
},
provider: {
type: String,
required: true,
},
}
export const API_CREATE_INTERSTITIAL_AD = 'createInterstitialAd'
export type API_TYPE_CREATE_INTERSTITIAL_AD = typeof uni.createInterstitialAd
export const CreateInterstitialAdOptions: ApiOptions<API_TYPE_CREATE_INTERSTITIAL_AD> =
{
formatArgs: {
adpid: '',
adUnitId: '',
},
}
export const CreateInterstitialAdProtocol: ApiProtocol<API_TYPE_CREATE_INTERSTITIAL_AD> =
{
adpid: String,
adUnitId: String,
}
export const API_CREATE_REWARDED_VIDEO_AD = 'createRewardedVideoAd'
export type API_TYPE_CREATE_REWARDED_VIDEO_AD = typeof uni.createRewardedVideoAd
export const CreateRewardedVideoAdOptions: ApiOptions<API_TYPE_CREATE_REWARDED_VIDEO_AD> =
{
formatArgs: {
adpid: '',
adUnitId: '',
},
}
export const CreateRewardedVideoAdProtocol: ApiProtocol<API_TYPE_CREATE_REWARDED_VIDEO_AD> =
{
adpid: String,
adUnitId: String,
}
const EventType = {
load: 'load',
close: 'close',
error: 'error',
adClicked: 'adClicked',
}
type PlusError = {
code: Number
message: String
}
class AdEventHandler {
private _callbacks: Record<string, Array<Function>>
constructor() {
this._callbacks = {}
}
onLoad(callback: (result: any) => void) {
this._addEventListener(EventType.load, callback)
}
onClose(callback: (result: any) => void) {
this._addEventListener(EventType.close, callback)
}
onError(callback: (result: any) => void) {
this._addEventListener(EventType.error, callback)
}
offLoad(callback: (result: any) => void) {
this._removeEventListener(EventType.load, callback)
}
offClose(callback: (result: any) => void) {
this._removeEventListener(EventType.close, callback)
}
offError(callback: (result: any) => void) {
this._removeEventListener(EventType.error, callback)
}
_addEventListener(type: string, callback: Function) {
if (typeof callback !== 'function') {
return
}
this._callbacks[type].push(callback)
}
_removeEventListener(type: string, callback: Function) {
const arrayFunction: Array<Function> = this._callbacks[type]
const index = arrayFunction.indexOf(callback)
if (index > -1) {
arrayFunction.splice(index, 1)
}
}
_dispatchEvent(name: string, data: object) {
this._callbacks[name].forEach((callback) => {
callback(data || {})
})
}
}
class AdBase extends AdEventHandler {
private _isLoaded: boolean = false
private _isLoading: boolean = false
private _preload: boolean = true
private _loadPromiseResolve: Function | null = null
private _loadPromiseReject: Function | null = null
private _showPromiseResolve: Function | null = null
private _showPromiseReject: Function | null = null
private _adInstance: any
constructor(adInstance: any, options: any) {
super()
this._preload = options.preload !== undefined ? options.preload : false
const ad = (this._adInstance = adInstance)
ad.onLoad(() => {
this._isLoaded = true
this._isLoading = false
if (this._loadPromiseResolve != null) {
this._loadPromiseResolve()
this._loadPromiseResolve = null
}
if (this._showPromiseResolve != null) {
this._showPromiseResolve()
this._showPromiseResolve = null
this._showAd()
}
this._dispatchEvent(EventType.load, {})
})
ad.onClose((e: any) => {
this._isLoaded = false
this._isLoading = false
this._dispatchEvent(EventType.close, e)
if (this._preload === true) {
this._loadAd()
}
})
ad.onError((e: PlusError) => {
this._isLoading = false
const data = {
code: e.code,
errMsg: e.message,
}
this._dispatchEvent(EventType.error, data)
const error = new Error(JSON.stringify(data))
if (this._loadPromiseReject != null) {
this._loadPromiseReject(error)
this._loadPromiseReject = null
}
if (this._showPromiseReject != null) {
this._showPromiseReject(error)
this._showPromiseReject = null
}
})
ad.onAdClicked &&
ad.onAdClicked(() => {
this._dispatchEvent(EventType.adClicked, {})
})
}
getProvider() {
return this._adInstance.getProvider()
}
load(): Promise<any> {
return new Promise((resolve, reject) => {
this._loadPromiseResolve = resolve
this._loadPromiseReject = reject
if (this._isLoading) {
return
}
if (this._isLoaded) {
resolve('')
} else {
this._loadAd()
}
})
}
show(): Promise<any> {
return new Promise((resolve, reject) => {
this._showPromiseResolve = resolve
this._showPromiseReject = reject
if (this._isLoading) {
return
}
if (this._isLoaded) {
this._showAd()
resolve('')
} else {
this._loadAd()
}
})
}
destroy() {
this._adInstance.destroy()
}
_loadAd() {
this._isLoaded = false
this._isLoading = true
this._adInstance.load()
}
_showAd() {
this._adInstance.show()
}
}
export { AdBase, AdEventHandler, EventType }
import {
defineSyncApi,
API_CREATE_FULL_SCREEN_VIDEO_AD,
API_TYPE_CREATE_FULL_SCREEN_VIDEO_AD,
CreateFullScreenVideoAdOptions,
CreateFullScreenVideoAdProtocol,
} from '@dcloudio/uni-api'
import { AdBase } from './adBase'
class FullScreenVideoAd
extends AdBase
implements UniApp.FullScreenVideoAdContext
{
constructor(options: any) {
super(plus.ad.createFullScreenVideoAd(options), options)
}
}
export const createFullScreenVideoAd = <API_TYPE_CREATE_FULL_SCREEN_VIDEO_AD>(
defineSyncApi(
API_CREATE_FULL_SCREEN_VIDEO_AD,
(options) => {
return new FullScreenVideoAd(options)
},
CreateFullScreenVideoAdProtocol,
CreateFullScreenVideoAdOptions
)
)
import {
defineSyncApi,
API_CREATE_INTERACTIVE_AD,
API_TYPE_CREATE_INTERACTIVE_AD,
CreateInteractiveAdOptions,
CreateInteractiveAdProtocol,
} from '@dcloudio/uni-api'
import { requireNativePlugin } from '../base'
import { AdEventHandler, EventType } from './adBase'
const sdkCache: Record<string, any> = {}
const sdkQueue: Record<string, Array<any>> = {}
function initSDK(options: any) {
const provider = options.provider
if (!sdkCache[provider]) {
sdkCache[provider] = {}
}
if (typeof sdkCache[provider].plugin === 'object') {
options.success(sdkCache[provider].plugin)
return
}
if (!sdkQueue[provider]) {
sdkQueue[provider] = []
}
sdkQueue[provider].push(options)
if (sdkCache[provider].status === true) {
options.__plugin = sdkCache[provider].plugin
return
}
sdkCache[provider].status = true
const plugin = requireNativePlugin(provider)
if (!plugin || !plugin.initSDK) {
sdkQueue[provider].forEach((item) => {
item.fail({
code: -1,
message: 'provider [' + provider + '] invalid',
})
})
sdkQueue[provider].length = 0
sdkCache[provider].status = false
return
}
// TODO
sdkCache[provider].plugin = plugin
options.__plugin = plugin
plugin.initSDK((res: any) => {
const isSuccess = res.code === 1 || res.code === '1'
if (isSuccess) {
sdkCache[provider].plugin = plugin
} else {
sdkCache[provider].status = false
}
sdkQueue[provider].forEach((item) => {
if (isSuccess) {
item.success(item.__plugin)
} else {
item.fail(res)
}
})
sdkQueue[provider].length = 0
})
}
class InteractiveAd
extends AdEventHandler
implements UniApp.InteractiveAdContext
{
private _adpid: string = ''
private _provider: string = ''
private _userData: any = null
private _isLoaded: boolean = false
private _isLoading: boolean = false
private _loadPromiseResolve: Function | null = null
private _loadPromiseReject: Function | null = null
private _showPromiseResolve: Function | null = null
private _showPromiseReject: Function | null = null
private _adInstance: any = null
private _adError: any = ''
constructor(options: any) {
super()
this._adpid = options.adpid
this._provider = options.provider
this._userData = options.userData
setTimeout(() => {
this._init()
})
}
_init() {
this._adError = ''
initSDK({
provider: this._provider,
success: (res: any) => {
this._adInstance = res
if (this._userData) {
this.bindUserData(this._userData)
}
this._loadAd()
},
fail: (err: any) => {
this._adError = err
if (this._loadPromiseReject != null) {
this._loadPromiseReject(this._createError(err))
this._loadPromiseReject = null
}
this._dispatchEvent(EventType.error, err)
},
})
}
getProvider() {
return this._provider
}
load(): Promise<any> {
return new Promise((resolve, reject) => {
this._loadPromiseResolve = resolve
this._loadPromiseReject = reject
if (this._isLoading) {
return
}
if (this._adError) {
this._init()
return
}
if (this._isLoaded) {
resolve('')
} else {
this._loadAd()
}
})
}
show(): Promise<any> {
return new Promise((resolve, reject) => {
this._showPromiseResolve = resolve
this._showPromiseReject = reject
if (this._isLoading) {
return
}
if (this._adError) {
this._init()
return
}
if (this._isLoaded) {
this._showAd()
resolve('')
} else {
this._loadAd()
}
})
}
reportExposure(): void {
if (this._adInstance !== null) {
this._adInstance.reportExposure()
}
}
bindUserData(data: any) {
if (this._adInstance !== null) {
this._adInstance.bindUserData(data)
}
}
destroy() {
if (this._adInstance !== null && this._adInstance.destroy) {
this._adInstance.destroy({
adpid: this._adpid,
})
}
}
_loadAd() {
if (this._adInstance !== null) {
if (this._isLoading === true) {
return
}
this._isLoading = true
this._adInstance.loadData(
{
adpid: this._adpid,
},
(res: any) => {
this._isLoaded = true
this._isLoading = false
if (this._loadPromiseResolve != null) {
this._loadPromiseResolve()
this._loadPromiseResolve = null
}
if (this._showPromiseResolve != null) {
this._showPromiseResolve()
this._showPromiseResolve = null
this._showAd()
}
this._dispatchEvent(EventType.load, res)
},
(err: any) => {
this._isLoading = false
if (this._showPromiseReject != null) {
this._showPromiseReject(this._createError(err))
this._showPromiseReject = null
}
this._dispatchEvent(EventType.error, err)
}
)
}
}
_showAd() {
if (this._adInstance !== null && this._isLoaded === true) {
this._adInstance.show(
{
adpid: this._adpid,
},
() => {
this._isLoaded = false
},
(err: any) => {
this._isLoaded = false
if (this._showPromiseReject != null) {
this._showPromiseReject(this._createError(err))
this._showPromiseReject = null
}
this._dispatchEvent(EventType.error, err)
}
)
}
}
_createError(err: any): Error {
return new Error(JSON.stringify(err))
}
}
export const createInteractiveAd = <API_TYPE_CREATE_INTERACTIVE_AD>(
defineSyncApi(
API_CREATE_INTERACTIVE_AD,
(options) => {
return new InteractiveAd(options)
},
CreateInteractiveAdProtocol,
CreateInteractiveAdOptions
)
)
import {
defineSyncApi,
API_CREATE_INTERSTITIAL_AD,
API_TYPE_CREATE_INTERSTITIAL_AD,
CreateInterstitialAdOptions,
CreateInterstitialAdProtocol,
} from '@dcloudio/uni-api'
import { AdBase } from './adBase'
class InterstitialAd extends AdBase implements UniApp.InterstitialAdContext {
constructor(options: any) {
super(plus.ad.createInterstitialAd(options), options)
this._loadAd()
}
}
export const createInterstitialAd = <API_TYPE_CREATE_INTERSTITIAL_AD>(
defineSyncApi(
API_CREATE_INTERSTITIAL_AD,
(options) => {
return new InterstitialAd(options)
},
CreateInterstitialAdProtocol,
CreateInterstitialAdOptions
)
)
import {
defineSyncApi,
API_CREATE_REWARDED_VIDEO_AD,
API_TYPE_CREATE_REWARDED_VIDEO_AD,
CreateRewardedVideoAdOptions,
CreateRewardedVideoAdProtocol,
} from '@dcloudio/uni-api'
import { AdBase } from './adBase'
class RewardedVideoAd extends AdBase implements UniApp.RewardedVideoAdContext {
constructor(options: any) {
super(plus.ad.createRewardedVideoAd(options), options)
this._loadAd()
}
}
export const createRewardedVideoAd = <API_TYPE_CREATE_REWARDED_VIDEO_AD>(
defineSyncApi(
API_CREATE_REWARDED_VIDEO_AD,
(options) => {
return new RewardedVideoAd(options)
},
CreateRewardedVideoAdProtocol,
CreateRewardedVideoAdOptions
)
)
......@@ -39,3 +39,8 @@ export * from './plugin/getProvider'
export * from './plugin/oauth'
export * from './plugin/share'
export * from './plugin/requestPayment'
export * from './ad/rewardedVideoAd'
export * from './ad/fullScreenVideoAd'
export * from './ad/interstitialAd'
export * from './ad/interactiveAd'
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册