added new overlays and docs

This commit is contained in:
Deven Joshi
2021-09-07 14:31:48 +05:30
parent ae2e8b740f
commit 0af7b1a0e6
2 changed files with 80 additions and 46 deletions
@@ -475,7 +475,7 @@ class MessageInputState extends State<MessageInput> {
_emojiOverlay != null || _emojiOverlay != null ||
_mentionsOverlay != null, _mentionsOverlay != null,
overlayBuilder: (context, offset) { overlayBuilder: (context, offset) {
late Widget child; late Widget? child;
if (_commandsOverlay != null) { if (_commandsOverlay != null) {
child = _buildCommandsOverlayEntry(); child = _buildCommandsOverlayEntry();
@@ -487,7 +487,7 @@ class MessageInputState extends State<MessageInput> {
return CenterAbout( return CenterAbout(
position: Offset(offset.dx, offset.dy), position: Offset(offset.dx, offset.dy),
child: child, child: child ?? const SizedBox(),
); );
}, },
child: child, child: child,
@@ -922,7 +922,7 @@ class MessageInputState extends State<MessageInput> {
} }
} }
Widget _buildCommandsOverlayEntry() { Widget? _buildCommandsOverlayEntry() {
final text = textEditingController.text.trimLeft(); final text = textEditingController.text.trimLeft();
final commands = StreamChannel.of(context) final commands = StreamChannel.of(context)
.channel .channel
@@ -931,6 +931,11 @@ class MessageInputState extends State<MessageInput> {
.where((c) => c.name.contains(text.replaceFirst('/', ''))) .where((c) => c.name.contains(text.replaceFirst('/', '')))
.toList() ?? .toList() ??
[]; [];
if (commands.isEmpty) {
return null;
}
final size = MediaQuery.of(context).size; final size = MediaQuery.of(context).size;
return Padding( return Padding(
@@ -1312,7 +1317,7 @@ class MessageInputState extends State<MessageInput> {
} }
} }
Widget _buildMentionsOverlayEntry() { Widget? _buildMentionsOverlayEntry() {
final splits = textEditingController.text final splits = textEditingController.text
.substring(0, textEditingController.value.selection.start) .substring(0, textEditingController.value.selection.start)
.split('@'); .split('@');
@@ -1332,6 +1337,10 @@ class MessageInputState extends State<MessageInput> {
.toList() ?? .toList() ??
[]; [];
if (members.isEmpty) {
return null;
}
// ignore: cast_nullable_to_non_nullable // ignore: cast_nullable_to_non_nullable
final renderBox = context.findRenderObject() as RenderBox; final renderBox = context.findRenderObject() as RenderBox;
final size = renderBox.size; final size = renderBox.size;
@@ -1410,7 +1419,7 @@ class MessageInputState extends State<MessageInput> {
); );
} }
Widget _buildEmojiOverlay() { Widget? _buildEmojiOverlay() {
final splits = textEditingController.text final splits = textEditingController.text
.substring(0, textEditingController.value.selection.start) .substring(0, textEditingController.value.selection.start)
.split(':'); .split(':');
@@ -1421,6 +1430,10 @@ class MessageInputState extends State<MessageInput> {
.map(Emoji.byName) .map(Emoji.byName)
.where((e) => e != null); .where((e) => e != null);
if (emojis.isEmpty) {
return null;
}
// ignore: cast_nullable_to_non_nullable // ignore: cast_nullable_to_non_nullable
final renderBox = context.findRenderObject() as RenderBox; final renderBox = context.findRenderObject() as RenderBox;
final size = renderBox.size; final size = renderBox.size;
@@ -1,49 +1,66 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
/// Class to create an overlay anchored to a child widget
class AnchoredOverlay extends StatelessWidget { class AnchoredOverlay extends StatelessWidget {
final bool showOverlay; /// Constructor for creating an [AnchoredOverlay]
final Widget Function(BuildContext, Offset anchor) overlayBuilder; const AnchoredOverlay({
final Widget child; Key? key,
AnchoredOverlay({
this.showOverlay = false, this.showOverlay = false,
required this.overlayBuilder, required this.overlayBuilder,
required this.child, required this.child,
}); }) : super(key: key);
/// Show or hide overlay
final bool showOverlay;
/// Builder for creating overlay widget
final Widget Function(BuildContext, Offset anchor) overlayBuilder;
/// Child to which overlay is anchored
final Widget child;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) => SizedBox(
return new Container( child: LayoutBuilder(
child: new LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) =>
builder: (BuildContext context, BoxConstraints constraints) { OverlayBuilder(
return new OverlayBuilder( showOverlay: showOverlay,
showOverlay: showOverlay, overlayBuilder: (BuildContext overlayContext) {
overlayBuilder: (BuildContext overlayContext) { final box = context.findRenderObject() as RenderBox?;
RenderBox box = context.findRenderObject() as RenderBox; if (box != null) {
final center = final center = box.size
box.size.center(box.localToGlobal(const Offset(0.0, 0.0))); .center(box.localToGlobal(const Offset(0, 0)));
return overlayBuilder(overlayContext, center); return overlayBuilder(overlayContext, center);
}, } else {
child: child, return const SizedBox();
); }
}), },
); child: child,
} )),
);
} }
/// Class for creating a declarative-ish overlay
class OverlayBuilder extends StatefulWidget { class OverlayBuilder extends StatefulWidget {
final bool showOverlay; /// Constructor for creating an [OverlayBuilder]
final Widget Function(BuildContext) overlayBuilder; const OverlayBuilder({
final Widget child; Key? key,
OverlayBuilder({
this.showOverlay = false, this.showOverlay = false,
required this.overlayBuilder, required this.overlayBuilder,
required this.child, required this.child,
}); }) : super(key: key);
/// Show or hide overlay
final bool showOverlay;
/// Builder for creating overlay widget
final Widget Function(BuildContext) overlayBuilder;
/// Child to which overlay is anchored
final Widget child;
@override @override
_OverlayBuilderState createState() => new _OverlayBuilderState(); _OverlayBuilderState createState() => _OverlayBuilderState();
} }
class _OverlayBuilderState extends State<OverlayBuilder> { class _OverlayBuilderState extends State<OverlayBuilder> {
@@ -112,31 +129,35 @@ class _OverlayBuilderState extends State<OverlayBuilder> {
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) => widget.child;
return widget.child;
}
} }
/// Class to position Overlay
class CenterAbout extends StatelessWidget { class CenterAbout extends StatelessWidget {
final Offset position; /// Constructor for creating an [CenterAbout]
final Widget child; const CenterAbout({
Key? key,
CenterAbout({
required this.position, required this.position,
required this.child, required this.child,
}); }) : super(key: key);
/// Position of child
final Offset position;
/// Child widget to which overlay is attached
final Widget child;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var size = MediaQuery.of(context).size; final size = MediaQuery.of(context).size;
return Positioned( return Positioned(
bottom: size.height - position.dy, bottom: size.height - position.dy,
left: position.dx, left: position.dx,
child: FractionalTranslation( child: FractionalTranslation(
translation: const Offset(-0.5, 0.0), translation: const Offset(-0.5, 0),
child: Padding( child: Padding(
padding: const EdgeInsets.only(bottom: 32.0), padding: const EdgeInsets.only(bottom: 32),
child: child, child: child,
), ),
), ),