call method

Future<void> call(
  1. ChatId chatId, {
  2. bool withAudio = true,
  3. bool withVideo = false,
  4. bool withScreen = false,
})

Starts an OngoingCall in a Chat with the given chatId.

Implementation

Future<void> call(
  ChatId chatId, {
  bool withAudio = true,
  bool withVideo = false,
  bool withScreen = false,
}) async {
  Log.debug(
    'call($chatId, $withAudio, $withVideo, $withScreen)',
    '$runtimeType',
  );

  final Rx<OngoingCall>? stored = _callsRepo[chatId];
  final WebStoredCall? webStored = WebUtils.getCall(chatId);
  final ChatCallDeviceId? webDevice = webStored?.deviceId;

  if (webDevice != null) {
    // Call seems to already exist in the Web, thus try to leave and remove
    // the existing one.
    WebUtils.removeCall(chatId);
    await _callsRepo.leave(chatId, webDevice);
  } else if (stored != null &&
      stored.value.state.value != OngoingCallState.ended) {
    // No-op, as already exists.
    return;
  }

  try {
    final Rx<OngoingCall> call = await _callsRepo.start(
      chatId,
      withAudio: withAudio,
      withVideo: withVideo,
      withScreen: withScreen,
    );

    if (isClosed) {
      call.value.dispose();
    } else {
      call.value.connect(this);
    }
  } on CallAlreadyJoinedException catch (e) {
    await _callsRepo.leave(chatId, e.deviceId);
    return await join(
      chatId,
      withAudio: withAudio,
      withVideo: withVideo,
      withScreen: withScreen,
    );
  } catch (e) {
    // If any other error occurs, it's guaranteed that the broken call will be
    // removed.
    _callsRepo.remove(chatId);
    rethrow;
  }
}