Merge pull request #838 from pangeachat/toolbar-min-dimensions
Toolbar min dimensions
This commit is contained in:
commit
ba0d7f98bf
18 changed files with 276 additions and 309 deletions
|
|
@ -23,6 +23,8 @@ abstract class AppConfig {
|
|||
static const bool allowOtherHomeservers = true;
|
||||
static const bool enableRegistration = true;
|
||||
static const double toolbarMaxHeight = 300.0;
|
||||
static const double toolbarMinHeight = 70.0;
|
||||
static const double toolbarMinWidth = 270.0;
|
||||
// #Pangea
|
||||
// static const Color primaryColor = Color(0xFF5625BA);
|
||||
// static const Color primaryColorLight = Color(0xFFCCBDEA);
|
||||
|
|
|
|||
|
|
@ -467,7 +467,7 @@ class AudioPlayerState extends State<AudioPlayerWidget> {
|
|||
borderRadius: BorderRadius.circular(2),
|
||||
),
|
||||
height: 32 * (waveform[i] / 1024),
|
||||
width: 1.5,
|
||||
width: 3,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ class InlineTooltip extends StatelessWidget {
|
|||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// Lightbulb icon on the left
|
||||
Icon(
|
||||
|
|
@ -39,16 +40,14 @@ class InlineTooltip extends StatelessWidget {
|
|||
),
|
||||
const SizedBox(width: 8),
|
||||
// Text in the middle
|
||||
Expanded(
|
||||
child: Center(
|
||||
child: Text(
|
||||
instructionsEnum.body(context),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
height: 1.5,
|
||||
),
|
||||
textAlign: TextAlign.left,
|
||||
Center(
|
||||
child: Text(
|
||||
instructionsEnum.body(context),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
height: 1.5,
|
||||
),
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
),
|
||||
// Close button on the right
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import 'dart:developer';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pages/chat/events/audio_player.dart';
|
||||
import 'package:fluffychat/pangea/controllers/text_to_speech_controller.dart';
|
||||
import 'package:fluffychat/pangea/extensions/pangea_event_extension.dart';
|
||||
|
|
@ -8,7 +9,6 @@ import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dar
|
|||
import 'package:fluffychat/pangea/models/pangea_token_model.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/widgets/chat/message_selection_overlay.dart';
|
||||
import 'package:fluffychat/pangea/widgets/chat/message_toolbar.dart';
|
||||
import 'package:fluffychat/pangea/widgets/chat/toolbar_content_loading_indicator.dart';
|
||||
import 'package:fluffychat/pangea/widgets/chat/tts_controller.dart';
|
||||
import 'package:fluffychat/pangea/widgets/igc/card_error_widget.dart';
|
||||
|
|
@ -190,7 +190,6 @@ class MessageAudioCardState extends State<MessageAudioCard> {
|
|||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
constraints: const BoxConstraints(minHeight: minCardHeight),
|
||||
alignment: Alignment.center,
|
||||
child: _isLoading
|
||||
? const ToolbarContentLoadingIndicator()
|
||||
|
|
@ -210,6 +209,7 @@ class MessageAudioCardState extends State<MessageAudioCard> {
|
|||
)
|
||||
: const CardErrorWidget(
|
||||
error: "Null audio file in message_audio_card",
|
||||
maxWidth: AppConfig.toolbarMinWidth,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -443,9 +443,7 @@ class MessageOverlayController extends State<MessageSelectionOverlay>
|
|||
}
|
||||
|
||||
final overlayMessage = Container(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: maxWidth,
|
||||
),
|
||||
constraints: BoxConstraints(maxWidth: maxWidth),
|
||||
child: Material(
|
||||
type: MaterialType.transparency,
|
||||
child: Column(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pangea/enum/instructions_enum.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/models/speech_to_text_models.dart';
|
||||
|
|
@ -148,9 +149,12 @@ class MessageSpeechToTextCardState extends State<MessageSpeechToTextCard> {
|
|||
return const ToolbarContentLoadingIndicator();
|
||||
}
|
||||
|
||||
//done fetchig but not results means some kind of error
|
||||
// done fetchig but not results means some kind of error
|
||||
if (speechToTextResponse == null) {
|
||||
return CardErrorWidget(error: error);
|
||||
return CardErrorWidget(
|
||||
error: error,
|
||||
maxWidth: AppConfig.toolbarMinWidth,
|
||||
);
|
||||
}
|
||||
|
||||
//TODO: find better icons
|
||||
|
|
|
|||
|
|
@ -114,6 +114,9 @@ class MessageToolbar extends StatelessWidget {
|
|||
),
|
||||
constraints: const BoxConstraints(
|
||||
maxHeight: AppConfig.toolbarMaxHeight,
|
||||
minWidth: AppConfig.toolbarMinWidth,
|
||||
minHeight: AppConfig.toolbarMinHeight,
|
||||
// maxWidth is set by MessageSelectionOverlay
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
child: AnimatedSize(
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pangea/enum/instructions_enum.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_token_model.dart';
|
||||
|
|
@ -130,46 +131,51 @@ class MessageTranslationCardState extends State<MessageTranslationCard> {
|
|||
if (!_fetchingTranslation &&
|
||||
repEvent == null &&
|
||||
selectionTranslation == null) {
|
||||
return const CardErrorWidget(error: "No translation found");
|
||||
return const CardErrorWidget(
|
||||
error: "No translation found",
|
||||
maxWidth: AppConfig.toolbarMinWidth,
|
||||
);
|
||||
}
|
||||
|
||||
final loadingTranslation =
|
||||
(widget.selection != null && selectionTranslation == null) ||
|
||||
(widget.selection == null && repEvent == null);
|
||||
|
||||
if (_fetchingTranslation || loadingTranslation) {
|
||||
return const ToolbarContentLoadingIndicator();
|
||||
}
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
padding: const EdgeInsets.fromLTRB(16, 20, 16, 16),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
_fetchingTranslation
|
||||
? const ToolbarContentLoadingIndicator()
|
||||
: Flexible(
|
||||
child: Column(
|
||||
children: [
|
||||
widget.selection != null
|
||||
? selectionTranslation != null
|
||||
? Text(
|
||||
selectionTranslation!,
|
||||
style: BotStyle.text(context),
|
||||
)
|
||||
: const ToolbarContentLoadingIndicator()
|
||||
: repEvent != null
|
||||
? Text(
|
||||
repEvent!.text,
|
||||
style: BotStyle.text(context),
|
||||
)
|
||||
: const ToolbarContentLoadingIndicator(),
|
||||
if (notGoingToTranslate && widget.selection == null)
|
||||
InlineTooltip(
|
||||
instructionsEnum: InstructionsEnum.l1Translation,
|
||||
onClose: () => setState(() {}),
|
||||
),
|
||||
if (widget.selection != null)
|
||||
InlineTooltip(
|
||||
instructionsEnum:
|
||||
InstructionsEnum.clickAgainToDeselect,
|
||||
onClose: () => setState(() {}),
|
||||
),
|
||||
],
|
||||
),
|
||||
Flexible(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
widget.selection != null
|
||||
? selectionTranslation!
|
||||
: repEvent!.text,
|
||||
style: BotStyle.text(context),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
if (notGoingToTranslate && widget.selection == null)
|
||||
InlineTooltip(
|
||||
instructionsEnum: InstructionsEnum.l1Translation,
|
||||
onClose: () => setState(() {}),
|
||||
),
|
||||
if (widget.selection != null)
|
||||
InlineTooltip(
|
||||
instructionsEnum: InstructionsEnum.clickAgainToDeselect,
|
||||
onClose: () => setState(() {}),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ class MessageUnsubscribedCard extends StatelessWidget {
|
|||
final bool inTrialWindow =
|
||||
MatrixState.pangeaController.userController.inTrialWindow;
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import 'package:fluffychat/pangea/widgets/chat/message_toolbar.dart';
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ToolbarContentLoadingIndicator extends StatelessWidget {
|
||||
|
|
@ -8,10 +8,9 @@ class ToolbarContentLoadingIndicator extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
constraints: const BoxConstraints(minHeight: minCardHeight),
|
||||
alignment: Alignment.center,
|
||||
return SizedBox(
|
||||
width: AppConfig.toolbarMinWidth,
|
||||
height: AppConfig.toolbarMinHeight,
|
||||
child: Center(
|
||||
child: SizedBox(
|
||||
height: 14,
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ class OverlayContainer extends StatelessWidget {
|
|||
constraints: BoxConstraints(
|
||||
maxWidth: maxWidth,
|
||||
maxHeight: maxHeight,
|
||||
minHeight: 100,
|
||||
minWidth: 100,
|
||||
),
|
||||
//PTODO - position card above input/message
|
||||
// margin: const EdgeInsets.all(10),
|
||||
|
|
|
|||
|
|
@ -9,21 +9,26 @@ class CardErrorWidget extends StatelessWidget {
|
|||
final Object? error;
|
||||
final Choreographer? choreographer;
|
||||
final int? offset;
|
||||
final double? maxWidth;
|
||||
|
||||
const CardErrorWidget({
|
||||
super.key,
|
||||
this.error,
|
||||
this.choreographer,
|
||||
this.offset,
|
||||
this.maxWidth,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final ErrorCopy errorCopy = ErrorCopy(context, error);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
return ConstrainedBox(
|
||||
constraints: maxWidth != null
|
||||
? BoxConstraints(maxWidth: maxWidth!)
|
||||
: const BoxConstraints(),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
CardHeader(
|
||||
text: errorCopy.title,
|
||||
|
|
@ -32,11 +37,13 @@ class CardErrorWidget extends StatelessWidget {
|
|||
cursorOffset: offset,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
Center(
|
||||
const SizedBox(height: 12.0),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Text(
|
||||
errorCopy.body,
|
||||
style: BotStyle.text(context),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pangea/utils/bot_style.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../widgets/matrix.dart';
|
||||
import '../common/bot_face_svg.dart';
|
||||
|
||||
class CardHeader extends StatelessWidget {
|
||||
|
|
@ -22,33 +22,31 @@ class CardHeader extends StatelessWidget {
|
|||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 5.0),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 3.0),
|
||||
child: BotFace(
|
||||
width: 50.0,
|
||||
expression: botExpression,
|
||||
BotFace(
|
||||
width: 50.0,
|
||||
expression: botExpression,
|
||||
),
|
||||
const SizedBox(width: 12.0),
|
||||
Flexible(
|
||||
child: Text(
|
||||
text,
|
||||
style: BotStyle.text(context),
|
||||
softWrap: true,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 5.0),
|
||||
Text(
|
||||
text,
|
||||
style: BotStyle.text(context),
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
const SizedBox(width: 5.0),
|
||||
CircleAvatar(
|
||||
backgroundColor: AppConfig.primaryColor.withOpacity(0.1),
|
||||
child: IconButton(
|
||||
icon: const Icon(Icons.close_outlined),
|
||||
onPressed: () {
|
||||
if (onClose != null) onClose!();
|
||||
MatrixState.pAnyState.closeOverlay();
|
||||
},
|
||||
color: Theme.of(context).brightness == Brightness.dark
|
||||
? AppConfig.primaryColorLight
|
||||
: AppConfig.primaryColor,
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.close_outlined),
|
||||
onPressed: () {
|
||||
if (onClose != null) onClose!();
|
||||
MatrixState.pAnyState.closeOverlay();
|
||||
},
|
||||
color: Theme.of(context).brightness == Brightness.dark
|
||||
? AppConfig.primaryColorLight
|
||||
: AppConfig.primaryColor,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pangea/constants/language_constants.dart';
|
||||
import 'package:fluffychat/pangea/controllers/contextual_definition_controller.dart';
|
||||
import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
|
||||
|
|
@ -7,8 +8,7 @@ import 'package:fluffychat/pangea/models/language_model.dart';
|
|||
import 'package:fluffychat/pangea/utils/bot_style.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/utils/firebase_analytics.dart';
|
||||
import 'package:fluffychat/pangea/widgets/chat/message_toolbar.dart';
|
||||
import 'package:fluffychat/pangea/widgets/common/p_circular_loader.dart';
|
||||
import 'package:fluffychat/pangea/widgets/chat/toolbar_content_loading_indicator.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
@ -166,71 +166,68 @@ class WordDataCardView extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (controller.wordNetError != null) {
|
||||
return CardErrorWidget(error: controller.wordNetError);
|
||||
return CardErrorWidget(
|
||||
error: controller.wordNetError,
|
||||
maxWidth: AppConfig.toolbarMinWidth,
|
||||
);
|
||||
}
|
||||
if (controller.activeL1 == null || controller.activeL2 == null) {
|
||||
ErrorHandler.logError(m: "should not be here");
|
||||
return CardErrorWidget(error: controller.noLanguages);
|
||||
return CardErrorWidget(
|
||||
error: controller.noLanguages,
|
||||
maxWidth: AppConfig.toolbarMinWidth,
|
||||
);
|
||||
}
|
||||
|
||||
final ScrollController scrollController = ScrollController();
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
constraints: const BoxConstraints(minHeight: minCardHeight),
|
||||
alignment: Alignment.center,
|
||||
child: Scrollbar(
|
||||
thumbVisibility: true,
|
||||
controller: scrollController,
|
||||
child: SingleChildScrollView(
|
||||
controller: scrollController,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
if (controller.widget.choiceFeedback != null)
|
||||
Text(
|
||||
controller.widget.choiceFeedback!,
|
||||
style: BotStyle.text(context),
|
||||
),
|
||||
const SizedBox(height: 5.0),
|
||||
if (controller.wordData != null &&
|
||||
controller.wordNetError == null &&
|
||||
controller.activeL1 != null &&
|
||||
controller.activeL2 != null)
|
||||
WordNetInfo(
|
||||
wordData: controller.wordData!,
|
||||
activeL1: controller.activeL1!,
|
||||
activeL2: controller.activeL2!,
|
||||
),
|
||||
if (controller.isLoadingWordNet) const PCircular(),
|
||||
const SizedBox(height: 5.0),
|
||||
// if (controller.widget.hasInfo &&
|
||||
// !controller.isLoadingContextualDefinition &&
|
||||
// controller.contextualDefinitionRes == null)
|
||||
// Material(
|
||||
// type: MaterialType.transparency,
|
||||
// child: ListTile(
|
||||
// leading: const BotFace(
|
||||
// width: 40, expression: BotExpression.surprised),
|
||||
// title: Text(L10n.of(context)!.askPangeaBot),
|
||||
// onTap: controller.handleGetDefinitionButtonPress,
|
||||
// ),
|
||||
// ),
|
||||
if (controller.isLoadingContextualDefinition) const PCircular(),
|
||||
if (controller.contextualDefinitionRes != null)
|
||||
Text(
|
||||
controller.contextualDefinitionRes!.text,
|
||||
style: BotStyle.text(context),
|
||||
),
|
||||
if (controller.definitionError != null)
|
||||
Text(
|
||||
L10n.of(context)!.sorryNoResults,
|
||||
style: BotStyle.text(context),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 20, 16, 16),
|
||||
child: Column(
|
||||
children: [
|
||||
if (controller.widget.choiceFeedback != null)
|
||||
Text(
|
||||
controller.widget.choiceFeedback!,
|
||||
style: BotStyle.text(context),
|
||||
),
|
||||
const SizedBox(height: 5.0),
|
||||
if (controller.wordData != null &&
|
||||
controller.wordNetError == null &&
|
||||
controller.activeL1 != null &&
|
||||
controller.activeL2 != null)
|
||||
WordNetInfo(
|
||||
wordData: controller.wordData!,
|
||||
activeL1: controller.activeL1!,
|
||||
activeL2: controller.activeL2!,
|
||||
),
|
||||
if (controller.isLoadingWordNet)
|
||||
const ToolbarContentLoadingIndicator(),
|
||||
const SizedBox(height: 5.0),
|
||||
// if (controller.widget.hasInfo &&
|
||||
// !controller.isLoadingContextualDefinition &&
|
||||
// controller.contextualDefinitionRes == null)
|
||||
// Material(
|
||||
// type: MaterialType.transparency,
|
||||
// child: ListTile(
|
||||
// leading: const BotFace(
|
||||
// width: 40, expression: BotExpression.surprised),
|
||||
// title: Text(L10n.of(context)!.askPangeaBot),
|
||||
// onTap: controller.handleGetDefinitionButtonPress,
|
||||
// ),
|
||||
// ),
|
||||
if (controller.isLoadingContextualDefinition)
|
||||
const ToolbarContentLoadingIndicator(),
|
||||
if (controller.contextualDefinitionRes != null)
|
||||
Text(
|
||||
controller.contextualDefinitionRes!.text,
|
||||
style: BotStyle.text(context),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
if (controller.definitionError != null)
|
||||
Text(
|
||||
L10n.of(context)!.sorryNoResults,
|
||||
style: BotStyle.text(context),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
@ -251,12 +248,14 @@ class WordNetInfo extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SensesForLanguage(
|
||||
wordData: wordData,
|
||||
languageType: LanguageType.target,
|
||||
language: activeL2,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
SensesForLanguage(
|
||||
wordData: wordData,
|
||||
languageType: LanguageType.base,
|
||||
|
|
@ -273,52 +272,6 @@ enum LanguageType {
|
|||
}
|
||||
|
||||
class SensesForLanguage extends StatelessWidget {
|
||||
const SensesForLanguage({
|
||||
super.key,
|
||||
required this.wordData,
|
||||
required this.languageType,
|
||||
required this.language,
|
||||
});
|
||||
|
||||
final LanguageModel language;
|
||||
final LanguageType languageType;
|
||||
final WordData wordData;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 5),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(7, 0, 0, 0),
|
||||
child: LanguageFlag(
|
||||
language: language,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: PartOfSpeechBlock(
|
||||
wordData: wordData,
|
||||
languageType: languageType,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class PartOfSpeechBlock extends StatelessWidget {
|
||||
final WordData wordData;
|
||||
final LanguageType languageType;
|
||||
|
||||
const PartOfSpeechBlock({
|
||||
super.key,
|
||||
required this.wordData,
|
||||
required this.languageType,
|
||||
});
|
||||
|
||||
String get exampleSentence => languageType == LanguageType.target
|
||||
? wordData.targetExampleSentence
|
||||
: wordData.baseExampleSentence;
|
||||
|
|
@ -336,70 +289,76 @@ class PartOfSpeechBlock extends StatelessWidget {
|
|||
return "$word (${wordData.formattedPartOfSpeech(languageType)})";
|
||||
}
|
||||
|
||||
const SensesForLanguage({
|
||||
super.key,
|
||||
required this.wordData,
|
||||
required this.languageType,
|
||||
required this.language,
|
||||
});
|
||||
|
||||
final LanguageModel language;
|
||||
final LanguageType languageType;
|
||||
final WordData wordData;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
formattedTitle(context),
|
||||
style: BotStyle.text(context, italics: true, bold: false),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 14.0, bottom: 10.0),
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Column(
|
||||
children: [
|
||||
if (definition.isNotEmpty)
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
style: BotStyle.text(
|
||||
context,
|
||||
italics: false,
|
||||
bold: false,
|
||||
),
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: "${L10n.of(context)!.definition}: ",
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
TextSpan(text: definition),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
if (exampleSentence.isNotEmpty)
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
style: BotStyle.text(
|
||||
context,
|
||||
italics: false,
|
||||
bold: false,
|
||||
),
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: "${L10n.of(context)!.exampleSentence}: ",
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
TextSpan(text: exampleSentence),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
LanguageFlag(language: language),
|
||||
const SizedBox(width: 10),
|
||||
Flexible(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
formattedTitle(context),
|
||||
style: BotStyle.text(context, italics: true, bold: false),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
if (definition.isNotEmpty)
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
style: BotStyle.text(
|
||||
context,
|
||||
italics: false,
|
||||
bold: false,
|
||||
),
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: "${L10n.of(context)!.definition}: ",
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
TextSpan(text: definition),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
if (exampleSentence.isNotEmpty)
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
style: BotStyle.text(
|
||||
context,
|
||||
italics: false,
|
||||
bold: false,
|
||||
),
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: "${L10n.of(context)!.exampleSentence}: ",
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
TextSpan(text: exampleSentence),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pangea/utils/bot_style.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
|
@ -71,18 +72,21 @@ class GamifiedTextWidget extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Column(
|
||||
children: [
|
||||
const StarAnimationWidget(),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
userMessage,
|
||||
style: BotStyle.text(context),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
return SizedBox(
|
||||
width: AppConfig.toolbarMinWidth,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 20, 16, 16),
|
||||
child: Column(
|
||||
children: [
|
||||
const StarAnimationWidget(),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
userMessage,
|
||||
style: BotStyle.text(context),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@ import 'package:fluffychat/pangea/models/analytics/constructs_model.dart';
|
|||
import 'package:fluffychat/pangea/models/practice_activities.dart/message_activity_request.dart';
|
||||
import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart';
|
||||
import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_record_model.dart';
|
||||
import 'package:fluffychat/pangea/utils/bot_style.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/widgets/animations/gain_points.dart';
|
||||
import 'package:fluffychat/pangea/widgets/chat/message_selection_overlay.dart';
|
||||
import 'package:fluffychat/pangea/widgets/chat/toolbar_content_loading_indicator.dart';
|
||||
import 'package:fluffychat/pangea/widgets/content_issue_button.dart';
|
||||
import 'package:fluffychat/pangea/widgets/practice_activity/multiple_choice_activity.dart';
|
||||
import 'package:fluffychat/pangea/widgets/practice_activity/no_more_practice_card.dart';
|
||||
|
|
@ -286,12 +286,10 @@ class PracticeActivityCardState extends State<PracticeActivityCard> {
|
|||
/// If there is no current activity, the widget returns a sizedbox with a height of 80.
|
||||
/// If the activity type is multiple choice, the widget returns a MultipleChoiceActivity.
|
||||
/// If the activity type is unknown, the widget logs an error and returns a text widget with an error message.
|
||||
Widget get activityWidget {
|
||||
if (currentActivity == null) {
|
||||
// return sizedbox with height of 80
|
||||
return const SizedBox(height: 80);
|
||||
}
|
||||
switch (currentActivity!.activityType) {
|
||||
Widget? get activityWidget {
|
||||
switch (currentActivity?.activityType) {
|
||||
case null:
|
||||
return null;
|
||||
case ActivityTypeEnum.multipleChoice:
|
||||
return MultipleChoiceActivity(
|
||||
practiceCardController: this,
|
||||
|
|
@ -304,18 +302,18 @@ class PracticeActivityCardState extends State<PracticeActivityCard> {
|
|||
practiceCardController: this,
|
||||
currentActivity: currentActivity!,
|
||||
);
|
||||
default:
|
||||
ErrorHandler.logError(
|
||||
e: Exception('Unknown activity type'),
|
||||
m: 'Unknown activity type',
|
||||
data: {
|
||||
'activityType': currentActivity!.activityType,
|
||||
},
|
||||
);
|
||||
return Text(
|
||||
L10n.of(context)!.oopsSomethingWentWrong,
|
||||
style: BotStyle.text(context),
|
||||
);
|
||||
// default:
|
||||
// ErrorHandler.logError(
|
||||
// e: Exception('Unknown activity type'),
|
||||
// m: 'Unknown activity type',
|
||||
// data: {
|
||||
// 'activityType': currentActivity!.activityType,
|
||||
// },
|
||||
// );
|
||||
// return Text(
|
||||
// L10n.of(context)!.oopsSomethingWentWrong,
|
||||
// style: BotStyle.text(context),
|
||||
// );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -334,20 +332,15 @@ class PracticeActivityCardState extends State<PracticeActivityCard> {
|
|||
const Positioned(
|
||||
child: PointsGainedAnimation(),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(8, 20, 8, 8),
|
||||
child: activityWidget,
|
||||
),
|
||||
if (activityWidget != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 20, 16, 16),
|
||||
child: activityWidget,
|
||||
),
|
||||
// Conditionally show the darkening and progress indicator based on the loading state
|
||||
if (!savoringTheJoy && fetchingActivity) ...[
|
||||
// Semi-transparent overlay
|
||||
Container(
|
||||
color: Colors.black.withOpacity(0.5), // Darkening effect
|
||||
),
|
||||
// Circular progress indicator in the center
|
||||
const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
const ToolbarContentLoadingIndicator(),
|
||||
],
|
||||
// Flag button in the top right corner
|
||||
Positioned(
|
||||
|
|
|
|||
|
|
@ -10,18 +10,11 @@ class SelectToDefine extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
L10n.of(context)!.selectToDefine,
|
||||
style: BotStyle.text(context),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
padding: const EdgeInsets.fromLTRB(16, 20, 16, 16),
|
||||
child: Text(
|
||||
L10n.of(context)!.selectToDefine,
|
||||
style: BotStyle.text(context),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ description: Learn a language while texting your friends.
|
|||
# Pangea#
|
||||
publish_to: none
|
||||
# On version bump also increase the build number for F-Droid
|
||||
version: 1.22.3+3553
|
||||
version: 1.22.4+3554
|
||||
|
||||
environment:
|
||||
sdk: ">=3.0.0 <4.0.0"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue