Commit 3840b7fe9005544c27e387368e9ea56b702aa63a

Authored by liangchengyou
1 parent 2e5751ab

feat:更新设置页面

assets/images/bg_reback.png 0 → 100644

65.4 KB

assets/images/photo_pause.png

304 KB | W: | H:

340 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
assets/images/re_button.png 0 → 100644

8.41 KB

assets/images/re_button_dis.png 0 → 100644

9.02 KB

lib/common/dialogs/customer_dialog.dart
... ... @@ -14,8 +14,8 @@ class CustomerTwoActionDialog extends Dialog {
14 14 final String leftTitle;
15 15 final String rightTitle;
16 16 final String content;
17   - final GestureTapCallback leftTap;
18   - final GestureTapCallback rightTap;
  17 + final GestureTapCallback? leftTap;
  18 + final GestureTapCallback? rightTap;
19 19  
20 20 @override
21 21 Widget build(BuildContext context) {
... ...
lib/common/dialogs/show_dialog.dart
... ... @@ -13,9 +13,9 @@ void showOneActionDialog(String title, String ensureTitle, String content, Gestu
13 13 });
14 14 }
15 15  
16   -void showTwoActionDialog(String title, String leftTitle, String rightTitle, String content, GestureTapCallback leftTap,
17   - GestureTapCallback rightTap,
18   - {bool? barrierDismissible}) {
  16 +void showTwoActionDialog(String title, String leftTitle, String rightTitle, String content,
  17 + {GestureTapCallback? leftTap,
  18 + GestureTapCallback? rightTap,bool? barrierDismissible}) {
19 19 showDialog<CustomerTwoActionDialog>(
20 20 context: AppRouter.context,
21 21 barrierDismissible: barrierDismissible ?? true,
... ...
lib/pages/login/loginpage/login_page.dart
... ... @@ -88,39 +88,40 @@ class _LoginPageView extends StatelessWidget {
88 88 ),
89 89 6.horizontalSpace,
90 90 RichText(
91   - text: TextSpan(children: [
92   - TextSpan(
93   - text: '我已阅读并同意',
94   - style: TextStyle(
95   - fontSize: 12.sp,
96   - color: const Color(0xFF333333),
97   - )),
98   - TextSpan(
99   - text: '《用户隐私协议》',
100   - style: TextStyle(
101   - fontSize: 12.sp,
102   - color: const Color(0xFF333333),
103   - ),
104   - recognizer: TapGestureRecognizer()
105   - ..onTap = () {
106   - Navigator.of(context).pushNamed(AppRouteName.webView, arguments: {
107   - 'urlStr': AppConsts.userPrivacyPolicyUrl,
108   - 'webViewTitle': '用户隐私协议'
109   - });
110   - }),
111   - TextSpan(
112   - text: ',', style: TextStyle(fontSize: 12.sp, color: const Color(0xFF333333))),
113   - TextSpan(
114   - text: '《儿童隐私政策》',
115   - style: TextStyle(fontSize: 12.sp, color: const Color(0xFF333333)),
116   - recognizer: TapGestureRecognizer()
117   - ..onTap = () {
118   - Navigator.of(context).pushNamed(AppRouteName.webView, arguments: {
119   - 'urlStr': AppConsts.childrenPrivacyPolicyUrl,
120   - 'webViewTitle': '儿童隐私协议'
121   - });
122   - })
123   - ]),
  91 + text: TextSpan(
  92 + children: [
  93 + TextSpan(
  94 + text: '我已阅读并同意',
  95 + style: TextStyle(
  96 + fontSize: 12.sp,
  97 + color: const Color(0xFF333333),
  98 + )),
  99 + TextSpan(
  100 + text: '《用户隐私协议》',
  101 + style: TextStyle(
  102 + fontSize: 12.sp,
  103 + color: const Color(0xFF333333),
  104 + ),
  105 + recognizer: TapGestureRecognizer()
  106 + ..onTap = () {
  107 + Navigator.of(context).pushNamed(AppRouteName.webView, arguments: {
  108 + 'urlStr': AppConsts.userPrivacyPolicyUrl,
  109 + 'webViewTitle': '用户隐私协议'
  110 + });
  111 + }),
  112 + TextSpan(
  113 + text: ',', style: TextStyle(fontSize: 12.sp, color: const Color(0xFF333333))),
  114 + TextSpan(
  115 + text: '《儿童隐私政策》',
  116 + style: TextStyle(fontSize: 12.sp, color: const Color(0xFF333333)),
  117 + recognizer: TapGestureRecognizer()
  118 + ..onTap = () {
  119 + Navigator.of(context).pushNamed(AppRouteName.webView, arguments: {
  120 + 'urlStr': AppConsts.childrenPrivacyPolicyUrl,
  121 + 'webViewTitle': '儿童隐私协议'
  122 + });
  123 + })
  124 + ]),
124 125 )
125 126 ],
126 127 ),
... ...
lib/pages/repeataftercontent/bloc/repeat_after_content_bloc.dart
... ... @@ -346,9 +346,9 @@ class RepeatAfterContentBloc extends Bloc&lt;RepeatAfterContentEvent, RepeatAfterCo
346 346 }
347 347  
348 348 void showDialog() async {
349   - showTwoActionDialog('提示', '取消', '去设置', '请进入设置页打开麦克风权限', () {
  349 + showTwoActionDialog('提示', '取消', '去设置', '请进入设置页打开麦克风权限', leftTap: (){
350 350 popPage();
351   - }, () {
  351 + },rightTap: (){
352 352 popPage();
353 353 openAppSettings();
354 354 });
... ...
lib/pages/user/modify/modify_user_information_page.dart
... ... @@ -64,10 +64,10 @@ class ModifyUserInformationPage extends StatelessWidget {
64 64 onBack: () {
65 65 final bloc = BlocProvider.of<UserInfoBloc>(context);
66 66 if (bloc.isChangeInfo) {
67   - showTwoActionDialog('提示', '确定离开', '继续修改', '您的信息尚未保存', () {
  67 + showTwoActionDialog('提示', '确定离开', '继续修改', '您的信息尚未保存',leftTap: (){
68 68 popPage();
69 69 popPage();
70   - }, () {
  70 + },rightTap: (){
71 71 popPage();
72 72 });
73 73 } else {
... ...
lib/pages/user/modify/user_avatar_bloc/user_avatar_bloc.dart
... ... @@ -122,9 +122,9 @@ class UserAvatarBloc extends Bloc&lt;UserAvatarEvent, UserAvatarState&gt; {
122 122  
123 123 void showDialog(Permission permission) {
124 124 final contentStr = permission == Permission.camera ? '相机权限未开启,请到设置中打开' : '相册权限未开启,请到设置中打开';
125   - showTwoActionDialog('提示', '取消', '去设置', contentStr, () {
  125 + showTwoActionDialog('提示', '取消', '去设置', contentStr, leftTap: (){
126 126 popPage();
127   - }, () {
  127 + },rightTap: (){
128 128 popPage();
129 129 openAppSettings();
130 130 });
... ...
lib/pages/user/setting/delete_account_page.dart 0 → 100644
  1 +import 'package:common_utils/common_utils.dart';
  2 +import 'package:flutter/material.dart';
  3 +import 'package:flutter_screenutil/flutter_screenutil.dart';
  4 +import 'package:wow_english/common/request/dao/user_dao.dart';
  5 +import 'package:wow_english/common/widgets/we_app_bar.dart';
  6 +import 'package:wow_english/utils/color_util.dart';
  7 +
  8 +import '../../../common/dialogs/show_dialog.dart';
  9 +import '../../../route/route.dart';
  10 +
  11 +class DeleteAccountPage extends StatefulWidget {
  12 + const DeleteAccountPage({super.key});
  13 +
  14 + @override
  15 + State<StatefulWidget> createState() {
  16 + return DeleteAccountPageState();
  17 + }
  18 +}
  19 +
  20 +class DeleteAccountPageState extends State<DeleteAccountPage> {
  21 +
  22 + late String _text;
  23 + late TimerUtil _timerUtil;
  24 + late bool _endTime;
  25 +
  26 + @override
  27 + void initState() {
  28 + super.initState();
  29 + _endTime = false;
  30 + _text = '请阅读注销条款15s';
  31 + _timerUtil = TimerUtil(mTotalTime: 15000);
  32 + _timerUtil.setOnTimerTickCallback((int tick) {
  33 + setState(() {
  34 + if (tick == 0) {
  35 + _endTime = true;
  36 + _text = '确认注销';
  37 + } else {
  38 + _text = '请阅读注销账号条款${tick~/1000}s';
  39 + }
  40 + });
  41 + });
  42 + _timerUtil.startCountDown();
  43 + }
  44 +
  45 + void deleteAccount() async {
  46 + showTwoActionDialog(
  47 + '注销账号', '取消', '注销', '请谨慎操作,注销后不可恢复!',
  48 + leftTap: () {popPage();},
  49 + rightTap: () {
  50 + popPage();
  51 + UserDao.deleteAccount();
  52 + });
  53 + }
  54 +
  55 + @override
  56 + void dispose() {
  57 + if (_timerUtil.isActive()) {
  58 + _timerUtil.cancel();
  59 + }
  60 + super.dispose();
  61 + }
  62 +
  63 + @override
  64 + Widget build(BuildContext context) {
  65 + return Scaffold(
  66 + appBar: const WEAppBar(
  67 + titleText: '注销账号',
  68 + ),
  69 + body: Container(
  70 + color: Colors.white,
  71 + padding: EdgeInsets.only(
  72 + bottom: 20.h
  73 + ),
  74 + child: SafeArea(
  75 + child: Center(
  76 + child: Column(
  77 + children: [
  78 + 26.verticalSpace,
  79 + Expanded(
  80 + child: ListView(
  81 + children: [
  82 + RichText(
  83 + textAlign: TextAlign.left,
  84 + text: TextSpan(
  85 + children: [
  86 + TextSpan(
  87 + text: '注销账号条件:\n',
  88 + style: TextStyle(
  89 + fontSize: 17.sp,
  90 + color: const Color(0xFF333333),
  91 + fontWeight: FontWeight.bold
  92 + )
  93 + ),
  94 + TextSpan(
  95 + text: '您提交注销申请后,wow english团队将对下列信息进行验证,以保证您的账号、财产安全:\n1.请确保帐户内没有余额。\n2.请确保账户内没有优惠券或其他卡券。\n3.请确保账户内没有虚拟财产权益。\n4.请确保账户内没有剩余课程\n5.请确保账户内没有VIP会员权益。\n\n',
  96 + style: TextStyle(
  97 + fontSize: 13.sp,
  98 + color: const Color(0xFF333333),
  99 + fontWeight: FontWeight.bold
  100 + )
  101 + ),
  102 + TextSpan(
  103 + text: '注销账号须知:\n',
  104 + style: TextStyle(
  105 + fontSize: 17.sp,
  106 + color: const Color(0xFF333333),
  107 + fontWeight: FontWeight.bold
  108 + )
  109 + ),
  110 + TextSpan(
  111 + text: '点击下方"确认注销”按钮,即表示您已阅读井同意《注销账号须知》\n1.注销账号是不可恢复的操作,请道慎操作,注销账号后,会永久删除账号下所有个人资料和历史信息,且无法找回。包括但不限于昵称头像、课程信息、关注、交易记录、余额、课时、优惠券、虚拟财产权益、VIP会员权益以及解除对外授权的绑定关系等。\n2.注销账号并不代表账号注销前的账号行为和相关责任得到豁免或减轻。\n3.操作前,请确认wow english账号内所有服务均己妥善处理,如因注销账号造成的损失,由您自行承担。',
  112 + style: TextStyle(
  113 + fontSize: 13.sp,
  114 + color: const Color(0xFF333333),
  115 + fontWeight: FontWeight.bold
  116 + )
  117 + )
  118 + ]
  119 + ),
  120 + )
  121 + ],
  122 + ),
  123 + ),
  124 + 14.verticalSpace,
  125 + InkWell(
  126 + onTap: () => deleteAccount(),
  127 + child: Container(
  128 + height: 40.h,
  129 + width: 430.w,
  130 + decoration: BoxDecoration(
  131 + color: _endTime?HexColor('#00B6F1'):HexColor('#C7C7C7'),
  132 + border: Border.all(
  133 + width: 1.5.w,
  134 + color: const Color(0xFF140C10)
  135 + ),
  136 + borderRadius: BorderRadius.circular(15.r),
  137 + ),
  138 + alignment: Alignment.center,
  139 + child: Text(
  140 + _text,
  141 + textAlign: TextAlign.center,
  142 + style: TextStyle(
  143 + fontSize: 17.sp,
  144 + color: _endTime?Colors.white:const Color(0xFF333333)
  145 + ),
  146 + ),
  147 + ),
  148 + )
  149 + ],
  150 + ),
  151 + ),
  152 + ),
  153 + ),
  154 + );
  155 + }
  156 +}
0 157 \ No newline at end of file
... ...
lib/pages/user/setting/reback_page.dart 0 → 100644
  1 +import 'package:flutter/material.dart';
  2 +import 'package:flutter_screenutil/flutter_screenutil.dart';
  3 +import 'package:wow_english/common/extension/string_extension.dart';
  4 +import 'package:wow_english/utils/color_util.dart';
  5 +
  6 +import '../../../common/widgets/we_app_bar.dart';
  7 +
  8 +class ReBackPage extends StatefulWidget {
  9 + const ReBackPage({super.key});
  10 +
  11 + @override
  12 + State<StatefulWidget> createState() {
  13 + return ReBackPageState();
  14 + }
  15 +}
  16 +
  17 +class ReBackPageState extends State<ReBackPage> {
  18 + late bool _canEnsure;
  19 +
  20 + @override
  21 + void initState() {
  22 + super.initState();
  23 + _canEnsure = false;
  24 + }
  25 +
  26 + @override
  27 + Widget build(BuildContext context) {
  28 + return Scaffold(
  29 + appBar: const WEAppBar(
  30 + titleText: '我要反馈',
  31 + ),
  32 + body: Container(
  33 + color: Colors.white,
  34 + padding: EdgeInsets.symmetric(
  35 + horizontal: 24.w
  36 + ),
  37 + child: SafeArea(
  38 + child: Column(
  39 + children: [
  40 + 20.verticalSpace,
  41 + Row(
  42 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
  43 + children: [
  44 + Text(
  45 + '请输入您要反馈的问题和意见,10-500个字',
  46 + textAlign: TextAlign.left,
  47 + style: TextStyle(
  48 + fontSize: 19.sp,
  49 + color: HexColor('#333333')
  50 + ),
  51 + ),
  52 + Text(
  53 + '48/500',
  54 + textAlign: TextAlign.right,
  55 + style: TextStyle(
  56 + fontSize: 19.sp,
  57 + color: HexColor('#333333')
  58 + ),)
  59 + ],
  60 + ),
  61 + 9.5.verticalSpace,
  62 + Expanded(
  63 + child: Container(
  64 + decoration: BoxDecoration(
  65 + image: DecorationImage(
  66 + fit: BoxFit.fill,
  67 + image: AssetImage('bg_reback'.assetPng)
  68 + )
  69 + ),
  70 + ),
  71 + ),
  72 + 4.5.verticalSpace,
  73 + Container(
  74 + decoration: BoxDecoration(
  75 + image: DecorationImage(
  76 + fit: BoxFit.fill,
  77 + image: AssetImage(_canEnsure?'re_button'.assetPng:'re_button_dis'.assetPng)
  78 + )
  79 + ),
  80 + alignment: Alignment.center,
  81 + width: 91.w,
  82 + height: 45.h,
  83 + child: Text(
  84 + '提交',
  85 + textAlign: TextAlign.center,
  86 + style: TextStyle(
  87 + color: Colors.white,
  88 + fontSize: 17.sp
  89 + ),
  90 + ),
  91 + )
  92 + ],
  93 + ),
  94 + ),
  95 + )
  96 + );
  97 + }
  98 +}
0 99 \ No newline at end of file
... ...
lib/pages/user/setting/setting_page.dart 0 → 100644
  1 +import 'package:flutter/material.dart';
  2 +import 'package:flutter_screenutil/flutter_screenutil.dart';
  3 +import 'package:wow_english/common/widgets/we_app_bar.dart';
  4 +
  5 +import '../../../route/route.dart';
  6 +
  7 +class SettingPage extends StatefulWidget {
  8 + const SettingPage({super.key});
  9 +
  10 + @override
  11 + State<StatefulWidget> createState() {
  12 + return SettingPageState();
  13 + }
  14 +}
  15 +
  16 +class SettingPageState extends State<SettingPage> {
  17 + @override
  18 + Widget build(BuildContext context) {
  19 + return Scaffold(
  20 + appBar: const WEAppBar(
  21 + titleText: '设置',
  22 + ),
  23 + body: Container(
  24 + color: Colors.white,
  25 + padding: EdgeInsets.only(left: 17.w, right: 17.w),
  26 + child: SafeArea(
  27 + child: Center(
  28 + child: ListView(
  29 + children: [
  30 + 34.verticalSpace,
  31 + _buildItemWidget('注销账号', onPress: (){
  32 + pushNamed(AppRouteName.deleteAccount);
  33 + }),
  34 + 12.verticalSpace,
  35 + _buildItemWidget('清除缓存', onPress: (){
  36 +
  37 + }),
  38 + 12.verticalSpace,
  39 + _buildItemWidget('帮助与反馈', onPress: (){
  40 + pushNamed(AppRouteName.reBack);
  41 + }),
  42 + ],
  43 + ),
  44 + ),
  45 + ),
  46 + ),
  47 + );
  48 + }
  49 +
  50 + Widget _buildItemWidget(String text,{VoidCallback? onPress}) {
  51 + return OutlinedButton(
  52 + onPressed: () => onPress?.call(),
  53 + style: ButtonStyle(
  54 + side: MaterialStateProperty.all(BorderSide(color: const Color(0xFF140C10), width: 1.5.w)),
  55 + shape: MaterialStateProperty.all(RoundedRectangleBorder(borderRadius: BorderRadius.circular(15.r))),
  56 + minimumSize: MaterialStateProperty.all(Size(double.infinity, 58.h)),
  57 + backgroundColor: MaterialStateProperty.all(Colors.white),
  58 + ),
  59 + child: Text(
  60 + text,
  61 + style: TextStyle(
  62 + //fontWeight: FontWeight.w600,
  63 + color: const Color(0xFF333333),
  64 + fontSize: 21.sp,
  65 + ),
  66 + ),
  67 + );
  68 + }
  69 +}
0 70 \ No newline at end of file
... ...
lib/pages/user/user_page.dart
... ... @@ -169,12 +169,22 @@ class _UserView extends StatelessWidget {
169 169 "隐私协议",
170 170 style: textStyle21sp,
171 171 )),
  172 + 12.verticalSpace,
  173 + OutlinedButton(
  174 + onPressed: () {
  175 + pushNamed(AppRouteName.setting);
  176 + },
  177 + style: normalButtonStyle,
  178 + child: Text(
  179 + "设置",
  180 + style: textStyle21sp,
  181 + )),
172 182 30.verticalSpace,
173 183 OutlinedButton(
174 184 onPressed: () {
175   - showTwoActionDialog(barrierDismissible:false,'提示', '取消', '确认', '您确认要退出Wow English吗?', () {
  185 + showTwoActionDialog(barrierDismissible:false,'提示', '取消', '确认', '您确认要退出Wow English吗?',leftTap: (){
176 186 popPage();
177   - }, () {
  187 + },rightTap: (){
178 188 popPage();
179 189 userBloc.add(UserLogout());
180 190 });
... ... @@ -194,25 +204,25 @@ class _UserView extends StatelessWidget {
194 204 fontSize: 17.sp,
195 205 ),
196 206 )),
197   - 30.verticalSpace,
198   - TextButton(
199   - onPressed: () {
200   - //userBloc.add(UserDelete())
201   - showTwoActionDialog('注销账号', '取消', '注销', '请谨慎操作!\n注销后不可恢复哦!', () {
202   - popPage();
203   - }, () {
204   - userBloc.add(UserDelete());
205   - popPage();
206   - });
207   - },
208   - child: Text(
209   - "注销账号",
210   - style: TextStyle(
211   - //fontWeight: FontWeight.w600,
212   - color: Colors.red,
213   - fontSize: 15.sp,
214   - ),
215   - )),
  207 + // 30.verticalSpace,
  208 + // TextButton(
  209 + // onPressed: () {
  210 + // //userBloc.add(UserDelete())
  211 + // showTwoActionDialog('注销账号', '取消', '注销', '请谨慎操作!\n注销后不可恢复哦!', () {
  212 + // popPage();
  213 + // }, () {
  214 + // userBloc.add(UserDelete());
  215 + // popPage();
  216 + // });
  217 + // },
  218 + // child: Text(
  219 + // "注销账号",
  220 + // style: TextStyle(
  221 + // //fontWeight: FontWeight.w600,
  222 + // color: Colors.red,
  223 + // fontSize: 15.sp,
  224 + // ),
  225 + // )),
216 226 ],
217 227 ),
218 228 ));
... ...
lib/pages/video/lookvideo/widgets/video_widget.dart
... ... @@ -44,6 +44,12 @@ class _VideoWidgetState extends State&lt;VideoWidget&gt; {
44 44 int totalSecond = _controller!.value.duration.inMinutes.remainder(60)*60+_controller!.value.duration.inSeconds.remainder(60);
45 45 _currentTime = formatDuration(_controller!.value.position);
46 46 _playDegree = currentSecond/totalSecond;
  47 + if (_playDegree > 1.0) {
  48 + _playDegree = 1.0;
  49 + }
  50 + if(_playDegree < 0) {
  51 + _playDegree = 0.0;
  52 + }
47 53 });
48 54 }
49 55 }
... ...
lib/route/route.dart
... ... @@ -18,10 +18,13 @@ import &#39;package:wow_english/pages/tab/tab_page.dart&#39;;
18 18 import 'package:wow_english/pages/user/information/user_information_page.dart';
19 19 import 'package:wow_english/pages/user/modify/modify_user_avatar_page.dart';
20 20 import 'package:wow_english/pages/user/modify/modify_user_information_page.dart';
  21 +import 'package:wow_english/pages/user/setting/setting_page.dart';
21 22 import 'package:wow_english/pages/user/user_page.dart';
22 23 import 'package:wow_english/pages/video/lookvideo/look_video_page.dart';
23 24  
24 25 import '../pages/reading/reading_page.dart';
  26 +import '../pages/user/setting/delete_account_page.dart';
  27 +import '../pages/user/setting/reback_page.dart';
25 28  
26 29 class AppRouteName {
27 30 static const String splash = 'splash';
... ... @@ -43,7 +46,6 @@ class AppRouteName {
43 46  
44 47 /// 用户详细信息页
45 48 static const String userInformation = 'userInformation';
46   -
47 49 /// 修改用户头像
48 50 static const String userAvatar = 'userAvatar';
49 51  
... ... @@ -51,13 +53,18 @@ class AppRouteName {
51 53 //static const String userModifyInformation = 'userModifyInformation';
52 54 ///看视频
53 55 static const String lookVideo = 'lookVideo';
54   -
55 56 ///绘本
56 57 static const String reading = 'reading';
57   -
58 58 ///视频跟读详情
59 59 static const String readAfterContent = 'readAfterContent';
60 60  
  61 + ///设置
  62 + static const String setting = 'setting';
  63 + ///注销账号
  64 + static const String deleteAccount = 'deleteAccount';
  65 + ///帮助与反馈
  66 + static const String reBack = 'reBack';
  67 +
61 68 static const String tab = '/';
62 69 }
63 70  
... ... @@ -158,6 +165,12 @@ class AppRouter {
158 165 videoFollowReadId = (settings.arguments as Map)['videoFollowReadId'] as String;
159 166 }
160 167 return CupertinoPageRoute(builder: (_) => RepeatAfterContentPage(videoFollowReadId: videoFollowReadId));
  168 + case AppRouteName.setting:
  169 + return CupertinoPageRoute(builder: (_) => const SettingPage());
  170 + case AppRouteName.deleteAccount:
  171 + return CupertinoPageRoute(builder: (_) => const DeleteAccountPage());
  172 + case AppRouteName.reBack:
  173 + return CupertinoPageRoute(builder: (_) => const ReBackPage());
161 174 case AppRouteName.tab:
162 175 return PageRouteBuilder(
163 176 opaque: false,
... ...