Merge pull request #405 from pangeachat/inline-tooltip

Inline-tooltip [WIP]
pull/1384/head
ggurdin 1 year ago committed by GitHub
commit f8ff2eb922
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -4065,6 +4065,8 @@
"practice": "Practice", "practice": "Practice",
"noLanguagesSet": "No languages set", "noLanguagesSet": "No languages set",
"noActivitiesFound": "No practice activities found for this message", "noActivitiesFound": "No practice activities found for this message",
"hintTitle": "Hint:",
"speechToTextBody": "See how well you did by looking at your Accuracy and Words Per Minute scores",
"previous": "Previous", "previous": "Previous",
"languageButtonLabel": "Language: {currentLanguage}", "languageButtonLabel": "Language: {currentLanguage}",
"@languageButtonLabel": { "@languageButtonLabel": {

@ -4,8 +4,8 @@ import 'package:fluffychat/pages/chat/events/message.dart';
import 'package:fluffychat/pages/chat/seen_by_row.dart'; import 'package:fluffychat/pages/chat/seen_by_row.dart';
import 'package:fluffychat/pages/chat/typing_indicators.dart'; import 'package:fluffychat/pages/chat/typing_indicators.dart';
import 'package:fluffychat/pages/user_bottom_sheet/user_bottom_sheet.dart'; import 'package:fluffychat/pages/user_bottom_sheet/user_bottom_sheet.dart';
import 'package:fluffychat/pangea/enum/instructions_enum.dart';
import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart';
import 'package:fluffychat/pangea/utils/instructions.dart';
import 'package:fluffychat/pangea/widgets/chat/locked_chat_message.dart'; import 'package:fluffychat/pangea/widgets/chat/locked_chat_message.dart';
import 'package:fluffychat/utils/account_config.dart'; import 'package:fluffychat/utils/account_config.dart';
import 'package:fluffychat/utils/adaptive_bottom_sheet.dart'; import 'package:fluffychat/utils/adaptive_bottom_sheet.dart';
@ -46,7 +46,7 @@ class ChatEventList extends StatelessWidget {
// card, attach it on top of the first shown message // card, attach it on top of the first shown message
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
if (events.isEmpty) return; if (events.isEmpty) return;
controller.pangeaController.instructions.show( controller.pangeaController.instructions.showInstructionsPopup(
context, context,
InstructionsEnum.clickMessage, InstructionsEnum.clickMessage,
events[0].eventId, events[0].eventId,

@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
import 'package:fluffychat/pangea/utils/instructions.dart'; import 'package:fluffychat/pangea/enum/instructions_enum.dart';
import 'package:fluffychat/widgets/matrix.dart'; import 'package:fluffychat/widgets/matrix.dart';
import 'package:flutter/material.dart';
import '../../widgets/common/bot_face_svg.dart'; import '../../widgets/common/bot_face_svg.dart';
import '../controllers/choreographer.dart'; import '../controllers/choreographer.dart';
import '../controllers/it_controller.dart'; import '../controllers/it_controller.dart';
@ -37,7 +37,7 @@ class ITBotButton extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
choreographer.pangeaController.instructions.show( choreographer.pangeaController.instructions.showInstructionsPopup(
context, context,
InstructionsEnum.itInstructions, InstructionsEnum.itInstructions,
choreographer.itBotTransformTargetKey, choreographer.itBotTransformTargetKey,
@ -46,7 +46,8 @@ class ITBotButton extends StatelessWidget {
return IconButton( return IconButton(
icon: const BotFace(width: 40.0, expression: BotExpression.idle), icon: const BotFace(width: 40.0, expression: BotExpression.idle),
onPressed: () => choreographer.pangeaController.instructions.show( onPressed: () =>
choreographer.pangeaController.instructions.showInstructionsPopup(
context, context,
InstructionsEnum.itInstructions, InstructionsEnum.itInstructions,
choreographer.itBotTransformTargetKey, choreographer.itBotTransformTargetKey,

@ -0,0 +1,45 @@
import 'package:fluffychat/utils/platform_infos.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
enum InstructionsEnum {
itInstructions,
clickMessage,
blurMeansTranslate,
tooltipInstructions,
speechToText,
}
extension Copy on InstructionsEnum {
String title(BuildContext context) {
switch (this) {
case InstructionsEnum.itInstructions:
return L10n.of(context)!.itInstructionsTitle;
case InstructionsEnum.clickMessage:
return L10n.of(context)!.clickMessageTitle;
case InstructionsEnum.blurMeansTranslate:
return L10n.of(context)!.blurMeansTranslateTitle;
case InstructionsEnum.tooltipInstructions:
return L10n.of(context)!.tooltipInstructionsTitle;
case InstructionsEnum.speechToText:
return L10n.of(context)!.hintTitle;
}
}
String body(BuildContext context) {
switch (this) {
case InstructionsEnum.itInstructions:
return L10n.of(context)!.itInstructionsBody;
case InstructionsEnum.clickMessage:
return L10n.of(context)!.clickMessageBody;
case InstructionsEnum.blurMeansTranslate:
return L10n.of(context)!.blurMeansTranslateBody;
case InstructionsEnum.speechToText:
return L10n.of(context)!.speechToTextBody;
case InstructionsEnum.tooltipInstructions:
return PlatformInfos.isMobile
? L10n.of(context)!.tooltipInstructionsMobileBody
: L10n.of(context)!.tooltipInstructionsBrowserBody;
}
}
}

@ -4,8 +4,8 @@ import 'package:country_picker/country_picker.dart';
import 'package:fluffychat/pangea/constants/local.key.dart'; import 'package:fluffychat/pangea/constants/local.key.dart';
import 'package:fluffychat/pangea/constants/model_keys.dart'; import 'package:fluffychat/pangea/constants/model_keys.dart';
import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
import 'package:fluffychat/pangea/enum/instructions_enum.dart';
import 'package:fluffychat/pangea/models/space_model.dart'; import 'package:fluffychat/pangea/models/space_model.dart';
import 'package:fluffychat/pangea/utils/instructions.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';

@ -1,4 +1,5 @@
import 'package:fluffychat/utils/platform_infos.dart'; import 'package:fluffychat/pangea/enum/instructions_enum.dart';
import 'package:fluffychat/pangea/utils/inline_tooltip.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
@ -14,17 +15,29 @@ import 'overlay.dart';
class InstructionsController { class InstructionsController {
late PangeaController _pangeaController; late PangeaController _pangeaController;
// We have these three methods to make sure that the instructions are not shown too much
/// Instruction popup was closed by the user
final Map<InstructionsEnum, bool> _instructionsClosed = {}; final Map<InstructionsEnum, bool> _instructionsClosed = {};
/// Instruction popup has already been shown this session
final Map<InstructionsEnum, bool> _instructionsShown = {}; final Map<InstructionsEnum, bool> _instructionsShown = {};
/// Returns true if the user requested this popup not be shown again
bool? toggledOff(InstructionsEnum key) =>
_pangeaController.pStoreService.read(key.toString());
InstructionsController(PangeaController pangeaController) { InstructionsController(PangeaController pangeaController) {
_pangeaController = pangeaController; _pangeaController = pangeaController;
} }
/// Returns true if the instructions were closed
/// or turned off by the user via the toggle switch
bool wereInstructionsTurnedOff(InstructionsEnum key) => bool wereInstructionsTurnedOff(InstructionsEnum key) =>
_pangeaController.pStoreService.read(key.toString()) ?? toggledOff(key) ?? _instructionsClosed[key] ?? false;
_instructionsClosed[key] ??
false; void turnOffInstruction(InstructionsEnum key) =>
_instructionsClosed[key] = true;
Future<void> updateEnableInstructions( Future<void> updateEnableInstructions(
InstructionsEnum key, InstructionsEnum key,
@ -35,7 +48,9 @@ class InstructionsController {
value, value,
); );
Future<void> show( /// Instruction Card gives users tips on
/// how to use Pangea Chat's features
Future<void> showInstructionsPopup(
BuildContext context, BuildContext context,
InstructionsEnum key, InstructionsEnum key,
String transformTargetKey, [ String transformTargetKey, [
@ -98,45 +113,35 @@ class InstructionsController {
), ),
); );
} }
}
enum InstructionsEnum { /// Returns a widget that will be added to existing widget
itInstructions, /// which displays hint text defined in the enum extension
clickMessage, Widget getInstructionInlineTooltip(
blurMeansTranslate, BuildContext context,
tooltipInstructions, InstructionsEnum key,
} VoidCallback onClose,
) {
extension Copy on InstructionsEnum { if (wereInstructionsTurnedOff(key)) {
String title(BuildContext context) { return const SizedBox();
switch (this) {
case InstructionsEnum.itInstructions:
return L10n.of(context)!.itInstructionsTitle;
case InstructionsEnum.clickMessage:
return L10n.of(context)!.clickMessageTitle;
case InstructionsEnum.blurMeansTranslate:
return L10n.of(context)!.blurMeansTranslateTitle;
case InstructionsEnum.tooltipInstructions:
return L10n.of(context)!.tooltipInstructionsTitle;
} }
}
String body(BuildContext context) { if (L10n.of(context) == null) {
switch (this) { ErrorHandler.logError(
case InstructionsEnum.itInstructions: m: "null context in ITBotButton.showCard",
return L10n.of(context)!.itInstructionsBody; s: StackTrace.current,
case InstructionsEnum.clickMessage: );
return L10n.of(context)!.clickMessageBody; return const SizedBox();
case InstructionsEnum.blurMeansTranslate:
return L10n.of(context)!.blurMeansTranslateBody;
case InstructionsEnum.tooltipInstructions:
return PlatformInfos.isMobile
? L10n.of(context)!.tooltipInstructionsMobileBody
: L10n.of(context)!.tooltipInstructionsBrowserBody;
} }
return InlineTooltip(
body: InstructionsEnum.speechToText.body(context),
onClose: onClose,
);
} }
} }
/// User can toggle on to prevent Instruction Card
/// from appearing in future sessions
class InstructionsToggle extends StatefulWidget { class InstructionsToggle extends StatefulWidget {
const InstructionsToggle({ const InstructionsToggle({
super.key, super.key,

@ -1,9 +1,9 @@
import 'dart:developer'; import 'dart:developer';
import 'package:fluffychat/pangea/enum/instructions_enum.dart';
import 'package:fluffychat/pangea/matrix_event_wrappers/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/models/speech_to_text_models.dart';
import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart';
import 'package:fluffychat/pangea/utils/instructions.dart';
import 'package:fluffychat/pangea/widgets/chat/toolbar_content_loading_indicator.dart'; import 'package:fluffychat/pangea/widgets/chat/toolbar_content_loading_indicator.dart';
import 'package:fluffychat/pangea/widgets/common/icon_number_widget.dart'; import 'package:fluffychat/pangea/widgets/common/icon_number_widget.dart';
import 'package:fluffychat/pangea/widgets/igc/card_error_widget.dart'; import 'package:fluffychat/pangea/widgets/igc/card_error_widget.dart';
@ -65,6 +65,13 @@ class MessageSpeechToTextCardState extends State<MessageSpeechToTextCard> {
} }
} }
void closeHint() {
MatrixState.pangeaController.instructions.turnOffInstruction(
InstructionsEnum.speechToText,
);
setState(() {});
}
TextSpan _buildTranscriptText(BuildContext context) { TextSpan _buildTranscriptText(BuildContext context) {
final Transcript transcript = speechToTextResponse!.transcript; final Transcript transcript = speechToTextResponse!.transcript;
final List<InlineSpan> spans = []; final List<InlineSpan> spans = [];
@ -172,7 +179,8 @@ class MessageSpeechToTextCardState extends State<MessageSpeechToTextCard> {
number: number:
"${selectedToken?.confidence ?? speechToTextResponse!.transcript.confidence}%", "${selectedToken?.confidence ?? speechToTextResponse!.transcript.confidence}%",
toolTip: L10n.of(context)!.accuracy, toolTip: L10n.of(context)!.accuracy,
onPressed: () => MatrixState.pangeaController.instructions.show( onPressed: () => MatrixState.pangeaController.instructions
.showInstructionsPopup(
context, context,
InstructionsEnum.tooltipInstructions, InstructionsEnum.tooltipInstructions,
widget.messageEvent.eventId, widget.messageEvent.eventId,
@ -184,7 +192,8 @@ class MessageSpeechToTextCardState extends State<MessageSpeechToTextCard> {
number: number:
wordsPerMinuteString != null ? "$wordsPerMinuteString" : "??", wordsPerMinuteString != null ? "$wordsPerMinuteString" : "??",
toolTip: L10n.of(context)!.wordsPerMinute, toolTip: L10n.of(context)!.wordsPerMinute,
onPressed: () => MatrixState.pangeaController.instructions.show( onPressed: () => MatrixState.pangeaController.instructions
.showInstructionsPopup(
context, context,
InstructionsEnum.tooltipInstructions, InstructionsEnum.tooltipInstructions,
widget.messageEvent.eventId, widget.messageEvent.eventId,
@ -193,6 +202,11 @@ class MessageSpeechToTextCardState extends State<MessageSpeechToTextCard> {
), ),
], ],
), ),
MatrixState.pangeaController.instructions.getInstructionInlineTooltip(
context,
InstructionsEnum.speechToText,
closeHint,
),
], ],
); );
} }

@ -137,6 +137,8 @@ class ToolbarDisplayController {
? Alignment.bottomLeft ? Alignment.bottomLeft
: Alignment.topLeft, : Alignment.topLeft,
backgroundColor: const Color.fromRGBO(0, 0, 0, 1).withAlpha(100), backgroundColor: const Color.fromRGBO(0, 0, 0, 1).withAlpha(100),
closePrevOverlay:
MatrixState.pangeaController.subscriptionController.isSubscribed,
); );
if (MatrixState.pAnyState.entries.isNotEmpty) { if (MatrixState.pAnyState.entries.isNotEmpty) {

@ -3,10 +3,10 @@ import 'dart:ui';
import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
import 'package:fluffychat/pangea/enum/instructions_enum.dart';
import 'package:fluffychat/pangea/matrix_event_wrappers/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/models/representation_content_model.dart';
import 'package:fluffychat/pangea/utils/error_handler.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'; import 'package:fluffychat/pangea/widgets/chat/message_context_menu.dart';
import 'package:fluffychat/pangea/widgets/chat/message_toolbar.dart'; import 'package:fluffychat/pangea/widgets/chat/message_toolbar.dart';
import 'package:fluffychat/widgets/matrix.dart'; import 'package:fluffychat/widgets/matrix.dart';
@ -115,7 +115,7 @@ class PangeaRichTextState extends State<PangeaRichText> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (blur > 0) { if (blur > 0) {
pangeaController.instructions.show( pangeaController.instructions.showInstructionsPopup(
context, context,
InstructionsEnum.blurMeansTranslate, InstructionsEnum.blurMeansTranslate,
widget.pangeaMessageEvent.eventId, widget.pangeaMessageEvent.eventId,

Loading…
Cancel
Save