joinMeeting.ts1.8 KBView on GitHub
import type { CalendarEvent } from '../types/calendar-types';

/**
 * "Where is this meeting, and open it."
 *
 * Lifted verbatim out of `EventDetailsPopover` — the `meetLink` memo at :1388 and
 * `handleJoinMeet` at :2131 — because the Meetings tab's action row needs the same two
 * lines and a second copy would drift the moment conferencing stops meaning "the first
 * video entry point". The popover now calls these, so there is one derivation of the
 * link and one way to open it, not two that merely agree today.
 *
 * Note the deliberate asymmetry with `detectGoogleMeet` in `calendarFollowUpUtils`: that
 * one answers "did this event HAVE a Meet?" and sniffs location/description too, because
 * it is deciding whether a follow-up should be created with conferencing. This one
 * answers "what URL do I open right now?", and only a real entry point can answer that —
 * a description that merely mentions meet.google.com is not something you can join.
 */
export function meetingLinkFromEvent(event: CalendarEvent): string | null {
  const entryPoints = event.conferenceData?.entryPoints;
  if (!entryPoints) return null;
  const videoEntry = entryPoints.find((ep) => ep.entryPointType === 'video');
  return videoEntry?.uri || null;
}

/**
 * Open a meeting link in a new tab. Returns whether there was anything to open, so a
 * caller that renders its own affordance can stay honest about a linkless meeting rather
 * than presenting a button that silently does nothing.
 *
 * `noopener,noreferrer` is not optional: without it the conferencing tab gets a live
 * `window.opener` handle back into the mail client.
 */
export function joinMeeting(link: string | null | undefined): boolean {
  if (!link) return false;
  window.open(link, '_blank', 'noopener,noreferrer');
  return true;
}