初始化
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:hgdj/assets_tool/images.dart';
|
||||
|
||||
import '../../hj_model/splash/ads_model.dart';
|
||||
import '../../hj_utils/screen.dart';
|
||||
import '../../tools_base/banner/ads_banner_widget.dart';
|
||||
import '../../tools_base/banner/ads_item.dart';
|
||||
|
||||
class AppCenterDialog extends StatefulWidget {
|
||||
final List<AdsInfoModel>? appList;
|
||||
final List<AdsInfoModel>? adsList;
|
||||
final VoidCallback? callback;
|
||||
|
||||
const AppCenterDialog({super.key, this.appList, this.callback, this.adsList});
|
||||
|
||||
@override
|
||||
State<AppCenterDialog> createState() => _AppCenterDialogState();
|
||||
}
|
||||
|
||||
class _AppCenterDialogState extends State<AppCenterDialog> {
|
||||
bool _showClose = false;
|
||||
|
||||
List<AdsInfoModel> get _appList => widget.appList ?? [];
|
||||
|
||||
/// 网格高度上限 = 4 行 + 底部留白,超出滚动。数字跟下面 gridDelegate 对应,改一处要同步。
|
||||
/// 别用「首帧 shrinkWrap 量高度、次帧再改成固定高」那套——两帧布局不同,弹窗又居中,打开瞬间会跳
|
||||
double get _maxGridHeight {
|
||||
final itemWidth = (Get.width - 32 * 2 - 12 * 3) / 4;
|
||||
return itemWidth * 93 / 68 * 4 + 16 * 3 + 25;
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// 1 秒后再显示关闭按钮,防误触
|
||||
Future.delayed(const Duration(milliseconds: 1000), () {
|
||||
if (mounted) setState(() => _showClose = true);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Material(
|
||||
color: Colors.black.withValues(alpha: 0.6),
|
||||
child: Center(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 32),
|
||||
alignment: Alignment.center,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (widget.adsList?.isNotEmpty == true)
|
||||
Container(
|
||||
margin: const EdgeInsets.only(bottom: 24),
|
||||
child: AdsBannerWidget(
|
||||
widget.adsList,
|
||||
width: 329,
|
||||
height: 88,
|
||||
autoPlayMs: 5000,
|
||||
),
|
||||
),
|
||||
//Flexible 兜住矮屏:内容再多也不会顶破屏幕
|
||||
Flexible(
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(maxHeight: _maxGridHeight),
|
||||
child: GridView.builder(
|
||||
padding: const EdgeInsets.only(bottom: 25),
|
||||
shrinkWrap: true, //不足 4 行时按内容收,不留空
|
||||
physics: const ClampingScrollPhysics(),
|
||||
itemCount: _appList.length,
|
||||
gridDelegate:
|
||||
const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 4,
|
||||
crossAxisSpacing: 12,
|
||||
mainAxisSpacing: 16,
|
||||
childAspectRatio: 68 / 93,
|
||||
),
|
||||
itemBuilder: (context, index) {
|
||||
return AdsItem(
|
||||
adInfo: _appList[index],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
32.sizeBoxH,
|
||||
//一直挂在树上只切显隐:等 _showClose 才 build 的话,asset 解码前图高是 0,
|
||||
//会先塌一下再弹回来,居中布局跟着抖
|
||||
Opacity(
|
||||
opacity: _showClose ? 1 : 0,
|
||||
child: IgnorePointer(
|
||||
ignoring: !_showClose,
|
||||
child: GestureDetector(
|
||||
onTap: () => Get.back(),
|
||||
child: Image.asset("close_button.png".commonImgPath,
|
||||
width: 32, height: 32),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
import 'package:easy_rich_text/easy_rich_text.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:hgdj/assets_tool/app_colors.dart';
|
||||
import 'package:hgdj/config/config.dart';
|
||||
import 'package:hgdj/hj_utils/screen.dart';
|
||||
import 'package:hgdj/routers/jump_router.dart';
|
||||
import 'package:hgdj/tools_base/widget/common_dialog.dart';
|
||||
|
||||
class LineErrorDialog extends StatelessWidget {
|
||||
static Future show({Function? callback}) {
|
||||
return Get.dialog(
|
||||
LineErrorDialog(callback: callback),
|
||||
barrierDismissible: false,
|
||||
);
|
||||
}
|
||||
|
||||
final Function? callback;
|
||||
|
||||
const LineErrorDialog({super.key, this.callback});
|
||||
|
||||
String get url => '91porn01.cc';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CommonDialog(
|
||||
//线路异常必须让用户处理,Get.dialog 的 barrierDismissible 到不了这层
|
||||
barrierDismissible: false,
|
||||
canTapClose: false,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'系统提示',
|
||||
style: TextStyle(
|
||||
color: Colors.white.withValues(alpha: .9),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
12.sizeBoxH,
|
||||
0.5.line,
|
||||
12.sizeBoxH,
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
"APP线路检测失败",
|
||||
style: TextStyle(
|
||||
color: Color(0xffF52C56),
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
12.sizeBoxH,
|
||||
Container(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: const Text(
|
||||
"解决方案:",
|
||||
style: TextStyle(
|
||||
color: Color(0xff656565),
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500),
|
||||
),
|
||||
),
|
||||
12.sizeBoxH,
|
||||
EasyRichText(
|
||||
'''1.请检测您的网络是否正常,手机是否开了VPN或10分钟后再尝试访问。
|
||||
2.前往官网地址 $url下载最新版。
|
||||
3.前往Telegram${Config.appName}官方交流群
|
||||
''',
|
||||
defaultStyle:
|
||||
TextStyle(fontSize: 12, color: Color(0xff656565), height: 1.8),
|
||||
patternList: [
|
||||
EasyRichTextPattern(
|
||||
targetString: url,
|
||||
style: TextStyle(color: AppColors.primaryHighColor),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
launchUrlToWeb('https://$url');
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
18.sizeBoxH,
|
||||
SizedBox(
|
||||
height: 38,
|
||||
child: Row(
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
Get.back();
|
||||
callback?.call();
|
||||
},
|
||||
child: Container(
|
||||
width: 96,
|
||||
height: 42,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(3),
|
||||
color: Colors.white.withValues(alpha: .1),
|
||||
),
|
||||
child: Text(
|
||||
"切换路线",
|
||||
style: TextStyle(
|
||||
color: Color(0xff989898),
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
12.sizeBoxW,
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
launchUrlToWeb('https://t.me/hougong9527');
|
||||
},
|
||||
child: Container(
|
||||
height: 42,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(3),
|
||||
color: AppColors.actionRed,
|
||||
),
|
||||
child: const Text(
|
||||
"前往群聊",
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
// ignore_for_file: prefer_const_constructors, use_key_in_widget_constructors, use_full_hex_values_for_flutter_colors, sized_box_for_whitespace, unnecessary_import
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:hgdj/assets_tool/images.dart';
|
||||
import 'package:hgdj/hj_model/splash/ads_model.dart';
|
||||
import 'package:hgdj/hj_utils/screen.dart';
|
||||
|
||||
import '../../tools_base/banner/ads_item.dart';
|
||||
|
||||
/// 系统公告--图片公告
|
||||
class NoticeImageDialog extends StatelessWidget {
|
||||
final AdsInfoModel? model;
|
||||
|
||||
NoticeImageDialog({this.model});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 32),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
AdsItem(
|
||||
adInfo: model!,
|
||||
showType: AdShowType.img,
|
||||
aspectRatio: 6 / 8,
|
||||
),
|
||||
20.sizeBoxH,
|
||||
InkWell(
|
||||
enableFeedback: false,
|
||||
onTap: () => Get.back(result: false),
|
||||
child: Image.asset("close_button.png".commonImgPath, width: 32),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 系统公告--上下双排图片公告
|
||||
class SystemImagesDialog extends StatelessWidget {
|
||||
final List<AdsInfoModel>? ads;
|
||||
|
||||
SystemImagesDialog({this.ads});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 32),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ListView.separated(
|
||||
shrinkWrap: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
itemBuilder: (context, index) {
|
||||
return AspectRatio(
|
||||
aspectRatio: 300 / 169,
|
||||
child: AdsItem(
|
||||
adInfo: ads![index],
|
||||
showType: AdShowType.img,
|
||||
aspectRatio: 6 / 8,
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) => 6.sizeBoxH,
|
||||
itemCount: ads?.length ?? 0,
|
||||
),
|
||||
20.sizeBoxH,
|
||||
InkWell(
|
||||
enableFeedback: false,
|
||||
onTap: () => Get.back(result: false),
|
||||
child: Image.asset("close_button.png".commonImgPath, width: 32),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
// ignore_for_file: prefer_const_constructors, use_key_in_widget_constructors
|
||||
|
||||
import 'package:easy_rich_text/easy_rich_text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:hgdj/assets_tool/app_colors.dart';
|
||||
import 'package:hgdj/hj_utils/screen.dart';
|
||||
import 'package:hgdj/tools_base/widget/common_dialog.dart';
|
||||
|
||||
import '../../hj_model/splash/ads_model.dart';
|
||||
|
||||
/// 系统公告--文字公告
|
||||
class NoticeTextDialog extends StatelessWidget {
|
||||
const NoticeTextDialog({
|
||||
this.content,
|
||||
this.addr,
|
||||
this.wordBean,
|
||||
});
|
||||
|
||||
final AnnounceInfoBean? wordBean;
|
||||
final String? content;
|
||||
final String? addr;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CommonDialog(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
wordBean?.title ?? "官方公告",
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
color: Colors.white.withValues(alpha: 0.9),
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
12.sizeBoxH,
|
||||
0.5.line,
|
||||
12.sizeBoxH,
|
||||
SizedBox(
|
||||
height: 220,
|
||||
child: SingleChildScrollView(
|
||||
child: EasyRichText(
|
||||
content ?? "",
|
||||
defaultStyle: TextStyle(
|
||||
color: Color(0xff656565), fontSize: 12, height: 25 / 12),
|
||||
patternList: [
|
||||
EasyRichTextPattern(
|
||||
targetString:
|
||||
'(http(s)?:\\/\\/.)?(www\\.)?[-a-zA-Z0-9:%._\\+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_\\+.~#?&//=]*)|https:\/\/t\\.me\/[0-9A-Za-z]{2,256}',
|
||||
urlType: 'web',
|
||||
style: TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
color: Colors.blue,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
12.sizeBoxH,
|
||||
InkWell(
|
||||
enableFeedback: false,
|
||||
onTap: () => Get.back(),
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
height: 44,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(3),
|
||||
color: AppColors.actionRed),
|
||||
child: Text(
|
||||
"我知道了",
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
// ignore_for_file: depend_on_referenced_packages
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:hgdj/assets_tool/app_colors.dart';
|
||||
import 'package:hgdj/hj_utils/install_util.dart';
|
||||
import 'package:hgdj/hj_utils/screen.dart';
|
||||
import 'package:hgdj/tools_base/toast.dart';
|
||||
import 'package:hgdj/tools_base/widget/common_dialog.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
import '../../hj_model/splash/domain_source_model.dart';
|
||||
import '../../hj_page/mine/identity/mine_identity_page.dart';
|
||||
import '../../routers/jump_router.dart';
|
||||
import '../../tools_base/net/load_apk/dio_cli.dart';
|
||||
import '../../tools_base/net/load_apk/dio_slice_downloader.dart';
|
||||
import '../../track_event_manager/device_service.dart';
|
||||
|
||||
//升级版本对话框
|
||||
class UpdateDialog extends StatefulWidget {
|
||||
static Future show(CheckVersionInfo phoneBean) async {
|
||||
return await Get.dialog(
|
||||
UpdateDialog(updateInfo: phoneBean),
|
||||
barrierDismissible: false,
|
||||
);
|
||||
}
|
||||
|
||||
final CheckVersionInfo updateInfo;
|
||||
|
||||
const UpdateDialog({super.key, required this.updateInfo});
|
||||
|
||||
@override
|
||||
State<UpdateDialog> createState() => _UpdateDialog();
|
||||
}
|
||||
|
||||
class _UpdateDialog extends State<UpdateDialog> {
|
||||
bool isDownloading = false; // 下载中:既防重入,也决定进度条露不露
|
||||
var progress = .0;
|
||||
|
||||
String apkPath = "";
|
||||
|
||||
/// 点「立即升级」:iOS 跳商店,Android 下载 apk,下完再点就是安装
|
||||
void _onUpdate() async {
|
||||
//iOS 没有下载安装 apk 那一套,直接跳 App Store;进度条也就不用起(isDownloading 不置位)
|
||||
if (Platform.isIOS) {
|
||||
final iosUrl = widget.updateInfo.iosUrl ?? '';
|
||||
iosUrl.isEmpty ? showToast("暂无更新地址,请稍后再试") : await launchUrlToWeb(iosUrl);
|
||||
return;
|
||||
}
|
||||
if (progress == 1.0) {
|
||||
await InstallUtil.installApk(apkPath);
|
||||
return;
|
||||
}
|
||||
if (isDownloading) {
|
||||
return;
|
||||
}
|
||||
//开始下载
|
||||
isDownloading = true;
|
||||
String devId = DeviceInfoService.deviceId;
|
||||
Clipboard.setData(ClipboardData(text: "***$devId^^^"));
|
||||
_downloadApk(widget.updateInfo.url ?? "");
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CommonDialog(
|
||||
//强更场景要挡住点空白关闭,Get.dialog 的 barrierDismissible 到不了这层
|
||||
barrierDismissible: false,
|
||||
canTapClose: false,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'系统升级',
|
||||
style: TextStyle(
|
||||
color: Colors.white.withValues(alpha: .9),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
12.sizeBoxH,
|
||||
0.5.line,
|
||||
12.sizeBoxH,
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
"更新版本 v ${widget.updateInfo.verName}",
|
||||
style: TextStyle(
|
||||
color: Colors.white.withValues(alpha: .9),
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
12.sizeBoxH,
|
||||
SizedBox(
|
||||
height: 175,
|
||||
child: SingleChildScrollView(
|
||||
physics: const ClampingScrollPhysics(),
|
||||
child: Row(
|
||||
children: [
|
||||
//Row 不给约束,Text 会按自然宽度排版撑出去,必须 Expanded 收回可用宽度才会换行
|
||||
Expanded(
|
||||
child: Text(
|
||||
widget.updateInfo.description
|
||||
?.replaceAll("|", "\n") ??
|
||||
"",
|
||||
style: TextStyle(
|
||||
color: Colors.white.withValues(alpha: .55),
|
||||
fontSize: 12,
|
||||
height: 1.6,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
18.sizeBoxH,
|
||||
InkWell(
|
||||
enableFeedback: false,
|
||||
onTap: () => Get.to(() => const MineAccountIdentityPage()),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
"保存账号凭证",
|
||||
style: TextStyle(
|
||||
color: Colors.white.withValues(alpha: .55),
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
3.sizeBoxW,
|
||||
Icon(
|
||||
Icons.arrow_forward_ios_outlined,
|
||||
size: 14,
|
||||
color: Color(0xffDCDCDC),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
18.sizeBoxH,
|
||||
if (isDownloading) ...[
|
||||
Container(
|
||||
padding: EdgeInsets.zero,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(3),
|
||||
child: LinearProgressIndicator(
|
||||
value: progress,
|
||||
minHeight: 3,
|
||||
backgroundColor: const Color(0xffBEBEBE),
|
||||
valueColor: AlwaysStoppedAnimation(AppColors.actionRed),
|
||||
),
|
||||
),
|
||||
12.sizeBoxH,
|
||||
Text(
|
||||
"${((progress * 100).toInt())}%",
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: Colors.white.withValues(alpha: .55),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
] else
|
||||
_buildButtonMenu(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildButtonMenu() {
|
||||
if (widget.updateInfo.forcedUpdate == true) {
|
||||
return _buildUpdateBtn();
|
||||
} else {
|
||||
return Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () => Get.back(),
|
||||
child: Container(
|
||||
height: 44,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(3),
|
||||
color: Colors.white.withValues(alpha: .1),
|
||||
),
|
||||
child: Text(
|
||||
"暂不升级",
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Color(0xff989898),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(child: _buildUpdateBtn()),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildUpdateBtn() {
|
||||
return GestureDetector(
|
||||
onTap: _onUpdate,
|
||||
child: Container(
|
||||
height: 44,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.actionRed,
|
||||
borderRadius: BorderRadius.circular(3),
|
||||
),
|
||||
child: const Text(
|
||||
"立即升级",
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
///下载 apk(仅 Android,iOS 走商店)
|
||||
Future<void> _downloadApk(String url) async {
|
||||
final saveDirectory =
|
||||
path.join((await getExternalStorageDirectory())?.path ?? "", "apk");
|
||||
DioSliceRetryDownloader(DioCli(), url, null, saveDirectory, "paofu.apk",
|
||||
onReceiveProgress: (count, total) {
|
||||
progress = (count / total);
|
||||
setState(() {});
|
||||
}, onRetry: (int retryCount) {
|
||||
showToast("下载发生错误正在自动重试中...($retryCount)");
|
||||
}).download().then((String savePath) async {
|
||||
apkPath = savePath;
|
||||
await InstallUtil.installApk(apkPath);
|
||||
}).catchError((e) {
|
||||
showToast("下载发生错误,点击重新进行下载.");
|
||||
setState(() => isDownloading = false);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user