refactor(ui): remove context from Commands and Mentions overlays
This commit is contained in:
-2
@@ -110,12 +110,10 @@ class _OverlayBuilderState extends State<OverlayBuilder> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void addToOverlay(OverlayEntry entry) async {
|
void addToOverlay(OverlayEntry entry) async {
|
||||||
print('addToOverlay');
|
|
||||||
Overlay.of(context)?.insert(entry);
|
Overlay.of(context)?.insert(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hideOverlay() {
|
void hideOverlay() {
|
||||||
print('hideOverlay');
|
|
||||||
overlayEntry?.remove();
|
overlayEntry?.remove();
|
||||||
overlayEntry = null;
|
overlayEntry = null;
|
||||||
}
|
}
|
||||||
@@ -1,33 +1,34 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
|
||||||
import 'package:stream_chat_flutter/src/extension.dart';
|
import 'package:stream_chat_flutter/src/extension.dart';
|
||||||
|
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||||
|
|
||||||
/// Overlay for displaying commands that can be used
|
/// Overlay for displaying commands that can be used
|
||||||
class CommandsOverlay extends StatelessWidget {
|
class CommandsOverlay extends StatelessWidget {
|
||||||
/// Constructor for creating a [CommandsOverlay]
|
/// Constructor for creating a [CommandsOverlay]
|
||||||
const CommandsOverlay(
|
const CommandsOverlay({
|
||||||
this.context, {
|
|
||||||
required this.text,
|
required this.text,
|
||||||
required this.onCommandResult,
|
required this.onCommandResult,
|
||||||
|
required this.size,
|
||||||
|
required this.channel,
|
||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
/// Context of the upper tree
|
/// The size of the overlay
|
||||||
final BuildContext context;
|
final Size size;
|
||||||
|
|
||||||
/// Query for searching commands
|
/// Query for searching commands
|
||||||
final String text;
|
final String text;
|
||||||
|
|
||||||
|
/// The channel to search for users
|
||||||
|
final Channel channel;
|
||||||
|
|
||||||
/// Callback called when a command is selected
|
/// Callback called when a command is selected
|
||||||
final ValueChanged<Command> onCommandResult;
|
final ValueChanged<Command> onCommandResult;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext otherContext) {
|
Widget build(BuildContext context) {
|
||||||
final _streamChatTheme = StreamChatTheme.of(context);
|
final _streamChatTheme = StreamChatTheme.of(context);
|
||||||
final commands = StreamChannel.of(context)
|
final commands = channel.config?.commands
|
||||||
.channel
|
|
||||||
.config
|
|
||||||
?.commands
|
|
||||||
.where((c) => c.name.contains(text.replaceFirst('/', '')))
|
.where((c) => c.name.contains(text.replaceFirst('/', '')))
|
||||||
.toList() ??
|
.toList() ??
|
||||||
[];
|
[];
|
||||||
@@ -36,8 +37,6 @@ class CommandsOverlay extends StatelessWidget {
|
|||||||
return const SizedBox();
|
return const SizedBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
final size = MediaQuery.of(context).size;
|
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(4),
|
padding: const EdgeInsets.all(4),
|
||||||
child: Card(
|
child: Card(
|
||||||
@@ -48,7 +47,7 @@ class CommandsOverlay extends StatelessWidget {
|
|||||||
color: _streamChatTheme.colorTheme.barsBg,
|
color: _streamChatTheme.colorTheme.barsBg,
|
||||||
clipBehavior: Clip.hardEdge,
|
clipBehavior: Clip.hardEdge,
|
||||||
child: Container(
|
child: Container(
|
||||||
constraints: BoxConstraints.loose(Size(size.width - 16, 400)),
|
constraints: BoxConstraints.loose(size),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: _streamChatTheme.colorTheme.barsBg,
|
color: _streamChatTheme.colorTheme.barsBg,
|
||||||
borderRadius: BorderRadius.circular(8)),
|
borderRadius: BorderRadius.circular(8)),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
|
||||||
import 'package:stream_chat_flutter/src/emoji/emoji.dart';
|
import 'package:stream_chat_flutter/src/emoji/emoji.dart';
|
||||||
import 'package:stream_chat_flutter/src/extension.dart';
|
import 'package:stream_chat_flutter/src/extension.dart';
|
||||||
|
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||||
import 'package:substring_highlight/substring_highlight.dart';
|
import 'package:substring_highlight/substring_highlight.dart';
|
||||||
|
|
||||||
/// Overlay for displaying emoji that can be used
|
/// Overlay for displaying emoji that can be used
|
||||||
|
|||||||
@@ -4,20 +4,24 @@ import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
|||||||
/// Overlay for displaying users that can be mentioned
|
/// Overlay for displaying users that can be mentioned
|
||||||
class MentionsOverlay extends StatelessWidget {
|
class MentionsOverlay extends StatelessWidget {
|
||||||
/// Constructor for creating a [MentionsOverlay]
|
/// Constructor for creating a [MentionsOverlay]
|
||||||
const MentionsOverlay(
|
const MentionsOverlay({
|
||||||
this.context, {
|
|
||||||
required this.query,
|
required this.query,
|
||||||
required this.onMentionResult,
|
required this.onMentionResult,
|
||||||
|
required this.size,
|
||||||
|
required this.channel,
|
||||||
this.mentionsTileBuilder,
|
this.mentionsTileBuilder,
|
||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
/// Context of the upper tree
|
/// The size of the overlay
|
||||||
final BuildContext context;
|
final Size size;
|
||||||
|
|
||||||
/// Query for searching users
|
/// Query for searching users
|
||||||
final String query;
|
final String query;
|
||||||
|
|
||||||
|
/// The channel to search for users
|
||||||
|
final Channel channel;
|
||||||
|
|
||||||
/// Callback called when a user is selected
|
/// Callback called when a user is selected
|
||||||
final ValueChanged<User?> onMentionResult;
|
final ValueChanged<User?> onMentionResult;
|
||||||
|
|
||||||
@@ -25,19 +29,18 @@ class MentionsOverlay extends StatelessWidget {
|
|||||||
final MentionTileBuilder? mentionsTileBuilder;
|
final MentionTileBuilder? mentionsTileBuilder;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext otherContext) {
|
Widget build(BuildContext context) {
|
||||||
final _streamChatTheme = StreamChatTheme.of(context);
|
final _streamChatTheme = StreamChatTheme.of(context);
|
||||||
|
|
||||||
Future<List<Member>>? queryMembers;
|
Future<List<Member>>? queryMembers;
|
||||||
|
|
||||||
final channelState = StreamChannel.of(context);
|
|
||||||
if (query.isNotEmpty) {
|
if (query.isNotEmpty) {
|
||||||
queryMembers = channelState.channel
|
queryMembers = channel
|
||||||
.queryMembers(filter: Filter.autoComplete('name', query))
|
.queryMembers(filter: Filter.autoComplete('name', query))
|
||||||
.then((res) => res.members);
|
.then((res) => res.members);
|
||||||
}
|
}
|
||||||
|
|
||||||
final members = channelState.channel.state?.members
|
final members = channel.state?.members
|
||||||
.where((m) => m.user?.name.toLowerCase().contains(query) == true)
|
.where((m) => m.user?.name.toLowerCase().contains(query) == true)
|
||||||
.toList() ??
|
.toList() ??
|
||||||
[];
|
[];
|
||||||
@@ -46,9 +49,6 @@ class MentionsOverlay extends StatelessWidget {
|
|||||||
return const SizedBox();
|
return const SizedBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore: cast_nullable_to_non_nullable
|
|
||||||
final renderBox = context.findRenderObject() as RenderBox;
|
|
||||||
final size = renderBox.size;
|
|
||||||
final child = Card(
|
final child = Card(
|
||||||
margin: const EdgeInsets.all(8),
|
margin: const EdgeInsets.all(8),
|
||||||
elevation: 2,
|
elevation: 2,
|
||||||
@@ -58,7 +58,7 @@ class MentionsOverlay extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
clipBehavior: Clip.hardEdge,
|
clipBehavior: Clip.hardEdge,
|
||||||
child: Container(
|
child: Container(
|
||||||
constraints: BoxConstraints.loose(Size(size.width - 16, 200)),
|
constraints: BoxConstraints.loose(size),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: _streamChatTheme.colorTheme.barsBg,
|
color: _streamChatTheme.colorTheme.barsBg,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import 'package:shimmer/shimmer.dart';
|
|||||||
import 'package:stream_chat_flutter/src/commands_overlay.dart';
|
import 'package:stream_chat_flutter/src/commands_overlay.dart';
|
||||||
import 'package:stream_chat_flutter/src/emoji_overlay.dart';
|
import 'package:stream_chat_flutter/src/emoji_overlay.dart';
|
||||||
import 'package:stream_chat_flutter/src/mentions_overlay.dart';
|
import 'package:stream_chat_flutter/src/mentions_overlay.dart';
|
||||||
import 'package:stream_chat_flutter/src/overlays.dart';
|
import 'package:stream_chat_flutter/src/anchored_overlay.dart';
|
||||||
import 'package:stream_chat_flutter/src/emoji/emoji.dart';
|
import 'package:stream_chat_flutter/src/emoji/emoji.dart';
|
||||||
import 'package:stream_chat_flutter/src/extension.dart';
|
import 'package:stream_chat_flutter/src/extension.dart';
|
||||||
import 'package:stream_chat_flutter/src/media_list_view.dart';
|
import 'package:stream_chat_flutter/src/media_list_view.dart';
|
||||||
@@ -923,7 +923,14 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
Widget _buildCommandsOverlayEntry() {
|
Widget _buildCommandsOverlayEntry() {
|
||||||
final text = textEditingController.text.trimLeft();
|
final text = textEditingController.text.trimLeft();
|
||||||
|
|
||||||
return CommandsOverlay(context, text: text, onCommandResult: _setCommand);
|
// ignore: cast_nullable_to_non_nullable
|
||||||
|
final renderObject = context.findRenderObject() as RenderBox;
|
||||||
|
return CommandsOverlay(
|
||||||
|
channel: StreamChannel.of(context).channel,
|
||||||
|
size: Size(renderObject.size.width - 16, 400),
|
||||||
|
text: text,
|
||||||
|
onCommandResult: _setCommand,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildFilePickerSection() {
|
Widget _buildFilePickerSection() {
|
||||||
@@ -1141,27 +1148,35 @@ class MessageInputState extends State<MessageInput> {
|
|||||||
.split('@');
|
.split('@');
|
||||||
final query = splits.last.toLowerCase();
|
final query = splits.last.toLowerCase();
|
||||||
|
|
||||||
return MentionsOverlay(context, query: query, onMentionResult: (user) {
|
// ignore: cast_nullable_to_non_nullable
|
||||||
if (user != null) {
|
final renderObject = context.findRenderObject() as RenderBox;
|
||||||
_mentionedUsers.add(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
splits[splits.length - 1] = user!.name;
|
return MentionsOverlay(
|
||||||
final rejoin = splits.join('@');
|
channel: StreamChannel.of(context).channel,
|
||||||
|
size: Size(renderObject.size.width - 16, 400),
|
||||||
|
query: query,
|
||||||
|
onMentionResult: (user) {
|
||||||
|
if (user != null) {
|
||||||
|
_mentionedUsers.add(user);
|
||||||
|
}
|
||||||
|
|
||||||
textEditingController.value = TextEditingValue(
|
splits[splits.length - 1] = user!.name;
|
||||||
text: rejoin +
|
final rejoin = splits.join('@');
|
||||||
textEditingController.text
|
|
||||||
.substring(textEditingController.selection.start),
|
textEditingController.value = TextEditingValue(
|
||||||
selection: TextSelection.collapsed(
|
text: rejoin +
|
||||||
offset: rejoin.length,
|
textEditingController.text
|
||||||
),
|
.substring(textEditingController.selection.start),
|
||||||
);
|
selection: TextSelection.collapsed(
|
||||||
_debounce!.cancel();
|
offset: rejoin.length,
|
||||||
setState(() {
|
),
|
||||||
_mentionsOverlay = null;
|
);
|
||||||
});
|
_debounce!.cancel();
|
||||||
});
|
setState(() {
|
||||||
|
_mentionsOverlay = null;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildEmojiOverlay() {
|
Widget _buildEmojiOverlay() {
|
||||||
|
|||||||
Reference in New Issue
Block a user