Skip to content

Overview ​

  • File: lib/views/contacts_page.dart

The contacts_page.dart file implements the contacts management screen of the HVC XR application. It provides functionality for viewing, selecting, calling, and messaging contacts. The page supports both individual and group interactions, with voice command capabilities for RealWear devices.

Class Structure ​

dart
class ContactsPage extends StatelessWidget {
  static const String routeName = '/ContactsPage';
  ContactsPage({Key? key}) : super(key: key);
  // Controller declarations
  // Methods
  // Build method
}

Dependencies ​

dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:hvc_xr/hlk_helpers/hlk_utils.dart';
import 'package:hvc_xr/main.dart';
import 'package:hvc_xr/widgets/contact_details_dialog.dart';
import 'package:hvc_xr/widgets/hvc_base_page.dart';
import 'package:permission_handler/permission_handler.dart';
// Additional imports for controllers, models, and widgets

Key Components ​

Controllers ​

The page uses several GetX controllers:

dart
final ContactsController contactsController = Get.find();
final MeetingsController meetingsController = Get.find();
final RealTimeController realTimeController = Get.find();
final MessagesController messagesController = Get.find();
final DigilensController digilensController = Get.find();

State Management ​

  • Uses GetX for state management
  • Implements reactive state with RxBool variables
  • Manages contact selection state
  • Handles pagination for contact lists

Contact Selection Management ​

Selection Methods ​

dart
void releaseSelections() {
  for (var c in contactsController.contacts) {
    c.isSelected = false;
  }
  contactsController.selected.clear();
  messagesController.messages.clear();
}

void onItemSelected(Contact contact, bool isSelected) {
  contact.isSelected = isSelected;
  if (isSelected) {
    contactsController.selected.add(contact);
  } else {
    contactsController.selected.remove(contact);
  }
}

Voice Command Integration ​

Contact Commander ​

dart
void applyContactCommander(Contact c) async {
  var call = 'call ${c.name.toLowerCase()}';
  var select = 'select ${c.name.toLowerCase()}';
  voiceCommandMap.clear();
  voiceCommandMap[call] = () => hvcDebounce(() => callContactByName(c), call);
  voiceCommandMap[getMethodFromCommand(call)] = () =>
      hvcDebounce(() => callContactByName(c), getMethodFromCommand(call));

  voiceCommandMap[select] =
      () => hvcDebounce(() => onItemSelected(c, !c.isSelected), select);
  voiceCommandMap[getMethodFromCommand(select)] = () => hvcDebounce(
      () => onItemSelected(c, !c.isSelected), getMethodFromCommand(select));

  await digilensController.loadPageCommands(routeName);
}

Call Functionality ​

Individual Call ​

dart
void callContactByName(Contact contact) async {
  contactsController.selected.add(contact);
  final callDto = InitCallDto(
    from: user.userId,
    fromName: user.name,
    targets: [contact.id],
    title: 'Meeting with ${user.name}',
    source: 'Headset',
    platform: 'Android',
  );

  await validatePermission(
      Permission.camera,
      () async => await validatePermission(Permission.microphone, () async {
            realTimeController.pageFrom = routeName;
            await realTimeController.makeCall(
                callDto, contact.name, true, contact.isGroup);
          }));

  releaseSelections();
}

Group Call ​

dart
void handleStartCall() async {
  logInfo('calling ...');
  if (contactsController.selected.length == 1) {
    // Individual call logic
  } else {
    // Group call logic
    final targets = contactsController.selected.map((ct) => ct.id).toList();
    final callDto = InitCallDto(
      from: user.userId,
      fromName: user.name,
      targets: targets,
      title: 'Group meeting with ${user.name}',
      platform: 'Android',
      source: 'HeadSet',
    );
    var isGroupCall = targets.length > 1 ||
        contactsController.selected.any((c) => c.isGroup);
    await validatePermission(
        Permission.camera,
        () async => await validatePermission(Permission.microphone, () async {
              realTimeController.pageFrom = routeName;
              await realTimeController.makeCall(
                  callDto, null, true, isGroupCall);
            }));

    releaseSelections();
  }
}

Messaging Functionality ​

dart
void handleMessage() {
  contactsController.showChat.value = true;
  messagesController.messages.clear();
  if (contactsController.selected.length == 1) {
    messagesController
        .loadChatMessagesForUser(contactsController.selected.first.id);
  } else {
    // todo load existing group chat and by the same occasion set groupId
  }
}

Contact Details Dialog ​

dart
void handleDetails(BuildContext context) {
  if (contactsController.selected.length == 1) {
    showDialog(
      context: context,
      builder: (ctx) => ContactDetailsDialog(
        contact: contactsController.selected.first,
        handleMessage: () {
          Get.back();
          contactsController.showChat.value = true;
          if (contactsController.selected.length == 1) {
            messagesController.loadChatMessagesForUser(
                contactsController.selected.first.id);
          }
        },
        handleCall: () async {
          // Call implementation
        },
      ),
    );
  }
}

UI Implementation ​

Base Page Structure ​

dart
return HvcBasePage(
  position: 1,
  pageTitle: 'Contacts',
  pageDescription: 'Select the people to participate in a meeting',
  showSearchBox: contactsController.showSearchBox,
  contactsForChat: contactsController.selectedIds,
  // Additional properties and handlers
);

Contact List ​

dart
Obx(
  () => ListView.builder(
      shrinkWrap: true,
      itemCount: contactsController.contacts.length,
      itemBuilder: (BuildContext context, int index) {
        final contact = contactsController.contacts[index];
        if (isDigiLens) applyContactCommander(contact);
        return ContactItem(
          selectByName: (newVal) => onItemSelected(
              contactsController.contacts[index], newVal!),
          callByName: () => callContactByName(contact),
          contact: contactsController.contacts[index],
          onTapHandler: () {
            // Dialog implementation
          },
          onSelected: (newVal) => onItemSelected(
              contactsController.contacts[index], newVal!),
        );
      }),
),

Selected Contacts Panel ​

dart
if (contactsController.selected.isNotEmpty)
  Positioned(
    right: 0,
    child: SelectedContacts(
      list: contactsController.selected,
      width: getWidth(0.35),
      height: getHeight(0.7),
      onCloseOrCancel: () {
        releaseSelections();
      },
      handleCall: handleStartCall,
      handleMessage: handleMessage,
      handleDetails: () => handleDetails(context),
    ),
  ),

Pagination ​

dart
handleNext: () async {
  contactsController.pageToShow.value = contactsController.page.value;
  contactsController.page.value = contactsController.page.value + 1;
  await contactsController.getContacts();
},
handlePrevious: () async {
  if (contactsController.page.value > 0) {
    contactsController.pageToShow.value = contactsController.page.value;
    contactsController.page.value = contactsController.page.value - 1;
    await contactsController.getContacts();
  }
},

Search Functionality ​

dart
handleSearch: (String newText) async {
  contactsController.name.value = newText;
  contactsController.page.value = 0;
  await contactsController.getContacts();
  contactsController.shouldReset.value = true;
},

Dependencies ​

  • get: State management
  • permission_handler: Permission management
  • hvc_xr/widgets: Custom widgets
  • hvc_xr/controllers: Application controllers
  • hvc_xr/models: Data models

Styling ​

  • Uses HvcBasePage for consistent layout
  • Implements responsive design with getWidth and getHeight
  • Uses custom widgets for contact items and selection panel
  • Maintains consistent styling across the application

Released under the MIT License.