chore: replace word audio icon button with gesture detector to remove in-built padding and be more exact about spacing (#2684)

This commit is contained in:
ggurdin 2025-05-06 11:13:50 -04:00 committed by GitHub
parent 61ba232195
commit 8468818ee4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 62 additions and 57 deletions

View file

@ -8,11 +8,11 @@ import 'package:fluffychat/widgets/matrix.dart';
class WordAudioButton extends StatefulWidget {
final String text;
final double size;
final bool isSelected;
final double baseOpacity;
final String uniqueID;
final String? langCode;
final EdgeInsets? padding;
/// If defined, this callback will be called instead of the default one
final void Function()? callbackOverride;
@ -21,11 +21,11 @@ class WordAudioButton extends StatefulWidget {
super.key,
required this.text,
required this.uniqueID,
this.size = 24,
this.isSelected = false,
this.baseOpacity = 1,
this.callbackOverride,
this.langCode,
this.padding,
});
@override
@ -58,59 +58,61 @@ class WordAudioButtonState extends State<WordAudioButton> {
.layerLinkAndKey('word-audio-button-${widget.uniqueID}')
.link,
child: Opacity(
key: MatrixState.pAnyState
.layerLinkAndKey('word-audio-button-${widget.uniqueID}')
.key,
opacity: widget.isSelected || _isPlaying ? 1 : widget.baseOpacity,
child: IconButton(
key: MatrixState.pAnyState
.layerLinkAndKey('word-audio-button-${widget.uniqueID}')
.key,
icon: const Icon(Icons.volume_up),
isSelected: _isPlaying,
selectedIcon: const Icon(Icons.pause_outlined),
color: widget.isSelected || _isPlaying
? Theme.of(context).colorScheme.primary
: null,
tooltip:
child: Tooltip(
message:
_isPlaying ? L10n.of(context).stop : L10n.of(context).playAudio,
iconSize: widget.size,
style: IconButton.styleFrom(
padding: const EdgeInsets.all(0),
child: MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
onTap: widget.callbackOverride ??
() async {
if (_isPlaying) {
await tts.stop();
if (mounted) {
setState(() => _isPlaying = false);
}
} else {
if (mounted) {
setState(() => _isPlaying = true);
}
try {
if (widget.langCode != null) {
await tts.tryToSpeak(
widget.text,
context: context,
targetID: 'word-audio-button-${widget.uniqueID}',
langCode: widget.langCode!,
);
}
} catch (e, s) {
ErrorHandler.logError(
e: e,
s: s,
data: {
"text": widget.text,
},
);
} finally {
if (mounted) {
setState(() => _isPlaying = false);
}
}
}
},
child: Padding(
padding: widget.padding ?? const EdgeInsets.all(0.0),
child: Icon(
_isPlaying ? Icons.pause_outlined : Icons.volume_up,
color:
_isPlaying ? Theme.of(context).colorScheme.primary : null,
),
),
),
),
constraints: const BoxConstraints(),
onPressed: widget.callbackOverride ??
() async {
if (_isPlaying) {
await tts.stop();
if (mounted) {
setState(() => _isPlaying = false);
}
} else {
if (mounted) {
setState(() => _isPlaying = true);
}
try {
if (widget.langCode != null) {
await tts.tryToSpeak(
widget.text,
context: context,
targetID: 'word-audio-button-${widget.uniqueID}',
langCode: widget.langCode!,
);
}
} catch (e, s) {
ErrorHandler.logError(
e: e,
s: s,
data: {
"text": widget.text,
},
);
} finally {
if (mounted) {
setState(() => _isPlaying = false);
}
}
}
}, // Disable button if language isn't supported
),
),
);

View file

@ -168,18 +168,21 @@ class LemmaWidgetState extends State<LemmaWidget> {
}
return Row(
spacing: 8.0,
children: [
Text(
widget.token.lemma.text,
style: Theme.of(context).textTheme.headlineSmall,
overflow: TextOverflow.ellipsis,
Padding(
padding: const EdgeInsets.all(4.0),
child: Text(
widget.token.lemma.text,
style: Theme.of(context).textTheme.headlineSmall,
overflow: TextOverflow.ellipsis,
),
),
WordAudioButton(
text: widget.token.lemma.text,
baseOpacity: 0.4,
uniqueID: "lemma-content-${widget.token.text.content}",
langCode: widget.pangeaMessageEvent.messageDisplayLangCode,
padding: const EdgeInsets.all(4.0),
),
],
);