full draft speech to text with word level feedback
This commit is contained in:
parent
f3bb717245
commit
4a77e6fb53
39 changed files with 637 additions and 274 deletions
|
|
@ -3887,7 +3887,7 @@
|
|||
"more": "More",
|
||||
"translationTooltip": "Translate",
|
||||
"audioTooltip": "Play Audio",
|
||||
"transcriptTooltip": "Transcript",
|
||||
"speechToTextTooltip": "Transcript",
|
||||
"certifyAge": "I certify that I am over {age} years of age",
|
||||
"@certifyAge": {
|
||||
"type": "text",
|
||||
|
|
|
|||
|
|
@ -4572,7 +4572,7 @@
|
|||
"more": "Más",
|
||||
"translationTooltip": "Traducir",
|
||||
"audioTooltip": "Reproducir audio",
|
||||
"transcriptTooltip": "Transcripción",
|
||||
"speechToTextTooltip": "Transcripción",
|
||||
"yourBirthdayPleaseShort": "Seleccione su grupo de edad",
|
||||
"certifyAge": "Certifico que soy mayor de {age} años",
|
||||
"@certifyAge": {
|
||||
|
|
|
|||
|
|
@ -17,11 +17,12 @@ import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart';
|
|||
import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
|
||||
import 'package:fluffychat/pangea/enum/use_type.dart';
|
||||
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/models/choreo_record.dart';
|
||||
import 'package:fluffychat/pangea/models/class_model.dart';
|
||||
import 'package:fluffychat/pangea/models/message_data_models.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/models/representation_content_model.dart';
|
||||
import 'package:fluffychat/pangea/models/student_analytics_summary_model.dart';
|
||||
import 'package:fluffychat/pangea/models/tokens_event_content_model.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/utils/firebase_analytics.dart';
|
||||
import 'package:fluffychat/pangea/utils/report_message.dart';
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/pages/chat/chat.dart';
|
||||
import 'package:fluffychat/pangea/enum/use_type.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/models/language_model.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/widgets/chat/message_toolbar.dart';
|
||||
import 'package:fluffychat/utils/date_time_extension.dart';
|
||||
import 'package:fluffychat/utils/string_color.dart';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:fluffychat/pages/chat/events/html_message.dart';
|
||||
import 'package:fluffychat/pages/chat/events/video_player.dart';
|
||||
import 'package:fluffychat/pangea/enum/message_mode_enum.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/widgets/chat/message_context_menu.dart';
|
||||
import 'package:fluffychat/pangea/widgets/chat/message_toolbar.dart';
|
||||
import 'package:fluffychat/pangea/widgets/igc/pangea_rich_text.dart';
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@ import 'package:fluffychat/pangea/enum/edit_type.dart';
|
|||
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
|
||||
import 'package:fluffychat/pangea/models/class_model.dart';
|
||||
import 'package:fluffychat/pangea/models/it_step.dart';
|
||||
import 'package:fluffychat/pangea/models/message_data_models.dart';
|
||||
import 'package:fluffychat/pangea/models/representation_content_model.dart';
|
||||
import 'package:fluffychat/pangea/models/tokens_event_content_model.dart';
|
||||
import 'package:fluffychat/pangea/utils/any_state_holder.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/utils/overlay.dart';
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ import 'package:matrix/matrix.dart';
|
|||
import '../constants/class_default_values.dart';
|
||||
import '../extensions/client_extension.dart';
|
||||
import '../extensions/pangea_room_extension.dart';
|
||||
import '../matrix_event_wrappers/construct_analytics_event.dart';
|
||||
import '../models/chart_analytics_model.dart';
|
||||
import '../models/construct_analytics_event.dart';
|
||||
import '../models/student_analytics_event.dart';
|
||||
import 'base_controller.dart';
|
||||
import 'pangea_controller.dart';
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@ import 'package:collection/collection.dart';
|
|||
import 'package:fluffychat/pangea/controllers/base_controller.dart';
|
||||
import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
|
||||
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
|
||||
import 'package:fluffychat/pangea/models/message_data_models.dart';
|
||||
import 'package:fluffychat/pangea/models/representation_content_model.dart';
|
||||
import 'package:fluffychat/pangea/models/tokens_event_content_model.dart';
|
||||
import 'package:fluffychat/pangea/repo/tokens_repo.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import 'dart:convert';
|
|||
import 'package:fluffychat/pangea/constants/pangea_event_types.dart';
|
||||
import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
|
||||
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
|
||||
import 'package:fluffychat/pangea/models/representation_content_model.dart';
|
||||
import 'package:fluffychat/pangea/models/speech_to_text_models.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
|
@ -13,10 +14,10 @@ import '../config/environment.dart';
|
|||
import '../network/requests.dart';
|
||||
import '../network/urls.dart';
|
||||
|
||||
// Assuming SpeechToTextRequestModel, SpeechToTextResponseModel and related models are already defined as in your provided code.
|
||||
// Assuming SpeechToTextRequestModel, SpeechToTextModel and related models are already defined as in your provided code.
|
||||
|
||||
class _SpeechToTextCacheItem {
|
||||
Future<SpeechToTextResponseModel> data;
|
||||
Future<SpeechToTextModel> data;
|
||||
|
||||
_SpeechToTextCacheItem({required this.data});
|
||||
}
|
||||
|
|
@ -43,7 +44,7 @@ class SpeechToTextController {
|
|||
_cacheClearTimer?.cancel();
|
||||
}
|
||||
|
||||
Future<SpeechToTextResponseModel> get(
|
||||
Future<SpeechToTextModel> get(
|
||||
SpeechToTextRequestModel requestModel,
|
||||
) async {
|
||||
final int cacheKey = requestModel.hashCode;
|
||||
|
|
@ -51,7 +52,7 @@ class SpeechToTextController {
|
|||
if (_cache.containsKey(cacheKey)) {
|
||||
return _cache[cacheKey]!.data;
|
||||
} else {
|
||||
final Future<SpeechToTextResponseModel> response = _fetchResponse(
|
||||
final Future<SpeechToTextModel> response = _fetchResponse(
|
||||
accessToken: await _pangeaController.userController.accessToken,
|
||||
requestModel: requestModel,
|
||||
);
|
||||
|
|
@ -61,8 +62,8 @@ class SpeechToTextController {
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> saveTranscriptAsMatrixEvent(
|
||||
SpeechToTextResponseModel response,
|
||||
Future<void> saveSpeechToTextAsRepresentationEvent(
|
||||
SpeechToTextModel response,
|
||||
SpeechToTextRequestModel requestModel,
|
||||
) {
|
||||
if (requestModel.audioEvent == null) {
|
||||
|
|
@ -72,19 +73,24 @@ class SpeechToTextController {
|
|||
return Future.value(null);
|
||||
}
|
||||
debugPrint('Saving transcript as matrix event');
|
||||
final json = response.toJson();
|
||||
|
||||
requestModel.audioEvent?.room.sendPangeaEvent(
|
||||
content: response.toJson(),
|
||||
content: PangeaRepresentation(
|
||||
langCode: response.langCode,
|
||||
text: response.transcript.text,
|
||||
originalSent: false,
|
||||
originalWritten: false,
|
||||
speechToText: response,
|
||||
).toJson(),
|
||||
parentEventId: requestModel.audioEvent!.eventId,
|
||||
type: PangeaEventTypes.transcript,
|
||||
type: PangeaEventTypes.representation,
|
||||
);
|
||||
debugPrint('Transcript saved as matrix event');
|
||||
|
||||
return Future.value(null);
|
||||
}
|
||||
|
||||
Future<SpeechToTextResponseModel> _fetchResponse({
|
||||
Future<SpeechToTextModel> _fetchResponse({
|
||||
required String accessToken,
|
||||
required SpeechToTextRequestModel requestModel,
|
||||
}) async {
|
||||
|
|
@ -101,9 +107,9 @@ class SpeechToTextController {
|
|||
if (res.statusCode == 200) {
|
||||
final Map<String, dynamic> json = jsonDecode(utf8.decode(res.bodyBytes));
|
||||
|
||||
final response = SpeechToTextResponseModel.fromJson(json);
|
||||
final response = SpeechToTextModel.fromJson(json);
|
||||
|
||||
saveTranscriptAsMatrixEvent(response, requestModel).onError(
|
||||
saveSpeechToTextAsRepresentationEvent(response, requestModel).onError(
|
||||
(error, stackTrace) => ErrorHandler.logError(e: error, s: stackTrace),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ AudioEncodingEnum mimeTypeToAudioEncoding(String mimeType) {
|
|||
return AudioEncodingEnum.mp4;
|
||||
case 'audio/ogg':
|
||||
return AudioEncodingEnum.oggOpus;
|
||||
case 'audio/x-flac':
|
||||
return AudioEncodingEnum.flac;
|
||||
default:
|
||||
return AudioEncodingEnum.encodingUnspecified;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ extension MessageModeExtension on MessageMode {
|
|||
case MessageMode.textToSpeech:
|
||||
return L10n.of(context)!.messageAudio;
|
||||
case MessageMode.speechToText:
|
||||
return L10n.of(context)!.transcriptTooltip;
|
||||
return L10n.of(context)!.speechToTextTooltip;
|
||||
case MessageMode.definition:
|
||||
return L10n.of(context)!.definitions;
|
||||
default:
|
||||
|
|
@ -43,7 +43,7 @@ extension MessageModeExtension on MessageMode {
|
|||
case MessageMode.textToSpeech:
|
||||
return L10n.of(context)!.audioTooltip;
|
||||
case MessageMode.speechToText:
|
||||
return L10n.of(context)!.transcriptTooltip;
|
||||
return L10n.of(context)!.speechToTextTooltip;
|
||||
case MessageMode.definition:
|
||||
return L10n.of(context)!.define;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/constants/pangea_event_types.dart';
|
||||
import 'package:fluffychat/pangea/models/choreo_record.dart';
|
||||
import 'package:fluffychat/pangea/models/message_data_models.dart';
|
||||
import 'package:fluffychat/pangea/models/representation_content_model.dart';
|
||||
import 'package:fluffychat/pangea/models/tokens_event_content_model.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
extension PangeaEvent on Event {
|
||||
V getPangeaContent<V>() {
|
||||
|
|
|
|||
|
|
@ -4,9 +4,10 @@ import 'dart:developer';
|
|||
import 'package:fluffychat/pangea/constants/class_default_values.dart';
|
||||
import 'package:fluffychat/pangea/constants/model_keys.dart';
|
||||
import 'package:fluffychat/pangea/constants/pangea_room_types.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/models/bot_options_model.dart';
|
||||
import 'package:fluffychat/pangea/models/class_model.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/models/tokens_event_content_model.dart';
|
||||
import 'package:fluffychat/pangea/utils/bot_name.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
|
@ -22,10 +23,10 @@ import '../../config/app_config.dart';
|
|||
import '../constants/pangea_event_types.dart';
|
||||
import '../enum/construct_type_enum.dart';
|
||||
import '../enum/use_type.dart';
|
||||
import '../matrix_event_wrappers/construct_analytics_event.dart';
|
||||
import '../models/choreo_record.dart';
|
||||
import '../models/construct_analytics_event.dart';
|
||||
import '../models/constructs_analytics_model.dart';
|
||||
import '../models/message_data_models.dart';
|
||||
import '../models/representation_content_model.dart';
|
||||
import '../models/student_analytics_event.dart';
|
||||
import '../models/student_analytics_summary_model.dart';
|
||||
import '../utils/p_store.dart';
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/extensions/pangea_event_extension.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import '../constants/pangea_event_types.dart';
|
||||
import 'choreo_record.dart';
|
||||
import '../models/choreo_record.dart';
|
||||
|
||||
class ChoreoEvent {
|
||||
Event event;
|
||||
|
|
@ -5,12 +5,13 @@ import 'package:fluffychat/pangea/constants/model_keys.dart';
|
|||
import 'package:fluffychat/pangea/controllers/text_to_speech_controller.dart';
|
||||
import 'package:fluffychat/pangea/enum/audio_encoding_enum.dart';
|
||||
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_representation_event.dart';
|
||||
import 'package:fluffychat/pangea/models/choreo_record.dart';
|
||||
import 'package:fluffychat/pangea/models/class_model.dart';
|
||||
import 'package:fluffychat/pangea/models/message_data_models.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_match_model.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_representation_event.dart';
|
||||
import 'package:fluffychat/pangea/models/representation_content_model.dart';
|
||||
import 'package:fluffychat/pangea/models/speech_to_text_models.dart';
|
||||
import 'package:fluffychat/pangea/models/tokens_event_content_model.dart';
|
||||
import 'package:fluffychat/pangea/utils/bot_name.dart';
|
||||
import 'package:fluffychat/pangea/widgets/chat/message_audio_card.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
@ -270,36 +271,33 @@ class PangeaMessageEvent {
|
|||
null;
|
||||
}).toSet();
|
||||
|
||||
Set<Event> get transcriptionEvents => _event.aggregatedEvents(
|
||||
timeline,
|
||||
PangeaEventTypes.transcript,
|
||||
);
|
||||
|
||||
Event? get transcriptionEvent => transcriptionEvents.lastOrNull;
|
||||
|
||||
Future<SpeechToTextResponseModel?> getSpeechToTextLocal() async {
|
||||
if (transcriptionEvent == null) return null;
|
||||
|
||||
return SpeechToTextResponseModel.fromJson(
|
||||
transcriptionEvent!.content[PangeaEventTypes.transcript]
|
||||
as Map<String, dynamic>,
|
||||
);
|
||||
}
|
||||
|
||||
Future<SpeechToTextResponseModel?> getSpeechToTextGlobal(
|
||||
Future<SpeechToTextModel?> getSpeechToText(
|
||||
String l1Code,
|
||||
String l2Code,
|
||||
) async {
|
||||
if (!isAudioMessage) {
|
||||
ErrorHandler.logError(
|
||||
e: 'Message is not an audio message ${_event.eventId}',
|
||||
e: 'Calling getSpeechToText on non-audio message',
|
||||
s: StackTrace.current,
|
||||
data: _event.content,
|
||||
data: {
|
||||
"content": _event.content,
|
||||
"eventId": _event.eventId,
|
||||
"roomId": _event.roomId,
|
||||
"userId": _event.room.client.userID,
|
||||
"account_data": _event.room.client.accountData,
|
||||
},
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (transcriptionEvent != null) return getSpeechToTextLocal();
|
||||
final SpeechToTextModel? speechToTextLocal = representations
|
||||
.firstWhereOrNull(
|
||||
(element) => element.content.speechToText != null,
|
||||
)
|
||||
?.content
|
||||
.speechToText;
|
||||
|
||||
if (speechToTextLocal != null) return speechToTextLocal;
|
||||
|
||||
final matrixFile = await _event.downloadAndDecryptAttachment();
|
||||
// Pangea#
|
||||
|
|
@ -323,7 +321,10 @@ class PangeaMessageEvent {
|
|||
|
||||
// audioFile = file;
|
||||
|
||||
final SpeechToTextResponseModel response =
|
||||
debugPrint("mimeType ${matrixFile.mimeType}");
|
||||
debugPrint("encoding ${mimeTypeToAudioEncoding(matrixFile.mimeType)}");
|
||||
|
||||
final SpeechToTextModel response =
|
||||
await MatrixState.pangeaController.speechToText.get(
|
||||
SpeechToTextRequestModel(
|
||||
audioContent: matrixFile.bytes,
|
||||
|
|
@ -332,7 +333,7 @@ class PangeaMessageEvent {
|
|||
encoding: mimeTypeToAudioEncoding(matrixFile.mimeType),
|
||||
//this is the default in the RecordConfig in record package
|
||||
//TODO: check if this is the correct value and make it a constant somewhere
|
||||
sampleRateHertz: 44100,
|
||||
sampleRateHertz: 22050,
|
||||
userL1: l1Code,
|
||||
userL2: l2Code,
|
||||
),
|
||||
|
|
@ -1,8 +1,10 @@
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:fluffychat/pangea/extensions/pangea_event_extension.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_choreo_event.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_choreo_event.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_token_model.dart';
|
||||
import 'package:fluffychat/pangea/models/speech_to_text_models.dart';
|
||||
import 'package:fluffychat/pangea/models/tokens_event_content_model.dart';
|
||||
import 'package:fluffychat/pangea/repo/tokens_repo.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
@ -13,9 +15,9 @@ import 'package:sentry_flutter/sentry_flutter.dart';
|
|||
import '../../widgets/matrix.dart';
|
||||
import '../constants/language_keys.dart';
|
||||
import '../constants/pangea_event_types.dart';
|
||||
import '../models/choreo_record.dart';
|
||||
import '../models/representation_content_model.dart';
|
||||
import '../utils/error_handler.dart';
|
||||
import 'choreo_record.dart';
|
||||
import 'message_data_models.dart';
|
||||
import 'pangea_tokens_event.dart';
|
||||
|
||||
class RepresentationEvent {
|
||||
|
|
@ -25,12 +27,15 @@ class RepresentationEvent {
|
|||
ChoreoRecord? _choreo;
|
||||
Timeline timeline;
|
||||
|
||||
SpeechToTextModel? _speechToTextResponse;
|
||||
|
||||
RepresentationEvent({
|
||||
required this.timeline,
|
||||
Event? event,
|
||||
PangeaRepresentation? content,
|
||||
PangeaMessageTokens? tokens,
|
||||
ChoreoRecord? choreo,
|
||||
SpeechToTextModel? speechToTextResponse,
|
||||
}) {
|
||||
if (event != null && event.type != PangeaEventTypes.representation) {
|
||||
throw Exception(
|
||||
|
|
@ -41,10 +46,14 @@ class RepresentationEvent {
|
|||
_content = content;
|
||||
_tokens = tokens;
|
||||
_choreo = choreo;
|
||||
_speechToTextResponse = speechToTextResponse;
|
||||
}
|
||||
|
||||
Event? get event => _event;
|
||||
|
||||
// Note: in the case where the event is the originalSent or originalWritten event,
|
||||
// the content will be set on initialization by the PangeaMessageEvent
|
||||
// Otherwise, the content will be fetched from the event where it is stored in content[type]
|
||||
PangeaRepresentation get content {
|
||||
if (_content != null) return _content!;
|
||||
_content = _event?.getPangeaContent<PangeaRepresentation>();
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
import 'package:fluffychat/pangea/extensions/pangea_event_extension.dart';
|
||||
import 'package:fluffychat/pangea/models/tokens_event_content_model.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/extensions/pangea_event_extension.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import '../constants/pangea_event_types.dart';
|
||||
import 'message_data_models.dart';
|
||||
|
||||
class TokensEvent {
|
||||
Event event;
|
||||
|
|
@ -1,9 +1,8 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:fluffychat/pangea/constants/language_keys.dart';
|
||||
import 'package:fluffychat/pangea/models/speech_to_text_models.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/models/pangea_token_model.dart';
|
||||
|
||||
/// this class is contained within a [RepresentationEvent]
|
||||
/// this event is the child of a [EventTypes.Message]
|
||||
/// the event has two potential children events -
|
||||
|
|
@ -22,6 +21,9 @@ class PangeaRepresentation {
|
|||
bool originalSent;
|
||||
bool originalWritten;
|
||||
|
||||
// a representation can be create via speech to text on the original message
|
||||
SpeechToTextModel? speechToText;
|
||||
|
||||
// how do we know which representation was sent by author?
|
||||
// RepresentationEvent.text == PangeaMessageEvent.event.body
|
||||
// use: to know whether directUse
|
||||
|
|
@ -49,20 +51,33 @@ class PangeaRepresentation {
|
|||
required this.text,
|
||||
required this.originalSent,
|
||||
required this.originalWritten,
|
||||
this.speechToText,
|
||||
});
|
||||
|
||||
factory PangeaRepresentation.fromJson(Map<String, dynamic> json) =>
|
||||
PangeaRepresentation(
|
||||
langCode: json[_langCodeKey],
|
||||
text: json[_textKey],
|
||||
originalSent: json[_originalSentKey] ?? false,
|
||||
originalWritten: json[_originalWrittenKey] ?? false,
|
||||
factory PangeaRepresentation.fromJson(Map<String, dynamic> json) {
|
||||
if (json[_langCodeKey] == LanguageKeys.unknownLanguage) {
|
||||
ErrorHandler.logError(
|
||||
e: Exception("Language code cannot be 'unk'"),
|
||||
s: StackTrace.current,
|
||||
data: {"rep_content": json},
|
||||
);
|
||||
}
|
||||
return PangeaRepresentation(
|
||||
langCode: json[_langCodeKey],
|
||||
text: json[_textKey],
|
||||
originalSent: json[_originalSentKey] ?? false,
|
||||
originalWritten: json[_originalWrittenKey] ?? false,
|
||||
speechToText: json[_speechToTextKey] == null
|
||||
? null
|
||||
: SpeechToTextModel.fromJson(json[_speechToTextKey]),
|
||||
);
|
||||
}
|
||||
|
||||
static const _textKey = "txt";
|
||||
static const _langCodeKey = "lang";
|
||||
static const _originalSentKey = "snt";
|
||||
static const _originalWrittenKey = "wrttn";
|
||||
static const _speechToTextKey = "stt";
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final data = <String, dynamic>{};
|
||||
|
|
@ -70,35 +85,9 @@ class PangeaRepresentation {
|
|||
data[_langCodeKey] = langCode;
|
||||
if (originalSent) data[_originalSentKey] = originalSent;
|
||||
if (originalWritten) data[_originalWrittenKey] = originalWritten;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
/// this class lives within a [PangeaTokensEvent]
|
||||
/// it always has a [RepresentationEvent] parent
|
||||
/// These live as separate event so that anyone can add and edit tokens to
|
||||
/// representation
|
||||
class PangeaMessageTokens {
|
||||
List<PangeaToken> tokens;
|
||||
|
||||
PangeaMessageTokens({
|
||||
required this.tokens,
|
||||
});
|
||||
|
||||
factory PangeaMessageTokens.fromJson(Map<String, dynamic> json) {
|
||||
return PangeaMessageTokens(
|
||||
tokens: (jsonDecode(json[_tokensKey] ?? "[]") as Iterable)
|
||||
.map((e) => PangeaToken.fromJson(e))
|
||||
.toList()
|
||||
.cast<PangeaToken>(),
|
||||
);
|
||||
}
|
||||
|
||||
static const _tokensKey = "tkns";
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final data = <String, dynamic>{};
|
||||
data[_tokensKey] = jsonEncode(tokens.map((e) => e.toJson()).toList());
|
||||
if (speechToText != null) {
|
||||
data[_speechToTextKey] = speechToText!.toJson();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,10 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pangea/enum/audio_encoding_enum.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_token_model.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
class SpeechToTextAudioConfigModel {
|
||||
|
|
@ -67,21 +70,37 @@ class SpeechToTextRequestModel {
|
|||
}
|
||||
}
|
||||
|
||||
class WordInfo {
|
||||
final String word;
|
||||
class STTToken {
|
||||
final PangeaToken token;
|
||||
final Duration? startTime;
|
||||
final Duration? endTime;
|
||||
final int? confidence;
|
||||
|
||||
WordInfo({
|
||||
required this.word,
|
||||
STTToken({
|
||||
required this.token,
|
||||
this.startTime,
|
||||
this.endTime,
|
||||
this.confidence,
|
||||
});
|
||||
|
||||
factory WordInfo.fromJson(Map<String, dynamic> json) => WordInfo(
|
||||
word: json['word'],
|
||||
int get offset => token.text.offset;
|
||||
|
||||
int get length => token.text.length;
|
||||
|
||||
Color color(BuildContext context) {
|
||||
if (confidence == null || confidence! > 80) {
|
||||
return Theme.of(context).brightness == Brightness.dark
|
||||
? AppConfig.primaryColorLight
|
||||
: AppConfig.primaryColor;
|
||||
}
|
||||
if (confidence! > 50) {
|
||||
return const Color.fromARGB(255, 184, 142, 43);
|
||||
}
|
||||
return Colors.red;
|
||||
}
|
||||
|
||||
factory STTToken.fromJson(Map<String, dynamic> json) => STTToken(
|
||||
token: PangeaToken.fromJson(json['token']),
|
||||
startTime: json['start_time'] != null
|
||||
? Duration(milliseconds: json['start_time'])
|
||||
: null,
|
||||
|
|
@ -92,7 +111,7 @@ class WordInfo {
|
|||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"word": word,
|
||||
"token": token,
|
||||
"start_time": startTime?.inMilliseconds,
|
||||
"end_time": endTime?.inMilliseconds,
|
||||
"confidence": confidence,
|
||||
|
|
@ -100,27 +119,32 @@ class WordInfo {
|
|||
}
|
||||
|
||||
class Transcript {
|
||||
final String transcript;
|
||||
final String text;
|
||||
final int confidence;
|
||||
final List<WordInfo> words;
|
||||
final List<STTToken> sttTokens;
|
||||
final String langCode;
|
||||
|
||||
Transcript({
|
||||
required this.transcript,
|
||||
required this.text,
|
||||
required this.confidence,
|
||||
required this.words,
|
||||
required this.sttTokens,
|
||||
required this.langCode,
|
||||
});
|
||||
|
||||
factory Transcript.fromJson(Map<String, dynamic> json) => Transcript(
|
||||
transcript: json['transcript'],
|
||||
text: json['transcript'],
|
||||
confidence: json['confidence'].toDouble(),
|
||||
words:
|
||||
(json['words'] as List).map((e) => WordInfo.fromJson(e)).toList(),
|
||||
sttTokens: (json['stt_tokens'] as List)
|
||||
.map((e) => STTToken.fromJson(e))
|
||||
.toList(),
|
||||
langCode: json['lang_code'],
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"transcript": transcript,
|
||||
"transcript": text,
|
||||
"confidence": confidence,
|
||||
"words": words.map((e) => e.toJson()).toList(),
|
||||
"stt_tokens": sttTokens.map((e) => e.toJson()).toList(),
|
||||
"lang_code": langCode,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -141,15 +165,19 @@ class SpeechToTextResult {
|
|||
};
|
||||
}
|
||||
|
||||
class SpeechToTextResponseModel {
|
||||
class SpeechToTextModel {
|
||||
final List<SpeechToTextResult> results;
|
||||
|
||||
SpeechToTextResponseModel({
|
||||
SpeechToTextModel({
|
||||
required this.results,
|
||||
});
|
||||
|
||||
factory SpeechToTextResponseModel.fromJson(Map<String, dynamic> json) =>
|
||||
SpeechToTextResponseModel(
|
||||
Transcript get transcript => results.first.transcripts.first;
|
||||
|
||||
String get langCode => results.first.transcripts.first.langCode;
|
||||
|
||||
factory SpeechToTextModel.fromJson(Map<String, dynamic> json) =>
|
||||
SpeechToTextModel(
|
||||
results: (json['results'] as List)
|
||||
.map((e) => SpeechToTextResult.fromJson(e))
|
||||
.toList(),
|
||||
|
|
|
|||
32
lib/pangea/models/tokens_event_content_model.dart
Normal file
32
lib/pangea/models/tokens_event_content_model.dart
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:fluffychat/pangea/models/pangea_token_model.dart';
|
||||
|
||||
/// this class lives within a [PangeaTokensEvent]
|
||||
/// it always has a [RepresentationEvent] parent
|
||||
/// These live as separate event so that anyone can add and edit tokens to
|
||||
/// representation
|
||||
class PangeaMessageTokens {
|
||||
List<PangeaToken> tokens;
|
||||
|
||||
PangeaMessageTokens({
|
||||
required this.tokens,
|
||||
});
|
||||
|
||||
factory PangeaMessageTokens.fromJson(Map<String, dynamic> json) {
|
||||
return PangeaMessageTokens(
|
||||
tokens: (jsonDecode(json[_tokensKey] ?? "[]") as Iterable)
|
||||
.map((e) => PangeaToken.fromJson(e))
|
||||
.toList()
|
||||
.cast<PangeaToken>(),
|
||||
);
|
||||
}
|
||||
|
||||
static const _tokensKey = "tkns";
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final data = <String, dynamic>{};
|
||||
data[_tokensKey] = jsonEncode(tokens.map((e) => e.toJson()).toList());
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
@ -5,11 +5,11 @@ import 'package:fluffychat/config/app_config.dart';
|
|||
import 'package:fluffychat/pangea/constants/pangea_event_types.dart';
|
||||
import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
|
||||
import 'package:fluffychat/pangea/enum/construct_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/models/construct_analytics_event.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/construct_analytics_event.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_representation_event.dart';
|
||||
import 'package:fluffychat/pangea/models/constructs_analytics_model.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_match_model.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_representation_event.dart';
|
||||
import 'package:fluffychat/pangea/pages/analytics/base_analytics.dart';
|
||||
import 'package:fluffychat/utils/date_time_extension.dart';
|
||||
import 'package:fluffychat/utils/string_color.dart';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class BotStyle {
|
||||
static TextStyle text(
|
||||
|
|
@ -25,6 +24,7 @@ class BotStyle {
|
|||
? AppConfig.primaryColorLight
|
||||
: AppConfig.primaryColor
|
||||
: null,
|
||||
inherit: true,
|
||||
);
|
||||
|
||||
return existingStyle?.merge(botStyle) ?? botStyle;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import 'package:syncfusion_flutter_xlsio/xlsio.dart';
|
|||
import 'package:universal_html/html.dart' as webFile;
|
||||
|
||||
import 'package:fluffychat/pangea/models/class_model.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import '../models/choreo_record.dart';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import 'package:fluffychat/pangea/constants/language_keys.dart';
|
||||
import 'package:fluffychat/pangea/constants/model_keys.dart';
|
||||
import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/models/class_model.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:fluffychat/pages/chat/events/audio_player.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/widgets/chat/toolbar_content_loading_indicator.dart';
|
||||
import 'package:fluffychat/pangea/widgets/igc/card_error_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
|
|
@ -74,17 +75,9 @@ class MessageAudioCardState extends State<MessageAudioCard> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
return Container(
|
||||
child: _isLoading
|
||||
? SizedBox(
|
||||
height: 14,
|
||||
width: 14,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2.0,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
)
|
||||
? const ToolbarContentLoadingIndicator()
|
||||
: localAudioEvent != null || audioFile != null
|
||||
? Container(
|
||||
constraints: const BoxConstraints(
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
import 'package:fluffychat/pangea/models/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/models/speech_to_text_models.dart';
|
||||
import 'package:fluffychat/pangea/utils/bot_style.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/widgets/chat/speech_to_text_score.dart';
|
||||
import 'package:fluffychat/pangea/widgets/chat/speech_to_text_text.dart';
|
||||
import 'package:fluffychat/pangea/widgets/chat/toolbar_content_loading_indicator.dart';
|
||||
import 'package:fluffychat/pangea/widgets/igc/card_error_widget.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
@ -19,7 +21,7 @@ class MessageSpeechToTextCard extends StatefulWidget {
|
|||
}
|
||||
|
||||
class MessageSpeechToTextCardState extends State<MessageSpeechToTextCard> {
|
||||
SpeechToTextResponseModel? speechToTextResponse;
|
||||
SpeechToTextModel? speechToTextResponse;
|
||||
bool _fetchingTranscription = true;
|
||||
Object? error;
|
||||
|
||||
|
|
@ -32,9 +34,6 @@ class MessageSpeechToTextCardState extends State<MessageSpeechToTextCard> {
|
|||
roomID: widget.messageEvent.room.id,
|
||||
);
|
||||
|
||||
String? get transcription => speechToTextResponse
|
||||
?.results.firstOrNull?.transcripts.firstOrNull?.transcript;
|
||||
|
||||
// look for transcription in message event
|
||||
// if not found, call API to transcribe audio
|
||||
Future<void> getSpeechToText() async {
|
||||
|
|
@ -43,7 +42,11 @@ class MessageSpeechToTextCardState extends State<MessageSpeechToTextCard> {
|
|||
throw Exception('Language selection not found');
|
||||
}
|
||||
speechToTextResponse ??=
|
||||
await widget.messageEvent.getSpeechToTextGlobal(l1Code!, l2Code!);
|
||||
await widget.messageEvent.getSpeechToText(l1Code!, l2Code!);
|
||||
|
||||
debugPrint(
|
||||
'Speech to text transcript: ${speechToTextResponse?.transcript.text}',
|
||||
);
|
||||
} catch (e, s) {
|
||||
error = e;
|
||||
ErrorHandler.logError(
|
||||
|
|
@ -64,25 +67,23 @@ class MessageSpeechToTextCardState extends State<MessageSpeechToTextCard> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (!_fetchingTranscription && speechToTextResponse == null) {
|
||||
if (_fetchingTranscription) {
|
||||
return const ToolbarContentLoadingIndicator();
|
||||
}
|
||||
|
||||
//done fetchig but not results means some kind of error
|
||||
if (speechToTextResponse == null) {
|
||||
return CardErrorWidget(error: error);
|
||||
}
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: _fetchingTranscription
|
||||
? SizedBox(
|
||||
height: 14,
|
||||
width: 14,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2.0,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
)
|
||||
: Text(
|
||||
transcription!,
|
||||
style: BotStyle.text(context),
|
||||
),
|
||||
return Column(
|
||||
children: [
|
||||
SpeechToTextText(transcript: speechToTextResponse!.transcript),
|
||||
const Divider(),
|
||||
SpeechToTextScoreWidget(
|
||||
score: speechToTextResponse!.transcript.confidence,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import 'package:fluffychat/config/themes.dart';
|
|||
import 'package:fluffychat/pages/chat/chat.dart';
|
||||
import 'package:fluffychat/pangea/constants/local.key.dart';
|
||||
import 'package:fluffychat/pangea/enum/message_mode_enum.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/utils/any_state_holder.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/utils/overlay.dart';
|
||||
|
|
@ -264,9 +264,11 @@ class MessageToolbarState extends State<MessageToolbar> {
|
|||
) ??
|
||||
true;
|
||||
autoplay
|
||||
? updateMode(widget.pangeaMessageEvent.isAudioMessage
|
||||
? MessageMode.speechToText
|
||||
: MessageMode.textToSpeech)
|
||||
? updateMode(
|
||||
widget.pangeaMessageEvent.isAudioMessage
|
||||
? MessageMode.speechToText
|
||||
: MessageMode.textToSpeech,
|
||||
)
|
||||
: updateMode(MessageMode.translation);
|
||||
});
|
||||
|
||||
|
|
@ -319,7 +321,10 @@ class MessageToolbarState extends State<MessageToolbar> {
|
|||
duration: FluffyThemes.animationDuration,
|
||||
child: Column(
|
||||
children: [
|
||||
toolbarContent ?? const SizedBox(),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: toolbarContent ?? const SizedBox(),
|
||||
),
|
||||
SizedBox(height: toolbarContent == null ? 0 : 20),
|
||||
],
|
||||
),
|
||||
|
|
@ -329,7 +334,7 @@ class MessageToolbarState extends State<MessageToolbar> {
|
|||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: MessageMode.values.map((mode) {
|
||||
if ([MessageMode.definition, MessageMode.textToSpeech]
|
||||
if ([MessageMode.definition, MessageMode.textToSpeech, MessageMode.translation]
|
||||
.contains(mode) &&
|
||||
widget.pangeaMessageEvent.isAudioMessage) {
|
||||
return const SizedBox.shrink();
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import 'package:fluffychat/pangea/models/message_data_models.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/models/representation_content_model.dart';
|
||||
import 'package:fluffychat/pangea/repo/full_text_translation_repo.dart';
|
||||
import 'package:fluffychat/pangea/utils/bot_style.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/widgets/chat/message_text_selection.dart';
|
||||
import 'package:fluffychat/pangea/widgets/chat/toolbar_content_loading_indicator.dart';
|
||||
import 'package:fluffychat/pangea/widgets/igc/card_error_widget.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
@ -139,17 +140,9 @@ class MessageTranslationCardState extends State<MessageTranslationCard> {
|
|||
return const CardErrorWidget();
|
||||
}
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
return Container(
|
||||
child: _fetchingRepresentation
|
||||
? SizedBox(
|
||||
height: 14,
|
||||
width: 14,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2.0,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
)
|
||||
? const ToolbarContentLoadingIndicator()
|
||||
: selectionTranslation != null
|
||||
? Text(
|
||||
selectionTranslation!,
|
||||
|
|
|
|||
|
|
@ -37,34 +37,31 @@ class MessageUnsubscribedCard extends StatelessWidget {
|
|||
MatrixState.pAnyState.closeOverlay();
|
||||
}
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(10, 10, 10, 0),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
style: BotStyle.text(context),
|
||||
"${L10n.of(context)!.subscribedToUnlockTools} $languageTool",
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: TextButton(
|
||||
onPressed: onButtonPress,
|
||||
style: ButtonStyle(
|
||||
backgroundColor: MaterialStateProperty.all<Color>(
|
||||
(AppConfig.primaryColor).withOpacity(0.1),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
inTrialWindow
|
||||
? L10n.of(context)!.activateTrial
|
||||
: L10n.of(context)!.getAccess,
|
||||
return Column(
|
||||
children: [
|
||||
Text(
|
||||
style: BotStyle.text(context),
|
||||
"${L10n.of(context)!.subscribedToUnlockTools} $languageTool",
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: TextButton(
|
||||
onPressed: onButtonPress,
|
||||
style: ButtonStyle(
|
||||
backgroundColor: MaterialStateProperty.all<Color>(
|
||||
(AppConfig.primaryColor).withOpacity(0.1),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
inTrialWindow
|
||||
? L10n.of(context)!.activateTrial
|
||||
: L10n.of(context)!.getAccess,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/pages/chat/events/message_content.dart';
|
||||
import 'package:fluffychat/pangea/enum/use_type.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/widgets/chat/message_toolbar.dart';
|
||||
import 'package:fluffychat/utils/date_time_extension.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
|
|||
29
lib/pangea/widgets/chat/speech_to_text_score.dart
Normal file
29
lib/pangea/widgets/chat/speech_to_text_score.dart
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class SpeechToTextScoreWidget extends StatefulWidget {
|
||||
final int score;
|
||||
const SpeechToTextScoreWidget({super.key, required this.score});
|
||||
|
||||
@override
|
||||
SpeechToTextScoreWidgetState createState() => SpeechToTextScoreWidgetState();
|
||||
}
|
||||
|
||||
class SpeechToTextScoreWidgetState extends State<SpeechToTextScoreWidget> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
child: AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 500),
|
||||
transitionBuilder: (Widget child, Animation<double> animation) {
|
||||
return FadeTransition(opacity: animation, child: child);
|
||||
},
|
||||
child: Text(
|
||||
'Score: ${widget.score}',
|
||||
key: ValueKey<int>(widget.score),
|
||||
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
65
lib/pangea/widgets/chat/speech_to_text_text.dart
Normal file
65
lib/pangea/widgets/chat/speech_to_text_text.dart
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
import 'package:fluffychat/pangea/models/speech_to_text_models.dart';
|
||||
import 'package:fluffychat/pangea/utils/bot_style.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SpeechToTextText extends StatelessWidget {
|
||||
final Transcript transcript;
|
||||
|
||||
const SpeechToTextText({super.key, required this.transcript});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return RichText(
|
||||
text: _buildTranscriptText(context, transcript),
|
||||
);
|
||||
}
|
||||
|
||||
TextSpan _buildTranscriptText(BuildContext context, Transcript transcript) {
|
||||
final List<InlineSpan> spans = [];
|
||||
final String fullText = transcript.text;
|
||||
int lastEnd = 0;
|
||||
|
||||
for (final token in transcript.sttTokens) {
|
||||
// debugPrint('Token confidence: ${token.confidence}');
|
||||
// debugPrint('color: ${token.color(context)}');
|
||||
if (token.offset > lastEnd) {
|
||||
// Add any plain text before the token
|
||||
spans.add(
|
||||
TextSpan(
|
||||
text: fullText.substring(lastEnd, token.offset),
|
||||
),
|
||||
);
|
||||
// debugPrint('Pre: ${fullText.substring(lastEnd, token.offset)}');
|
||||
}
|
||||
|
||||
spans.add(
|
||||
TextSpan(
|
||||
text: fullText.substring(token.offset, token.offset + token.length),
|
||||
style: BotStyle.text(
|
||||
context,
|
||||
existingStyle: TextStyle(color: token.color(context)),
|
||||
setColor: false,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// debugPrint(
|
||||
// 'Main: ${fullText.substring(token.offset, token.offset + token.length)}',
|
||||
// );
|
||||
|
||||
lastEnd = token.offset + token.length;
|
||||
}
|
||||
|
||||
if (lastEnd < fullText.length) {
|
||||
// Add any remaining text after the last token
|
||||
spans.add(
|
||||
TextSpan(
|
||||
text: fullText.substring(lastEnd),
|
||||
),
|
||||
);
|
||||
// debugPrint('Post: ${fullText.substring(lastEnd)}');
|
||||
}
|
||||
|
||||
return TextSpan(children: spans);
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ import 'dart:developer';
|
|||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pages/chat/chat.dart';
|
||||
import 'package:fluffychat/pages/chat/events/audio_player.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class ToolbarContentLoadingIndicator extends StatelessWidget {
|
||||
const ToolbarContentLoadingIndicator({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: 14,
|
||||
width: 14,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2.0,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,8 +4,8 @@ import 'dart:ui';
|
|||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pangea/constants/language_keys.dart';
|
||||
import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
|
||||
import 'package:fluffychat/pangea/models/message_data_models.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/models/representation_content_model.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/utils/instructions.dart';
|
||||
import 'package:fluffychat/pangea/widgets/chat/message_context_menu.dart';
|
||||
|
|
@ -87,8 +87,10 @@ class PangeaRichTextState extends State<PangeaRichText> {
|
|||
context: context,
|
||||
langCode: widget.pangeaMessageEvent.messageDisplayLangCode,
|
||||
)
|
||||
.onError((error, stackTrace) =>
|
||||
ErrorHandler.logError(e: error, s: stackTrace))
|
||||
.onError(
|
||||
(error, stackTrace) =>
|
||||
ErrorHandler.logError(e: error, s: stackTrace),
|
||||
)
|
||||
.then((event) {
|
||||
repEvent = event;
|
||||
widget.toolbarController?.toolbar?.textSelection.setMessageText(
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@ PODS:
|
|||
- FlutterMacOS
|
||||
- audio_session (0.0.1):
|
||||
- FlutterMacOS
|
||||
- desktop_drop (0.0.1):
|
||||
- connectivity_plus (0.0.1):
|
||||
- FlutterMacOS
|
||||
- ReachabilitySwift
|
||||
- desktop_lifecycle (0.0.1):
|
||||
- FlutterMacOS
|
||||
- device_info_plus (0.0.1):
|
||||
- FlutterMacOS
|
||||
|
|
@ -13,6 +16,66 @@ PODS:
|
|||
- FlutterMacOS
|
||||
- file_selector_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
- Firebase/Analytics (10.18.0):
|
||||
- Firebase/Core
|
||||
- Firebase/Core (10.18.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseAnalytics (~> 10.18.0)
|
||||
- Firebase/CoreOnly (10.18.0):
|
||||
- FirebaseCore (= 10.18.0)
|
||||
- Firebase/Messaging (10.18.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseMessaging (~> 10.18.0)
|
||||
- firebase_analytics (10.8.0):
|
||||
- Firebase/Analytics (= 10.18.0)
|
||||
- firebase_core
|
||||
- FlutterMacOS
|
||||
- firebase_core (2.24.2):
|
||||
- Firebase/CoreOnly (~> 10.18.0)
|
||||
- FlutterMacOS
|
||||
- firebase_messaging (14.7.10):
|
||||
- Firebase/CoreOnly (~> 10.18.0)
|
||||
- Firebase/Messaging (~> 10.18.0)
|
||||
- firebase_core
|
||||
- FlutterMacOS
|
||||
- FirebaseAnalytics (10.18.0):
|
||||
- FirebaseAnalytics/AdIdSupport (= 10.18.0)
|
||||
- FirebaseCore (~> 10.0)
|
||||
- FirebaseInstallations (~> 10.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
|
||||
- GoogleUtilities/MethodSwizzler (~> 7.11)
|
||||
- GoogleUtilities/Network (~> 7.11)
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.11)"
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- FirebaseAnalytics/AdIdSupport (10.18.0):
|
||||
- FirebaseCore (~> 10.0)
|
||||
- FirebaseInstallations (~> 10.0)
|
||||
- GoogleAppMeasurement (= 10.18.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
|
||||
- GoogleUtilities/MethodSwizzler (~> 7.11)
|
||||
- GoogleUtilities/Network (~> 7.11)
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.11)"
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- FirebaseCore (10.18.0):
|
||||
- FirebaseCoreInternal (~> 10.0)
|
||||
- GoogleUtilities/Environment (~> 7.12)
|
||||
- GoogleUtilities/Logger (~> 7.12)
|
||||
- FirebaseCoreInternal (10.21.0):
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.8)"
|
||||
- FirebaseInstallations (10.21.0):
|
||||
- FirebaseCore (~> 10.0)
|
||||
- GoogleUtilities/Environment (~> 7.8)
|
||||
- GoogleUtilities/UserDefaults (~> 7.8)
|
||||
- PromisesObjC (~> 2.1)
|
||||
- FirebaseMessaging (10.18.0):
|
||||
- FirebaseCore (~> 10.0)
|
||||
- FirebaseInstallations (~> 10.0)
|
||||
- GoogleDataTransport (~> 9.2)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
|
||||
- GoogleUtilities/Environment (~> 7.8)
|
||||
- GoogleUtilities/Reachability (~> 7.8)
|
||||
- GoogleUtilities/UserDefaults (~> 7.8)
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- flutter_app_badger (1.3.0):
|
||||
- FlutterMacOS
|
||||
- flutter_local_notifications (0.0.1):
|
||||
|
|
@ -32,12 +95,63 @@ PODS:
|
|||
- FMDB/standard (2.7.5)
|
||||
- geolocator_apple (1.2.0):
|
||||
- FlutterMacOS
|
||||
- GoogleAppMeasurement (10.18.0):
|
||||
- GoogleAppMeasurement/AdIdSupport (= 10.18.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
|
||||
- GoogleUtilities/MethodSwizzler (~> 7.11)
|
||||
- GoogleUtilities/Network (~> 7.11)
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.11)"
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- GoogleAppMeasurement/AdIdSupport (10.18.0):
|
||||
- GoogleAppMeasurement/WithoutAdIdSupport (= 10.18.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
|
||||
- GoogleUtilities/MethodSwizzler (~> 7.11)
|
||||
- GoogleUtilities/Network (~> 7.11)
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.11)"
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- GoogleAppMeasurement/WithoutAdIdSupport (10.18.0):
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.11)
|
||||
- GoogleUtilities/MethodSwizzler (~> 7.11)
|
||||
- GoogleUtilities/Network (~> 7.11)
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.11)"
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- GoogleDataTransport (9.3.0):
|
||||
- GoogleUtilities/Environment (~> 7.7)
|
||||
- nanopb (< 2.30910.0, >= 2.30908.0)
|
||||
- PromisesObjC (< 3.0, >= 1.2)
|
||||
- GoogleUtilities/AppDelegateSwizzler (7.12.0):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Network
|
||||
- GoogleUtilities/Environment (7.12.0):
|
||||
- PromisesObjC (< 3.0, >= 1.2)
|
||||
- GoogleUtilities/Logger (7.12.0):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/MethodSwizzler (7.12.0):
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Network (7.12.0):
|
||||
- GoogleUtilities/Logger
|
||||
- "GoogleUtilities/NSData+zlib"
|
||||
- GoogleUtilities/Reachability
|
||||
- "GoogleUtilities/NSData+zlib (7.12.0)"
|
||||
- GoogleUtilities/Reachability (7.12.0):
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/UserDefaults (7.12.0):
|
||||
- GoogleUtilities/Logger
|
||||
- in_app_purchase_storekit (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- just_audio (0.0.1):
|
||||
- FlutterMacOS
|
||||
- macos_ui (0.1.0):
|
||||
- FlutterMacOS
|
||||
- macos_window_utils (1.0.0):
|
||||
- FlutterMacOS
|
||||
- nanopb (2.30909.1):
|
||||
- nanopb/decode (= 2.30909.1)
|
||||
- nanopb/encode (= 2.30909.1)
|
||||
- nanopb/decode (2.30909.1)
|
||||
- nanopb/encode (2.30909.1)
|
||||
- package_info_plus (0.0.1):
|
||||
- FlutterMacOS
|
||||
- pasteboard (0.0.1):
|
||||
|
|
@ -45,8 +159,24 @@ PODS:
|
|||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- record_macos (0.2.0):
|
||||
- PromisesObjC (2.3.1)
|
||||
- purchases_flutter (5.8.0):
|
||||
- FlutterMacOS
|
||||
- PurchasesHybridCommon (= 6.3.0)
|
||||
- PurchasesHybridCommon (6.3.0):
|
||||
- RevenueCat (= 4.26.1)
|
||||
- ReachabilitySwift (5.0.0)
|
||||
- record_darwin (1.0.0):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- RevenueCat (4.26.1)
|
||||
- Sentry/HybridSDK (8.17.2):
|
||||
- SentryPrivate (= 8.17.2)
|
||||
- sentry_flutter (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- Sentry/HybridSDK (= 8.17.2)
|
||||
- SentryPrivate (8.17.2)
|
||||
- share_plus (0.0.1):
|
||||
- FlutterMacOS
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
|
|
@ -80,11 +210,15 @@ PODS:
|
|||
DEPENDENCIES:
|
||||
- appkit_ui_element_colors (from `Flutter/ephemeral/.symlinks/plugins/appkit_ui_element_colors/macos`)
|
||||
- audio_session (from `Flutter/ephemeral/.symlinks/plugins/audio_session/macos`)
|
||||
- desktop_drop (from `Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos`)
|
||||
- connectivity_plus (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos`)
|
||||
- desktop_lifecycle (from `Flutter/ephemeral/.symlinks/plugins/desktop_lifecycle/macos`)
|
||||
- device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`)
|
||||
- dynamic_color (from `Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos`)
|
||||
- emoji_picker_flutter (from `Flutter/ephemeral/.symlinks/plugins/emoji_picker_flutter/macos`)
|
||||
- file_selector_macos (from `Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos`)
|
||||
- firebase_analytics (from `Flutter/ephemeral/.symlinks/plugins/firebase_analytics/macos`)
|
||||
- firebase_core (from `Flutter/ephemeral/.symlinks/plugins/firebase_core/macos`)
|
||||
- firebase_messaging (from `Flutter/ephemeral/.symlinks/plugins/firebase_messaging/macos`)
|
||||
- flutter_app_badger (from `Flutter/ephemeral/.symlinks/plugins/flutter_app_badger/macos`)
|
||||
- flutter_local_notifications (from `Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos`)
|
||||
- flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`)
|
||||
|
|
@ -92,13 +226,16 @@ DEPENDENCIES:
|
|||
- flutter_webrtc (from `Flutter/ephemeral/.symlinks/plugins/flutter_webrtc/macos`)
|
||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||
- geolocator_apple (from `Flutter/ephemeral/.symlinks/plugins/geolocator_apple/macos`)
|
||||
- in_app_purchase_storekit (from `Flutter/ephemeral/.symlinks/plugins/in_app_purchase_storekit/darwin`)
|
||||
- just_audio (from `Flutter/ephemeral/.symlinks/plugins/just_audio/macos`)
|
||||
- macos_ui (from `Flutter/ephemeral/.symlinks/plugins/macos_ui/macos`)
|
||||
- macos_window_utils (from `Flutter/ephemeral/.symlinks/plugins/macos_window_utils/macos`)
|
||||
- package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
|
||||
- pasteboard (from `Flutter/ephemeral/.symlinks/plugins/pasteboard/macos`)
|
||||
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- record_macos (from `Flutter/ephemeral/.symlinks/plugins/record_macos/macos`)
|
||||
- purchases_flutter (from `Flutter/ephemeral/.symlinks/plugins/purchases_flutter/macos`)
|
||||
- record_darwin (from `Flutter/ephemeral/.symlinks/plugins/record_darwin/macos`)
|
||||
- sentry_flutter (from `Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos`)
|
||||
- share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`)
|
||||
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`)
|
||||
|
|
@ -111,7 +248,23 @@ DEPENDENCIES:
|
|||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- Firebase
|
||||
- FirebaseAnalytics
|
||||
- FirebaseCore
|
||||
- FirebaseCoreInternal
|
||||
- FirebaseInstallations
|
||||
- FirebaseMessaging
|
||||
- FMDB
|
||||
- GoogleAppMeasurement
|
||||
- GoogleDataTransport
|
||||
- GoogleUtilities
|
||||
- nanopb
|
||||
- PromisesObjC
|
||||
- PurchasesHybridCommon
|
||||
- ReachabilitySwift
|
||||
- RevenueCat
|
||||
- Sentry
|
||||
- SentryPrivate
|
||||
- SQLCipher
|
||||
- WebRTC-SDK
|
||||
|
||||
|
|
@ -120,8 +273,10 @@ EXTERNAL SOURCES:
|
|||
:path: Flutter/ephemeral/.symlinks/plugins/appkit_ui_element_colors/macos
|
||||
audio_session:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/audio_session/macos
|
||||
desktop_drop:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos
|
||||
connectivity_plus:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos
|
||||
desktop_lifecycle:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/desktop_lifecycle/macos
|
||||
device_info_plus:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos
|
||||
dynamic_color:
|
||||
|
|
@ -130,6 +285,12 @@ EXTERNAL SOURCES:
|
|||
:path: Flutter/ephemeral/.symlinks/plugins/emoji_picker_flutter/macos
|
||||
file_selector_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos
|
||||
firebase_analytics:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/firebase_analytics/macos
|
||||
firebase_core:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/firebase_core/macos
|
||||
firebase_messaging:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/firebase_messaging/macos
|
||||
flutter_app_badger:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/flutter_app_badger/macos
|
||||
flutter_local_notifications:
|
||||
|
|
@ -144,6 +305,8 @@ EXTERNAL SOURCES:
|
|||
:path: Flutter/ephemeral
|
||||
geolocator_apple:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/geolocator_apple/macos
|
||||
in_app_purchase_storekit:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/in_app_purchase_storekit/darwin
|
||||
just_audio:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/just_audio/macos
|
||||
macos_ui:
|
||||
|
|
@ -156,8 +319,12 @@ EXTERNAL SOURCES:
|
|||
:path: Flutter/ephemeral/.symlinks/plugins/pasteboard/macos
|
||||
path_provider_foundation:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
|
||||
record_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/record_macos/macos
|
||||
purchases_flutter:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/purchases_flutter/macos
|
||||
record_darwin:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/record_darwin/macos
|
||||
sentry_flutter:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos
|
||||
share_plus:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/share_plus/macos
|
||||
shared_preferences_foundation:
|
||||
|
|
@ -180,11 +347,21 @@ EXTERNAL SOURCES:
|
|||
SPEC CHECKSUMS:
|
||||
appkit_ui_element_colors: 39bb2d80be3f19b152ccf4c70d5bbe6cba43d74a
|
||||
audio_session: dea1f41890dbf1718f04a56f1d6150fd50039b72
|
||||
desktop_drop: 69eeff437544aa619c8db7f4481b3a65f7696898
|
||||
connectivity_plus: 18d3c32514c886e046de60e9c13895109866c747
|
||||
desktop_lifecycle: a600c10e12fe033c7be9078f2e929b8241f2c1e3
|
||||
device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f
|
||||
dynamic_color: 2eaa27267de1ca20d879fbd6e01259773fb1670f
|
||||
emoji_picker_flutter: 533634326b1c5de9a181ba14b9758e6dfe967a20
|
||||
file_selector_macos: 468fb6b81fac7c0e88d71317f3eec34c3b008ff9
|
||||
Firebase: 414ad272f8d02dfbf12662a9d43f4bba9bec2a06
|
||||
firebase_analytics: 687a47ef9af9c5a8a9fc612c100987f843d0a281
|
||||
firebase_core: a74ee8b3ab5f91ae6b73f4913eaca996c24458b6
|
||||
firebase_messaging: 1298099739b30786ab5be9fdbfe00b2019065745
|
||||
FirebaseAnalytics: 4d310b35c48eaa4a058ddc04bdca6bdb5dc0fe80
|
||||
FirebaseCore: 2322423314d92f946219c8791674d2f3345b598f
|
||||
FirebaseCoreInternal: 43c1788eaeee9d1b97caaa751af567ce11010d00
|
||||
FirebaseInstallations: 390ea1d10a4d02b20c965cbfd527ee9b3b412acb
|
||||
FirebaseMessaging: 9bc34a98d2e0237e1b121915120d4d48ddcf301e
|
||||
flutter_app_badger: 55a64b179f8438e89d574320c77b306e327a1730
|
||||
flutter_local_notifications: 3805ca215b2fb7f397d78b66db91f6a747af52e4
|
||||
flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea
|
||||
|
|
@ -193,25 +370,38 @@ SPEC CHECKSUMS:
|
|||
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
||||
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
||||
geolocator_apple: 821be05bbdb1b49500e029ebcbf2d6acf2dfb966
|
||||
GoogleAppMeasurement: 70ce9aa438cff1cfb31ea3e660bcc67734cb716e
|
||||
GoogleDataTransport: 57c22343ab29bc686febbf7cbb13bad167c2d8fe
|
||||
GoogleUtilities: 0759d1a57ebb953965c2dfe0ba4c82e95ccc2e34
|
||||
in_app_purchase_storekit: 9e9931234f0adcf71ae323f8c83785b96030edf1
|
||||
just_audio: 9b67ca7b97c61cfc9784ea23cd8cc55eb226d489
|
||||
macos_ui: 6229a8922cd97bafb7d9636c8eb8dfb0744183ca
|
||||
macos_window_utils: 933f91f64805e2eb91a5bd057cf97cd097276663
|
||||
nanopb: d4d75c12cd1316f4a64e3c6963f879ecd4b5e0d5
|
||||
package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce
|
||||
pasteboard: 9b69dba6fedbb04866be632205d532fe2f6b1d99
|
||||
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
|
||||
record_macos: 937889e0f2a7a12b6fc14e97a3678e5a18943de6
|
||||
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
|
||||
PromisesObjC: c50d2056b5253dadbd6c2bea79b0674bd5a52fa4
|
||||
purchases_flutter: 36a8c669148173e56f19dfc20df724bc734ab475
|
||||
PurchasesHybridCommon: 5ee5e13fe009876850a03f52bb0349b6fa91d976
|
||||
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
|
||||
record_darwin: 1f6619f2abac4d1ca91d3eeab038c980d76f1517
|
||||
RevenueCat: 4e8899a69fd57180ef166237d1eb670023be05de
|
||||
Sentry: 64a9f9c3637af913adcf53deced05bbe452d1410
|
||||
sentry_flutter: 57912cf425e09398bdf47f38842a1fcb9836f1be
|
||||
SentryPrivate: 024c6fed507ac39ae98e6d087034160f942920d5
|
||||
share_plus: 76dd39142738f7a68dd57b05093b5e8193f220f7
|
||||
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
|
||||
shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
|
||||
sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea
|
||||
sqflite_sqlcipher: d1ac7c60596e4d624d9757e3ec96e9cfafb734d6
|
||||
SQLCipher: 905b145f65f349f26da9e60a19901ad24adcd381
|
||||
url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95
|
||||
video_compress: c896234f100791b5fef7f049afa38f6d2ef7b42f
|
||||
video_player_avfoundation: e9e6f9cae7d7a6d9b43519b0aab382bca60fcfd1
|
||||
video_player_avfoundation: 02011213dab73ae3687df27ce441fbbcc82b5579
|
||||
wakelock_plus: 4783562c9a43d209c458cb9b30692134af456269
|
||||
WebRTC-SDK: c24d2a6c9f571f2ed42297cb8ffba9557093142b
|
||||
window_to_front: 4cdc24ddd8461ad1a55fa06286d6a79d8b29e8d8
|
||||
|
||||
PODFILE CHECKSUM: d0975b16fbdecb73b109d8fbc88aa77ffe4c7a8d
|
||||
|
||||
COCOAPODS: 1.14.3
|
||||
COCOAPODS: 1.15.2
|
||||
|
|
|
|||
|
|
@ -829,7 +829,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -1683,7 +1683,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -2537,7 +2537,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -3391,7 +3391,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -4245,7 +4245,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -5068,7 +5068,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -5922,7 +5922,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -6776,7 +6776,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -7615,7 +7615,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -8438,7 +8438,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -9292,7 +9292,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -10146,7 +10146,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -11000,7 +11000,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -11854,7 +11854,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -12677,7 +12677,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -13531,7 +13531,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -14385,7 +14385,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -15226,7 +15226,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -16080,7 +16080,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -16934,7 +16934,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -17788,7 +17788,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -18627,7 +18627,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -19481,7 +19481,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -20335,7 +20335,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -21189,7 +21189,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -22043,7 +22043,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -22897,7 +22897,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -23751,7 +23751,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -24605,7 +24605,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -25459,7 +25459,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -26282,7 +26282,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -27136,7 +27136,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -27990,7 +27990,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -28817,7 +28817,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -29671,7 +29671,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -30525,7 +30525,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -31379,7 +31379,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -32233,7 +32233,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -33087,7 +33087,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -33941,7 +33941,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -34780,7 +34780,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -35619,7 +35619,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -36473,7 +36473,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -37312,7 +37312,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
@ -38166,7 +38166,7 @@
|
|||
"more",
|
||||
"translationTooltip",
|
||||
"audioTooltip",
|
||||
"transcriptTooltip",
|
||||
"speechToTextTooltip",
|
||||
"certifyAge",
|
||||
"kickBotWarning",
|
||||
"joinToView",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue