feat: legacy mobile apps created
This commit is contained in:
@@ -0,0 +1,241 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:krow/core/presentation/styles/kw_text_styles.dart';
|
||||
import 'package:krow/core/presentation/styles/theme.dart';
|
||||
import 'package:krow/core/presentation/widgets/ui_kit/kw_app_bar.dart';
|
||||
import 'package:qr_code_scanner_plus/qr_code_scanner_plus.dart';
|
||||
|
||||
@RoutePage()
|
||||
class QrScannerScreen extends StatefulWidget {
|
||||
const QrScannerScreen({super.key});
|
||||
|
||||
@override
|
||||
State<QrScannerScreen> createState() => _QrScannerScreenState();
|
||||
}
|
||||
|
||||
class _QrScannerScreenState extends State<QrScannerScreen>
|
||||
with SingleTickerProviderStateMixin {
|
||||
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
|
||||
QRViewController? _cameraController;
|
||||
Timer? _debounceTimer;
|
||||
|
||||
var _scannerColor = AppColors.grayWhite;
|
||||
var popped = false;
|
||||
|
||||
late AnimationController _animationController;
|
||||
|
||||
@override
|
||||
void reassemble() {
|
||||
super.reassemble();
|
||||
if (Platform.isAndroid) {
|
||||
_cameraController!.pauseCamera();
|
||||
} else if (Platform.isIOS) {
|
||||
_cameraController!.resumeCamera();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_animationController = AnimationController(
|
||||
vsync: this,
|
||||
duration: const Duration(seconds: 2),
|
||||
)..repeat(reverse: true);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var size = MediaQuery.of(context).size.width * 0.75;
|
||||
return Scaffold(
|
||||
body: Stack(
|
||||
children: [
|
||||
_buildQrPreview(context, size),
|
||||
_buildOverlayContent(),
|
||||
_buildScannerAnimation(size)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildScannerAnimation(double size) {
|
||||
return Center(
|
||||
child: Container(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
height: size,
|
||||
width: size,
|
||||
decoration: const BoxDecoration(),
|
||||
child: Stack(
|
||||
children: [
|
||||
AnimatedBuilder(
|
||||
animation: _animationController,
|
||||
builder: (context, child) {
|
||||
return Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: size - (_animationController.value * (size - 20) + 10),
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
width: size - 6,
|
||||
height: 4,
|
||||
decoration:
|
||||
BoxDecoration(color: _scannerColor, boxShadow: [
|
||||
BoxShadow(
|
||||
color: _scannerColor.withAlpha(0xFA),
|
||||
blurRadius: 21,
|
||||
spreadRadius: 1,
|
||||
offset: Offset(
|
||||
0,
|
||||
_animationController.status ==
|
||||
AnimationStatus.reverse
|
||||
? -10
|
||||
: 10),
|
||||
),
|
||||
BoxShadow(
|
||||
color: _scannerColor.withAlpha(0xD9),
|
||||
blurRadius: 39,
|
||||
spreadRadius: 1,
|
||||
offset: Offset(
|
||||
0,
|
||||
_animationController.status ==
|
||||
AnimationStatus.reverse
|
||||
? -39
|
||||
: 39),
|
||||
)
|
||||
]),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Column _buildOverlayContent() {
|
||||
return Column(
|
||||
children: [
|
||||
KwAppBar(
|
||||
titleText: 'QR Code',
|
||||
contentColor: AppColors.grayWhite,
|
||||
backgroundColor: Colors.transparent,
|
||||
iconColorStyle: AppBarIconColorStyle.inverted,
|
||||
),
|
||||
const Gap(12),
|
||||
Text(
|
||||
'scan_qr_code'.tr(),
|
||||
style: AppTextStyles.headingH1.copyWith(color: AppColors.grayWhite),
|
||||
),
|
||||
const Gap(4),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 20, right: 20),
|
||||
child: Text(
|
||||
'align_qr_code'.tr(),
|
||||
textAlign: TextAlign.center,
|
||||
style: AppTextStyles.bodyMediumReg
|
||||
.copyWith(color: AppColors.blackCaptionText)),
|
||||
),
|
||||
const Spacer(),
|
||||
_bottomTooltip()
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Container _bottomTooltip() {
|
||||
return Container(
|
||||
padding: const EdgeInsets.fromLTRB(8, 8, 20, 8),
|
||||
margin: const EdgeInsets.only(bottom: 60),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.grayWhite.withAlpha(25),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text('tips'.tr(),
|
||||
style: AppTextStyles.bodyMediumMed
|
||||
.copyWith(color: AppColors.grayWhite)),
|
||||
],
|
||||
),
|
||||
const Gap(8),
|
||||
Text(
|
||||
'tips_qr'.tr(),
|
||||
style: AppTextStyles.bodyTinyMed
|
||||
.copyWith(color: AppColors.grayWhite))
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Column _buildQrPreview(BuildContext context, size) {
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: QRView(
|
||||
overlay: QrScannerOverlayShape(
|
||||
overlayColor: AppColors.blackBlack.withAlpha(0xCC),
|
||||
borderColor: _scannerColor,
|
||||
borderRadius: 12,
|
||||
borderLength: 42,
|
||||
borderWidth: 5,
|
||||
cutOutSize: size,
|
||||
),
|
||||
key: qrKey,
|
||||
onQRViewCreated: _onQRViewCreated,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
void _onQRViewCreated(QRViewController controller) {
|
||||
_cameraController = controller;
|
||||
controller.scannedDataStream.listen((scanData) {
|
||||
if (scanData.code == null) {
|
||||
setState(() {
|
||||
_scannerColor = AppColors.statusRate;
|
||||
});
|
||||
}
|
||||
var json = const JsonDecoder().convert(scanData.code??'{}');
|
||||
|
||||
if (json['type'] == 'event' && json['birth'] == 'app') {
|
||||
if (mounted && !popped) {
|
||||
popped = true;
|
||||
context.router.maybePop(json['eventId']);
|
||||
}
|
||||
} else {
|
||||
setState(() {
|
||||
_scannerColor = AppColors.statusError;
|
||||
});
|
||||
if (_debounceTimer?.isActive ?? false) {
|
||||
_debounceTimer?.cancel();
|
||||
}
|
||||
|
||||
_debounceTimer = Timer(const Duration(seconds: 1), () {
|
||||
setState(() {
|
||||
_scannerColor = AppColors.grayWhite;
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_debounceTimer?.cancel();
|
||||
_animationController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user