Files
rasadyar_application/lib/presentation/pages/splash/logic.dart

246 lines
7.2 KiB
Dart

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:rasadyar_app/data/model/app_info_model.dart';
import 'package:rasadyar_app/presentation/routes/app_pages.dart';
import 'package:rasadyar_auth/data/services/token_storage_service.dart';
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_inspection/inspection.dart';
class SplashLogic extends GetxController with GetTickerProviderStateMixin {
late final AnimationController scaleController;
late final AnimationController rotateController;
Rxn<Animation<double>> scaleAnimation = Rxn();
Rxn<Animation<double>> rotationAnimation = Rxn();
RxBool hasUpdated = false.obs;
RxBool onUpdateDownload = false.obs;
RxDouble percent = 0.0.obs;
final RxnString _updateFilePath = RxnString();
final platform = MethodChannel('apk_installer');
final Dio _dio = Dio();
var tokenService = Get.find<TokenStorageService>();
AppInfoModel? appInfoModel;
@override
void onInit() {
super.onInit();
scaleController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 1500),
);
rotateController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 8000),
);
scaleAnimation.value = Tween<double>(begin: 0.8, end: 1.2).animate(scaleController);
rotationAnimation.value = Tween<double>(begin: 0.0, end: 1).animate(rotateController);
rotateController.forward();
rotateController.addStatusListener((status) {
if (status == AnimationStatus.completed) {
rotateController.repeat();
} else if (status == AnimationStatus.dismissed) {
rotateController.forward();
}
});
scaleController.forward();
scaleController.addStatusListener((status) {
if (status == AnimationStatus.completed) {
scaleController.reverse();
} else if (status == AnimationStatus.dismissed) {
scaleController.forward();
}
});
hasUpdated.listen((data) {
if (data) {
requiredUpdateDialog(
onConfirm: () async {
await fileDownload();
},
);
} else if (!data && Get.isDialogOpen == true) {
Get.back();
}
});
onUpdateDownload.listen((data) {
hasUpdated.value = false;
if (data) {
Get.bottomSheet(
isDismissible: false,
isScrollControlled: true,
backgroundColor: Colors.transparent,
Container(
height: 170,
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(16.0)),
),
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisSize: MainAxisSize.min,
spacing: 8,
children: [
const Text('در حال دانلود بروزرسانی برنامه...'),
Obx(
() => Row(
spacing: 8,
children: [
Expanded(
child: LinearProgressIndicator(
value: percent.value,
color: AppColor.greenNormal,
minHeight: 4,
),
),
SizedBox(
width: 55.w,
child: Text(
'${(percent.value * 100).toStringAsFixed(2)}%',
textAlign: TextAlign.center,
),
),
],
),
),
Row(
spacing: 8,
children: [
Expanded(
child: ObxValue((data) {
return RElevated(
backgroundColor: AppColor.greenNormal,
height: 40.h,
onPressed: data.value != null
? () {
installApk();
Get.back();
}
: null,
text: 'نصب',
);
}, _updateFilePath),
),
Expanded(
child: ROutlinedElevated(
borderColor: AppColor.error,
text: 'خروج',
onPressed: () async {
exit(0);
},
),
),
],
),
],
),
),
);
}
});
}
@override
void onReady() {
super.onReady();
Future.delayed(const Duration(milliseconds: 250), () async {
try {
final isUpdateNeeded = await checkVersion();
if (isUpdateNeeded) return;
final module = tokenService.appModule.value;
final target = getTargetPage(module);
Get.offAndToNamed(InspectionRoutes.init);
} catch (e, st) {
debugPrint("onReady error: $e\n$st");
}
});
}
@override
void onClose() {
rotateController.dispose();
scaleController.dispose();
super.onClose();
}
Future<bool> checkVersion() async {
try {
final info = await PackageInfo.fromPlatform();
int version = info.version.versionNumber;
var res = await _dio.get("https://rsibackend.rasadyaar.ir/app/apk-info/");
appInfoModel = AppInfoModel.fromJson(res.data);
if ((appInfoModel?.info?.version?.versionNumber ?? 0) > version) {
hasUpdated.value = !hasUpdated.value;
return true;
}
return false;
} catch (e) {
return false;
}
}
Future<void> fileDownload() async {
onUpdateDownload.value = true;
final dir = await getApplicationDocumentsDirectory();
final filePath = "${dir.path}/rasadyar.apk";
final file = File(filePath);
if (await file.exists()) {
await file.delete();
}
int attempts = 0;
int retryCount = 4;
bool success = false;
while (attempts < retryCount && !success) {
try {
await _dio.download(
appInfoModel?.download_link ?? '',
filePath,
onReceiveProgress: (count, total) {
if (total != -1 && total > 0) {
percent.value = count / total;
}
},
);
success = true;
} on DioException catch (e) {
attempts++;
percent.value = 0.0;
if (attempts >= retryCount) {
eLog("Download failed after $attempts attempts: ${e.message}");
} else {
await Future.delayed(const Duration(milliseconds: 1200));
}
}
}
if (success) {
_updateFilePath.value = filePath;
}
onUpdateDownload.value = false;
}
Future<void> installApk() async {
try {
eLog(_updateFilePath.value);
final dir = await getApplicationDocumentsDirectory();
await platform.invokeMethod('apk_installer', {'appPath': _updateFilePath.value});
} catch (e) {
print("خطا در نصب: $e");
}
}
}