Parcourir la source

增加广告数据回传和埋点时间上报

guoziyun il y a 6 mois
Parent
commit
b1a834de6c

+ 50 - 124
lib/ads/applovin_ads_controller.dart

@@ -10,9 +10,8 @@ import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:logging/logging.dart';
-import 'package:provider/provider.dart';
 import 'package:puzzleweave/ads/ad_helper.dart';
-import 'package:puzzleweave/config/device.dart';
+import 'package:puzzleweave/firebase/adjust_helper.dart';
 import 'package:puzzleweave/firebase/firebase_helper.dart';
 
 import '../persistence/persistence.dart';
@@ -85,6 +84,7 @@ class ApplovinAdsController {
   Widget get bannerAdWidget => MaxAdView(
     adUnitId: AdHelper.applovinBannerAdUnitId,
     adFormat: AdFormat.banner,
+    placement: 'banner',
     extraParameters: const {'adaptive_banner': 'true'},
     listener: AdViewAdListener(
       onAdLoadedCallback: (ad) {
@@ -112,56 +112,56 @@ class ApplovinAdsController {
       onAdRevenuePaidCallback: (ad) {
         _log.info('woooooooooo, applovin banner paid event: revenue: ${ad.revenue} precision: ${ad.revenuePrecision}');
         if (ad.revenue > 0) {
-          onBannerAdPaid(ad.revenue * 1000000, 'USD', ad); // revenue 单位转化为 valueMicro,以便和admod一致
+          onAdRevenuePaid(ad); // revenue 单位转化为 valueMicro,以便和admod一致
         }
       },
     ),
   );
 
-  // banner广告收益回调的处理
-  onBannerAdPaid(double valueMicros, String currencyCode, MaxAd ad) async {
-    // 原来的逻辑
-    bannerPaidValueMicros += valueMicros;
-    int nowTimestamp = DateTime.now().millisecondsSinceEpoch;
-    if ((nowTimestamp - lastBannerPaidReportTimestamp) >= bannerReportDuration) {
-      _log.info('report banner ad paid: ${bannerPaidValueMicros / 1000000}$currencyCode');
-      FirebaseHelper.logEvent("ad_impression", {
-        "ad_count": 1,
-        "ad_platform": 'appLovin',
-        "ad_source": ad.networkName,
-        "ad_format": 'banner',
-        "ad_unit_name": ad.adUnitId,
-        "value": bannerPaidValueMicros / 1000000,
-        "currency": "USD",
-      });
-      Statistics.postEvent({
-        "project_id": Persistence().projectId,
-        "user_id": Persistence().uuid,
-        "library_name": Persistence().libraryName,
-        "library_version": Persistence().packageVersion,
-        "name": "revenue",
-        "sku_id": '',
-        "tab_source": 'play',
-        "ad_src": 'play',
-        "ad_count": bannerPaidValueMicros ~/ valueMicros,
-        "ad_type": 'banner',
-        "ad_rev": bannerPaidValueMicros / 1000000,
-      });
-      bannerPaidValueMicros = 0; // 累计清零
-      lastBannerPaidReportTimestamp = nowTimestamp;
-      Persistence().lastBannerPaidReportTimestamp = lastBannerPaidReportTimestamp;
-    }
-    Persistence().bannerPaidValueMicros = bannerPaidValueMicros;
-
-    // 新的逻辑, 累计收益超过规定阈值,上报firebase和appsflyer
-    allPaidValueMicros += valueMicros;
-    if ((allPaidValueMicros / 1000000) >= revenueThreshold) {
-      _log.info('report all ad paid: ${allPaidValueMicros / 1000000}$currencyCode');
-      FirebaseHelper.logEvent("ad_paid", {"currency": currencyCode, "value": allPaidValueMicros / 1000000});
-      // AppsflyerHelper.logEvent("ad_paid", {"af_currency": currencyCode, "af_revenue": allPaidValueMicros / 1000000});
-      allPaidValueMicros = 0; // 累计清零
+  // revenue 回调处理,所有广告类型统一在此处理
+  onAdRevenuePaid(MaxAd ad) async {
+    _log.info('report ad revenue paid: ${ad.revenue}');
+
+    Map<String, Object> params = {
+      "ad_platform": 'appLovin',
+      "ad_source": ad.networkName,
+      "ad_format": ad.placement,
+      "ad_unit_name": ad.adUnitId,
+      "value": ad.revenue,
+      "currency": "USD",
+    };
+
+    // for ARO : ad_impression 上报给firebase
+    FirebaseHelper.logEvent("ad_impression", params);
+    // for Taichi
+    FirebaseHelper.logEvent('"Ad_Impression_Revenue', params);
+
+    // 累计超过0.01 USD 上报 Total_Ads_Revenue_001
+    double previousTroasCache = Persistence().tRoasCache;
+    double currentTroasCache = previousTroasCache + ad.revenue;
+    if (currentTroasCache >= revenueThreshold) {
+      FirebaseHelper.logEvent('"Total_Ads_Revenue_001', {"value": currentTroasCache, "currency": "USD"});
+      Persistence().tRoasCache = 0; // 缓存清零
+    } else {
+      Persistence().tRoasCache = currentTroasCache;
     }
-    Persistence().allPaidValueMicros = allPaidValueMicros;
+
+    // adRevenue 事件上报给adjust
+    AdjustHelper.trackAdRevenue(ad.placement, 1, ad.revenue, 'USD');
+
+    // revenue 埋点时间上报给自主BI平台
+    Statistics.postEvent({
+      "project_id": Persistence().projectId,
+      "user_id": Persistence().uuid,
+      "library_name": Persistence().libraryName,
+      "library_version": Persistence().packageVersion,
+      "name": 'revenue',
+      "tab_source": adSrc,
+      "sku_id": skuId,
+      "ad_src": adSrc,
+      "ad_type": ad.placement,
+      "ad_rev": ad.revenue,
+    });
   }
 
   ////////////////////////////  interstitialAd /////////////////////////////
@@ -211,7 +211,7 @@ class ApplovinAdsController {
         onAdRevenuePaidCallback: (ad) {
           _log.info('woooooooooo, applovin interstitial paid event: revenue: ${ad.revenue}, precision: ${ad.revenuePrecision}');
           if (ad.revenue > 0) {
-            onInterstitialAdPaid(ad.revenue * 1000000, 'USD', ad); // revenue 单位转化为 valueMicro,以便和admod一致
+            onAdRevenuePaid(ad); // revenue 单位转化为 valueMicro,以便和admod一致
           }
         },
       ),
@@ -267,7 +267,7 @@ class ApplovinAdsController {
       }
       bool isReady = (await AppLovinMAX.isInterstitialReady(AdHelper.applovinInterstitialAdUnitId))!;
       if (isReady) {
-        AppLovinMAX.showInterstitial(AdHelper.applovinInterstitialAdUnitId);
+        AppLovinMAX.showInterstitial(AdHelper.applovinInterstitialAdUnitId, placement: 'inters');
       } else {
         AppLovinMAX.loadInterstitial(AdHelper.applovinInterstitialAdUnitId);
       }
@@ -278,43 +278,6 @@ class ApplovinAdsController {
     }
   }
 
-  onInterstitialAdPaid(double valueMicros, String currencyCode, MaxAd ad) async {
-    // 老的逻辑,每次收益都上报
-    _log.info('report interstitial ad paid: ${valueMicros / 1000000}$currencyCode');
-    FirebaseHelper.logEvent("ad_impression", {
-      "ad_count": 1,
-      "ad_platform": 'appLovin',
-      "ad_source": ad.networkName,
-      "ad_format": 'inters',
-      "ad_unit_name": ad.adUnitId,
-      "value": valueMicros / 1000000,
-      "currency": "USD",
-    });
-    Statistics.postEvent({
-      "project_id": Persistence().projectId,
-      "user_id": Persistence().uuid,
-      "library_name": Persistence().libraryName,
-      "library_version": Persistence().packageVersion,
-      "name": 'revenue',
-      "tab_source": adSrc,
-      "sku_id": skuId,
-      "ad_src": adSrc,
-      "ad_count": 1,
-      "ad_type": "inters",
-      "ad_rev": valueMicros / 1000000,
-    });
-
-    // 新的逻辑, 累计收益超过规定阈值,上报firebase和appsflyer
-    allPaidValueMicros += valueMicros;
-    if ((allPaidValueMicros / 1000000) >= revenueThreshold) {
-      _log.info('report all ad paid: ${allPaidValueMicros / 1000000}$currencyCode');
-      FirebaseHelper.logEvent("ad_paid", {"currency": currencyCode, "value": allPaidValueMicros / 1000000});
-      // AppsflyerHelper.logEvent("ad_paid", {"af_currency": currencyCode, "af_revenue": allPaidValueMicros / 1000000});
-      allPaidValueMicros = 0; // 累计清零
-    }
-    Persistence().allPaidValueMicros = allPaidValueMicros;
-  }
-
   ////////////////////////////  rewardedAd /////////////////////////////
   ValueNotifier<AdState> rewardedAdState = ValueNotifier(AdState.initial);
   var _rewardedAdRetryAttempt = 0;
@@ -364,7 +327,7 @@ class ApplovinAdsController {
         onAdRevenuePaidCallback: (ad) {
           _log.info('woooooooooo, applovin rewarded paid event: revenue: ${ad.revenue} precision: ${ad.revenuePrecision}');
           if (ad.revenue > 0) {
-            onRewardedAdPaid(ad.revenue * 1000000, 'USD', ad); // revenue 单位转化为 valueMicro,以便和admod一致
+            onAdRevenuePaid(ad); // revenue 单位转化为 valueMicro,以便和admod一致
           }
         },
       ),
@@ -423,7 +386,7 @@ class ApplovinAdsController {
       }
       bool isReady = (await AppLovinMAX.isRewardedAdReady(AdHelper.applovinRewardedAdUnitId))!;
       if (isReady) {
-        AppLovinMAX.showRewardedAd(AdHelper.applovinRewardedAdUnitId);
+        AppLovinMAX.showRewardedAd(AdHelper.applovinRewardedAdUnitId, placement: 'reward');
         rewardCallback = onUserEarnedReward;
         return true;
       } else {
@@ -438,41 +401,4 @@ class ApplovinAdsController {
       return false;
     }
   }
-
-  onRewardedAdPaid(double valueMicros, String currencyCode, MaxAd ad) async {
-    // 老的逻辑,每次收益都上报
-    _log.info('report rewarded ad paid: ${valueMicros / 1000000}$currencyCode');
-    FirebaseHelper.logEvent("ad_impression", {
-      "ad_count": 1,
-      "ad_platform": 'appLovin',
-      "ad_source": ad.networkName,
-      "ad_format": 'reward',
-      "ad_unit_name": ad.adUnitId,
-      "value": valueMicros / 1000000,
-      "currency": "USD",
-    });
-    Statistics.postEvent({
-      "project_id": Persistence().projectId,
-      "user_id": Persistence().uuid,
-      "library_name": Persistence().libraryName,
-      "library_version": Persistence().packageVersion,
-      "name": 'revenue',
-      "tab_source": adSrc,
-      "sku_id": skuId,
-      "ad_src": adSrc,
-      "ad_count": 1,
-      "ad_type": "reward",
-      "ad_rev": valueMicros / 1000000,
-    });
-
-    // 新的逻辑, 累计收益超过规定阈值,上报firebase和appsflyer
-    allPaidValueMicros += valueMicros;
-    if ((allPaidValueMicros / 1000000) >= revenueThreshold) {
-      _log.info('report all ad paid: ${allPaidValueMicros / 1000000}$currencyCode');
-      FirebaseHelper.logEvent("ad_paid", {"currency": currencyCode, "value": allPaidValueMicros / 1000000});
-      // AppsflyerHelper.logEvent("ad_paid", {"af_currency": currencyCode, "af_revenue": allPaidValueMicros / 1000000});
-      allPaidValueMicros = 0; // 累计清零
-    }
-    Persistence().allPaidValueMicros = allPaidValueMicros;
-  }
 }

+ 135 - 0
lib/firebase/adjust_helper.dart

@@ -0,0 +1,135 @@
+import 'dart:io';
+
+import 'package:adjust_sdk/adjust.dart';
+import 'package:adjust_sdk/adjust_ad_revenue.dart';
+import 'package:adjust_sdk/adjust_config.dart';
+import 'package:adjust_sdk/adjust_event.dart';
+import 'package:flutter/foundation.dart';
+import 'package:logging/logging.dart';
+
+final Logger _log = Logger('AdjustHelper');
+
+class AdjustHelper {
+  static String get appToken {
+    if (Platform.isAndroid) {
+      return 'r4m6v9abjjsw';
+    } else if (Platform.isIOS) {
+      return '';
+    } else {
+      return '';
+    }
+  }
+
+  static String get levelStartToken {
+    if (Platform.isAndroid) {
+      return 'tpb9bw';
+    } else if (Platform.isIOS) {
+      return '';
+    } else {
+      return '';
+    }
+  }
+
+  static String get levelDoneToken {
+    if (Platform.isAndroid) {
+      return '626ngi';
+    } else if (Platform.isIOS) {
+      return '';
+    } else {
+      return '';
+    }
+  }
+
+  static String get levelDone3Token {
+    if (Platform.isAndroid) {
+      return 'ytq750';
+    } else if (Platform.isIOS) {
+      return '';
+    } else {
+      return '';
+    }
+  }
+
+  static String get levelDone10Token {
+    if (Platform.isAndroid) {
+      return 'jdeyc8';
+    } else if (Platform.isIOS) {
+      return '';
+    } else {
+      return '';
+    }
+  }
+
+  static String get levelDone20Token {
+    if (Platform.isAndroid) {
+      return 'iz3fud';
+    } else if (Platform.isIOS) {
+      return '';
+    } else {
+      return '';
+    }
+  }
+
+  static String get levelDone30Token {
+    if (Platform.isAndroid) {
+      return 'vn6ivu';
+    } else if (Platform.isIOS) {
+      return '';
+    } else {
+      return '';
+    }
+  }
+
+  static String get useDailyLevelStartToken {
+    if (Platform.isAndroid) {
+      return 'p4ivhg';
+    } else if (Platform.isIOS) {
+      return '';
+    } else {
+      return '';
+    }
+  }
+
+  static String get useDailyLevelDoneToken {
+    if (Platform.isAndroid) {
+      return 'hl6z50';
+    } else if (Platform.isIOS) {
+      return '';
+    } else {
+      return '';
+    }
+  }
+
+  static Future<void> init(String uuid) async {
+    _log.info('init Adjust');
+
+    if (appToken.isEmpty) return;
+
+    AdjustConfig adjustConfig = AdjustConfig(appToken, kDebugMode ? AdjustEnvironment.sandbox : AdjustEnvironment.production);
+
+    adjustConfig.logLevel = kDebugMode ? AdjustLogLevel.debug : AdjustLogLevel.warn;
+    adjustConfig.externalDeviceId = uuid;
+
+    Adjust.initSdk(adjustConfig);
+  }
+
+  static void trackEvent(String eventToken) async {
+    _log.info('Adjust logEvent, eventToken: $eventToken');
+
+    if (eventToken.isEmpty) return;
+
+    Adjust.trackEvent(AdjustEvent(eventToken));
+  }
+
+  /// placement: 广告位置(banner|interstitial|reward)
+  /// count: 广告展示数量
+  /// revenue: 广告收益额
+  /// currency: 货币单位
+  static void trackAdRevenue(String placement, int count, double revenue, String currency) {
+    AdjustAdRevenue adjustAdRevenue = AdjustAdRevenue('applovin_max_sdk');
+    adjustAdRevenue.setRevenue(revenue, currency);
+    adjustAdRevenue.adRevenuePlacement = placement;
+    adjustAdRevenue.adImpressionsCount = count;
+    Adjust.trackAdRevenue(adjustAdRevenue);
+  }
+}

+ 2 - 0
lib/homepage/home_screen.dart

@@ -16,6 +16,7 @@ import 'package:puzzleweave/audio/jc_audio_controller.dart';
 import 'package:puzzleweave/collection/collection_screen.dart';
 import 'package:puzzleweave/config/config.dart';
 import 'package:puzzleweave/config/device.dart';
+import 'package:puzzleweave/firebase/adjust_helper.dart';
 import 'package:puzzleweave/homepage/home_board_play.dart';
 import 'package:puzzleweave/l10n/app_localizations.dart';
 import 'package:puzzleweave/models/cached_request.dart';
@@ -554,6 +555,7 @@ class _HomeScreen extends AdsState<HomeScreen> with TickerProviderStateMixin {
     }
     initFCM(); // 消息推送许可弹窗
     initAd(); // admod 的广告加载安排在iOS ATT 之后,以便能够加载到个性化广告
+    AdjustHelper.init(Persistence().uuid); // 初始化Adjust
 
     final idfa = await AppTrackingTransparency.getAdvertisingIdentifier();
     _log.info("idfa: $idfa");

+ 13 - 2
lib/models/data.dart

@@ -43,14 +43,25 @@ class Data {
 
   /// 清除已完成作品的缓存文件。
   void _clearCompletedItemCache(ListItem item) async {
+    // 删除进度状态json
+    try {
+      final file = await localFile(item.jsonPath);
+      if (await file.exists()) {
+        await file.delete();
+        _log.info('Successfully cleared json cache file for ${item.id}');
+      } else {
+        _log.warning('json cache file not found for ${item.id} at path: ${item.jsonPath}');
+      }
+    } catch (e) {
+      _log.severe('Failed to clear json cache for item ${item.id}, error: $e');
+    }
+
     // 只有 RemoteItem 才会有需要清理的下载缓存
     if (item is RemoteItem) {
       _log.info('Work done for remote item ${item.id}. Attempting to clear cache at path: ${item.cachePath}');
 
       try {
-        // 使用 cachePath 定义,并通过 localFile 找到实际的文件路径
         final file = await localFile(item.cachePath);
-
         if (await file.exists()) {
           await file.delete();
           _log.info('Successfully cleared cache file for ${item.id}');

+ 6 - 0
lib/persistence/persistence.dart

@@ -66,6 +66,7 @@ class Persistence {
     _lastBannerPaidReportTimestamp = PreferencesValue<int>('last_banner_paid_report_timestamp', DateTime.now().millisecondsSinceEpoch, _prefs);
     _bannerPaidValueMicros = PreferencesValue<double>('banner_paid_value_micros', 0, _prefs);
     _allPaidValueMicros = PreferencesValue<double>('all_paid_value_micros', 0, _prefs);
+    _tRoasCache = PreferencesValue<double>('troas_cache', 0, _prefs);
 
     // !!! 改造点:完成作品集 - 存储 Work 对象列表
     _completedWorks = PreferencesValue<List<Work>>(
@@ -160,6 +161,11 @@ class Persistence {
   double get allPaidValueMicros => _allPaidValueMicros.value;
   set allPaidValueMicros(double value) => _allPaidValueMicros.value = value;
 
+  // 广告收益缓存,单位美元
+  late PreferencesValue<double> _tRoasCache;
+  double get tRoasCache => _tRoasCache.value;
+  set tRoasCache(double value) => _tRoasCache.value = value;
+
   // !!! 改造点:已完成作品集合
   late PreferencesValue<List<Work>> _completedWorks;
   List<Work> get completedWorks => _completedWorks.value;

+ 80 - 1
lib/play/board_play.dart

@@ -10,10 +10,13 @@ import 'package:logging/logging.dart';
 import 'package:provider/provider.dart';
 import 'package:puzzleweave/audio/jc_audio_controller.dart';
 import 'package:puzzleweave/config/device.dart';
+import 'package:puzzleweave/firebase/adjust_helper.dart';
+import 'package:puzzleweave/firebase/firebase_helper.dart';
 import 'package:puzzleweave/l10n/app_localizations.dart';
 import 'package:puzzleweave/models/data.dart';
 import 'package:puzzleweave/models/download.dart';
 import 'package:puzzleweave/models/items.dart';
+import 'package:puzzleweave/persistence/persistence.dart';
 import 'package:puzzleweave/play/board.dart';
 import 'package:puzzleweave/play/board_painter.dart';
 import 'package:puzzleweave/play/confetti_layer.dart';
@@ -24,6 +27,7 @@ import 'package:puzzleweave/rating/rating_utils.dart';
 import 'package:puzzleweave/settings/settings_controller.dart';
 import 'package:puzzleweave/settings/settings_dialog.dart';
 import 'package:puzzleweave/skin/skin.dart';
+import 'package:puzzleweave/statistics/statistics.dart';
 import 'package:puzzleweave/utils/mybutton.dart';
 import 'package:puzzleweave/utils/utils.dart';
 import 'package:vector_math/vector_math.dart' as vmath;
@@ -48,8 +52,9 @@ class BoardPlay extends StatefulWidget {
   final ListItem item;
   final bool firstRun;
   final bool reset;
+  final String tag;
 
-  const BoardPlay({super.key, required this.item, this.firstRun = false, this.reset = false});
+  const BoardPlay({super.key, required this.item, this.firstRun = false, this.reset = false, this.tag = 'home'});
 
   @override
   State<StatefulWidget> createState() {
@@ -575,6 +580,68 @@ class _BoardPlayState extends AdsState<BoardPlay> with TickerProviderStateMixin
     _successAnimationController.forward(from: 0.0);
 
     setState(() {});
+
+    // 数据上报
+    FirebaseHelper.logEvent("level_done", {'id': widget.item.id, 'level': data.currentLevel});
+    AdjustHelper.trackEvent(AdjustHelper.levelDoneToken);
+    Statistics.postEvent({
+      "project_id": Persistence().projectId,
+      "user_id": Persistence().uuid,
+      "library_name": Persistence().libraryName,
+      "library_version": Persistence().packageVersion,
+      "name": 'level_done',
+      "tab_source": widget.tag,
+      "sku_id": widget.item.id,
+    });
+    if (data.currentLevel == 3) {
+      FirebaseHelper.logEvent("level_done_3", {});
+      AdjustHelper.trackEvent(AdjustHelper.levelDone3Token);
+      Statistics.postEvent({
+        "project_id": Persistence().projectId,
+        "user_id": Persistence().uuid,
+        "library_name": Persistence().libraryName,
+        "library_version": Persistence().packageVersion,
+        "name": 'level_done_3',
+        "tab_source": widget.tag,
+        "sku_id": widget.item.id,
+      });
+    } else if (data.currentLevel == 10) {
+      FirebaseHelper.logEvent("level_done_10", {});
+      AdjustHelper.trackEvent(AdjustHelper.levelDone10Token);
+      Statistics.postEvent({
+        "project_id": Persistence().projectId,
+        "user_id": Persistence().uuid,
+        "library_name": Persistence().libraryName,
+        "library_version": Persistence().packageVersion,
+        "name": 'level_done_10',
+        "tab_source": widget.tag,
+        "sku_id": widget.item.id,
+      });
+    } else if (data.currentLevel == 20) {
+      FirebaseHelper.logEvent("level_done_20", {});
+      AdjustHelper.trackEvent(AdjustHelper.levelDone20Token);
+      Statistics.postEvent({
+        "project_id": Persistence().projectId,
+        "user_id": Persistence().uuid,
+        "library_name": Persistence().libraryName,
+        "library_version": Persistence().packageVersion,
+        "name": 'level_done_20',
+        "tab_source": widget.tag,
+        "sku_id": widget.item.id,
+      });
+    } else if (data.currentLevel == 30) {
+      FirebaseHelper.logEvent("level_done_30", {});
+      AdjustHelper.trackEvent(AdjustHelper.levelDone30Token);
+      Statistics.postEvent({
+        "project_id": Persistence().projectId,
+        "user_id": Persistence().uuid,
+        "library_name": Persistence().libraryName,
+        "library_version": Persistence().packageVersion,
+        "name": 'level_done_30',
+        "tab_source": widget.tag,
+        "sku_id": widget.item.id,
+      });
+    }
   }
 
   _init() async {
@@ -624,6 +691,18 @@ class _BoardPlayState extends AdsState<BoardPlay> with TickerProviderStateMixin
         board = await Board.restore(this, image, cardImage, widget.item.rows, widget.item.cols, widget.item.hard, targetRect, device, widget.item.jsonPath);
       } else {
         board = await Board.create(this, image, cardImage, widget.item.rows, widget.item.cols, widget.item.hard, targetRect, device);
+
+        FirebaseHelper.logEvent("level_start", {'id': widget.item.id, 'level': data.currentLevel + 1});
+        AdjustHelper.trackEvent(AdjustHelper.levelStartToken);
+        Statistics.postEvent({
+          "project_id": Persistence().projectId,
+          "user_id": Persistence().uuid,
+          "library_name": Persistence().libraryName,
+          "library_version": Persistence().packageVersion,
+          "name": 'level_start',
+          "tab_source": widget.tag,
+          "sku_id": widget.item.id,
+        });
       }
     }
 

+ 1 - 1
lib/settings/settings_dialog.dart

@@ -88,7 +88,7 @@ class _SettingDialogState extends State<SettingsDialog> {
                     MyElevatedButton(
                       onPressed: () {
                         audio.playSfx(SfxType.click);
-                        PageRouteBuilder? pageRouteBuilder = BoardPlay.buildRoute(widget.item!);
+                        PageRouteBuilder? pageRouteBuilder = BoardPlay.buildRoute(widget.item!, reset: true);
                         Navigator.pop(context);
                         Navigator.pushReplacement(context, pageRouteBuilder);
                       },

+ 8 - 0
pubspec.lock

@@ -9,6 +9,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.3.64"
+  adjust_sdk:
+    dependency: "direct main"
+    description:
+      name: adjust_sdk
+      sha256: "7ff7534f5ef1409e15bd8e8221cb8fdd7fc108512b19fada7b315ac68d6b6715"
+      url: "https://pub.dev"
+    source: hosted
+    version: "5.5.0"
   ansicolor:
     dependency: transitive
     description:

+ 1 - 0
pubspec.yaml

@@ -71,6 +71,7 @@ dependencies:
   flutter_launcher_icons: ^0.14.4
   flutter_native_splash: ^2.4.7
   flutter_svg: ^2.2.3
+  adjust_sdk: ^5.0.1
 
 dev_dependencies:
   flutter_test: