make overlay separate/stacked on top of word card

This commit is contained in:
avashilling 2025-07-03 11:44:59 -04:00
parent cec627386b
commit 71e1423fd9
2 changed files with 208 additions and 200 deletions

View file

@ -5,13 +5,11 @@ import 'package:fluffychat/pangea/constructs/construct_level_enum.dart';
import 'package:flutter/material.dart';
class NewWordOverlay extends StatefulWidget {
final Widget child;
final Color overlayColor;
final GlobalKey cardKey;
const NewWordOverlay({
super.key,
required this.child,
required this.overlayColor,
required this.cardKey,
});
@ -137,17 +135,20 @@ class _NewWordOverlayState extends State<NewWordOverlay>
Widget build(BuildContext context) {
return Stack(
children: [
widget.child,
Container(
height: size.height,
width: size.width,
color: Colors.transparent,
),
Positioned(
left: 5,
right: 5,
top: 50,
bottom: 5,
child: FadeTransition(
opacity: ReverseAnimation(_fadeAnim ?? kAlwaysCompleteAnimation),
child: Container(
color: widget.overlayColor,
),
child: Container(
height: size.height,
width: size.width,
color: widget.overlayColor,
),
),
],

View file

@ -45,212 +45,219 @@ class WordZoomWidget extends StatelessWidget {
Widget build(BuildContext context) {
final GlobalKey cardKey = GlobalKey();
final overlayColor = Theme.of(context).scaffoldBackgroundColor;
final Widget card = Container(
key: cardKey,
padding: const EdgeInsets.all(12.0),
constraints: const BoxConstraints(
minHeight: AppConfig.toolbarMinHeight - 8,
maxHeight: AppConfig.toolbarMaxHeight - 8,
maxWidth: AppConfig.toolbarMinWidth,
),
child: SingleChildScrollView(
child: Column(
spacing: 12.0,
mainAxisSize: MainAxisSize.min,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
return Stack(
children: [
Container(
key: cardKey,
padding: const EdgeInsets.all(12.0),
constraints: const BoxConstraints(
minHeight: AppConfig.toolbarMinHeight - 8,
maxHeight: AppConfig.toolbarMaxHeight - 8,
maxWidth: AppConfig.toolbarMinWidth,
),
child: SingleChildScrollView(
child: Column(
spacing: 12.0,
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
width: 24.0,
height: 24.0,
child: MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
onTap: () => overlayController.updateSelectedSpan(
token.text,
),
child: const Icon(
Icons.close,
size: 16.0,
),
),
),
),
Flexible(
child: Text(
token.text.content,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 32.0,
fontWeight: FontWeight.w600,
height: 1.2,
color: Theme.of(context).brightness == Brightness.light
? AppConfig.yellowDark
: AppConfig.yellowLight,
),
),
),
ConstructXpWidget(
id: token.vocabConstructID,
onTap: () => AnalyticsPopupWrapper.show(
context,
constructZoom: token.vocabConstructID,
view: ConstructTypeEnum.vocab,
),
),
],
),
LemmaMeaningBuilder(
langCode: messageEvent.messageDisplayLangCode,
constructId: token.vocabConstructID,
builder: (context, controller) {
if (controller.editMode) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"${L10n.of(context).pangeaBotIsFallible} ${L10n.of(context).whatIsMeaning(
token.vocabConstructID.lemma,
token.vocabConstructID.category,
)}",
textAlign: TextAlign.center,
style: const TextStyle(fontStyle: FontStyle.italic),
),
const SizedBox(height: 10),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: TextField(
minLines: 1,
maxLines: 3,
controller: controller.controller,
decoration: InputDecoration(
hintText: controller.lemmaInfo?.meaning,
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(
width: 24.0,
height: 24.0,
child: MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
onTap: () => overlayController.updateSelectedSpan(
token.text,
),
child: const Icon(
Icons.close,
size: 16.0,
),
),
),
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.center,
),
Flexible(
child: Text(
token.text.content,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 32.0,
fontWeight: FontWeight.w600,
height: 1.2,
color:
Theme.of(context).brightness == Brightness.light
? AppConfig.yellowDark
: AppConfig.yellowLight,
),
),
),
ConstructXpWidget(
id: token.vocabConstructID,
onTap: () => AnalyticsPopupWrapper.show(
context,
constructZoom: token.vocabConstructID,
view: ConstructTypeEnum.vocab,
),
),
],
),
LemmaMeaningBuilder(
langCode: messageEvent.messageDisplayLangCode,
constructId: token.vocabConstructID,
builder: (context, controller) {
if (controller.editMode) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
ElevatedButton(
onPressed: () => controller.toggleEditMode(false),
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
padding:
const EdgeInsets.symmetric(horizontal: 10),
),
child: Text(L10n.of(context).cancel),
Text(
"${L10n.of(context).pangeaBotIsFallible} ${L10n.of(context).whatIsMeaning(
token.vocabConstructID.lemma,
token.vocabConstructID.category,
)}",
textAlign: TextAlign.center,
style: const TextStyle(fontStyle: FontStyle.italic),
),
const SizedBox(width: 10),
ElevatedButton(
onPressed: () => controller.controller.text !=
controller.lemmaInfo?.meaning &&
controller.controller.text.isNotEmpty
? controller.editLemmaMeaning(
controller.controller.text,
)
: null,
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
const SizedBox(height: 10),
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 16.0),
child: TextField(
minLines: 1,
maxLines: 3,
controller: controller.controller,
decoration: InputDecoration(
hintText: controller.lemmaInfo?.meaning,
),
padding:
const EdgeInsets.symmetric(horizontal: 10),
),
child: Text(L10n.of(context).saveChanges),
),
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () =>
controller.toggleEditMode(false),
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
padding: const EdgeInsets.symmetric(
horizontal: 10,
),
),
child: Text(L10n.of(context).cancel),
),
const SizedBox(width: 10),
ElevatedButton(
onPressed: () => controller.controller.text !=
controller.lemmaInfo?.meaning &&
controller.controller.text.isNotEmpty
? controller.editLemmaMeaning(
controller.controller.text,
)
: null,
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
padding: const EdgeInsets.symmetric(
horizontal: 10,
),
),
child: Text(L10n.of(context).saveChanges),
),
],
),
],
),
],
);
}
);
}
return Column(
spacing: 12.0,
mainAxisSize: MainAxisSize.min,
children: [
if (MatrixState
.pangeaController.languageController.showTrancription)
PhoneticTranscriptionWidget(
text: token.text.content,
textLanguage: PLanguageStore.byLangCode(
messageEvent.messageDisplayLangCode,
) ??
LanguageModel.unknown,
style: const TextStyle(fontSize: 14.0),
iconSize: 24.0,
)
else
WordAudioButton(
text: token.text.content,
uniqueID: "lemma-content-${token.text.content}",
langCode: messageEvent.messageDisplayLangCode,
iconSize: 24.0,
),
LemmaReactionPicker(
cId: _selectedToken.vocabConstructID,
controller: overlayController.widget.chatController,
),
if (controller.error != null)
Text(
L10n.of(context).oopsSomethingWentWrong,
textAlign: TextAlign.center,
)
else if (controller.isLoading ||
controller.lemmaInfo == null)
const CircularProgressIndicator.adaptive()
else
GestureDetector(
onLongPress: () => controller.toggleEditMode(true),
onDoubleTap: () => controller.toggleEditMode(true),
child: token.lemma.text == token.text.content
? Text(
controller.lemmaInfo!.meaning,
style: const TextStyle(fontSize: 14.0),
textAlign: TextAlign.center,
)
: RichText(
text: TextSpan(
style: DefaultTextStyle.of(context)
.style
.copyWith(
fontSize: 14.0,
),
children: [
TextSpan(text: token.lemma.text),
const WidgetSpan(
child: SizedBox(width: 8.0),
return Column(
spacing: 12.0,
mainAxisSize: MainAxisSize.min,
children: [
if (MatrixState.pangeaController.languageController
.showTrancription)
PhoneticTranscriptionWidget(
text: token.text.content,
textLanguage: PLanguageStore.byLangCode(
messageEvent.messageDisplayLangCode,
) ??
LanguageModel.unknown,
style: const TextStyle(fontSize: 14.0),
iconSize: 24.0,
)
else
WordAudioButton(
text: token.text.content,
uniqueID: "lemma-content-${token.text.content}",
langCode: messageEvent.messageDisplayLangCode,
iconSize: 24.0,
),
LemmaReactionPicker(
cId: _selectedToken.vocabConstructID,
controller: overlayController.widget.chatController,
),
if (controller.error != null)
Text(
L10n.of(context).oopsSomethingWentWrong,
textAlign: TextAlign.center,
)
else if (controller.isLoading ||
controller.lemmaInfo == null)
const CircularProgressIndicator.adaptive()
else
GestureDetector(
onLongPress: () => controller.toggleEditMode(true),
onDoubleTap: () => controller.toggleEditMode(true),
child: token.lemma.text == token.text.content
? Text(
controller.lemmaInfo!.meaning,
style: const TextStyle(fontSize: 14.0),
textAlign: TextAlign.center,
)
: RichText(
text: TextSpan(
style: DefaultTextStyle.of(context)
.style
.copyWith(
fontSize: 14.0,
),
children: [
TextSpan(text: token.lemma.text),
const WidgetSpan(
child: SizedBox(width: 8.0),
),
const TextSpan(text: ":"),
const WidgetSpan(
child: SizedBox(width: 8.0),
),
TextSpan(
text: controller.lemmaInfo!.meaning,
),
],
),
const TextSpan(text: ":"),
const WidgetSpan(
child: SizedBox(width: 8.0),
),
TextSpan(
text: controller.lemmaInfo!.meaning,
),
],
),
),
),
],
);
},
),
),
],
);
},
),
],
),
],
),
),
),
wordIsNew
? NewWordOverlay(
overlayColor: overlayColor,
cardKey: cardKey,
)
: const SizedBox.shrink(),
],
);
return wordIsNew
? NewWordOverlay(
overlayColor: overlayColor,
cardKey: cardKey,
child: card,
)
: card;
}
}