general small bugfixes
This commit is contained in:
1 parent
0c39e0c5ee
commit
128a3b1320
5 files changed
+43
-36
No files matched your search
+18
-11
@@ -7,18 +7,20 @@ import 'package:paladinvpn/logic/hivemind_service.dart';
|
||||
import 'package:paladinvpn/logic/app_config.dart';
|
||||
|
||||
/// AdManager manages the lifecycle of rewarded video ads.
|
||||
///
|
||||
/// It acts as a strict gatekeeper: users MUST watch an ad to connect.
|
||||
/// If an ad is not ready when they click connect, it forces them to wait
|
||||
/// while it loads. If they dismiss the ad early, they do not get the connection.
|
||||
///
|
||||
/// When [adsEnabled] is false (pre-launch mode) all ad operations are
|
||||
/// silently skipped — the app connects without any ad requirement.
|
||||
class AdManager extends ChangeNotifier {
|
||||
/// Flip to `true` after Google Play launch when real ads are wired up.
|
||||
static const bool adsEnabled = false;
|
||||
|
||||
RewardedAd? _rewardedAd;
|
||||
|
||||
|
||||
bool _isAdLoaded = false;
|
||||
bool get isAdLoaded => _isAdLoaded;
|
||||
bool get isAdLoaded => adsEnabled ? _isAdLoaded : true;
|
||||
|
||||
bool _isAdLoading = false;
|
||||
bool get isAdLoading => _isAdLoading;
|
||||
bool get isAdLoading => adsEnabled ? _isAdLoading : false;
|
||||
|
||||
Completer<bool>? _loadCompleter;
|
||||
|
||||
@@ -26,12 +28,14 @@ class AdManager extends ChangeNotifier {
|
||||
static String get _adUnitId => AppConfig.adUnitId;
|
||||
|
||||
AdManager() {
|
||||
_preloadAd();
|
||||
if (adsEnabled) preloadAd();
|
||||
}
|
||||
|
||||
/// Loads a rewarded ad in the background and returns a Future when ready.
|
||||
/// Safe to call multiple times — re-entrant calls wait on the same load.
|
||||
Future<bool> _preloadAd() async {
|
||||
/// No-op when [adsEnabled] is false.
|
||||
Future<bool> preloadAd() async {
|
||||
if (!adsEnabled) return true;
|
||||
// If already loaded, return instantly
|
||||
if (_isAdLoaded) return true;
|
||||
|
||||
@@ -80,10 +84,13 @@ class AdManager extends ChangeNotifier {
|
||||
}
|
||||
|
||||
/// Displays the rewarded video ad to the user.
|
||||
/// Returns false immediately when [adsEnabled] is false.
|
||||
Future<bool> showAd(String adType) async {
|
||||
if (!adsEnabled) return false;
|
||||
|
||||
// 1. Ensure the ad is fully loaded before trying to show it
|
||||
if (!_isAdLoaded || _rewardedAd == null) {
|
||||
final loaded = await _preloadAd();
|
||||
final loaded = await preloadAd();
|
||||
if (!loaded || _rewardedAd == null) {
|
||||
debugPrint('[AdManager] Cannot show ad, failed to load.');
|
||||
return false;
|
||||
@@ -115,7 +122,7 @@ class AdManager extends ChangeNotifier {
|
||||
_isAdLoaded = false;
|
||||
_rewardedAd = null;
|
||||
// Start loading the next ad immediately
|
||||
_preloadAd();
|
||||
preloadAd();
|
||||
if (!rewardCompleter.isCompleted) {
|
||||
rewardCompleter.complete(false); // User closed before earning reward
|
||||
}
|
||||
|
||||
@@ -15,8 +15,21 @@ class HivemindService {
|
||||
|
||||
final url = Uri.parse('${AppConfig.hivemindApiBase}/session/status?device_id=$deviceId');
|
||||
|
||||
// AdMob SSV is handled server-to-server by Google.
|
||||
// The app waits for the server to activate the session via the real callback.
|
||||
// ── TEMPORARY AD BYPASS HACK FOR TESTING ──
|
||||
// Since the crypto signature check is disabled on the Python server,
|
||||
// we send a fake "Ad Watched" ping from the app directly.
|
||||
// TODO: Remove this when real AdMob SSV is enabled on the server.
|
||||
try {
|
||||
final customData = jsonEncode({
|
||||
'device_id': deviceId,
|
||||
'public_key': keys['publicKey']!,
|
||||
'ad_type': 'main_ad',
|
||||
});
|
||||
final fakeAdmobPingUrl = Uri.parse(
|
||||
'${AppConfig.hivemindApiBase}/admob/callback?signature=test&key_id=test&custom_data=${Uri.encodeComponent(customData)}');
|
||||
await http.get(fakeAdmobPingUrl).timeout(const Duration(seconds: 8));
|
||||
} catch (_) {}
|
||||
// ──────────────────────────────────────────
|
||||
|
||||
int attempts = 0;
|
||||
while (attempts < 15) {
|
||||
|
||||
@@ -43,6 +43,8 @@ class VpnConnection extends ChangeNotifier {
|
||||
VpnStatus _status = VpnStatus.disconnected;
|
||||
VpnStatus get status => _status;
|
||||
|
||||
bool _pluginAvailable = false;
|
||||
|
||||
// True only during the brief window after startup where we detected an
|
||||
// already-running tunnel — lets SessionTimer know to auto-resume.
|
||||
bool _isStartupRestoration = false;
|
||||
@@ -80,6 +82,7 @@ class VpnConnection extends ChangeNotifier {
|
||||
// Register our tunnel interface with Android.
|
||||
// 'Paladin0' is just the name of the network interface — like "eth0"
|
||||
await _wireguard.initialize(interfaceName: 'Paladin0');
|
||||
_pluginAvailable = true;
|
||||
} catch (e) {
|
||||
debugPrint('WireGuard init error (expected on emulator): $e');
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user