diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 3d81c9a91..c830d3583 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -3934,8 +3934,11 @@ "continuedWithoutSubscription": "Continue without subscribing", "trialPeriodExpired": "Your trial period has expired", "selectToDefine": "To define a word in this message, just select it!", - "translation": "translation", - "audio": "message audio", + "translations": "translations", + "messageAudio": "message audio", "definitions": "definitions", - "subscribedToUnlockTools": "Subscribe to unlock language tools, including" + "subscribedToUnlockTools": "Subscribe to unlock language tools, including", + "more": "More", + "translationTooltip": "Translate", + "audioTooltip": "Play Audio" } \ No newline at end of file diff --git a/assets/l10n/intl_es.arb b/assets/l10n/intl_es.arb index 93255f55c..78e109aca 100644 --- a/assets/l10n/intl_es.arb +++ b/assets/l10n/intl_es.arb @@ -4570,10 +4570,13 @@ "continuedWithoutSubscription": "Continuar sin suscribirse", "trialPeriodExpired": "Su periodo de prueba ha expirado", "selectToDefine": "Para definir una palabra en este mensaje, ¡sólo tiene que seleccionarla!", - "translation": "traducción", - "audio": "mensaje de audio", + "translations": "traducciónes", + "messageAudio": "mensaje de audio", "definitions": "definiciones", "subscribedToUnlockTools": "Suscríbase para desbloquear herramientas lingüísticas, como", "clickMessageTitle": "¿Necesitas ayuda?", - "clickMessageBody": "Haga clic en los mensajes para acceder a las definiciones, traducciones y audio." + "clickMessageBody": "Haga clic en los mensajes para acceder a las definiciones, traducciones y audio.", + "more": "Más", + "translationTooltip": "Traducir", + "audioTooltip": "Reproducir audio" } diff --git a/lib/pages/chat/events/audio_player.dart b/lib/pages/chat/events/audio_player.dart index 0593c6122..a3c5658ab 100644 --- a/lib/pages/chat/events/audio_player.dart +++ b/lib/pages/chat/events/audio_player.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:developer'; import 'dart:io'; +import 'package:fluffychat/pangea/widgets/chat/message_audio_card.dart'; import 'package:fluffychat/utils/error_reporter.dart'; import 'package:fluffychat/utils/localized_exception_extension.dart'; import 'package:flutter/foundation.dart'; @@ -14,8 +15,10 @@ import '../../../utils/matrix_sdk_extensions/event_extension.dart'; class AudioPlayerWidget extends StatefulWidget { final Color color; - final Event event; // #Pangea + // final Event event; + final Event? event; + final PangeaAudioFile? matrixFile; final bool autoplay; // Pangea# @@ -26,8 +29,9 @@ class AudioPlayerWidget extends StatefulWidget { const AudioPlayerWidget( this.event, { this.color = Colors.black, - super.key, // #Pangea + this.matrixFile, + super.key, this.autoplay = false, // Pangea# }); @@ -68,16 +72,27 @@ class AudioPlayerState extends State { } Future _downloadAction() async { - if (status != AudioPlayerStatus.notDownloaded) return; + // #Pangea + // if (status != AudioPlayerStatus.notDownloaded) return; + if (status != AudioPlayerStatus.notDownloaded || widget.event == null) { + return; + } + // Pangea# setState(() => status = AudioPlayerStatus.downloading); try { - final matrixFile = await widget.event.downloadAndDecryptAttachment(); + // #Pangea + // final matrixFile = await widget.event.downloadAndDecryptAttachment(); + final matrixFile = await widget.event!.downloadAndDecryptAttachment(); + // Pangea# File? file; if (!kIsWeb) { final tempDir = await getTemporaryDirectory(); final fileName = Uri.encodeComponent( - widget.event.attachmentOrThumbnailMxcUrl()!.pathSegments.last, + // #Pangea + // widget.event.attachmentOrThumbnailMxcUrl()!.pathSegments.last, + widget.event!.attachmentOrThumbnailMxcUrl()!.pathSegments.last, + // Pangea# ); file = File('${tempDir.path}/${fileName}_${matrixFile.name}'); await file.writeAsBytes(matrixFile.bytes); @@ -104,14 +119,20 @@ class AudioPlayerState extends State { void _playAction() async { final audioPlayer = this.audioPlayer ??= AudioPlayer(); - if (AudioPlayerWidget.currentId != widget.event.eventId) { + // #Pangea + // if (AudioPlayerWidget.currentId != widget.event.eventId) { + if (AudioPlayerWidget.currentId != widget.event?.eventId) { + // Pangea# if (AudioPlayerWidget.currentId != null) { if (audioPlayer.playerState.playing) { await audioPlayer.stop(); setState(() {}); } } - AudioPlayerWidget.currentId = widget.event.eventId; + // #Pangea + // AudioPlayerWidget.currentId = widget.event.eventId; + AudioPlayerWidget.currentId = widget.event?.eventId; + // Pangea# } if (audioPlayer.playerState.playing) { await audioPlayer.pause(); @@ -146,27 +167,20 @@ class AudioPlayerState extends State { audioPlayer.setFilePath(audioFile.path); } else { // #Pangea - // final data = matrixFile!.bytes; - final mimeType = matrixFile!.mimeType; - //shouldn't have to be settting this here - //TODO: figure out why this is necessary - matrixFile = MatrixAudioFile( - bytes: matrixFile!.bytes, - name: matrixFile!.name, - mimeType: mimeType, - ); - debugPrint("audioType is $mimeType"); - // TODO - figure out why it's a wav at this point - // if (!TextToSpeechController.isOggFile(matrixFile!.bytes)) { - // debugger(when: kDebugMode); - // } else { - // debugPrint("still an ogg file!"); - // } try { - // Pangea# - await audioPlayer.setAudioSource(MatrixFileAudioSource(matrixFile!)); - // #Pangea - } catch (e, s) { + if (widget.matrixFile != null) { + await audioPlayer.setAudioSource( + BytesAudioSource( + widget.matrixFile!.bytes, + widget.matrixFile!.mimeType, + ), + ); + } else { + // Pangea# + await audioPlayer.setAudioSource(MatrixFileAudioSource(matrixFile!)); + // #Pangea + } + } catch (e, _) { debugger(when: kDebugMode); } // Pangea# @@ -180,18 +194,32 @@ class AudioPlayerState extends State { static const double buttonSize = 36; String? get _durationString { - final durationInt = widget.event.content - .tryGetMap('info') - ?.tryGet('duration'); + // #Pangea + int? durationInt; + if (widget.matrixFile?.duration != null) { + durationInt = widget.matrixFile!.duration; + } else { + // final durationInt = widget.event?.content + durationInt = widget.event?.content + .tryGetMap('info') + ?.tryGet('duration'); + } + // Pangea# if (durationInt == null) return null; final duration = Duration(milliseconds: durationInt); return '${duration.inMinutes.toString().padLeft(2, '0')}:${(duration.inSeconds % 60).toString().padLeft(2, '0')}'; } List _getWaveform() { - final eventWaveForm = widget.event.content - .tryGetMap('org.matrix.msc1767.audio') - ?.tryGetList('waveform'); + // #Pangea + final eventWaveForm = widget.matrixFile?.waveform ?? + widget.event?.content + .tryGetMap('org.matrix.msc1767.audio') + ?.tryGetList('waveform'); + // final eventWaveForm = widget.event?.content + // .tryGetMap('org.matrix.msc1767.audio') + // ?.tryGetList('waveform'); + // Pangea# if (eventWaveForm == null || eventWaveForm.isEmpty) { return List.filled(AudioPlayerWidget.wavesCount, 500); } @@ -211,17 +239,37 @@ class AudioPlayerState extends State { late final List waveform; + // #Pangea + Future _downloadMatrixFile() async { + if (kIsWeb) return; + final temp = await getTemporaryDirectory(); + final tempDir = temp; + final file = File('${tempDir.path}/${widget.matrixFile!.name}'); + await file.writeAsBytes(widget.matrixFile!.bytes); + audioFile = file; + } + // Pangea# + @override void initState() { super.initState(); waveform = _getWaveform(); // #Pangea - if (widget.autoplay) { + if (widget.matrixFile != null) { + _downloadMatrixFile().then((_) { + setState(() => status = AudioPlayerStatus.downloaded); + if (widget.autoplay) { + status == AudioPlayerStatus.downloaded + ? _playAction() + : _downloadAction(); + } + }); + } else if (widget.autoplay) { status == AudioPlayerStatus.downloaded ? _playAction() : _downloadAction(); - // Pangea# } + // Pangea# } @override @@ -250,7 +298,10 @@ class AudioPlayerState extends State { color: widget.color, ), ), - onLongPress: () => widget.event.saveFile(context), + // #Pangea + // onLongPress: () => widget.event.saveFile(context), + onLongPress: () => widget.event?.saveFile(context), + // Pangea# onTap: () { if (status == AudioPlayerStatus.downloaded) { _playAction(); @@ -330,3 +381,24 @@ class MatrixFileAudioSource extends StreamAudioSource { ); } } + +// #Pangea +class BytesAudioSource extends StreamAudioSource { + final Uint8List bytes; + final String mimeType; + BytesAudioSource(this.bytes, this.mimeType); + + @override + Future request([int? start, int? end]) async { + start ??= 0; + end ??= bytes.length; + return StreamAudioResponse( + sourceLength: bytes.length, + contentLength: end - start, + offset: start, + stream: Stream.value(bytes.sublist(start, end)), + contentType: mimeType, + ); + } +} +// Pangea# diff --git a/lib/pangea/models/pangea_message_event.dart b/lib/pangea/models/pangea_message_event.dart index 0b15faa99..288b4b899 100644 --- a/lib/pangea/models/pangea_message_event.dart +++ b/lib/pangea/models/pangea_message_event.dart @@ -10,6 +10,7 @@ import 'package:fluffychat/pangea/models/class_model.dart'; import 'package:fluffychat/pangea/models/message_data_models.dart'; import 'package:fluffychat/pangea/models/pangea_representation_event.dart'; import 'package:fluffychat/pangea/utils/bot_name.dart'; +import 'package:fluffychat/pangea/widgets/chat/message_audio_card.dart'; import 'package:flutter/material.dart'; import 'package:matrix/matrix.dart'; @@ -82,6 +83,81 @@ class PangeaMessageEvent { return true; } + Future getMatrixAudioFile( + String langCode, + BuildContext context, + ) async { + final String text = (await representationByLanguageGlobal( + context: context, + langCode: langCode, + )) + ?.text ?? + body; + final TextToSpeechRequest params = TextToSpeechRequest( + text: text, + langCode: langCode, + ); + + final TextToSpeechResponse response = + await MatrixState.pangeaController.textToSpeech.get( + params, + ); + + final audioBytes = base64.decode(response.audioContent); + final eventIdParam = _event.eventId; + final fileName = + "audio_for_${eventIdParam}_$langCode.${response.fileExtension}"; + + final file = PangeaAudioFile( + bytes: audioBytes, + name: fileName, + mimeType: response.mimeType, + duration: response.durationMillis, + waveform: response.waveform, + ); + + sendAudioEvent(file, response, text, langCode); + + return file; + } + + Future sendAudioEvent( + PangeaAudioFile file, + TextToSpeechResponse response, + String text, + String langCode, + ) async { + final String? eventId = await room.sendFileEvent( + file, + inReplyTo: _event, + extraContent: { + 'info': { + ...file.info, + 'duration': response.durationMillis, + }, + 'org.matrix.msc3245.voice': {}, + 'org.matrix.msc1767.audio': { + 'duration': response.durationMillis, + 'waveform': response.waveform, + }, + ModelKey.transcription: { + ModelKey.text: text, + ModelKey.langCode: langCode, + }, + }, + ); + + debugPrint("eventId in getAudioGlobal $eventId"); + final Event? audioEvent = + eventId != null ? await room.getEventById(eventId) : null; + + if (audioEvent == null) { + return null; + } + allAudio.add(audioEvent); + return audioEvent; + } + //get audio for text and language //if no audio exists, create it //if audio exists, return it diff --git a/lib/pangea/widgets/chat/message_audio_card.dart b/lib/pangea/widgets/chat/message_audio_card.dart index a7caba153..ddd8caf61 100644 --- a/lib/pangea/widgets/chat/message_audio_card.dart +++ b/lib/pangea/widgets/chat/message_audio_card.dart @@ -1,4 +1,3 @@ -import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pages/chat/events/audio_player.dart'; import 'package:fluffychat/pangea/models/pangea_message_event.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; @@ -22,17 +21,33 @@ class MessageAudioCard extends StatefulWidget { class MessageAudioCardState extends State { bool _isLoading = false; Event? localAudioEvent; + PangeaAudioFile? audioFile; - void fetchAudio() { + Future fetchAudio() async { if (!mounted) return; setState(() => _isLoading = true); - widget.messageEvent - .getAudioGlobal(widget.messageEvent.messageDisplayLangCode) - .then((Event? event) { - localAudioEvent = event; - }).catchError((e) { + + try { + final String langCode = widget.messageEvent.messageDisplayLangCode; + final String? text = + widget.messageEvent.representationByLanguage(langCode)?.text; + if (text != null) { + final Event? localEvent = + widget.messageEvent.getAudioLocal(langCode, text); + if (localEvent != null) { + localAudioEvent = localEvent; + if (mounted) setState(() => _isLoading = false); + return; + } + } + + audioFile = + await widget.messageEvent.getMatrixAudioFile(langCode, context); + if (mounted) setState(() => _isLoading = false); + } catch (e, _) { debugPrint(StackTrace.current.toString()); - if (!mounted) return null; + if (!mounted) return; + setState(() => _isLoading = false); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(L10n.of(context)!.errorGettingAudio), @@ -47,10 +62,8 @@ class MessageAudioCardState extends State { widget.messageEvent.messageDisplayLangCode, }, ); - return null; - }).whenComplete(() { - if (mounted) setState(() => _isLoading = false); - }); + } + return; } @override @@ -61,20 +74,6 @@ class MessageAudioCardState extends State { @override Widget build(BuildContext context) { - final playButton = InkWell( - borderRadius: BorderRadius.circular(64), - onTap: fetchAudio, - child: Material( - color: AppConfig.primaryColor.withAlpha(64), - borderRadius: BorderRadius.circular(64), - child: const Icon( - // Change the icon based on some condition. If you have an audio player state, use it here. - Icons.play_arrow_outlined, - color: AppConfig.primaryColor, - ), - ), - ); - return Padding( padding: const EdgeInsets.all(8), child: _isLoading @@ -86,7 +85,7 @@ class MessageAudioCardState extends State { color: Theme.of(context).colorScheme.primary, ), ) - : localAudioEvent != null + : localAudioEvent != null || audioFile != null ? Container( constraints: const BoxConstraints( maxWidth: 250, @@ -94,8 +93,9 @@ class MessageAudioCardState extends State { child: Column( children: [ AudioPlayerWidget( - localAudioEvent!, + localAudioEvent, color: Theme.of(context).colorScheme.onPrimaryContainer, + matrixFile: audioFile, autoplay: true, ), ], @@ -105,3 +105,15 @@ class MessageAudioCardState extends State { ); } } + +class PangeaAudioFile extends MatrixAudioFile { + List? waveform; + + PangeaAudioFile({ + required super.bytes, + required super.name, + super.mimeType, + super.duration, + this.waveform, + }); +} diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index 5cb259d02..4a331e80a 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -167,9 +167,9 @@ class MessageToolbarState extends State { String getModeTitle(MessageMode mode) { switch (mode) { case MessageMode.translation: - return L10n.of(context)!.translation; + return L10n.of(context)!.translations; case MessageMode.play: - return L10n.of(context)!.audio; + return L10n.of(context)!.messageAudio; case MessageMode.definition: return L10n.of(context)!.definitions; default: @@ -178,6 +178,20 @@ class MessageToolbarState extends State { } } + String getModeTooltip(MessageMode mode) { + switch (mode) { + case MessageMode.translation: + return L10n.of(context)!.translationTooltip; + case MessageMode.play: + return L10n.of(context)!.audioTooltip; + case MessageMode.definition: + return L10n.of(context)!.define; + default: + return L10n.of(context)! + .oopsSomethingWentWrong; // Title to indicate an error or unsupported mode + } + } + void updateMode(MessageMode newMode) { if (updatingMode) return; debugPrint("updating toolbar mode"); @@ -190,6 +204,8 @@ class MessageToolbarState extends State { if (!subscribed) { child = MessageUnsubscribedCard( languageTool: getModeTitle(newMode), + mode: newMode, + toolbarModeStream: widget.toolbarModeStream, ); } else { switch (currentMode) { @@ -321,18 +337,24 @@ class MessageToolbarState extends State { Row( mainAxisSize: MainAxisSize.min, children: MessageMode.values.map((mode) { - return IconButton( - icon: Icon(getIconData(mode)), - color: currentMode == mode - ? Theme.of(context).colorScheme.primary - : null, - onPressed: () => updateMode(mode), + return Tooltip( + message: getModeTooltip(mode), + child: IconButton( + icon: Icon(getIconData(mode)), + color: currentMode == mode + ? Theme.of(context).colorScheme.primary + : null, + onPressed: () => updateMode(mode), + ), ); }).toList() + [ - IconButton( - icon: Icon(Icons.adaptive.more_outlined), - onPressed: showMore, + Tooltip( + message: L10n.of(context)!.more, + child: IconButton( + icon: Icon(Icons.adaptive.more_outlined), + onPressed: showMore, + ), ), ], ), diff --git a/lib/pangea/widgets/chat/message_unsubscribed_card.dart b/lib/pangea/widgets/chat/message_unsubscribed_card.dart index 542fb85e6..8219e2355 100644 --- a/lib/pangea/widgets/chat/message_unsubscribed_card.dart +++ b/lib/pangea/widgets/chat/message_unsubscribed_card.dart @@ -1,19 +1,40 @@ +import 'dart:async'; + import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/utils/bot_style.dart'; +import 'package:fluffychat/pangea/widgets/chat/message_toolbar.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; class MessageUnsubscribedCard extends StatelessWidget { final String languageTool; + final MessageMode mode; + final StreamController toolbarModeStream; const MessageUnsubscribedCard({ super.key, required this.languageTool, + required this.mode, + required this.toolbarModeStream, }); @override Widget build(BuildContext context) { + final bool inTrialWindow = + MatrixState.pangeaController.userController.inTrialWindow; + + void onButtonPress() { + if (inTrialWindow) { + MatrixState.pangeaController.subscriptionController + .activateNewUserTrial(); + toolbarModeStream.add(mode); + } else { + MatrixState.pangeaController.subscriptionController + .showPaywall(context); + } + } + return Padding( padding: const EdgeInsets.fromLTRB(10, 10, 10, 0), child: Column( @@ -27,17 +48,17 @@ class MessageUnsubscribedCard extends StatelessWidget { SizedBox( width: double.infinity, child: TextButton( - onPressed: () { - MatrixState.pangeaController.subscriptionController - .showPaywall(context); - MatrixState.pAnyState.closeOverlay(); - }, + onPressed: onButtonPress, style: ButtonStyle( backgroundColor: MaterialStateProperty.all( (AppConfig.primaryColor).withOpacity(0.1), ), ), - child: Text(L10n.of(context)!.getAccess), + child: Text( + inTrialWindow + ? L10n.of(context)!.activateTrial + : L10n.of(context)!.getAccess, + ), ), ), ], diff --git a/lib/pangea/widgets/igc/paywall_card.dart b/lib/pangea/widgets/igc/paywall_card.dart index 9b6cfd1b0..a9dc1a86d 100644 --- a/lib/pangea/widgets/igc/paywall_card.dart +++ b/lib/pangea/widgets/igc/paywall_card.dart @@ -14,6 +14,9 @@ class PaywallCard extends StatelessWidget { @override Widget build(BuildContext context) { + final bool inTrialWindow = + MatrixState.pangeaController.userController.inTrialWindow; + return Column( mainAxisSize: MainAxisSize.max, crossAxisAlignment: CrossAxisAlignment.center, @@ -40,8 +43,11 @@ class PaywallCard extends StatelessWidget { width: double.infinity, child: TextButton( onPressed: () { - MatrixState.pangeaController.subscriptionController - .showPaywall(context); + inTrialWindow + ? MatrixState.pangeaController.subscriptionController + .activateNewUserTrial() + : MatrixState.pangeaController.subscriptionController + .showPaywall(context); MatrixState.pAnyState.closeOverlay(); }, style: ButtonStyle( @@ -49,7 +55,11 @@ class PaywallCard extends StatelessWidget { (AppConfig.primaryColor).withOpacity(0.1), ), ), - child: Text(L10n.of(context)!.seeOptions), + child: Text( + inTrialWindow + ? L10n.of(context)!.activateTrial + : L10n.of(context)!.seeOptions, + ), ), ), const SizedBox(height: 5.0), diff --git a/needed-translations.txt b/needed-translations.txt index 72d449649..ce3531669 100644 --- a/needed-translations.txt +++ b/needed-translations.txt @@ -809,7 +809,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "bn": [ @@ -1637,7 +1643,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "bo": [ @@ -2465,7 +2477,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "ca": [ @@ -3293,7 +3311,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "cs": [ @@ -4121,7 +4145,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "de": [ @@ -4918,7 +4948,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "el": [ @@ -5746,7 +5782,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "eo": [ @@ -6574,14 +6616,26 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "es": [ "errorGettingAudio", "define", "listen", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "et": [ @@ -7394,7 +7448,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "eu": [ @@ -8191,7 +8251,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "fa": [ @@ -9019,7 +9085,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "fi": [ @@ -9847,7 +9919,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "fr": [ @@ -10675,7 +10753,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "ga": [ @@ -11503,7 +11587,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "gl": [ @@ -12300,7 +12390,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "he": [ @@ -13128,7 +13224,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "hi": [ @@ -13956,7 +14058,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "hr": [ @@ -14771,7 +14879,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "hu": [ @@ -15599,7 +15713,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "id": [ @@ -16427,7 +16547,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "ie": [ @@ -17255,7 +17381,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "it": [ @@ -18068,7 +18200,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "ja": [ @@ -18896,7 +19034,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "ko": [ @@ -19724,7 +19868,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "lt": [ @@ -20552,7 +20702,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "lv": [ @@ -21380,7 +21536,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "nb": [ @@ -22208,7 +22370,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "nl": [ @@ -23036,7 +23204,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "pl": [ @@ -23864,7 +24038,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "pt": [ @@ -24692,7 +24872,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "pt_BR": [ @@ -25489,7 +25675,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "pt_PT": [ @@ -26317,7 +26509,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "ro": [ @@ -27145,7 +27343,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "ru": [ @@ -27946,7 +28150,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "sk": [ @@ -28774,7 +28984,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "sl": [ @@ -29602,7 +29818,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "sr": [ @@ -30430,7 +30652,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "sv": [ @@ -31258,7 +31486,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "ta": [ @@ -32086,7 +32320,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "th": [ @@ -32914,7 +33154,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "tr": [ @@ -33727,7 +33973,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "uk": [ @@ -34540,7 +34792,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "vi": [ @@ -35368,7 +35626,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "zh": [ @@ -36181,7 +36445,13 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ], "zh_Hant": [ @@ -37009,6 +37279,12 @@ "enableModeration", "enableModerationDesc", "conversationLanguageLevel", - "showDefinition" + "showDefinition", + "acceptedKeyVerification", + "canceledKeyVerification", + "completedKeyVerification", + "isReadyForKeyVerification", + "requestedKeyVerification", + "startedKeyVerification" ] }