5th commit
This commit is contained in:
@@ -26,7 +26,7 @@ class MyApp extends StatelessWidget {
|
||||
Theme.of(context).textTheme,
|
||||
)
|
||||
),
|
||||
initialRoute: AppRouter.bookingPage,
|
||||
initialRoute: AppRouter.splashScreen,
|
||||
onGenerateRoute: AppRouter.generateRoute,
|
||||
);
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
import 'dart:io';
|
||||
import 'package:citycards_partner_flutter/core/app_router.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:mobile_scanner/mobile_scanner.dart';
|
||||
import '../bloc/qr_scan_bloc.dart';
|
||||
import '../bloc/qr_scan_event.dart';
|
||||
@@ -19,6 +19,7 @@ class _QrScanScreenState extends State<QrScanScreen>
|
||||
with WidgetsBindingObserver {
|
||||
late MobileScannerController _cameraController;
|
||||
final ValueNotifier<bool> _isTorchOn = ValueNotifier(false);
|
||||
bool _cameraAvailable = true;
|
||||
|
||||
final collapsedKey = GlobalKey();
|
||||
final ValueNotifier<double> sheetExtent = ValueNotifier(0.5);
|
||||
@@ -30,7 +31,17 @@ class _QrScanScreenState extends State<QrScanScreen>
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
|
||||
_cameraController = MobileScannerController();
|
||||
|
||||
// 🔍 Detect if running in iOS Simulator
|
||||
if (Platform.isIOS && !Platform.isMacOS) {
|
||||
_cameraAvailable = !Platform.environment.containsKey(
|
||||
'SIMULATOR_DEVICE_NAME',
|
||||
);
|
||||
}
|
||||
|
||||
// 🔦 Update torch state
|
||||
_cameraController.addListener(() {
|
||||
final torchState = _cameraController.value.torchState;
|
||||
_isTorchOn.value = (torchState == TorchState.on);
|
||||
@@ -48,6 +59,8 @@ class _QrScanScreenState extends State<QrScanScreen>
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
if (!mounted) return;
|
||||
if (!_cameraAvailable) return;
|
||||
|
||||
if (state == AppLifecycleState.paused) {
|
||||
_cameraController.stop();
|
||||
} else if (state == AppLifecycleState.resumed) {
|
||||
@@ -55,14 +68,17 @@ class _QrScanScreenState extends State<QrScanScreen>
|
||||
}
|
||||
}
|
||||
|
||||
void _safeStartCamera() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
if (mounted) {
|
||||
try {
|
||||
await _cameraController.start();
|
||||
} catch (_) {}
|
||||
/// ✅ Start camera safely (prevent multiple starts)
|
||||
void _safeStartCamera() async {
|
||||
if (!mounted || !_cameraAvailable) return;
|
||||
|
||||
try {
|
||||
if (!_cameraController.value.isStarting) {
|
||||
await _cameraController.start();
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
debugPrint("⚠️ Camera already running or failed to start: $e");
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -101,37 +117,47 @@ class _QrScanScreenState extends State<QrScanScreen>
|
||||
backgroundColor: Colors.black,
|
||||
body: Stack(
|
||||
children: [
|
||||
/// 📷 QR Scanner
|
||||
MobileScanner(
|
||||
controller: _cameraController,
|
||||
fit: BoxFit.cover,
|
||||
onDetect: (capture) {
|
||||
final barcode =
|
||||
capture.barcodes.first.rawValue ?? '';
|
||||
if (barcode.isNotEmpty && !state.isLocked) {
|
||||
viewModel.onQrDetected(barcode);
|
||||
}
|
||||
},
|
||||
),
|
||||
/// 🚫 Show this if no camera available (iOS simulator)
|
||||
if (!_cameraAvailable)
|
||||
const Center(
|
||||
child: Text(
|
||||
"Camera not available on iOS Simulator.\nPlease test on a real device.",
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
)
|
||||
else
|
||||
/// 📷 QR Scanner
|
||||
MobileScanner(
|
||||
controller: _cameraController,
|
||||
fit: BoxFit.cover,
|
||||
onDetect: (capture) {
|
||||
final barcode =
|
||||
capture.barcodes.first.rawValue ?? '';
|
||||
if (barcode.isNotEmpty && !state.isLocked) {
|
||||
viewModel.onQrDetected(barcode);
|
||||
}
|
||||
},
|
||||
),
|
||||
|
||||
/// 🔲 Scanner Frame
|
||||
Positioned(
|
||||
left: scanCenter.dx - 125,
|
||||
top: scanCenter.dy - 200,
|
||||
child: CustomPaint(
|
||||
size: const Size(250, 250),
|
||||
painter: CornerBorderPainter(
|
||||
const LinearGradient(
|
||||
colors: [
|
||||
Colors.white,
|
||||
Colors.white,
|
||||
Colors.white,
|
||||
],
|
||||
if (_cameraAvailable)
|
||||
Positioned(
|
||||
left: scanCenter.dx - 125,
|
||||
top: scanCenter.dy - 200,
|
||||
child: CustomPaint(
|
||||
size: const Size(250, 250),
|
||||
painter: CornerBorderPainter(
|
||||
const LinearGradient(
|
||||
colors: [Colors.white, Colors.white],
|
||||
),
|
||||
strokeWidth: 4,
|
||||
),
|
||||
strokeWidth: 4,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
/// 🧾 Draggable Bottom Sheet
|
||||
SafeArea(
|
||||
@@ -250,14 +276,15 @@ class _QrScanScreenState extends State<QrScanScreen>
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _headerIcons(
|
||||
BuildContext context,
|
||||
bool isExpanded,
|
||||
QrScanStatus status,
|
||||
MobileScannerController controller,
|
||||
DraggableScrollableController sheetController,
|
||||
double initFraction,
|
||||
) {
|
||||
BuildContext context,
|
||||
bool isExpanded,
|
||||
QrScanStatus status,
|
||||
MobileScannerController controller,
|
||||
DraggableScrollableController sheetController,
|
||||
double initFraction,
|
||||
) {
|
||||
final icons = [
|
||||
{'img': 'assets/scan/flash.png', 'route': '/flash'},
|
||||
{'img': 'assets/scan/menu.png', 'route': '/menu'},
|
||||
@@ -342,7 +369,6 @@ class _QrScanScreenState extends State<QrScanScreen>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/// ✅ Success Layout
|
||||
Widget _successLayout() => Card(
|
||||
color: Colors.green[50],
|
||||
|
||||
@@ -81,7 +81,7 @@ class _SupportFormView extends StatelessWidget {
|
||||
body: BlocBuilder<TicketBloc, TicketState>(
|
||||
builder: (context, state) {
|
||||
return SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
|
||||
Reference in New Issue
Block a user