decoupling playing audio and sending audio event

pull/1011/head
Gabby Gurdin 2 years ago
parent 3d10d5a34c
commit 186982918d

@ -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,13 +15,24 @@ 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;
// Pangea#
static String? currentId;
static const int wavesCount = 40;
const AudioPlayerWidget(this.event, {this.color = Colors.black, super.key});
const AudioPlayerWidget(
this.event, {
this.color = Colors.black,
// #Pangea
this.matrixFile,
// Pangea#
super.key,
});
@override
AudioPlayerState createState() => AudioPlayerState();
@ -58,16 +70,27 @@ class AudioPlayerState extends State<AudioPlayerWidget> {
}
Future<void> _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);
@ -94,14 +117,17 @@ class AudioPlayerState extends State<AudioPlayerWidget> {
void _playAction() async {
final audioPlayer = this.audioPlayer ??= AudioPlayer();
if (AudioPlayerWidget.currentId != widget.event.eventId) {
// #Pangea
// if (AudioPlayerWidget.currentId != widget.event.eventId) {
// Pangea#
if (AudioPlayerWidget.currentId != widget.event?.eventId) {
if (AudioPlayerWidget.currentId != null) {
if (audioPlayer.playerState.playing) {
await audioPlayer.stop();
setState(() {});
}
}
AudioPlayerWidget.currentId = widget.event.eventId;
AudioPlayerWidget.currentId = widget.event?.eventId;
}
if (audioPlayer.playerState.playing) {
await audioPlayer.pause();
@ -136,27 +162,20 @@ class AudioPlayerState extends State<AudioPlayerWidget> {
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#
@ -170,18 +189,32 @@ class AudioPlayerState extends State<AudioPlayerWidget> {
static const double buttonSize = 36;
String? get _durationString {
final durationInt = widget.event.content
.tryGetMap<String, dynamic>('info')
?.tryGet<int>('duration');
// #Pangea
int? durationInt;
if (widget.matrixFile?.duration != null) {
durationInt = widget.matrixFile!.duration;
} else {
// final durationInt = widget.event?.content
durationInt = widget.event?.content
.tryGetMap<String, dynamic>('info')
?.tryGet<int>('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<int> _getWaveform() {
final eventWaveForm = widget.event.content
.tryGetMap<String, dynamic>('org.matrix.msc1767.audio')
?.tryGetList<int>('waveform');
// #Pangea
final eventWaveForm = widget.matrixFile?.waveform ??
widget.event?.content
.tryGetMap<String, dynamic>('org.matrix.msc1767.audio')
?.tryGetList<int>('waveform');
// final eventWaveForm = widget.event?.content
// .tryGetMap<String, dynamic>('org.matrix.msc1767.audio')
// ?.tryGetList<int>('waveform');
// Pangea#
if (eventWaveForm == null || eventWaveForm.isEmpty) {
return List<int>.filled(AudioPlayerWidget.wavesCount, 500);
}
@ -205,6 +238,20 @@ class AudioPlayerState extends State<AudioPlayerWidget> {
void initState() {
super.initState();
waveform = _getWaveform();
// #Pangea
if (widget.matrixFile != null) {
if (!kIsWeb) {
getTemporaryDirectory().then((val) {
final tempDir = val;
final file = File('${tempDir.path}/${widget.matrixFile!.name}');
file.writeAsBytesSync(widget.matrixFile!.bytes);
audioFile = file;
});
}
status = AudioPlayerStatus.downloaded;
setState(() {});
}
// Pangea#
}
@override
@ -233,7 +280,7 @@ class AudioPlayerState extends State<AudioPlayerWidget> {
color: widget.color,
),
),
onLongPress: () => widget.event.saveFile(context),
onLongPress: () => widget.event?.saveFile(context),
onTap: () {
if (status == AudioPlayerStatus.downloaded) {
_playAction();
@ -313,3 +360,24 @@ class MatrixFileAudioSource extends StreamAudioSource {
);
}
}
// #Pangea
class BytesAudioSource extends StreamAudioSource {
final Uint8List bytes;
final String mimeType;
BytesAudioSource(this.bytes, this.mimeType);
@override
Future<StreamAudioResponse> 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#

@ -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,73 @@ class PangeaMessageEvent {
return true;
}
Future<PangeaAudioFile> getMatrixAudioFile(String langCode) async {
final String text = representationByLanguage(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<Event?> 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

@ -21,17 +21,36 @@ class MessageAudioCard extends StatefulWidget {
class MessageAudioCardState extends State<MessageAudioCard> {
bool _isLoading = false;
Event? localAudioEvent;
PangeaAudioFile? audioFile;
void fetchAudio() {
Future<void> fetchAudio() async {
if (!mounted) return;
setState(() => _isLoading = true);
widget.messageEvent
.getAudioGlobal(widget.messageEvent.messageDisplayLangCode)
.then((Event? event) {
localAudioEvent = event;
}).catchError((e) {
// first, try to get the audio event
// if there's not audio event, then call the API
// Then, if on mobile, save it to a temp file and use that as audio source
// If on web, stream the audio bytes
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);
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),
@ -46,10 +65,8 @@ class MessageAudioCardState extends State<MessageAudioCard> {
widget.messageEvent.messageDisplayLangCode,
},
);
return null;
}).whenComplete(() {
if (mounted) setState(() => _isLoading = false);
});
}
return;
}
@override
@ -85,7 +102,7 @@ class MessageAudioCardState extends State<MessageAudioCard> {
color: Theme.of(context).colorScheme.primary,
),
)
: localAudioEvent != null
: localAudioEvent != null || audioFile != null
? Container(
constraints: const BoxConstraints(
maxWidth: 250,
@ -93,8 +110,9 @@ class MessageAudioCardState extends State<MessageAudioCard> {
child: Column(
children: [
AudioPlayerWidget(
localAudioEvent!,
localAudioEvent,
color: Theme.of(context).colorScheme.onPrimaryContainer,
matrixFile: audioFile,
),
],
),
@ -106,3 +124,15 @@ class MessageAudioCardState extends State<MessageAudioCard> {
);
}
}
class PangeaAudioFile extends MatrixAudioFile {
List<int>? waveform;
PangeaAudioFile({
required super.bytes,
required super.name,
super.mimeType,
super.duration,
this.waveform,
});
}

@ -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"
]
}

Loading…
Cancel
Save