onInit method
override
Called immediately after the widget is allocated in memory. You might use this to initialize something for the controller.
Implementation
@override
void onInit() {
ISentrySpan span = _ready.startChild('init');
super.onInit();
_currentCall.value.init(getChat: _chatService.get);
HardwareKeyboard.instance.addHandler(_onKey);
if (PlatformUtils.isMobile && !PlatformUtils.isWeb) {
BackButtonInterceptor.add(_onBack, ifNotYetIntercepted: true);
}
speakerSwitched = RxBool(!PlatformUtils.isIOS);
fullscreen = RxBool(false);
minimized = RxBool(!PlatformUtils.isMobile && !WebUtils.isPopup);
isMobile = PlatformUtils.isMobile;
_hiddenTimer = Timer(const Duration(seconds: 1), () {
if (hidden.value) {
hidden.value = false;
refresh();
}
});
_applyRect(null);
_settingsRepository.getCallRect(_currentCall.value.chatId.value).then((v) {
if (hidden.value) {
hidden.value = false;
refresh();
}
_applyRect(v);
});
final double secondarySize = (size.shortestSide * secondaryRatio).clamp(
_minSHeight,
250,
);
secondaryWidth = RxDouble(secondarySize);
secondaryHeight = RxDouble(secondarySize);
_chatWorker = ever(_currentCall.value.chatId, (ChatId id) {
final FutureOr<RxChat?> chatOrFuture = _chatService.get(id);
if (chatOrFuture is RxChat?) {
_updateChat(chatOrFuture);
} else {
chatOrFuture.then(_updateChat);
}
});
_stateWorker = ever(state, (OngoingCallState state) {
switch (state) {
case OngoingCallState.active:
if (_durationTimer == null) {
SchedulerBinding.instance.addPostFrameCallback((_) {
dockRect.value = dockKey.globalPaintBounds;
relocateSecondary();
});
DateTime begunAt = DateTime.now();
_durationTimer = FixedTimer.periodic(
const Duration(seconds: 1),
() {
duration.value = DateTime.now().difference(begunAt);
if (hoveredParticipantTimeout > 0 &&
draggedRenderer.value == null) {
--hoveredParticipantTimeout;
if (hoveredParticipantTimeout == 0) {
hoveredParticipant.value = null;
isCursorHidden.value = true;
}
}
},
);
keepUi();
_ensureNotEarpiece();
}
break;
case OngoingCallState.joining:
SchedulerBinding.instance.addPostFrameCallback(
(_) => SchedulerBinding.instance.addPostFrameCallback(
(_) => relocateSecondary(),
),
);
break;
case OngoingCallState.pending:
case OngoingCallState.local:
case OngoingCallState.ended:
// No-op.
break;
}
refresh();
});
_onFullscreenChange = PlatformUtils.onFullscreenChange.listen((bool v) {
fullscreen.value = v;
refresh();
});
_onWindowFocus = WebUtils.onWindowFocus.listen((e) {
if (!e) {
hoveredParticipant.value = null;
if (_uiTimer?.isActive != true) {
if (displayMore.isTrue) {
keepUi();
} else {
keepUi(false);
}
}
}
});
// Constructs a list of [CallButton]s from the provided [list] of [String]s.
List<CallButton> toButtons(List<String>? list) {
Set<CallButton>? persisted =
list
?.map((e) {
switch (e) {
case 'ScreenButton':
return ScreenButton(this);
case 'VideoButton':
return VideoButton(this);
case 'EndCallButton':
return EndCallButton(this);
case 'AudioButton':
return AudioButton(this);
case 'MoreButton':
return MoreButton(this);
case 'SettingsButton':
return SettingsButton(this);
case 'ParticipantsButton':
return ParticipantsButton(this);
case 'HandButton':
return HandButton(this);
case 'RemoteVideoButton':
return RemoteVideoButton(this);
case 'RemoteAudioButton':
return RemoteAudioButton(this);
}
})
.nonNulls
.toSet();
// Add default [CallButton]s, if none are persisted.
if (persisted?.isNotEmpty != true) {
persisted = {
ScreenButton(this),
VideoButton(this),
EndCallButton(this),
AudioButton(this),
MoreButton(this),
};
}
// Ensure [EndCallButton] is always in the list.
if (persisted!.whereType<EndCallButton>().isEmpty) {
persisted.add(EndCallButton(this));
}
// Ensure [MoreButton] is always in the list.
if (persisted.whereType<MoreButton>().isEmpty) {
persisted.add(MoreButton(this));
}
return persisted.toList();
}
buttons = RxList(
toButtons(_settingsRepository.applicationSettings.value?.callButtons),
);
panel = RxList([
SettingsButton(this),
ParticipantsButton(this),
HandButton(this),
ScreenButton(this),
RemoteVideoButton(this),
RemoteAudioButton(this),
VideoButton(this),
AudioButton(this),
]);
_buttonsWorker = ever(buttons, (List<CallButton> list) {
_settingsRepository.setCallButtons(
list.map((e) => e.runtimeType.toString()).toList(),
);
});
List<String>? previous =
_settingsRepository.applicationSettings.value?.callButtons;
_settingsWorker = ever(_settingsRepository.applicationSettings, (
ApplicationSettings? settings,
) {
if (!const ListEquality().equals(settings?.callButtons, previous)) {
if (settings != null) {
buttons.value = toButtons(settings.callButtons);
}
previous = settings?.callButtons;
}
});
_showUiWorker = ever(showUi, (bool showUi) {
if (displayMore.value && !showUi) {
displayMore.value = false;
}
});
_notificationsSubscription = _currentCall.value.notifications.listen((e) {
notifications.add(e);
_notificationTimers.add(
Timer(_notificationDuration, () => notifications.remove(e)),
);
});
_reconnectWorker = ever(_currentCall.value.connectionLost, (b) {
if (b) {
_reconnectAudio = AudioUtils.play(
AudioSource.asset('audio/$_reconnect'),
);
} else {
_reconnectAudio?.cancel();
}
});
if (PlatformUtils.isMobile && !PlatformUtils.isWeb) {
try {
_proximitySubscription = proximityEvents?.listen((e) {
Log.debug('[debug] proximityEvents: ${e.getValue()}');
});
} catch (e) {
Log.warning(
'Failed to initialize proximity sensor: $e',
'$runtimeType',
);
}
}
span.finish();
span = _ready.startChild('chat');
_initChat();
}