Adjust translation animation (#2556)

* chore: some edits to message toolbar

* chore: some updates to reading assistance
This commit is contained in:
ggurdin 2025-04-25 09:41:07 -04:00 committed by GitHub
parent 22f46caf80
commit 7f11a5dba9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 334 additions and 311 deletions

View file

@ -138,6 +138,16 @@ class MessageContent extends StatelessWidget {
if (overlayController != null) {
overlayController?.onClickOverlayMessageToken(token);
return;
} else {
Future.delayed(
const Duration(
milliseconds: AppConfig.overlayAnimationDuration,
), () {
controller.choreographer.tts.tryToSpeak(
token.text.content,
langCode: pangeaMessageEvent!.messageDisplayLangCode,
);
});
}
controller.showToolbar(

View file

@ -116,7 +116,6 @@ class ChoicesArrayState extends State<ChoicesArray> {
widget.langCode != null) {
widget.tts?.tryToSpeak(
value,
context,
targetID: null,
langCode: widget.langCode!,
);

View file

@ -149,9 +149,9 @@ class OverlayUtil {
transformTargetOffset.dy + (transformTargetSize.height / 2);
final halfMaxWidth = maxWidth / 2;
final hasLeftOverflow = (horizontalMidpoint - halfMaxWidth) < 0;
final hasLeftOverflow = (horizontalMidpoint - halfMaxWidth) < 10;
final hasRightOverflow = (horizontalMidpoint + halfMaxWidth) >
(MediaQuery.of(context).size.width - columnWidth);
(MediaQuery.of(context).size.width - columnWidth - 10);
hasTopOverflow = (verticalMidpoint - maxHeight) < 0;
double xOffset = 0;

View file

@ -159,11 +159,11 @@ class TtsController {
/// A safer version of speak, that handles the case of
/// the language not being supported by the TTS engine
Future<void> tryToSpeak(
String text,
BuildContext context, {
String text, {
required String langCode,
// Target ID for where to show warning popup
String? targetID,
BuildContext? context,
}) async {
chatController?.stopAudioStream.add(null);
await _setSpeakingLanguage(langCode);
@ -180,7 +180,7 @@ class TtsController {
text,
langCode,
));
} else if (targetID != null) {
} else if (targetID != null && context != null) {
await _showTTSDisabledPopup(context, targetID);
}
}

View file

@ -66,7 +66,7 @@ class PracticeMatchItemState extends State<PracticeMatchItem> {
if (l2 != null) {
await tts.tryToSpeak(
widget.audioContent!,
context,
context: context,
targetID: 'word-audio-button',
langCode: l2,
);

View file

@ -6,12 +6,12 @@ import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/pages/chat/chat.dart';
import 'package:fluffychat/pages/chat/reactions_picker.dart';
import 'package:fluffychat/pangea/toolbar/enums/message_mode_enum.dart';
import 'package:fluffychat/pangea/toolbar/enums/reading_assistance_mode_enum.dart';
import 'package:fluffychat/pangea/toolbar/widgets/message_mode_locked_card.dart';
import 'package:fluffychat/pangea/toolbar/widgets/message_selection_overlay.dart';
import 'package:fluffychat/pangea/toolbar/widgets/message_speech_to_text_card.dart';
import 'package:fluffychat/pangea/toolbar/widgets/message_translation_card.dart';
import 'package:fluffychat/pangea/toolbar/widgets/practice_activity/practice_activity_card.dart';
import 'package:fluffychat/pangea/toolbar/widgets/word_zoom/morph_focus_widget.dart';
const double minContentHeight = 120;
@ -26,6 +26,11 @@ class ReadingAssistanceInputBar extends StatelessWidget {
});
Widget barContent(BuildContext context) {
if (overlayController.readingAssistanceMode !=
ReadingAssistanceMode.practiceMode) {
return ReactionsPicker(controller);
}
Widget? content;
final target =
overlayController.toolbarMode.associatedActivityType != null &&
@ -84,12 +89,6 @@ class ReadingAssistanceInputBar extends StatelessWidget {
targetTokensAndActivityType: target,
overlayController: overlayController,
);
} else if (overlayController.selectedMorph != null) {
content = MorphFocusWidget(
morphFeature: overlayController.selectedMorph!.morph,
pangeaMessageEvent: overlayController.pangeaMessageEvent!,
overlayController: overlayController,
);
} else {
content = Center(
child: Text(

View file

@ -534,7 +534,8 @@ class MessageOverlayController extends State<MessageSelectionOverlay>
void onClickOverlayMessageToken(
PangeaToken token,
) {
if (practiceSelection?.hasHiddenWordActivity == true) {
if (practiceSelection?.hasHiddenWordActivity == true ||
readingAssistanceMode == ReadingAssistanceMode.practiceMode) {
return;
}
@ -548,7 +549,6 @@ class MessageOverlayController extends State<MessageSelectionOverlay>
!hideWordCardContent) {
widget.chatController.choreographer.tts.tryToSpeak(
token.text.content,
context,
targetID: null,
langCode: pangeaMessageEvent!.messageDisplayLangCode,
);

View file

@ -430,7 +430,7 @@ class MessageSelectionPositionerState extends State<MessageSelectionPositioner>
} else {
return Offset(
_ownMessage ? _messageRightOffset : _messageLeftOffset,
_footerHeight + AppConfig.toolbarSpacing,
_footerHeight + (AppConfig.toolbarSpacing * 2),
);
}
}

View file

@ -2,8 +2,6 @@ import 'package:flutter/material.dart';
import 'package:matrix/matrix.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/config/themes.dart';
import 'package:fluffychat/pages/chat/chat.dart';
import 'package:fluffychat/pages/chat/events/message_reactions.dart';
import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart';
@ -55,8 +53,6 @@ class OverlayCenterContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
final showTranslation = overlayController.showTranslation &&
overlayController.translationText != null;
return IgnorePointer(
ignoring: !isTransitionAnimation &&
readingAssistanceMode != ReadingAssistanceMode.practiceMode,
@ -70,80 +66,31 @@ class OverlayCenterContent extends StatelessWidget {
? CrossAxisAlignment.end
: CrossAxisAlignment.start,
children: [
Stack(
alignment: Alignment.topCenter,
children: [
if (overlayController.readingAssistanceMode ==
ReadingAssistanceMode.selectMode)
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(
AppConfig.borderRadius,
),
color: Theme.of(context).colorScheme.primaryContainer,
),
padding: EdgeInsets.all(
showTranslation ? 8.0 : 0.0,
),
constraints: BoxConstraints(
maxWidth: messageWidth ?? maxWidth,
),
child: Column(
children: [
AnimatedContainer(
duration: FluffyThemes.animationDuration,
height: showTranslation ? messageHeight : 0,
width: showTranslation ? messageWidth : 0,
),
AnimatedSize(
duration: FluffyThemes.animationDuration,
child: SizedBox(
width: messageWidth,
child: showTranslation
? Text(
overlayController.translationText!,
style: AppConfig.messageTextStyle(
event,
Theme.of(context)
.colorScheme
.onPrimaryContainer,
),
textAlign: TextAlign.center,
)
: const SizedBox(),
),
),
],
),
),
MeasureRenderBox(
onChange: onChangeMessageSize,
child: OverlayMessage(
event,
pangeaMessageEvent: pangeaMessageEvent,
immersionMode: chatController.choreographer.immersionMode,
controller: chatController,
overlayController: overlayController,
nextEvent: nextEvent,
prevEvent: prevEvent,
timeline: chatController.timeline!,
sizeAnimation: sizeAnimation,
// there's a split seconds between when the transition animation starts and
// when the sizeAnimation is set when the original dimensions need to be enforced
messageWidth:
(sizeAnimation == null && isTransitionAnimation)
? messageWidth
: null,
messageHeight:
(sizeAnimation == null && isTransitionAnimation)
? messageHeight
: null,
maxHeight: maxHeight,
isTransitionAnimation: isTransitionAnimation,
readingAssistanceMode: readingAssistanceMode,
),
),
],
MeasureRenderBox(
onChange: onChangeMessageSize,
child: OverlayMessage(
event,
pangeaMessageEvent: pangeaMessageEvent,
immersionMode: chatController.choreographer.immersionMode,
controller: chatController,
overlayController: overlayController,
nextEvent: nextEvent,
prevEvent: prevEvent,
timeline: chatController.timeline!,
sizeAnimation: sizeAnimation,
// there's a split seconds between when the transition animation starts and
// when the sizeAnimation is set when the original dimensions need to be enforced
messageWidth: (sizeAnimation == null && isTransitionAnimation)
? messageWidth
: null,
messageHeight:
(sizeAnimation == null && isTransitionAnimation)
? messageHeight
: null,
maxHeight: maxHeight,
isTransitionAnimation: isTransitionAnimation,
readingAssistanceMode: readingAssistanceMode,
),
),
if (hasReactions)
Padding(

View file

@ -124,6 +124,9 @@ class OverlayMessage extends StatelessWidget {
? ThemeData.dark().colorScheme.onPrimary
: theme.colorScheme.onSurface;
final showTranslation = overlayController.showTranslation &&
overlayController.translationText != null;
final content = Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(
@ -253,18 +256,48 @@ class OverlayMessage extends StatelessWidget {
shape: RoundedRectangleBorder(
borderRadius: borderRadius,
),
child: sizeAnimation != null
? AnimatedBuilder(
animation: sizeAnimation!,
builder: (context, child) {
return SizedBox(
height: sizeAnimation!.value.height,
width: sizeAnimation!.value.width,
child: content,
);
},
)
: content,
child: Container(
decoration: BoxDecoration(
borderRadius: borderRadius,
color: color,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
sizeAnimation != null
? AnimatedBuilder(
animation: sizeAnimation!,
builder: (context, child) {
return SizedBox(
height: sizeAnimation!.value.height,
width: sizeAnimation!.value.width,
child: content,
);
},
)
: content,
if (showTranslation)
SizedBox(
width: messageWidth,
child: Padding(
padding: const EdgeInsets.fromLTRB(
12.0,
20.0,
12.0,
12.0,
),
child: Text(
overlayController.translationText!,
style:
AppConfig.messageTextStyle(event, textColor).copyWith(
fontStyle: FontStyle.italic,
),
),
),
),
],
),
),
);
}
}

View file

@ -87,7 +87,7 @@ class WordAudioButtonState extends State<WordAudioButton> {
if (widget.langCode != null) {
await tts.tryToSpeak(
widget.text,
context,
context: context,
targetID: 'word-audio-button-${widget.uniqueID}',
langCode: widget.langCode!,
);

View file

@ -83,7 +83,7 @@ class WordAudioButtonState extends State<WordTextWithAudioButton> {
if (l2 != null) {
await tts.tryToSpeak(
widget.text,
context,
context: context,
targetID: 'text-audio-button-${widget.uniqueID}',
langCode: l2,
);

View file

@ -10,7 +10,6 @@ import 'package:material_symbols_icons/symbols.dart';
import 'package:matrix/matrix.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/config/themes.dart';
import 'package:fluffychat/pages/chat/events/audio_player.dart';
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
import 'package:fluffychat/pangea/common/widgets/pressable_button.dart';
@ -113,7 +112,6 @@ class SelectModeButtonsState extends State<SelectModeButtons> {
if (_selectedMode == SelectMode.translate) {
widget.overlayController.setShowTranslation(false, null);
await Future.delayed(FluffyThemes.animationDuration);
}
setState(
@ -245,7 +243,7 @@ class SelectModeButtonsState extends State<SelectModeButtons> {
return Icon(
_audioPlayer.playerState.playing == true
? Icons.pause_outlined
: Icons.play_arrow,
: Icons.volume_up,
size: 20,
color: mode == _selectedMode ? Colors.white : null,
);
@ -294,6 +292,9 @@ class SelectModeButtonsState extends State<SelectModeButtons> {
color: Theme.of(context).colorScheme.primaryContainer,
onPressed: () => _updateMode(mode),
playSound: true,
colorFactor: Theme.of(context).brightness == Brightness.light
? 0.55
: 0.3,
child: Container(
height: buttonSize,
width: buttonSize,

View file

@ -38,6 +38,8 @@ class ToolbarButton extends StatelessWidget {
color: color(context),
onPressed: () => onPressed(mode),
playSound: true,
colorFactor:
Theme.of(context).brightness == Brightness.light ? 0.55 : 0.3,
child: AnimatedContainer(
duration: FluffyThemes.animationDuration,
height: buttonSize,

View file

@ -1,165 +0,0 @@
// stateful widget that displays morphological label and a shimmer effect while the text is loading
// takes a token and morphological feature as input
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:fluffychat/pangea/analytics_details_popup/analytics_details_popup.dart';
import 'package:fluffychat/pangea/analytics_details_popup/morph_meaning_widget.dart';
import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
import 'package:fluffychat/pangea/constructs/construct_level_enum.dart';
import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart';
import 'package:fluffychat/pangea/events/models/pangea_token_model.dart';
import 'package:fluffychat/pangea/lemmas/construct_xp_widget.dart';
import 'package:fluffychat/pangea/morphs/edit_morph_widget.dart';
import 'package:fluffychat/pangea/morphs/morph_feature_display.dart';
import 'package:fluffychat/pangea/morphs/morph_features_enum.dart';
import 'package:fluffychat/pangea/morphs/morph_tag_display.dart';
import 'package:fluffychat/pangea/toolbar/reading_assistance_input_row/morph_selection.dart';
import 'package:fluffychat/pangea/toolbar/widgets/message_selection_overlay.dart';
class MorphFocusWidget extends StatefulWidget {
final MorphFeaturesEnum morphFeature;
final PangeaMessageEvent pangeaMessageEvent;
final MessageOverlayController overlayController;
const MorphFocusWidget({
required this.morphFeature,
required this.pangeaMessageEvent,
required this.overlayController,
super.key,
});
@override
MorphFocusWidgetState createState() => MorphFocusWidgetState();
}
class MorphFocusWidgetState extends State<MorphFocusWidget> {
PangeaToken get token => widget.overlayController.selectedToken!;
bool _editMode = false;
/// the morphological tag that the user has selected in edit mode
String _selectedMorphTag = "";
final ScrollController _scrollController = ScrollController();
void _resetMorphTag() {
setState(
() => _selectedMorphTag = token.getMorphTag(widget.morphFeature) ?? "X",
);
}
@override
void initState() {
super.initState();
_resetMorphTag();
}
@override
void didUpdateWidget(MorphFocusWidget oldWidget) {
if (widget.morphFeature != oldWidget.morphFeature) {
_resetMorphTag();
setState(() => _editMode = false);
}
super.didUpdateWidget(oldWidget);
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
void _enterEditMode() {
setState(() {
_editMode = true;
});
}
ConstructIdentifier get _id {
return ConstructIdentifier(
lemma: _selectedMorphTag,
type: ConstructTypeEnum.morph,
category: widget.morphFeature.name,
);
}
@override
Widget build(BuildContext context) {
if (!_editMode) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
spacing: 8.0,
children: [
MorphFeatureDisplay(
morphFeature: widget.morphFeature,
),
if (token.getMorphTag(widget.morphFeature) != null) ...[
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Tooltip(
triggerMode: TooltipTriggerMode.tap,
message: L10n.of(context).doubleClickToEdit,
child: GestureDetector(
onLongPress: _enterEditMode,
onDoubleTap: _enterEditMode,
child: MorphTagDisplay(
morphFeature: widget.morphFeature,
morphTag: token.getMorphTag(widget.morphFeature) ??
L10n.of(context).nan,
textColor: Theme.of(context).brightness ==
Brightness.light
? _id.constructUses.lemmaCategory.darkColor(context)
: _id.constructUses.lemmaCategory.color(context),
),
),
),
const SizedBox(width: 6),
ConstructXpWidget(
id: _id,
onTap: () => showDialog<AnalyticsPopupWrapper>(
context: context,
builder: (context) => AnalyticsPopupWrapper(
constructZoom: _id,
view: ConstructTypeEnum.morph,
),
),
),
],
),
MorphMeaningWidget(
feature: widget.morphFeature,
tag: token.getMorphTag(widget.morphFeature)!,
style: Theme.of(context).textTheme.bodyLarge,
),
] else
Text(L10n.of(context).nan),
],
);
}
return Padding(
padding: const EdgeInsets.all(4.0),
child: EditMorphWidget(
token: token,
pangeaMessageEvent: widget.pangeaMessageEvent,
morphFeature: widget.morphFeature,
onClose: () {
setState(() => _editMode = false);
widget.overlayController.onMorphActivitySelect(
MorphSelection(
token,
widget.morphFeature,
),
);
},
),
);
}
}

View file

@ -1,16 +1,29 @@
import 'dart:developer';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/pangea/analytics_details_popup/analytics_details_popup.dart';
import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
import 'package:fluffychat/pangea/common/utils/overlay.dart';
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
import 'package:fluffychat/pangea/events/models/pangea_token_model.dart';
import 'package:fluffychat/pangea/lemmas/construct_xp_widget.dart';
import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart';
import 'package:fluffychat/pangea/morphs/morph_features_enum.dart';
import 'package:fluffychat/pangea/morphs/morph_icon.dart';
import 'package:fluffychat/pangea/morphs/morph_meaning/morph_info_repo.dart';
import 'package:fluffychat/pangea/practice_activities/activity_type_enum.dart';
import 'package:fluffychat/pangea/toolbar/enums/message_mode_enum.dart';
import 'package:fluffychat/pangea/toolbar/reading_assistance_input_row/morph_selection.dart';
import 'package:fluffychat/pangea/toolbar/widgets/message_selection_overlay.dart';
import 'package:fluffychat/pangea/toolbar/widgets/practice_activity/word_zoom_activity_button.dart';
import 'package:fluffychat/widgets/matrix.dart';
class MorphologicalListItem extends StatelessWidget {
final MorphFeaturesEnum morphFeature;
@ -41,40 +54,223 @@ class MorphologicalListItem extends StatelessWidget {
String get morphTag => token.getMorphTag(morphFeature) ?? "X";
ConstructIdentifier get cId =>
token.morphIdByFeature(morphFeature) ??
ConstructIdentifier(
type: ConstructTypeEnum.morph,
category: morphFeature.name,
lemma: morphTag,
);
void _openDefintionPopup(BuildContext context) async {
const width = 300.0;
const height = 150.0;
try {
OverlayUtil.showPositionedCard(
context: context,
cardToShow: MorphMeaningPopup(
cId: cId,
width: width,
height: height,
),
transformTargetId: cId.string,
backDropToDismiss: true,
borderColor: Theme.of(context).colorScheme.primary,
closePrevOverlay: false,
addBorder: false,
maxHeight: height,
maxWidth: width,
);
} catch (e, s) {
debugger(when: kDebugMode);
ErrorHandler.logError(
data: cId.toJson(),
e: e,
s: s,
);
}
}
@override
Widget build(BuildContext context) {
return SizedBox(
width: 40,
height: 40,
child: WordZoomActivityButton(
icon: shouldDoActivity
? const Icon(Symbols.toys_and_games)
: MorphIcon(
morphFeature: morphFeature,
morphTag: token.getMorphTag(morphFeature),
size: const Size(24, 24),
),
isSelected: isSelected,
onPressed: () => overlayController
.onMorphActivitySelect(MorphSelection(token, morphFeature)),
onLongPress: () {
overlayController
.onMorphActivitySelect(MorphSelection(token, morphFeature));
editMorph();
},
onDoubleTap: () {
overlayController
.onMorphActivitySelect(MorphSelection(token, morphFeature));
editMorph();
},
tooltip: shouldDoActivity
? morphFeature.getDisplayCopy(context)
: getGrammarCopy(
category: morphFeature.name,
lemma: morphTag,
context: context,
),
opacity: isSelected ? 1 : 0.7,
return CompositedTransformTarget(
link: MatrixState.pAnyState.layerLinkAndKey(cId.string).link,
child: SizedBox(
key: MatrixState.pAnyState.layerLinkAndKey(cId.string).key,
width: 40,
height: 40,
child: WordZoomActivityButton(
icon: shouldDoActivity
? const Icon(Symbols.toys_and_games)
: MorphIcon(
morphFeature: morphFeature,
morphTag: token.getMorphTag(morphFeature),
size: const Size(24, 24),
),
isSelected: isSelected,
onPressed: () {
overlayController
.onMorphActivitySelect(MorphSelection(token, morphFeature));
_openDefintionPopup(context);
},
onLongPress: () {
overlayController
.onMorphActivitySelect(MorphSelection(token, morphFeature));
editMorph();
},
tooltip: shouldDoActivity
? morphFeature.getDisplayCopy(context)
: getGrammarCopy(
category: morphFeature.name,
lemma: morphTag,
context: context,
),
opacity: isSelected ? 1 : 0.7,
),
),
);
}
}
class MorphMeaningPopup extends StatefulWidget {
final ConstructIdentifier cId;
final double width;
final double height;
const MorphMeaningPopup({
super.key,
required this.cId,
required this.width,
required this.height,
});
@override
State<MorphMeaningPopup> createState() => MorphMeaningPopupState();
}
class MorphMeaningPopupState extends State<MorphMeaningPopup> {
MorphFeaturesEnum get _morphFeature =>
MorphFeaturesEnumExtension.fromString(widget.cId.category);
String get _morphTag => widget.cId.lemma;
String? _defintion;
@override
void initState() {
super.initState();
_fetchDefinition();
}
@override
void didUpdateWidget(covariant MorphMeaningPopup oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.cId != widget.cId) {
_fetchDefinition();
}
}
Future<void> _fetchDefinition() async {
try {
final response = await MorphInfoRepo.get(
feature: _morphFeature,
tag: _morphTag,
);
if (mounted) {
setState(
() => _defintion = response ?? L10n.of(context).meaningNotFound,
);
}
} catch (e, s) {
debugger(when: kDebugMode);
ErrorHandler.logError(
data: widget.cId.toJson(),
e: e,
s: s,
);
}
}
@override
Widget build(BuildContext context) {
return Material(
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
child: Container(
padding: const EdgeInsets.all(8),
height: widget.height,
width: widget.width,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
boxShadow: [
BoxShadow(
color: Theme.of(context).colorScheme.onSurface.withAlpha(50),
blurRadius: 4,
offset: const Offset(0, 2),
),
],
),
alignment: Alignment.center,
child: SingleChildScrollView(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
spacing: 16.0,
children: [
SizedBox(
width: 24.0,
height: 24.0,
child: MorphIcon(
morphFeature: _morphFeature,
morphTag: _morphTag,
),
),
Text(
getGrammarCopy(
category: _morphFeature.name,
lemma: _morphTag,
context: context,
) ??
_morphTag,
style: Theme.of(context).textTheme.titleMedium,
),
SizedBox(
width: 24.0,
height: 24.0,
child: ConstructXpWidget(
id: widget.cId,
onTap: () => showDialog<AnalyticsPopupWrapper>(
context: context,
builder: (context) => AnalyticsPopupWrapper(
constructZoom: widget.cId,
view: ConstructTypeEnum.morph,
backButtonOverride: IconButton(
icon: const Icon(Icons.close),
onPressed: () => Navigator.of(context).pop(),
),
),
),
),
),
],
),
Padding(
padding: const EdgeInsets.only(top: 16.0),
child: _defintion != null
? Text(
_defintion!,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyMedium,
)
: const LinearProgressIndicator(),
),
],
),
),
),
);
}

View file

@ -76,8 +76,9 @@ class WordZoomWidget extends StatelessWidget {
children: [
//@ggurdin - might need to play with size to properly center
IconButton(
onPressed: () =>
overlayController.onClickOverlayMessageToken(token),
onPressed: () => overlayController.updateSelectedSpan(
token.text,
),
icon: const Icon(Icons.close),
),
LemmaWidget(