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.