Skip to content

Overview ​

  • File: lib/views/new_scanner_page.dart

The new_scanner_page.dart file implements a QR code scanner functionality for the HVC XR application. It provides capabilities for scanning QR codes for both login and meeting purposes, with support for device orientation handling and automatic timeout. The page is designed to work with RealWear devices and includes features for rapid connect functionality.

Class Structure ​

dart
class NewScannerPage extends StatefulWidget {
  static const String routeName = '/NewScannerPage';
  const NewScannerPage({Key? key}) : super(key: key);

  @override
  State<NewScannerPage> createState() => _NewScannerPageState();
}

class _NewScannerPageState extends State<NewScannerPage> {
  // State variables and methods
}

Dependencies ​

dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:mobile_scanner/mobile_scanner.dart';
import 'package:native_device_orientation/native_device_orientation.dart';
// Additional imports for controllers and models

Key Components ​

State Variables ​

dart
MobileScannerController cameraController = MobileScannerController();
String qrcode = '';
Timer? _timer;
RxInt rotationValue = 0.obs;
String title = 'Please scan QR code to login';
String meetingId = '';

Controllers ​

dart
final AuthController authController = Get.find();
final RealTimeController realTimeController = Get.find();
final MeetingsController meetingsController = Get.find();

Scanner Initialization ​

Timer Management ​

dart
void _cancelTimer() {
  if (_timer != null) {
    _timer?.cancel();
    _timer = null;
  }
}
dart
void proceed() {
  if (authController.scannerResult.value.type.containsIgnoreCase('login')) {
    goToPage(const PinPage(pinType: PinType.login), closePage: false);
  } else if (authController.scannerResult.value.type.containsIgnoreCase('meeting')) {
    if (getBoolean(authController.scannerResult.value.meetingData?.pinRequired)) {
      goToPage(const PinPage(pinType: PinType.meeting), closePage: true);
    }
  }
}

void goToPage(Widget page, {bool closePage = true}) async {
  await SystemChrome.setPreferredOrientations([
    DeviceOrientation.landscapeLeft,
    DeviceOrientation.landscapeRight,
  ]).then((value) => closePage ? Get.off(page) : Get.to(page));
}

Device Orientation Handling ​

Orientation Setup ​

dart
@override
void initState() {
  super.initState();
  NativeDeviceOrientationCommunicator()
      .onOrientationChanged()
      .listen((event) {
    if (event == NativeDeviceOrientation.landscapeRight) {
      rotationValue.value = -2;
    } else {
      rotationValue.value = 0;
    }
  });
  meetingId = (Get.arguments ?? '') as String;
  if (meetingId.isNotEmpty) title = 'Scan Rapid Connect QR Code';
}

@override
void didChangeDependencies() {
  super.didChangeDependencies();
  Future.delayed(Duration.zero, () async {
    var nDor = await NativeDeviceOrientationCommunicator().orientation();
    rotationValue.value =
        nDor == NativeDeviceOrientation.landscapeRight ? -2 : 0;
  });
}

QR Code Processing ​

Scanner Configuration ​

dart
var scanner = MobileScanner(
    allowDuplicates: false,
    controller: cameraController,
    onDetect: (barcode, args) async {
      if (barcode.rawValue == null) {
        debugPrint('Failed to scan Barcode');
      } else {
        qrcode = barcode.rawValue!.trim();
        // Process QR code data
      }
    });

QR Code Processing Logic ​

dart
  try {
              if (!GetUtils.isNullOrBlank(qrcode)!) {
                if (qrcode.isNumericOnly && meetingId.isNotEmpty) {
                  logInfo('addDeviceToEvents data => $qrcode');
                  var res = await realTimeController.addDeviceToEvent(
                    qrcode,
                    meetingId,
                  );
                  logInfo('addDeviceToEvents resData => $res');
                  Get.back(result: getBoolean(res?.success));
                  if (res != null) {
                    if (res.success) {
                      HlkDialog.showSuccessSnackBar(
                          res.message ?? 'request sent successfully');
                    } else {
                      HlkDialog.showErrorSnackBar(
                          res.message ?? 'device request failed');
                    }
                  } else {
                    HlkDialog.showErrorSnackBar('request failed');
                  }
                } else {
                  authController.scannerResult.value =
                      ScannerResult.fromJson(qrcode);

                  if (widget.isScanCode != null && widget.isScanCode!) {
                    if (authController.scannerResult.value.type
                        .containsIgnoreCase('login')) {
                      authController.scannerResult.value.loginData =
                          LoginData.fromMap(
                              authController.scannerResult.value.data);
                      //scanDataProcessed = true;
                      proceed();
                    } else if (authController.scannerResult.value.type
                        .containsIgnoreCase('meeting')) {
                      final MeetingData meetingData = MeetingData.fromMap(
                          authController.scannerResult.value.data);
                      authController.scannerResult.value.meetingData =
                          meetingData;

                      //scanDataProcessed = true;

                      meetingsController.meetingCode.value =
                          meetingData.meetingCode;
                      meetingsController.joinMeetingDto.value.meetingToken =
                          meetingData.meetingToken;
                      // flow has changed now, from now on, always proceed
                      proceed();
                    } else {
                      qrcode = 'unknown data';
                      cameraController.start();
                    }
                  } else {
                    if (authController.scannerResult.value.type
                        .containsIgnoreCase("device")) {
                      _processDeviceCode(barcode.rawValue!);
                    } else {
                      qrcode = 'unknown data';
                      cameraController.start();
                    }
                  }
                }
              } else {
                qrcode = 'empty data scanned';
                cameraController.start();
              }
            } catch (e) {
              qrcode = 'invalid data scanned';
              cameraController.start();
              handleException(e);
            }

UI Implementation ​

Scanner View ​

dart
return Scaffold(
  appBar: AppBar(
    title: Text(title),
  ),
  body: Obx(
      () => RotatedBox(quarterTurns: rotationValue.value, child: scanner)),
);

Resource Management ​

Cleanup Methods ​

dart
@override
void deactivate() {
  super.deactivate();
  _cancelTimer();
  cameraController.stop();
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.landscapeLeft,
    DeviceOrientation.landscapeRight,
  ]);
}

@override
void dispose() {
  cameraController.dispose();
  super.dispose();
}

Dependencies ​

  • mobile_scanner: QR code scanning
  • native_device_orientation: Device orientation handling
  • get: State management
  • flutter/services.dart: System services

Styling ​

  • Uses consistent app bar styling
  • Implements responsive design
  • Maintains proper orientation
  • Provides clear visual feedback

Released under the MIT License.