227 lines
6.8 KiB
Dart
227 lines
6.8 KiB
Dart
/// Real Adsgram SDK interface using JavaScript interop
|
|
///
|
|
/// This provides a Dart interface to the Adsgram JavaScript SDK.
|
|
/// The SDK is loaded via script tag in web/index.html:
|
|
/// <script src="https://sad.adsgram.ai/js/sad.min.js"></script>
|
|
///
|
|
/// The JavaScript bridge functions are defined in web/foos.js
|
|
library;
|
|
|
|
import 'dart:developer' as developer;
|
|
import 'dart:js_util' as js_util;
|
|
|
|
/// Configuration for Adsgram ad display
|
|
class AdsgramAd {
|
|
/// Adsgram block ID (required)
|
|
final String blockId;
|
|
|
|
/// Reward amount (for tracking purposes)
|
|
final int rewardAmount;
|
|
|
|
/// Callback invoked when ad completes successfully
|
|
final void Function()? onReward;
|
|
|
|
/// Callback invoked when ad fails or is closed early
|
|
final void Function(String error)? onError;
|
|
|
|
const AdsgramAd({
|
|
required this.blockId,
|
|
required this.rewardAmount,
|
|
this.onReward,
|
|
this.onError,
|
|
});
|
|
}
|
|
|
|
/// Adsgram SDK interface for showing rewarded ads
|
|
class Adsgram {
|
|
static final Adsgram _instance = Adsgram._internal();
|
|
static Adsgram get instance => _instance;
|
|
|
|
Adsgram._internal();
|
|
|
|
/// Check if Adsgram SDK is available in the JavaScript environment
|
|
bool get isAvailable {
|
|
try {
|
|
final adsgram = js_util.getProperty<dynamic>(js_util.globalThis, 'Adsgram');
|
|
return adsgram != null;
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// Show a rewarded ad using the Adsgram JavaScript SDK
|
|
///
|
|
/// This method:
|
|
/// 1. Validates the ad configuration
|
|
/// 2. Checks SDK availability
|
|
/// 3. Sets up JavaScript callbacks for reward/error events
|
|
/// 4. Calls the JavaScript showAdWithBlockId() function
|
|
/// 5. Handles ad lifecycle events via callbacks
|
|
///
|
|
/// Throws [Exception] if SDK is not available or ad fails to show
|
|
/// Throws [ArgumentError] if ad configuration is invalid
|
|
Future<void> showRewardedAd(AdsgramAd adConfig) async {
|
|
// Validate block ID
|
|
if (adConfig.blockId.trim().isEmpty) {
|
|
final error = 'Block ID is required and cannot be empty';
|
|
developer.log(error, name: 'Adsgram');
|
|
adConfig.onError?.call(error);
|
|
throw ArgumentError.value(
|
|
adConfig.blockId,
|
|
'blockId',
|
|
error,
|
|
);
|
|
}
|
|
|
|
// Check SDK availability
|
|
if (!isAvailable) {
|
|
final error = 'Adsgram SDK not available. Make sure sad.min.js is loaded.';
|
|
developer.log(error, name: 'Adsgram');
|
|
adConfig.onError?.call(error);
|
|
throw Exception(error);
|
|
}
|
|
|
|
// Validate that JavaScript bridge functions exist
|
|
try {
|
|
final showAdFunction = js_util.getProperty<dynamic>(
|
|
js_util.globalThis,
|
|
'showAdWithBlockId',
|
|
);
|
|
if (showAdFunction == null) {
|
|
final error = 'JavaScript bridge function showAdWithBlockId not found. Make sure foos.js is loaded.';
|
|
developer.log(error, name: 'Adsgram');
|
|
adConfig.onError?.call(error);
|
|
throw Exception(error);
|
|
}
|
|
} catch (e) {
|
|
final error = 'Failed to access JavaScript bridge: $e';
|
|
developer.log(error, name: 'Adsgram');
|
|
adConfig.onError?.call(error);
|
|
throw Exception(error);
|
|
}
|
|
|
|
try {
|
|
developer.log(
|
|
'Showing rewarded ad with block ID: ${adConfig.blockId}',
|
|
name: 'Adsgram',
|
|
);
|
|
|
|
// Set up callbacks in JavaScript before showing ad
|
|
await _setupCallbacks(adConfig);
|
|
|
|
// Call the JavaScript showAdWithBlockId function
|
|
// The function is defined in web/foos.js and handles the Adsgram SDK
|
|
await js_util.promiseToFuture<void>(
|
|
js_util.callMethod(
|
|
js_util.globalThis,
|
|
'showAdWithBlockId',
|
|
<Object?>[adConfig.blockId],
|
|
),
|
|
);
|
|
|
|
developer.log('Ad show request completed', name: 'Adsgram');
|
|
// Note: The actual reward/error callbacks are triggered from JavaScript
|
|
// when ad completes or fails
|
|
} catch (e, s) {
|
|
developer.log(
|
|
'Failed to show ad',
|
|
error: e,
|
|
stackTrace: s,
|
|
name: 'Adsgram',
|
|
);
|
|
// If JavaScript call fails, call error callback
|
|
final errorMessage = 'Failed to show ad: $e';
|
|
adConfig.onError?.call(errorMessage);
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
/// Set up JavaScript callbacks for ad completion
|
|
///
|
|
/// Creates JavaScript wrapper functions that call the Dart callbacks
|
|
/// These are registered with the JavaScript bridge in foos.js
|
|
Future<void> _setupCallbacks(AdsgramAd adConfig) async {
|
|
try {
|
|
// Create JavaScript function for reward callback
|
|
final rewardJsFunction = js_util.allowInterop(() {
|
|
developer.log('Ad reward callback triggered', name: 'Adsgram');
|
|
adConfig.onReward?.call();
|
|
});
|
|
|
|
// Create JavaScript function for error callback
|
|
final errorJsFunction = js_util.allowInterop((dynamic error) {
|
|
final errorMessage = error?.toString() ?? 'Unknown error';
|
|
developer.log(
|
|
'Ad error callback triggered: $errorMessage',
|
|
name: 'Adsgram',
|
|
);
|
|
adConfig.onError?.call(errorMessage);
|
|
});
|
|
|
|
// Register callbacks with JavaScript bridge
|
|
// Check if callback functions exist before calling
|
|
final setRewardCallback = js_util.getProperty<dynamic>(
|
|
js_util.globalThis,
|
|
'setRewardCallback',
|
|
);
|
|
final setErrorCallback = js_util.getProperty<dynamic>(
|
|
js_util.globalThis,
|
|
'setErrorCallback',
|
|
);
|
|
|
|
if (setRewardCallback == null || setErrorCallback == null) {
|
|
throw Exception(
|
|
'JavaScript bridge callback functions not found. Make sure foos.js is loaded.',
|
|
);
|
|
}
|
|
|
|
js_util.callMethod<void>(
|
|
js_util.globalThis,
|
|
'setRewardCallback',
|
|
<Object?>[rewardJsFunction],
|
|
);
|
|
|
|
js_util.callMethod<void>(
|
|
js_util.globalThis,
|
|
'setErrorCallback',
|
|
<Object?>[errorJsFunction],
|
|
);
|
|
|
|
developer.log('Callbacks registered with JavaScript bridge', name: 'Adsgram');
|
|
} catch (e, s) {
|
|
developer.log(
|
|
'Failed to set up callbacks',
|
|
error: e,
|
|
stackTrace: s,
|
|
name: 'Adsgram',
|
|
);
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
/// Alternative method to show ad with specific block ID
|
|
///
|
|
/// This allows dynamic block ID configuration without creating
|
|
/// an AdsgramAd object. Prefer using [showRewardedAd] for better
|
|
/// error handling and callback management.
|
|
///
|
|
/// Throws [Exception] if ad fails to show
|
|
@Deprecated('Use showRewardedAd() instead for better error handling')
|
|
Future<void> showAdWithBlockId(String blockId) async {
|
|
if (!isAvailable) {
|
|
throw Exception('Adsgram SDK not available');
|
|
}
|
|
|
|
try {
|
|
await js_util.promiseToFuture<void>(
|
|
js_util.callMethod(
|
|
js_util.globalThis,
|
|
'showAdWithBlockId',
|
|
<Object?>[blockId],
|
|
),
|
|
);
|
|
} catch (e) {
|
|
throw Exception('Failed to show ad with block ID $blockId: $e');
|
|
}
|
|
}
|
|
}
|