Commit 2a9895f67ae9dd8f9617a57c3c55b328e3b0ee7d

Authored by 吴启风
1 parent bcd49b8e

feat:首次启动隐私协议弹窗

lib/app/splash_page.dart
... ... @@ -16,6 +16,9 @@ import 'package:wow_english/route/route.dart';
16 16 import 'package:wow_english/utils/log_util.dart';
17 17 import 'package:wow_english/utils/sp_util.dart';
18 18  
  19 +import '../common/core/app_consts.dart';
  20 +import '../common/widgets/webview_dialog.dart';
  21 +
19 22 class SplashPage extends StatelessWidget {
20 23 const SplashPage({super.key});
21 24  
... ... @@ -72,7 +75,33 @@ class _TransitionViewState extends State<TransitionView> {
72 75 } else {
73 76 pushNamedAndRemoveUntil(AppRouteName.login, (route) => false);
74 77 }*/
75   - pushNamedAndRemoveUntil(AppRouteName.moduleSelect, (route) => false);
  78 + bool isAggreementAccepted = AppConfigHelper.getAgreementAccepted();
  79 + if (isAggreementAccepted) {
  80 + pushNamedAndRemoveUntil(AppRouteName.moduleSelect, (route) => false);
  81 + } else {
  82 + showDialog(
  83 + context: context,
  84 + barrierDismissible: false,
  85 + builder: (BuildContext context) {
  86 + return WillPopScope(
  87 + onWillPop: () => Future.value(false),
  88 + child: WebviewDialog(
  89 + title: "服务条款及隐私政策",
  90 + webUrl: AppConsts.userPrivacyPolicyUrl,
  91 + leftTap: () {
  92 + AppConfigHelper.saveAgreementAccepted(true);
  93 + pushNamedAndRemoveUntil(
  94 + AppRouteName.moduleSelect, (route) => false);
  95 + },
  96 + rightTap: () {
  97 + // 退出应用
  98 + SystemNavigator.pop();
  99 + },
  100 + ),
  101 + );
  102 + },
  103 + );
  104 + }
76 105 });
77 106 }
78 107  
... ...
lib/common/core/app_config_helper.dart
... ... @@ -3,9 +3,11 @@ import 'dart:io';
3 3  
4 4 import 'package:flutter/cupertino.dart';
5 5 import 'package:package_info_plus/package_info_plus.dart';
  6 +import 'package:wow_english/common/core/sp_const.dart';
6 7 import 'package:wow_english/common/core/user_util.dart';
7 8  
8 9 import '../../models/app_config_entity.dart';
  10 +import '../../utils/sp_util.dart';
9 11 import '../request/dao/system_dao.dart';
10 12  
11 13 class AppConfigHelper {
... ... @@ -41,4 +43,16 @@ class AppConfigHelper {
41 43 debugPrint('versionName=$versionName versionCode=$versionCode platForm=${Platform.operatingSystem}');
42 44 return versionCode;
43 45 }
  46 +
  47 + static void saveAgreementAccepted(bool accepted) {
  48 + SpUtil.getInstance().setData(SpConst.prefsKeyAgreementAccepted, accepted);
  49 + }
  50 +
  51 + static bool getAgreementAccepted() {
  52 + return SpUtil.getInstance().get<bool>(SpConst.prefsKeyAgreementAccepted) ?? false;
  53 + }
  54 +
  55 + static void _clearUserData() {
  56 + SpUtil.getInstance().remove(SpConst.prefsKeyAgreementAccepted);
  57 + }
44 58 }
... ...
lib/common/core/sp_const.dart
1 1 class SpConst {
2 2 static const String prefsKeyUserInfo = "key_user_info";
  3 +
  4 + static const String prefsKeyAgreementAccepted = "privacy_agreement_accepted";
3 5 }
... ...
lib/common/widgets/webview_dialog.dart 0 → 100644
  1 +import 'package:flutter/material.dart';
  2 +import 'package:flutter_easyloading/flutter_easyloading.dart';
  3 +import 'package:webview_flutter/webview_flutter.dart';
  4 +
  5 +class WebviewDialog extends StatelessWidget {
  6 + final String title;
  7 + final String webUrl;
  8 + final VoidCallback leftTap;
  9 + final VoidCallback rightTap;
  10 +
  11 + const WebviewDialog(
  12 + {super.key,
  13 + required this.title,
  14 + required this.webUrl,
  15 + required this.leftTap,
  16 + required this.rightTap});
  17 +
  18 + @override
  19 + Widget build(BuildContext context) {
  20 + return AlertDialog(
  21 + title: Center(
  22 + child: Text(title),
  23 + ),
  24 + content: SizedBox(
  25 + width: MediaQuery.of(context).size.height - 100,
  26 + height: MediaQuery.of(context).size.width - 100,
  27 + child: FutureBuilder(
  28 + // 异步方法
  29 + future: buildWebViewController(webUrl),
  30 + builder: (context, snapshot) {
  31 + // 等待状态显示的widget
  32 + if (snapshot.connectionState == ConnectionState.waiting) {
  33 + return const Center(
  34 + child: CircularProgressIndicator(),
  35 + );
  36 + // 错误时显示的widget
  37 + } else if (snapshot.hasError) {
  38 + return const Text('Error');
  39 + } else {
  40 + return snapshot.data ?? const Text('No data');
  41 + }
  42 + })),
  43 + actions: <Widget>[
  44 + TextButton(
  45 + child:
  46 + const Text('同意并继续', style: TextStyle(color: Color(0xFFFBB621))),
  47 + onPressed: () {
  48 + // 处理接受按钮的点击事件
  49 + leftTap(); // 关闭对话框
  50 + },
  51 + ),
  52 + TextButton(
  53 + child: const Text('不同意,退出应用'),
  54 + onPressed: () {
  55 + // 处理拒绝按钮的点击事件
  56 + rightTap(); // 关闭对话框
  57 + },
  58 + ),
  59 + ],
  60 + );
  61 + }
  62 +
  63 + Future<Widget> buildWebViewController(String url) async {
  64 + Widget res;
  65 + try {
  66 + WebViewController controller = WebViewController()
  67 + ..setJavaScriptMode(JavaScriptMode.unrestricted)
  68 + ..setBackgroundColor(const Color(0x00000000))
  69 + ..setNavigationDelegate(
  70 + NavigationDelegate(
  71 + onProgress: (int progress) {
  72 + // Update loading bar.
  73 + },
  74 + onPageStarted: (String url) {
  75 + EasyLoading.show();
  76 + },
  77 + onPageFinished: (String url) {
  78 + EasyLoading.dismiss();
  79 + },
  80 + onWebResourceError: (WebResourceError error) {
  81 + EasyLoading.showError(error.description);
  82 + },
  83 + onNavigationRequest: (NavigationRequest request) {
  84 + return NavigationDecision.navigate;
  85 + },
  86 + ),
  87 + );
  88 + await controller.loadRequest(Uri.parse(url));
  89 + res = WebViewWidget(controller: controller);
  90 + } catch (error) {
  91 + res = Text("加载失败:${error.toString()}");
  92 + debugPrint("WebViewController加载失败:${error.toString()}");
  93 + }
  94 + return res;
  95 + }
  96 +}
... ...