fix(videocall): apply PR review fixes and add i18n translations
- Replace setState with FutureBuilder in VideoViewWidget - Remove comments from datasource impl - Replace GetIt.I with ref.read(provider) in controllers - Fix state comparison using isTalking getter - Add hangUp/stopAudio/stopCamera cleanup on dispose - Remove duplicate SafeArea from IncomingCallOverlay - Add missedCall error event to enum - Replace Colors.white70 with theme colorScheme - Move VIDEOCALL_INTEGRATION.md to apps/mobile_app/docs/ - Gitignore config JSON files with app keys - Add 28 i18n keys in 6 locales for all videocall strings - Map error events to specific i18n messages
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -24,6 +24,9 @@
|
|||||||
*.iml
|
*.iml
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|
||||||
|
# App config (contains API keys, passed via --dart-define-from-file)
|
||||||
|
apps/mobile_app/config/*.json
|
||||||
|
|
||||||
# macOS
|
# macOS
|
||||||
.DS_Store
|
.DS_Store
|
||||||
**/.DS_Store
|
**/.DS_Store
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"env": "development",
|
|
||||||
"apiBaseUrl": "https://api-neki-b2b.neki.es/gateway/api/",
|
|
||||||
"apiOrigin": "https://neki-b2b.neki.es",
|
|
||||||
"wsUrl": "wss://api-neki-b2b.neki.es/websocket",
|
|
||||||
"juphoonAppKey": "9efcf2d889dc8a0320925096"
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"env": "production",
|
|
||||||
"apiBaseUrl": "https://api-platform.savefamily.app/gateway/api/",
|
|
||||||
"apiOrigin": "https://platform.savefamily.app",
|
|
||||||
"wsUrl": "wss://api-platform.savefamily.app/websocket",
|
|
||||||
"juphoonAppKey": "9efcf2d889dc8a0320925096"
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"env": "staging",
|
|
||||||
"apiBaseUrl": "https://api-platform.pre.savefamilygps.net/gateway/api/",
|
|
||||||
"apiOrigin": "https://platform.pre.savefamilygps.net",
|
|
||||||
"wsUrl": "wss://api-platform.pre.savefamilygps.net/websocket",
|
|
||||||
"juphoonAppKey": "9efcf2d889dc8a0320925096"
|
|
||||||
}
|
|
||||||
@@ -13,15 +13,12 @@ class VideocallSignalingDatasourceImpl implements VideocallSignalingDatasource {
|
|||||||
required String appAccount,
|
required String appAccount,
|
||||||
required String roomNumber,
|
required String roomNumber,
|
||||||
}) async {
|
}) async {
|
||||||
// TODO: Implement when backend API spec is available
|
|
||||||
// await _repository.post('/devices/$deviceId/videocall/initiate', body: {...});
|
|
||||||
throw UnimplementedError(
|
throw UnimplementedError(
|
||||||
'Backend signaling API not yet available. Waiting for endpoint spec.');
|
'Backend signaling API not yet available. Waiting for endpoint spec.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> cancelCall({required String deviceId}) async {
|
Future<void> cancelCall({required String deviceId}) async {
|
||||||
// TODO: Implement when backend API spec is available
|
|
||||||
throw UnimplementedError(
|
throw UnimplementedError(
|
||||||
'Backend signaling API not yet available. Waiting for endpoint spec.');
|
'Backend signaling API not yet available. Waiting for endpoint spec.');
|
||||||
}
|
}
|
||||||
@@ -31,14 +28,12 @@ class VideocallSignalingDatasourceImpl implements VideocallSignalingDatasource {
|
|||||||
required String deviceId,
|
required String deviceId,
|
||||||
required String roomNumber,
|
required String roomNumber,
|
||||||
}) async {
|
}) async {
|
||||||
// TODO: Implement when backend API spec is available
|
|
||||||
throw UnimplementedError(
|
throw UnimplementedError(
|
||||||
'Backend signaling API not yet available. Waiting for endpoint spec.');
|
'Backend signaling API not yet available. Waiting for endpoint spec.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<int> getRoomParticipantCount({required String roomNumber}) async {
|
Future<int> getRoomParticipantCount({required String roomNumber}) async {
|
||||||
// TODO: Implement when backend API spec is available
|
|
||||||
throw UnimplementedError(
|
throw UnimplementedError(
|
||||||
'Backend signaling API not yet available. Waiting for endpoint spec.');
|
'Backend signaling API not yet available. Waiting for endpoint spec.');
|
||||||
}
|
}
|
||||||
@@ -49,7 +44,6 @@ class VideocallSignalingDatasourceImpl implements VideocallSignalingDatasource {
|
|||||||
required int count,
|
required int count,
|
||||||
required int type,
|
required int type,
|
||||||
}) async {
|
}) async {
|
||||||
// TODO: Implement when backend API spec is available
|
|
||||||
throw UnimplementedError(
|
throw UnimplementedError(
|
||||||
'Backend signaling API not yet available. Waiting for endpoint spec.');
|
'Backend signaling API not yet available. Waiting for endpoint spec.');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ enum VideocallErrorEvent {
|
|||||||
authentication,
|
authentication,
|
||||||
callStart,
|
callStart,
|
||||||
callAnswer,
|
callAnswer,
|
||||||
|
missedCall,
|
||||||
network,
|
network,
|
||||||
cameraPermission,
|
cameraPermission,
|
||||||
microphonePermission,
|
microphonePermission,
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:get_it/get_it.dart';
|
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:videocall_sdk/videocall_sdk.dart';
|
import 'package:videocall_sdk/videocall_sdk.dart';
|
||||||
|
|
||||||
@@ -28,8 +27,8 @@ class GroupCallController extends _$GroupCallController {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
GroupCallState build() {
|
GroupCallState build() {
|
||||||
_channelService = GetIt.I<VideocallChannelService>();
|
_channelService = ref.read(videocallChannelServiceProvider);
|
||||||
_deviceService = GetIt.I<VideocallDeviceService>();
|
_deviceService = ref.read(videocallDeviceServiceProvider);
|
||||||
|
|
||||||
ref.onDispose(_disposeSubscriptions);
|
ref.onDispose(_disposeSubscriptions);
|
||||||
_subscribeToStreams();
|
_subscribeToStreams();
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ final class GroupCallControllerProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
String _$groupCallControllerHash() =>
|
String _$groupCallControllerHash() =>
|
||||||
r'c8528072cb1b6d2bb15d50b199405938e7d3acd0';
|
r'0d3c5bd234ef3ed76b0b0f7666ddb73c8b98be55';
|
||||||
|
|
||||||
abstract class _$GroupCallController extends $Notifier<GroupCallState> {
|
abstract class _$GroupCallController extends $Notifier<GroupCallState> {
|
||||||
GroupCallState build();
|
GroupCallState build();
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:get_it/get_it.dart';
|
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:sf_shared/sf_shared.dart';
|
import 'package:sf_shared/sf_shared.dart';
|
||||||
import 'package:videocall_sdk/videocall_sdk.dart' hide VideocallState;
|
import 'package:videocall_sdk/videocall_sdk.dart' hide VideocallState;
|
||||||
@@ -25,10 +24,10 @@ class VideocallController extends _$VideocallController {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
VideocallState build() {
|
VideocallState build() {
|
||||||
_manager = GetIt.I<VideocallSdkManager>();
|
_manager = ref.read(videocallManagerProvider);
|
||||||
_callService = GetIt.I<VideocallCallService>();
|
_callService = ref.read(videocallCallServiceProvider);
|
||||||
_deviceService = GetIt.I<VideocallDeviceService>();
|
_deviceService = ref.read(videocallDeviceServiceProvider);
|
||||||
_client = GetIt.I<VideocallClient>();
|
_client = ref.read(videocallClientProvider);
|
||||||
|
|
||||||
final device = ref.read(selectedDeviceProvider).value;
|
final device = ref.read(selectedDeviceProvider).value;
|
||||||
final deviceId = device?.identificator ?? '';
|
final deviceId = device?.identificator ?? '';
|
||||||
@@ -79,18 +78,17 @@ class VideocallController extends _$VideocallController {
|
|||||||
|
|
||||||
void _subscribeToStreams() {
|
void _subscribeToStreams() {
|
||||||
_callAddSub = _callService.callItemAddStream.listen(_onCallItemAdd);
|
_callAddSub = _callService.callItemAddStream.listen(_onCallItemAdd);
|
||||||
_callUpdateSub =
|
_callUpdateSub = _callService.callItemUpdateStream.listen(
|
||||||
_callService.callItemUpdateStream.listen(_onCallItemUpdate);
|
_onCallItemUpdate,
|
||||||
_callRemoveSub =
|
);
|
||||||
_callService.callItemRemoveStream.listen(_onCallItemRemove);
|
_callRemoveSub = _callService.callItemRemoveStream.listen(
|
||||||
|
_onCallItemRemove,
|
||||||
|
);
|
||||||
_missedCallSub = _callService.missedCallStream.listen(_onMissedCall);
|
_missedCallSub = _callService.missedCallStream.listen(_onMissedCall);
|
||||||
_clientStateSub = _client.stateStream.listen(_onClientStateChange);
|
_clientStateSub = _client.stateStream.listen(_onClientStateChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> login({
|
Future<bool> login({required String userId, required String password}) async {
|
||||||
required String userId,
|
|
||||||
required String password,
|
|
||||||
}) async {
|
|
||||||
final ok = await _client.login(userId: userId, password: password);
|
final ok = await _client.login(userId: userId, password: password);
|
||||||
if (!ref.mounted) return false;
|
if (!ref.mounted) return false;
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
@@ -103,8 +101,9 @@ class VideocallController extends _$VideocallController {
|
|||||||
|
|
||||||
Future<void> startCall(String remoteUserId) async {
|
Future<void> startCall(String remoteUserId) async {
|
||||||
final device = ref.read(selectedDeviceProvider).value;
|
final device = ref.read(selectedDeviceProvider).value;
|
||||||
final targetUserId =
|
final targetUserId = remoteUserId.isNotEmpty
|
||||||
remoteUserId.isNotEmpty ? remoteUserId : 'w_${device?.imei ?? ''}';
|
? remoteUserId
|
||||||
|
: 'w_${device?.imei ?? ''}';
|
||||||
|
|
||||||
state = state.copyWith(
|
state = state.copyWith(
|
||||||
remoteUserId: targetUserId,
|
remoteUserId: targetUserId,
|
||||||
@@ -252,7 +251,7 @@ class VideocallController extends _$VideocallController {
|
|||||||
if (!ref.mounted) return;
|
if (!ref.mounted) return;
|
||||||
state = state.copyWith(currentCall: item);
|
state = state.copyWith(currentCall: item);
|
||||||
|
|
||||||
final isTalking = item.state.name == 'talking';
|
final isTalking = item.isTalking;
|
||||||
|
|
||||||
if (isTalking && state.screenMode != VideocallScreenMode.inCall) {
|
if (isTalking && state.screenMode != VideocallScreenMode.inCall) {
|
||||||
state = state.copyWith(
|
state = state.copyWith(
|
||||||
@@ -293,9 +292,7 @@ class VideocallController extends _$VideocallController {
|
|||||||
|
|
||||||
void _onMissedCall(VideocallItem item) {
|
void _onMissedCall(VideocallItem item) {
|
||||||
if (!ref.mounted) return;
|
if (!ref.mounted) return;
|
||||||
state = state.copyWith(
|
state = state.copyWith(errorEvent: VideocallErrorEvent.missedCall);
|
||||||
errorEvent: VideocallErrorEvent.callStart,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onClientStateChange(VideocallClientState clientState) {
|
void _onClientStateChange(VideocallClientState clientState) {
|
||||||
@@ -319,5 +316,10 @@ class VideocallController extends _$VideocallController {
|
|||||||
_callRemoveSub?.cancel();
|
_callRemoveSub?.cancel();
|
||||||
_missedCallSub?.cancel();
|
_missedCallSub?.cancel();
|
||||||
_clientStateSub?.cancel();
|
_clientStateSub?.cancel();
|
||||||
|
if (state.screenMode != VideocallScreenMode.idle) {
|
||||||
|
_callService.hangUp();
|
||||||
|
_deviceService.stopAudio();
|
||||||
|
_deviceService.stopCamera();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ final class VideocallControllerProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
String _$videocallControllerHash() =>
|
String _$videocallControllerHash() =>
|
||||||
r'2fc967b9e44ca13586fd36e0d3eaab1014d52821';
|
r'910674a27ecef98e5df917d193f97fca1c60ac02';
|
||||||
|
|
||||||
abstract class _$VideocallController extends $Notifier<VideocallState> {
|
abstract class _$VideocallController extends $Notifier<VideocallState> {
|
||||||
VideocallState build();
|
VideocallState build();
|
||||||
|
|||||||
@@ -42,15 +42,14 @@ class _VideocallScreenState extends ConsumerState<VideocallScreen> {
|
|||||||
(_, next) {
|
(_, next) {
|
||||||
if (next == null) return;
|
if (next == null) return;
|
||||||
final key = switch (next) {
|
final key = switch (next) {
|
||||||
VideocallErrorEvent.sdkInitialization ||
|
VideocallErrorEvent.sdkInitialization => I18n.videocallErrorSdkInit,
|
||||||
VideocallErrorEvent.authentication ||
|
VideocallErrorEvent.authentication => I18n.videocallErrorAuth,
|
||||||
VideocallErrorEvent.callStart ||
|
VideocallErrorEvent.callStart => I18n.videocallErrorCallStart,
|
||||||
VideocallErrorEvent.callAnswer ||
|
VideocallErrorEvent.callAnswer => I18n.videocallErrorCallAnswer,
|
||||||
VideocallErrorEvent.cameraPermission ||
|
VideocallErrorEvent.missedCall => I18n.videocallErrorMissedCall,
|
||||||
VideocallErrorEvent.microphonePermission ||
|
VideocallErrorEvent.cameraPermission => I18n.videocallErrorCamera,
|
||||||
VideocallErrorEvent.network ||
|
VideocallErrorEvent.microphonePermission => I18n.videocallErrorMic,
|
||||||
VideocallErrorEvent.generic =>
|
VideocallErrorEvent.network || VideocallErrorEvent.generic => I18n.errorGeneric,
|
||||||
I18n.errorGeneric,
|
|
||||||
};
|
};
|
||||||
showErrorDialog(context, key);
|
showErrorDialog(context, key);
|
||||||
vm.clearError();
|
vm.clearError();
|
||||||
@@ -109,7 +108,7 @@ class _IdleView extends StatelessWidget {
|
|||||||
CircularProgressIndicator(color: colorScheme.onSurface),
|
CircularProgressIndicator(color: colorScheme.onSurface),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Text(
|
Text(
|
||||||
'Inicializando SDK...',
|
context.translate(I18n.videocallInitializingSdk),
|
||||||
style: TextStyle(color: colorScheme.onSurface.withValues(alpha: 0.7)),
|
style: TextStyle(color: colorScheme.onSurface.withValues(alpha: 0.7)),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -125,7 +124,7 @@ class _IdleView extends StatelessWidget {
|
|||||||
Icon(Icons.videocam, color: colorScheme.onSurface, size: 64),
|
Icon(Icons.videocam, color: colorScheme.onSurface, size: 64),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
Text(
|
Text(
|
||||||
'Videollamada',
|
context.translate(I18n.videocallTitle),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: colorScheme.onSurface,
|
color: colorScheme.onSurface,
|
||||||
fontSize: 24,
|
fontSize: 24,
|
||||||
@@ -137,7 +136,7 @@ class _IdleView extends StatelessWidget {
|
|||||||
controller: controller,
|
controller: controller,
|
||||||
style: TextStyle(color: colorScheme.onSurface),
|
style: TextStyle(color: colorScheme.onSurface),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: 'User ID del destinatario',
|
hintText: context.translate(I18n.videocallRecipientUserId),
|
||||||
hintStyle: TextStyle(color: colorScheme.onSurface.withValues(alpha: 0.38)),
|
hintStyle: TextStyle(color: colorScheme.onSurface.withValues(alpha: 0.38)),
|
||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(color: colorScheme.onSurface.withValues(alpha: 0.24)),
|
borderSide: BorderSide(color: colorScheme.onSurface.withValues(alpha: 0.24)),
|
||||||
@@ -162,7 +161,7 @@ class _IdleView extends StatelessWidget {
|
|||||||
vm.startCall(userId);
|
vm.startCall(userId);
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.videocam),
|
icon: const Icon(Icons.videocam),
|
||||||
label: const Text('Iniciar videollamada'),
|
label: Text(context.translate(I18n.videocallStart)),
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: context.sfColors.legacyPrimary,
|
backgroundColor: context.sfColors.legacyPrimary,
|
||||||
foregroundColor: colorScheme.onPrimary,
|
foregroundColor: colorScheme.onPrimary,
|
||||||
@@ -185,7 +184,7 @@ class _IdleView extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
if (state.localUserId.isNotEmpty)
|
if (state.localUserId.isNotEmpty)
|
||||||
Text(
|
Text(
|
||||||
'Logged in as: ${state.localUserId}',
|
context.translate(I18n.videocallLoggedInAs, args: {'userId': state.localUserId}),
|
||||||
style: TextStyle(color: colorScheme.onSurface.withValues(alpha: 0.38), fontSize: 12),
|
style: TextStyle(color: colorScheme.onSurface.withValues(alpha: 0.38), fontSize: 12),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -252,7 +251,7 @@ class _InCallView extends StatelessWidget {
|
|||||||
Icon(Icons.person, color: colorScheme.onSurface.withValues(alpha: 0.24), size: 96),
|
Icon(Icons.person, color: colorScheme.onSurface.withValues(alpha: 0.24), size: 96),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Text(
|
Text(
|
||||||
'Esperando video remoto...',
|
context.translate(I18n.videocallWaitingRemoteVideo),
|
||||||
style: TextStyle(color: colorScheme.onSurface.withValues(alpha: 0.38)),
|
style: TextStyle(color: colorScheme.onSurface.withValues(alpha: 0.38)),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:sf_localizations/sf_localizations.dart';
|
||||||
|
|
||||||
class CallControlsWidget extends StatelessWidget {
|
class CallControlsWidget extends StatelessWidget {
|
||||||
const CallControlsWidget({
|
const CallControlsWidget({
|
||||||
@@ -29,7 +30,7 @@ class CallControlsWidget extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
_ControlButton(
|
_ControlButton(
|
||||||
icon: isMicEnabled ? Icons.mic : Icons.mic_off,
|
icon: isMicEnabled ? Icons.mic : Icons.mic_off,
|
||||||
label: isMicEnabled ? 'Mic On' : 'Mic Off',
|
label: context.translate(isMicEnabled ? I18n.videocallMicOn : I18n.videocallMicOff),
|
||||||
isActive: isMicEnabled,
|
isActive: isMicEnabled,
|
||||||
onPressed: onToggleMic,
|
onPressed: onToggleMic,
|
||||||
),
|
),
|
||||||
@@ -37,19 +38,19 @@ class CallControlsWidget extends StatelessWidget {
|
|||||||
icon: isSpeakerEnabled
|
icon: isSpeakerEnabled
|
||||||
? Icons.volume_up
|
? Icons.volume_up
|
||||||
: Icons.volume_off,
|
: Icons.volume_off,
|
||||||
label: isSpeakerEnabled ? 'Speaker' : 'Earpiece',
|
label: context.translate(isSpeakerEnabled ? I18n.videocallSpeaker : I18n.videocallEarpiece),
|
||||||
isActive: isSpeakerEnabled,
|
isActive: isSpeakerEnabled,
|
||||||
onPressed: onToggleSpeaker,
|
onPressed: onToggleSpeaker,
|
||||||
),
|
),
|
||||||
_ControlButton(
|
_ControlButton(
|
||||||
icon: Icons.cameraswitch,
|
icon: Icons.cameraswitch,
|
||||||
label: isFrontCamera ? 'Front' : 'Back',
|
label: context.translate(isFrontCamera ? I18n.videocallCameraFront : I18n.videocallCameraBack),
|
||||||
isActive: true,
|
isActive: true,
|
||||||
onPressed: onSwitchCamera,
|
onPressed: onSwitchCamera,
|
||||||
),
|
),
|
||||||
_ControlButton(
|
_ControlButton(
|
||||||
icon: Icons.call_end,
|
icon: Icons.call_end,
|
||||||
label: 'Hang Up',
|
label: context.translate(I18n.videocallHangUp),
|
||||||
isActive: false,
|
isActive: false,
|
||||||
isDestructive: true,
|
isDestructive: true,
|
||||||
onPressed: onHangUp,
|
onPressed: onHangUp,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:sf_localizations/sf_localizations.dart';
|
||||||
|
|
||||||
import '../../domain/entities/videocall_error.dart';
|
import '../../domain/entities/videocall_error.dart';
|
||||||
|
|
||||||
@@ -17,8 +18,8 @@ class CallStatusIndicator extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final (text, showCancel) = switch (screenMode) {
|
final (text, showCancel) = switch (screenMode) {
|
||||||
VideocallScreenMode.outgoing => ('Llamando a $remoteUserId...', true),
|
VideocallScreenMode.outgoing => (context.translate(I18n.videocallCalling, args: {'userId': remoteUserId}), true),
|
||||||
VideocallScreenMode.incoming => ('$remoteUserId te está llamando', false),
|
VideocallScreenMode.incoming => (context.translate(I18n.videocallUserCalling, args: {'userId': remoteUserId}), false),
|
||||||
_ => ('', false),
|
_ => ('', false),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:sf_localizations/sf_localizations.dart';
|
||||||
|
|
||||||
class IncomingCallOverlay extends StatelessWidget {
|
class IncomingCallOverlay extends StatelessWidget {
|
||||||
const IncomingCallOverlay({
|
const IncomingCallOverlay({
|
||||||
@@ -20,7 +21,6 @@ class IncomingCallOverlay extends StatelessWidget {
|
|||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
color: colorScheme.surface,
|
color: colorScheme.surface,
|
||||||
child: SafeArea(
|
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
@@ -32,7 +32,7 @@ class IncomingCallOverlay extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
Text(
|
Text(
|
||||||
isVideo ? 'Videollamada entrante' : 'Llamada entrante',
|
context.translate(isVideo ? I18n.videocallIncomingVideo : I18n.videocallIncomingAudio),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: colorScheme.onSurface.withValues(alpha: 0.7),
|
color: colorScheme.onSurface.withValues(alpha: 0.7),
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
@@ -56,13 +56,13 @@ class IncomingCallOverlay extends StatelessWidget {
|
|||||||
_ActionButton(
|
_ActionButton(
|
||||||
icon: Icons.call_end,
|
icon: Icons.call_end,
|
||||||
color: colorScheme.error,
|
color: colorScheme.error,
|
||||||
label: 'Rechazar',
|
label: context.translate(I18n.videocallReject),
|
||||||
onPressed: onReject,
|
onPressed: onReject,
|
||||||
),
|
),
|
||||||
_ActionButton(
|
_ActionButton(
|
||||||
icon: isVideo ? Icons.videocam : Icons.call,
|
icon: isVideo ? Icons.videocam : Icons.call,
|
||||||
color: Colors.green,
|
color: Colors.green,
|
||||||
label: 'Aceptar',
|
label: context.translate(I18n.videocallAccept),
|
||||||
onPressed: onAccept,
|
onPressed: onAccept,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -70,7 +70,6 @@ class IncomingCallOverlay extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:sf_localizations/sf_localizations.dart';
|
||||||
|
|
||||||
import '../../domain/entities/videocall_participant.dart';
|
import '../../domain/entities/videocall_participant.dart';
|
||||||
import 'participant_tile_widget.dart';
|
import 'participant_tile_widget.dart';
|
||||||
@@ -14,10 +15,12 @@ class ParticipantGridWidget extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (participants.isEmpty) {
|
if (participants.isEmpty) {
|
||||||
return const Center(
|
return Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
'Esperando participantes...',
|
context.translate(I18n.videocallWaitingParticipants),
|
||||||
style: TextStyle(color: Colors.white70),
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.onSurface.withValues(alpha: 0.7),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:sf_localizations/sf_localizations.dart';
|
||||||
|
|
||||||
import '../../domain/entities/videocall_participant.dart';
|
import '../../domain/entities/videocall_participant.dart';
|
||||||
import 'video_view_widget.dart';
|
import 'video_view_widget.dart';
|
||||||
@@ -52,7 +53,7 @@ class ParticipantTileWidget extends StatelessWidget {
|
|||||||
child: Icon(Icons.mic_off, color: colorScheme.error, size: 14),
|
child: Icon(Icons.mic_off, color: colorScheme.error, size: 14),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
participant.isSelf ? 'Tú' : participant.userId,
|
participant.isSelf ? context.translate(I18n.videocallYou) : participant.userId,
|
||||||
style: TextStyle(color: colorScheme.onSurface, fontSize: 12),
|
style: TextStyle(color: colorScheme.onSurface, fontSize: 12),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import 'dart:io';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:videocall_sdk/videocall_sdk.dart';
|
import 'package:videocall_sdk/videocall_sdk.dart';
|
||||||
|
|
||||||
class VideoViewWidget extends StatefulWidget {
|
class VideoViewWidget extends StatelessWidget {
|
||||||
const VideoViewWidget({
|
const VideoViewWidget({
|
||||||
super.key,
|
super.key,
|
||||||
required this.canvas,
|
required this.canvas,
|
||||||
@@ -17,51 +17,26 @@ class VideoViewWidget extends StatefulWidget {
|
|||||||
final double height;
|
final double height;
|
||||||
final BoxFit fit;
|
final BoxFit fit;
|
||||||
|
|
||||||
@override
|
Future<Widget> _buildVideoView() {
|
||||||
State<VideoViewWidget> createState() => _VideoViewWidgetState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _VideoViewWidgetState extends State<VideoViewWidget> {
|
|
||||||
Widget? _videoWidget;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_initVideoView();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void didUpdateWidget(VideoViewWidget oldWidget) {
|
|
||||||
super.didUpdateWidget(oldWidget);
|
|
||||||
if (oldWidget.canvas.videoCanvasId != widget.canvas.videoCanvasId) {
|
|
||||||
_initVideoView();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _initVideoView() async {
|
|
||||||
final Widget videoWidget;
|
|
||||||
if (Platform.isIOS) {
|
if (Platform.isIOS) {
|
||||||
videoWidget = await widget.canvas.getIOSVideoView(
|
return canvas.getIOSVideoView((_) {}, width, height);
|
||||||
(viewId) {},
|
|
||||||
widget.width,
|
|
||||||
widget.height,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
videoWidget = await widget.canvas.getAndroidVideoView();
|
|
||||||
}
|
|
||||||
if (mounted) {
|
|
||||||
setState(() => _videoWidget = videoWidget);
|
|
||||||
}
|
}
|
||||||
|
return canvas.getAndroidVideoView();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
width: widget.width,
|
width: width,
|
||||||
height: widget.height,
|
height: height,
|
||||||
child: _videoWidget ??
|
child: FutureBuilder<Widget>(
|
||||||
const Center(
|
future: _buildVideoView(),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.hasData) return snapshot.data!;
|
||||||
|
return const Center(
|
||||||
child: CircularProgressIndicator(strokeWidth: 2),
|
child: CircularProgressIndicator(strokeWidth: 2),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -683,6 +683,34 @@
|
|||||||
"locationRevealSkip": "Überspringen",
|
"locationRevealSkip": "Überspringen",
|
||||||
"locationDeleteGeofenceConfirm": "Möchten Sie diese sichere Zone wirklich löschen?",
|
"locationDeleteGeofenceConfirm": "Möchten Sie diese sichere Zone wirklich löschen?",
|
||||||
"locationDeleteFrequentPlaceConfirm": "Möchten Sie diesen häufigen Ort wirklich löschen?",
|
"locationDeleteFrequentPlaceConfirm": "Möchten Sie diesen häufigen Ort wirklich löschen?",
|
||||||
|
"videocallTitle": "Videoanruf",
|
||||||
|
"videocallInitializingSdk": "SDK wird initialisiert...",
|
||||||
|
"videocallRecipientUserId": "Benutzer-ID des Empfängers",
|
||||||
|
"videocallStart": "Videoanruf starten",
|
||||||
|
"videocallLoggedInAs": "Angemeldet als: {userId}",
|
||||||
|
"videocallCalling": "{userId} wird angerufen...",
|
||||||
|
"videocallUserCalling": "{userId} ruft dich an",
|
||||||
|
"videocallIncomingVideo": "Eingehender Videoanruf",
|
||||||
|
"videocallIncomingAudio": "Eingehender Anruf",
|
||||||
|
"videocallReject": "Ablehnen",
|
||||||
|
"videocallAccept": "Annehmen",
|
||||||
|
"videocallMicOn": "Mikro an",
|
||||||
|
"videocallMicOff": "Mikro aus",
|
||||||
|
"videocallSpeaker": "Lautsprecher",
|
||||||
|
"videocallEarpiece": "Hörer",
|
||||||
|
"videocallCameraFront": "Vorne",
|
||||||
|
"videocallCameraBack": "Hinten",
|
||||||
|
"videocallHangUp": "Auflegen",
|
||||||
|
"videocallWaitingParticipants": "Warten auf Teilnehmer...",
|
||||||
|
"videocallWaitingRemoteVideo": "Warten auf Remote-Video...",
|
||||||
|
"videocallYou": "Du",
|
||||||
|
"videocallErrorSdkInit": "Fehler beim Initialisieren des Videoanrufs",
|
||||||
|
"videocallErrorAuth": "Authentifizierungsfehler beim Videoanruf",
|
||||||
|
"videocallErrorCallStart": "Fehler beim Starten des Anrufs",
|
||||||
|
"videocallErrorCallAnswer": "Fehler beim Annehmen des Anrufs",
|
||||||
|
"videocallErrorCamera": "Kameraberechtigung erforderlich",
|
||||||
|
"videocallErrorMic": "Mikrofonberechtigung erforderlich",
|
||||||
|
"videocallErrorMissedCall": "Verpasster Anruf",
|
||||||
"positionUpdated": "Letzte verfügbare Position aktualisiert",
|
"positionUpdated": "Letzte verfügbare Position aktualisiert",
|
||||||
"locationMapStyleLight": "Hell",
|
"locationMapStyleLight": "Hell",
|
||||||
"locationMapStyleDark": "Dunkel",
|
"locationMapStyleDark": "Dunkel",
|
||||||
@@ -757,7 +785,7 @@
|
|||||||
"frequentPlaceCreated": "Häufiger Ort erstellt",
|
"frequentPlaceCreated": "Häufiger Ort erstellt",
|
||||||
"frequentPlaceUpdated": "Häufiger Ort aktualisiert",
|
"frequentPlaceUpdated": "Häufiger Ort aktualisiert",
|
||||||
"frequentPlaceDeleted": "Häufiger Ort gelöscht",
|
"frequentPlaceDeleted": "Häufiger Ort gelöscht",
|
||||||
"errorGeneric": "Etwas ist schiefgelaufen. Bitte versuchen Sie es erneut.",
|
"errorGeneric": "Ein unerwarteter Fehler ist aufgetreten.",
|
||||||
"pullDownToRetry": "Zum Wiederholen nach unten ziehen",
|
"pullDownToRetry": "Zum Wiederholen nach unten ziehen",
|
||||||
"errorGeofenceCreate": "Die Sicherheitszone konnte nicht erstellt werden",
|
"errorGeofenceCreate": "Die Sicherheitszone konnte nicht erstellt werden",
|
||||||
"errorGeofenceUpdate": "Die Sicherheitszone konnte nicht aktualisiert werden",
|
"errorGeofenceUpdate": "Die Sicherheitszone konnte nicht aktualisiert werden",
|
||||||
@@ -1060,6 +1088,5 @@
|
|||||||
"errorSessionExpired": "Deine Sitzung ist abgelaufen. Bitte melde dich erneut an.",
|
"errorSessionExpired": "Deine Sitzung ist abgelaufen. Bitte melde dich erneut an.",
|
||||||
"errorValidation": "Die eingegebenen Daten sind ungültig.",
|
"errorValidation": "Die eingegebenen Daten sind ungültig.",
|
||||||
"errorScaRequired": "Eine zusätzliche Authentifizierung ist erforderlich.",
|
"errorScaRequired": "Eine zusätzliche Authentifizierung ist erforderlich.",
|
||||||
"errorDeviceNotOwned": "Du hast keine Berechtigung, auf dieses Gerät zuzugreifen.",
|
"errorDeviceNotOwned": "Du hast keine Berechtigung, auf dieses Gerät zuzugreifen."
|
||||||
"errorGeneric": "Ein unerwarteter Fehler ist aufgetreten."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -863,6 +863,34 @@
|
|||||||
"locationRevealSkip": "Skip",
|
"locationRevealSkip": "Skip",
|
||||||
"locationDeleteGeofenceConfirm": "Are you sure you want to delete this safe zone?",
|
"locationDeleteGeofenceConfirm": "Are you sure you want to delete this safe zone?",
|
||||||
"locationDeleteFrequentPlaceConfirm": "Are you sure you want to delete this frequent place?",
|
"locationDeleteFrequentPlaceConfirm": "Are you sure you want to delete this frequent place?",
|
||||||
|
"videocallTitle": "Video Call",
|
||||||
|
"videocallInitializingSdk": "Initializing SDK...",
|
||||||
|
"videocallRecipientUserId": "Recipient User ID",
|
||||||
|
"videocallStart": "Start video call",
|
||||||
|
"videocallLoggedInAs": "Logged in as: {userId}",
|
||||||
|
"videocallCalling": "Calling {userId}...",
|
||||||
|
"videocallUserCalling": "{userId} is calling you",
|
||||||
|
"videocallIncomingVideo": "Incoming video call",
|
||||||
|
"videocallIncomingAudio": "Incoming call",
|
||||||
|
"videocallReject": "Reject",
|
||||||
|
"videocallAccept": "Accept",
|
||||||
|
"videocallMicOn": "Mic On",
|
||||||
|
"videocallMicOff": "Mic Off",
|
||||||
|
"videocallSpeaker": "Speaker",
|
||||||
|
"videocallEarpiece": "Earpiece",
|
||||||
|
"videocallCameraFront": "Front",
|
||||||
|
"videocallCameraBack": "Back",
|
||||||
|
"videocallHangUp": "Hang Up",
|
||||||
|
"videocallWaitingParticipants": "Waiting for participants...",
|
||||||
|
"videocallWaitingRemoteVideo": "Waiting for remote video...",
|
||||||
|
"videocallYou": "You",
|
||||||
|
"videocallErrorSdkInit": "Error initializing video call",
|
||||||
|
"videocallErrorAuth": "Video call authentication error",
|
||||||
|
"videocallErrorCallStart": "Error starting the call",
|
||||||
|
"videocallErrorCallAnswer": "Error answering the call",
|
||||||
|
"videocallErrorCamera": "Camera permission required",
|
||||||
|
"videocallErrorMic": "Microphone permission required",
|
||||||
|
"videocallErrorMissedCall": "Missed call",
|
||||||
"positionUpdated": "Updated to latest available position",
|
"positionUpdated": "Updated to latest available position",
|
||||||
"locationMapStyleLight": "Light",
|
"locationMapStyleLight": "Light",
|
||||||
"locationMapStyleDark": "Dark",
|
"locationMapStyleDark": "Dark",
|
||||||
@@ -931,7 +959,7 @@
|
|||||||
"frequentPlaceCreated": "Frequent place created",
|
"frequentPlaceCreated": "Frequent place created",
|
||||||
"frequentPlaceUpdated": "Frequent place updated",
|
"frequentPlaceUpdated": "Frequent place updated",
|
||||||
"frequentPlaceDeleted": "Frequent place deleted",
|
"frequentPlaceDeleted": "Frequent place deleted",
|
||||||
"errorGeneric": "Something went wrong. Please try again.",
|
"errorGeneric": "An unexpected error occurred.",
|
||||||
"pullDownToRetry": "Pull down to retry",
|
"pullDownToRetry": "Pull down to retry",
|
||||||
"errorGeofenceCreate": "Could not create the safety zone",
|
"errorGeofenceCreate": "Could not create the safety zone",
|
||||||
"errorGeofenceUpdate": "Could not update the safety zone",
|
"errorGeofenceUpdate": "Could not update the safety zone",
|
||||||
@@ -1060,6 +1088,5 @@
|
|||||||
"errorSessionExpired": "Your session has expired. Please sign in again.",
|
"errorSessionExpired": "Your session has expired. Please sign in again.",
|
||||||
"errorValidation": "The information you entered is not valid.",
|
"errorValidation": "The information you entered is not valid.",
|
||||||
"errorScaRequired": "Additional authentication is required to continue.",
|
"errorScaRequired": "Additional authentication is required to continue.",
|
||||||
"errorDeviceNotOwned": "You don't have permission to access this device.",
|
"errorDeviceNotOwned": "You don't have permission to access this device."
|
||||||
"errorGeneric": "An unexpected error occurred."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -864,6 +864,34 @@
|
|||||||
"locationRevealSkip": "Saltar",
|
"locationRevealSkip": "Saltar",
|
||||||
"locationDeleteGeofenceConfirm": "¿Seguro que quieres eliminar esta zona segura?",
|
"locationDeleteGeofenceConfirm": "¿Seguro que quieres eliminar esta zona segura?",
|
||||||
"locationDeleteFrequentPlaceConfirm": "¿Seguro que quieres eliminar este lugar frecuente?",
|
"locationDeleteFrequentPlaceConfirm": "¿Seguro que quieres eliminar este lugar frecuente?",
|
||||||
|
"videocallTitle": "Videollamada",
|
||||||
|
"videocallInitializingSdk": "Inicializando SDK...",
|
||||||
|
"videocallRecipientUserId": "User ID del destinatario",
|
||||||
|
"videocallStart": "Iniciar videollamada",
|
||||||
|
"videocallLoggedInAs": "Conectado como: {userId}",
|
||||||
|
"videocallCalling": "Llamando a {userId}...",
|
||||||
|
"videocallUserCalling": "{userId} te está llamando",
|
||||||
|
"videocallIncomingVideo": "Videollamada entrante",
|
||||||
|
"videocallIncomingAudio": "Llamada entrante",
|
||||||
|
"videocallReject": "Rechazar",
|
||||||
|
"videocallAccept": "Aceptar",
|
||||||
|
"videocallMicOn": "Mic On",
|
||||||
|
"videocallMicOff": "Mic Off",
|
||||||
|
"videocallSpeaker": "Altavoz",
|
||||||
|
"videocallEarpiece": "Auricular",
|
||||||
|
"videocallCameraFront": "Frontal",
|
||||||
|
"videocallCameraBack": "Trasera",
|
||||||
|
"videocallHangUp": "Colgar",
|
||||||
|
"videocallWaitingParticipants": "Esperando participantes...",
|
||||||
|
"videocallWaitingRemoteVideo": "Esperando video remoto...",
|
||||||
|
"videocallYou": "Tú",
|
||||||
|
"videocallErrorSdkInit": "Error al inicializar videollamada",
|
||||||
|
"videocallErrorAuth": "Error de autenticación de videollamada",
|
||||||
|
"videocallErrorCallStart": "Error al iniciar la llamada",
|
||||||
|
"videocallErrorCallAnswer": "Error al contestar la llamada",
|
||||||
|
"videocallErrorCamera": "Se requiere permiso de cámara",
|
||||||
|
"videocallErrorMic": "Se requiere permiso de micrófono",
|
||||||
|
"videocallErrorMissedCall": "Llamada perdida",
|
||||||
"positionUpdated": "Última posición disponible actualizada",
|
"positionUpdated": "Última posición disponible actualizada",
|
||||||
"locationMapStyleLight": "Claro",
|
"locationMapStyleLight": "Claro",
|
||||||
"locationMapStyleDark": "Oscuro",
|
"locationMapStyleDark": "Oscuro",
|
||||||
@@ -932,7 +960,7 @@
|
|||||||
"frequentPlaceCreated": "Lugar frecuente creado",
|
"frequentPlaceCreated": "Lugar frecuente creado",
|
||||||
"frequentPlaceUpdated": "Lugar frecuente actualizado",
|
"frequentPlaceUpdated": "Lugar frecuente actualizado",
|
||||||
"frequentPlaceDeleted": "Lugar frecuente eliminado",
|
"frequentPlaceDeleted": "Lugar frecuente eliminado",
|
||||||
"errorGeneric": "Algo salió mal. Inténtalo de nuevo.",
|
"errorGeneric": "Ha ocurrido un error inesperado.",
|
||||||
"pullDownToRetry": "Desliza hacia abajo para reintentar",
|
"pullDownToRetry": "Desliza hacia abajo para reintentar",
|
||||||
"errorGeofenceCreate": "No se pudo crear la zona de seguridad",
|
"errorGeofenceCreate": "No se pudo crear la zona de seguridad",
|
||||||
"errorGeofenceUpdate": "No se pudo actualizar la zona de seguridad",
|
"errorGeofenceUpdate": "No se pudo actualizar la zona de seguridad",
|
||||||
@@ -1060,6 +1088,5 @@
|
|||||||
"errorSessionExpired": "Tu sesión ha caducado. Vuelve a iniciar sesión.",
|
"errorSessionExpired": "Tu sesión ha caducado. Vuelve a iniciar sesión.",
|
||||||
"errorValidation": "Los datos introducidos no son válidos.",
|
"errorValidation": "Los datos introducidos no son válidos.",
|
||||||
"errorScaRequired": "Se requiere autenticación adicional para continuar.",
|
"errorScaRequired": "Se requiere autenticación adicional para continuar.",
|
||||||
"errorDeviceNotOwned": "No tienes permiso para acceder a este dispositivo.",
|
"errorDeviceNotOwned": "No tienes permiso para acceder a este dispositivo."
|
||||||
"errorGeneric": "Ha ocurrido un error inesperado."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -683,6 +683,34 @@
|
|||||||
"locationRevealSkip": "Passer",
|
"locationRevealSkip": "Passer",
|
||||||
"locationDeleteGeofenceConfirm": "Voulez-vous supprimer cette zone sûre ?",
|
"locationDeleteGeofenceConfirm": "Voulez-vous supprimer cette zone sûre ?",
|
||||||
"locationDeleteFrequentPlaceConfirm": "Voulez-vous supprimer ce lieu fréquent ?",
|
"locationDeleteFrequentPlaceConfirm": "Voulez-vous supprimer ce lieu fréquent ?",
|
||||||
|
"videocallTitle": "Appel vidéo",
|
||||||
|
"videocallInitializingSdk": "Initialisation du SDK...",
|
||||||
|
"videocallRecipientUserId": "ID utilisateur du destinataire",
|
||||||
|
"videocallStart": "Démarrer l'appel vidéo",
|
||||||
|
"videocallLoggedInAs": "Connecté en tant que : {userId}",
|
||||||
|
"videocallCalling": "Appel de {userId}...",
|
||||||
|
"videocallUserCalling": "{userId} vous appelle",
|
||||||
|
"videocallIncomingVideo": "Appel vidéo entrant",
|
||||||
|
"videocallIncomingAudio": "Appel entrant",
|
||||||
|
"videocallReject": "Rejeter",
|
||||||
|
"videocallAccept": "Accepter",
|
||||||
|
"videocallMicOn": "Micro activé",
|
||||||
|
"videocallMicOff": "Micro désactivé",
|
||||||
|
"videocallSpeaker": "Haut-parleur",
|
||||||
|
"videocallEarpiece": "Écouteur",
|
||||||
|
"videocallCameraFront": "Avant",
|
||||||
|
"videocallCameraBack": "Arrière",
|
||||||
|
"videocallHangUp": "Raccrocher",
|
||||||
|
"videocallWaitingParticipants": "En attente de participants...",
|
||||||
|
"videocallWaitingRemoteVideo": "En attente de la vidéo distante...",
|
||||||
|
"videocallYou": "Vous",
|
||||||
|
"videocallErrorSdkInit": "Erreur d'initialisation de l'appel vidéo",
|
||||||
|
"videocallErrorAuth": "Erreur d'authentification de l'appel vidéo",
|
||||||
|
"videocallErrorCallStart": "Erreur lors du démarrage de l'appel",
|
||||||
|
"videocallErrorCallAnswer": "Erreur lors de la réponse à l'appel",
|
||||||
|
"videocallErrorCamera": "Autorisation de la caméra requise",
|
||||||
|
"videocallErrorMic": "Autorisation du microphone requise",
|
||||||
|
"videocallErrorMissedCall": "Appel manqué",
|
||||||
"positionUpdated": "Dernière position disponible mise à jour",
|
"positionUpdated": "Dernière position disponible mise à jour",
|
||||||
"locationMapStyleLight": "Clair",
|
"locationMapStyleLight": "Clair",
|
||||||
"locationMapStyleDark": "Sombre",
|
"locationMapStyleDark": "Sombre",
|
||||||
@@ -757,7 +785,7 @@
|
|||||||
"frequentPlaceCreated": "Lieu fréquent créé",
|
"frequentPlaceCreated": "Lieu fréquent créé",
|
||||||
"frequentPlaceUpdated": "Lieu fréquent mis à jour",
|
"frequentPlaceUpdated": "Lieu fréquent mis à jour",
|
||||||
"frequentPlaceDeleted": "Lieu fréquent supprimé",
|
"frequentPlaceDeleted": "Lieu fréquent supprimé",
|
||||||
"errorGeneric": "Une erreur est survenue. Veuillez réessayer.",
|
"errorGeneric": "Une erreur inattendue s'est produite.",
|
||||||
"pullDownToRetry": "Tirez vers le bas pour réessayer",
|
"pullDownToRetry": "Tirez vers le bas pour réessayer",
|
||||||
"errorGeofenceCreate": "Impossible de créer la zone de sécurité",
|
"errorGeofenceCreate": "Impossible de créer la zone de sécurité",
|
||||||
"errorGeofenceUpdate": "Impossible de mettre à jour la zone de sécurité",
|
"errorGeofenceUpdate": "Impossible de mettre à jour la zone de sécurité",
|
||||||
@@ -1060,6 +1088,5 @@
|
|||||||
"errorSessionExpired": "Votre session a expiré. Veuillez vous reconnecter.",
|
"errorSessionExpired": "Votre session a expiré. Veuillez vous reconnecter.",
|
||||||
"errorValidation": "Les données saisies ne sont pas valides.",
|
"errorValidation": "Les données saisies ne sont pas valides.",
|
||||||
"errorScaRequired": "Une authentification supplémentaire est requise pour continuer.",
|
"errorScaRequired": "Une authentification supplémentaire est requise pour continuer.",
|
||||||
"errorDeviceNotOwned": "Vous n'avez pas l'autorisation d'accéder à cet appareil.",
|
"errorDeviceNotOwned": "Vous n'avez pas l'autorisation d'accéder à cet appareil."
|
||||||
"errorGeneric": "Une erreur inattendue s'est produite."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -683,6 +683,34 @@
|
|||||||
"locationRevealSkip": "Salta",
|
"locationRevealSkip": "Salta",
|
||||||
"locationDeleteGeofenceConfirm": "Sei sicuro di voler eliminare questa zona sicura?",
|
"locationDeleteGeofenceConfirm": "Sei sicuro di voler eliminare questa zona sicura?",
|
||||||
"locationDeleteFrequentPlaceConfirm": "Sei sicuro di voler eliminare questo luogo frequente?",
|
"locationDeleteFrequentPlaceConfirm": "Sei sicuro di voler eliminare questo luogo frequente?",
|
||||||
|
"videocallTitle": "Videochiamata",
|
||||||
|
"videocallInitializingSdk": "Inizializzazione SDK...",
|
||||||
|
"videocallRecipientUserId": "ID utente del destinatario",
|
||||||
|
"videocallStart": "Avvia videochiamata",
|
||||||
|
"videocallLoggedInAs": "Connesso come: {userId}",
|
||||||
|
"videocallCalling": "Chiamata a {userId}...",
|
||||||
|
"videocallUserCalling": "{userId} ti sta chiamando",
|
||||||
|
"videocallIncomingVideo": "Videochiamata in arrivo",
|
||||||
|
"videocallIncomingAudio": "Chiamata in arrivo",
|
||||||
|
"videocallReject": "Rifiuta",
|
||||||
|
"videocallAccept": "Accetta",
|
||||||
|
"videocallMicOn": "Micro attivo",
|
||||||
|
"videocallMicOff": "Micro disattivato",
|
||||||
|
"videocallSpeaker": "Altoparlante",
|
||||||
|
"videocallEarpiece": "Auricolare",
|
||||||
|
"videocallCameraFront": "Anteriore",
|
||||||
|
"videocallCameraBack": "Posteriore",
|
||||||
|
"videocallHangUp": "Riaggancia",
|
||||||
|
"videocallWaitingParticipants": "In attesa di partecipanti...",
|
||||||
|
"videocallWaitingRemoteVideo": "In attesa del video remoto...",
|
||||||
|
"videocallYou": "Tu",
|
||||||
|
"videocallErrorSdkInit": "Errore nell'inizializzazione della videochiamata",
|
||||||
|
"videocallErrorAuth": "Errore di autenticazione della videochiamata",
|
||||||
|
"videocallErrorCallStart": "Errore nell'avvio della chiamata",
|
||||||
|
"videocallErrorCallAnswer": "Errore nel rispondere alla chiamata",
|
||||||
|
"videocallErrorCamera": "Permesso fotocamera richiesto",
|
||||||
|
"videocallErrorMic": "Permesso microfono richiesto",
|
||||||
|
"videocallErrorMissedCall": "Chiamata persa",
|
||||||
"positionUpdated": "Ultima posizione disponibile aggiornata",
|
"positionUpdated": "Ultima posizione disponibile aggiornata",
|
||||||
"locationMapStyleLight": "Chiaro",
|
"locationMapStyleLight": "Chiaro",
|
||||||
"locationMapStyleDark": "Scuro",
|
"locationMapStyleDark": "Scuro",
|
||||||
@@ -757,7 +785,7 @@
|
|||||||
"frequentPlaceCreated": "Luogo frequente creato",
|
"frequentPlaceCreated": "Luogo frequente creato",
|
||||||
"frequentPlaceUpdated": "Luogo frequente aggiornato",
|
"frequentPlaceUpdated": "Luogo frequente aggiornato",
|
||||||
"frequentPlaceDeleted": "Luogo frequente eliminato",
|
"frequentPlaceDeleted": "Luogo frequente eliminato",
|
||||||
"errorGeneric": "Qualcosa è andato storto. Riprova.",
|
"errorGeneric": "Si è verificato un errore imprevisto.",
|
||||||
"pullDownToRetry": "Trascina verso il basso per riprovare",
|
"pullDownToRetry": "Trascina verso il basso per riprovare",
|
||||||
"errorGeofenceCreate": "Impossibile creare la zona di sicurezza",
|
"errorGeofenceCreate": "Impossibile creare la zona di sicurezza",
|
||||||
"errorGeofenceUpdate": "Impossibile aggiornare la zona di sicurezza",
|
"errorGeofenceUpdate": "Impossibile aggiornare la zona di sicurezza",
|
||||||
@@ -1060,6 +1088,5 @@
|
|||||||
"errorSessionExpired": "La tua sessione è scaduta. Accedi di nuovo.",
|
"errorSessionExpired": "La tua sessione è scaduta. Accedi di nuovo.",
|
||||||
"errorValidation": "I dati inseriti non sono validi.",
|
"errorValidation": "I dati inseriti non sono validi.",
|
||||||
"errorScaRequired": "È richiesta un'autenticazione aggiuntiva per continuare.",
|
"errorScaRequired": "È richiesta un'autenticazione aggiuntiva per continuare.",
|
||||||
"errorDeviceNotOwned": "Non hai il permesso di accedere a questo dispositivo.",
|
"errorDeviceNotOwned": "Non hai il permesso di accedere a questo dispositivo."
|
||||||
"errorGeneric": "Si è verificato un errore imprevisto."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -683,6 +683,34 @@
|
|||||||
"locationRevealSkip": "Saltar",
|
"locationRevealSkip": "Saltar",
|
||||||
"locationDeleteGeofenceConfirm": "Tens a certeza que queres eliminar esta zona segura?",
|
"locationDeleteGeofenceConfirm": "Tens a certeza que queres eliminar esta zona segura?",
|
||||||
"locationDeleteFrequentPlaceConfirm": "Tens a certeza que queres eliminar este lugar frequente?",
|
"locationDeleteFrequentPlaceConfirm": "Tens a certeza que queres eliminar este lugar frequente?",
|
||||||
|
"videocallTitle": "Videochamada",
|
||||||
|
"videocallInitializingSdk": "A inicializar SDK...",
|
||||||
|
"videocallRecipientUserId": "ID do utilizador destinatário",
|
||||||
|
"videocallStart": "Iniciar videochamada",
|
||||||
|
"videocallLoggedInAs": "Conectado como: {userId}",
|
||||||
|
"videocallCalling": "A ligar para {userId}...",
|
||||||
|
"videocallUserCalling": "{userId} está a ligar-te",
|
||||||
|
"videocallIncomingVideo": "Videochamada recebida",
|
||||||
|
"videocallIncomingAudio": "Chamada recebida",
|
||||||
|
"videocallReject": "Rejeitar",
|
||||||
|
"videocallAccept": "Aceitar",
|
||||||
|
"videocallMicOn": "Micro ligado",
|
||||||
|
"videocallMicOff": "Micro desligado",
|
||||||
|
"videocallSpeaker": "Altifalante",
|
||||||
|
"videocallEarpiece": "Auricular",
|
||||||
|
"videocallCameraFront": "Frontal",
|
||||||
|
"videocallCameraBack": "Traseira",
|
||||||
|
"videocallHangUp": "Desligar",
|
||||||
|
"videocallWaitingParticipants": "A aguardar participantes...",
|
||||||
|
"videocallWaitingRemoteVideo": "A aguardar vídeo remoto...",
|
||||||
|
"videocallYou": "Tu",
|
||||||
|
"videocallErrorSdkInit": "Erro ao inicializar videochamada",
|
||||||
|
"videocallErrorAuth": "Erro de autenticação da videochamada",
|
||||||
|
"videocallErrorCallStart": "Erro ao iniciar a chamada",
|
||||||
|
"videocallErrorCallAnswer": "Erro ao atender a chamada",
|
||||||
|
"videocallErrorCamera": "Permissão de câmara necessária",
|
||||||
|
"videocallErrorMic": "Permissão de microfone necessária",
|
||||||
|
"videocallErrorMissedCall": "Chamada perdida",
|
||||||
"positionUpdated": "Última posição disponível atualizada",
|
"positionUpdated": "Última posição disponível atualizada",
|
||||||
"locationMapStyleLight": "Claro",
|
"locationMapStyleLight": "Claro",
|
||||||
"locationMapStyleDark": "Escuro",
|
"locationMapStyleDark": "Escuro",
|
||||||
@@ -757,7 +785,7 @@
|
|||||||
"frequentPlaceCreated": "Local frequente criado",
|
"frequentPlaceCreated": "Local frequente criado",
|
||||||
"frequentPlaceUpdated": "Local frequente atualizado",
|
"frequentPlaceUpdated": "Local frequente atualizado",
|
||||||
"frequentPlaceDeleted": "Local frequente eliminado",
|
"frequentPlaceDeleted": "Local frequente eliminado",
|
||||||
"errorGeneric": "Algo correu mal. Tente novamente.",
|
"errorGeneric": "Ocorreu um erro inesperado.",
|
||||||
"pullDownToRetry": "Deslize para baixo para tentar novamente",
|
"pullDownToRetry": "Deslize para baixo para tentar novamente",
|
||||||
"errorGeofenceCreate": "Não foi possível criar a zona de segurança",
|
"errorGeofenceCreate": "Não foi possível criar a zona de segurança",
|
||||||
"errorGeofenceUpdate": "Não foi possível atualizar a zona de segurança",
|
"errorGeofenceUpdate": "Não foi possível atualizar a zona de segurança",
|
||||||
@@ -1060,6 +1088,5 @@
|
|||||||
"errorSessionExpired": "A tua sessão expirou. Inicia sessão novamente.",
|
"errorSessionExpired": "A tua sessão expirou. Inicia sessão novamente.",
|
||||||
"errorValidation": "Os dados introduzidos não são válidos.",
|
"errorValidation": "Os dados introduzidos não são válidos.",
|
||||||
"errorScaRequired": "É necessária autenticação adicional para continuar.",
|
"errorScaRequired": "É necessária autenticação adicional para continuar.",
|
||||||
"errorDeviceNotOwned": "Não tens permissão para aceder a este dispositivo.",
|
"errorDeviceNotOwned": "Não tens permissão para aceder a este dispositivo."
|
||||||
"errorGeneric": "Ocorreu um erro inesperado."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1006,6 +1006,34 @@ class I18n {
|
|||||||
static const String verifyAccount = 'verifyAccount';
|
static const String verifyAccount = 'verifyAccount';
|
||||||
static const String vibrationOnly = 'vibrationOnly';
|
static const String vibrationOnly = 'vibrationOnly';
|
||||||
static const String videoCall = 'videoCall';
|
static const String videoCall = 'videoCall';
|
||||||
|
static const String videocallAccept = 'videocallAccept';
|
||||||
|
static const String videocallCalling = 'videocallCalling';
|
||||||
|
static const String videocallCameraBack = 'videocallCameraBack';
|
||||||
|
static const String videocallCameraFront = 'videocallCameraFront';
|
||||||
|
static const String videocallEarpiece = 'videocallEarpiece';
|
||||||
|
static const String videocallErrorAuth = 'videocallErrorAuth';
|
||||||
|
static const String videocallErrorCallAnswer = 'videocallErrorCallAnswer';
|
||||||
|
static const String videocallErrorCallStart = 'videocallErrorCallStart';
|
||||||
|
static const String videocallErrorCamera = 'videocallErrorCamera';
|
||||||
|
static const String videocallErrorMic = 'videocallErrorMic';
|
||||||
|
static const String videocallErrorMissedCall = 'videocallErrorMissedCall';
|
||||||
|
static const String videocallErrorSdkInit = 'videocallErrorSdkInit';
|
||||||
|
static const String videocallHangUp = 'videocallHangUp';
|
||||||
|
static const String videocallIncomingAudio = 'videocallIncomingAudio';
|
||||||
|
static const String videocallIncomingVideo = 'videocallIncomingVideo';
|
||||||
|
static const String videocallInitializingSdk = 'videocallInitializingSdk';
|
||||||
|
static const String videocallLoggedInAs = 'videocallLoggedInAs';
|
||||||
|
static const String videocallMicOff = 'videocallMicOff';
|
||||||
|
static const String videocallMicOn = 'videocallMicOn';
|
||||||
|
static const String videocallRecipientUserId = 'videocallRecipientUserId';
|
||||||
|
static const String videocallReject = 'videocallReject';
|
||||||
|
static const String videocallSpeaker = 'videocallSpeaker';
|
||||||
|
static const String videocallStart = 'videocallStart';
|
||||||
|
static const String videocallTitle = 'videocallTitle';
|
||||||
|
static const String videocallUserCalling = 'videocallUserCalling';
|
||||||
|
static const String videocallWaitingParticipants = 'videocallWaitingParticipants';
|
||||||
|
static const String videocallWaitingRemoteVideo = 'videocallWaitingRemoteVideo';
|
||||||
|
static const String videocallYou = 'videocallYou';
|
||||||
static const String volumeAlarm = 'volumeAlarm';
|
static const String volumeAlarm = 'volumeAlarm';
|
||||||
static const String volumeControl = 'volumeControl';
|
static const String volumeControl = 'volumeControl';
|
||||||
static const String volumeHint = 'volumeHint';
|
static const String volumeHint = 'volumeHint';
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ class VideocallItem {
|
|||||||
final bool uploadVideoStreamSelf;
|
final bool uploadVideoStreamSelf;
|
||||||
final bool uploadVideoStreamOther;
|
final bool uploadVideoStreamOther;
|
||||||
|
|
||||||
|
bool get isTalking => state == VideocallState.talking;
|
||||||
|
|
||||||
VideocallItem copyWith({
|
VideocallItem copyWith({
|
||||||
String? userId,
|
String? userId,
|
||||||
bool? isVideo,
|
bool? isVideo,
|
||||||
|
|||||||
Reference in New Issue
Block a user