Appearance
Login Page Documentation
Overview
The LoginPage is a stateful widget that serves as the authentication gateway for the HVC XR application. It provides multiple login methods optimized for RealWear devices and handles device registration, authentication, and real-time communication.
Key Features
Authentication Methods:
- QR code scanning (both landscape and portrait modes)
- Rapid Connect for quick access
- Device enrollment for new devices
Device Management:
- Device registration and ping system
- Real-time device summoning
- Tenant-specific configuration
State Management:
- Reactive UI with GetX
- Persistent storage with GetStorage
- Lifecycle management
Class Structure
dart
class LoginPage extends StatefulWidget {
static const String routeName = '/LoginPage';
const LoginPage({Key? key}) : super(key: key);
@override
State<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage>
with WidgetsBindingObserver, RouteAware {
// State management and controllers
// Lifecycle methods
// Authentication methods
// UI building
}Dependencies
dart
// Core Flutter
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
// State Management
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
// Utilities
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:graphql/client.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:device_info_plus/device_info_plus.dart';
// App-specific
import '../controllers/auth_controller.dart';
import '../controllers/digilens_controller.dart';
import '../controllers/graphql_controller.dart';
import '../controllers/meetings_controller.dart';
import '../controllers/real_time_controller.dart';
import '../hlk_helpers/graphql_manager.dart';
import '../hlk_helpers/hlk_utils.dart';
import '../hlk_helpers/hlk_widgets.dart';
import '../models/core_models.dart';
import '../models/dto_models.dart';
import '../shared/common.dart';
import '../shared/constants.dart';
import '../shared/config.dart';
import '../widgets/logo_banner.dart';
import 'rapid_connect_page.dart';
import 'scanner_page.dart';
import 'new_scanner_page.dart';State Management
Controllers
dart
final storage = GetStorage();
final authController = Get.find<AuthController>();
final realTimeController = Get.find<RealTimeController>();
final digilensController = Get.find<DigilensController>();
final meetingsController = Get.find<MeetingsController>();Reactive State
dart
Rx<RegisteredDeviceData> registeredDevice = RegisteredDeviceData(...).obs;
RxBool showAddDeviceButton = true.obs;
RxBool isSubscribed = false.obs;
RxBool loading = false.obs;Lifecycle Management
Key Methods
dart
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
_initializeDeviceData();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
_pingDevice();
}
}
@override
void dispose() {
_pingTimer?.cancel();
_clearSubscriptions();
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}Authentication Flows
QR Code Scanning
- Validates camera permissions
- Sets appropriate device orientation
- Routes to scanner page based on device type:
ScannerPagefor Navigator 500NewScannerPagefor other devices
dart
onPressed: () async {
await validatePermission(Permission.camera, () async {
await _clearSubscriptions();
Get.toNamed(isNavigator500
? ScannerPage.routeName
: NewScannerPage.routeName);
});
}Rapid Connect
- Retrieves last used organization
- Initiates rapid connection
- Stores user data
- Initializes real-time controller
- Routes to
RapidConnectPage
dart
Future initRapidConnect(RxBool loading) async {
// Implementation details
}Device Enrollment
- Checks for existing device registration
- Handles new device setup
- Manages GraphQL subscriptions
dart
void _initializeDeviceData() async {
// Device registration logic
}Real-Time Communication
Device Summoning
dart
Future<void> _deviceSummoned() async {
// GraphQL subscription setup
}Device Ping
dart
void _startPingTimer() {
_pingTimer = Timer.periodic(const Duration(minutes: 15), (timer) {
_pingDevice();
});
}UI Components
Main Structure
dart
PageWithBackground(
assetImagePath: 'assets/images/hvc_xr_bg.jpeg',
child: Scaffold(
body: Stack(
children: [
// Logo and buttons
// Version info
// Device status indicator
],
),
),
)Buttons
Scan Code Button:
- Handles camera permission
- Manages device orientation
- Routes to appropriate scanner
Rapid Connect Button:
- Shows loading state
- Initiates rapid connection flow
Enroll Device Button:
- Conditionally shown
- Handles new device registration
Status Indicators
Connection Status:
- Green/red dot for subscription state
- Displays device and tenant info
Version Info:
- Shows app version and build number
- Positioned at bottom-left
Error Handling
- Permission validation
- Network error handling
- Device registration errors
- Subscription management
Data Models
RegisteredDeviceData
dart
class RegisteredDeviceData {
final String deviceName;
final int tenantId;
final String tenantName;
final String tenantDomain;
final String tenantUrl;
final String regRefId;
// Constructor and methods
}DeviceByIdResponse
dart
class DeviceByIdResponse {
final bool success;
final String message;
final int code;
final TenantDeviceData? data;
// JSON serialization
}Voice Command Support
dart
voiceCommandMap["rapidConnect"] = () => hvcDebounce(
() => initRapidConnect(loading),
"Init Rapid Connect",
duration: const Duration(milliseconds: 100));Best Practices
Resource Management:
- Proper subscription cleanup
- Timer cancellation
- Lifecycle awareness
Error Handling:
- Comprehensive try-catch blocks
- User-friendly error messages
- State recovery
Performance:
- Debounced actions
- Conditional rendering
- Efficient state updates
Usage Notes
- Requires camera permission for QR scanning
- Optimized for RealWear devices
- Supports both portrait and landscape orientations
- Handles both production and debug builds