Skip to content

Event Call Page

  • File: src/pages/private/events/[eventId]/index.svelte

Overview

The Event Call page manages video conferencing sessions within the application. It handles real-time communication, participant management, device configuration, and call states for virtual meetings.

Core Components

1. View Components

  • PrecallView: Pre-call setup and participant waiting room
  • CallView: Main video conference interface
  • MessageView: Status and error message display
  • LoadingView: Loading state interface

2. Page States

ts
export enum Page {
  Ringing, // Initial connection state
  PreCall, // Pre-meeting setup
  Call, // Active call session
  Message, // Information display
  Loading, // Loading state
}

Data Management

1. Event Data Structure

ts
interface Event {
  id: string;
  title: string;
  notes: string;
  startDate: Date;
  endDate: Date;
  sessionId: string;
  startTime: Date;
  endTime: Date;
  participants: {
    contactId: string;
    contact: {
      profileImageUrl: string;
      online: boolean;
      specialty: string;
      phoneNumber: string;
      email: string;
      firstName: string;
      lastName: string;
      timeOffset: string;
      id: string;
      username: string;
    };
  }[];
}

Core Functions

1. Event Data Fetching

svelte
async function getEvent(eventId) {
  const {data, error} = await query<{xs}>(`
    query {
      xs: events(where: { id: { eq: ${eventId}}}) {
        items {
          id, title, notes,
          startDate, endDate,
          sessionId, startTime, endTime,
          participants { ... }
        }
      }
    }
  `);

  // Process response and format data
  if (error) return { success: false, message: error.message, code: 400 };
  const evt = data.xs.items[0];
  if (!evt) return { success: false, message: "Event not found", code: 404 };

  // Format dates and participant data
  evt.startDate = getDateDetail(evt.startDate);
  evt.endDate = getDateDetail(evt.endDate);
  evt.participants = formatParticipants(evt.participants);

  return { success: true, data: evt };
}

2. WebSocket Communication

svelte
const url = `${wsServer}/calls/${eventId}`;
let ws = new WebSocket(url);

// WebSocket event handlers
ws.onopen = () => wsOpened = true;
ws.onclose = () => wsOpened = false;
ws.onmessage = (msg) => {
  let partitions = JSON.parse(msg.data)
    .filter(x => x.id > 0)
    .filter(x => x.id !== myId)
    .map(x => ({
      ...x,
      initials: getInitials(x.name)
    }))
    .reduce((s, x) => {
      if (x.page === "call") s[1].push(x)
      else s[0].push(x)
      return s
    }, [[], []]);

  precallUsers = partitions[0];
  incallUsers = partitions[1];
};

3. Call State Management

svelte
async function refresh() {
  // Wait for user info and connection
  if (!$userInfo || !connected()) {
    setTimeout(refresh, 100);
    return;
  }

  // Fetch event data
  const ret = await getEvent(eventId);
  if (!ret.success) {
    handleError(ret);
    return;
  }

  // Setup call configuration
  const meetingData = await getMeetingDetails(+eventId, null);
  if (!meetingData.success) {
    setLocalError(meetingData.message);
    return;
  }

  callConfig = meetingData.data;
  event = { ...ret.data };
  activePage = Page.PreCall;
}

Event Handlers

1. Call Control

svelte
function onJoinCall({detail}) {
  // Set device configurations
  selectedCamera = detail.selectedCamera;
  selectedMic = detail.selectedMic;
  selectedSpeaker = detail.selectedSpeaker;
  micOn = detail.micOn;
  cameraOn = detail.cameraOn;
  noAudio = detail.noAudio;
  noVideo = detail.noVideo;

  activePage = Page.Call;
}

function onDisconnected() {
  errorMessage = "Call Disconnected";
  isError = false;
  activePage = Page.Message;
  countdown = window.opener ? defaultCcountdown : 0;
}

Lifecycle Management

svelte
onMount(async () => {
  // Initialize call
  await refresh();

  // Load peripheral devices
  try {
    const ret = await loadPeripherals();
    if (ret.success) {
      peripherals = ret.data;
    }
  } catch (e) {
    showError(e?.message || e);
  }
});

onDestroy(() => {
  ws.close();
});

UI Structure

svelte
<div class="bg-[#2d4e8c] flex-grow grid place-items-center w-screen h-screen">
  <div class="w-full h-full p-3 lg:py-6 overflow-hidden">
    {#if activePage === Page.PreCall}
      <PrecallView {event} on:cancel={onCancel} on:joinCall={onJoinCall}
        {precallUsers} {incallUsers}/>
    {:else if activePage === Page.Call}
      <CallView {event} config={callConfig} {contacts} {selectedCamera}
        {selectedMic} {selectedSpeaker} {micOn} {cameraOn}
        on:disconnected={onDisconnected} {devices} {noAudio} {noVideo}
        {cnt} {peripherals}/>
    {:else if activePage === Page.Message}
      <MessageView {message} {isError} {countdown}
        on:countDownOver={_ => window.close()}/>
    {:else if activePage === Page.Loading}
      <LoadingView />
    {/if}
  </div>
</div>

Released under the MIT License.