WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit 3ffe6e9

Browse files
feat: ✨ Add selection and copy options for text view.
1 parent 5b76dd2 commit 3ffe6e9

File tree

4 files changed

+112
-9
lines changed

4 files changed

+112
-9
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
## [3.0.0] (unreleased)
2-
2+
* **Feat**: [401](https://github.com/SimformSolutionsPvtLtd/chatview/pull/401)
3+
Add selection and copy options for text view.
34
* **Breaking**: [318](https://github.com/SimformSolutionsPvtLtd/chatview/issues/318)
45
Provide support for action item widgets on the chat text field with position options
56
`leadingActions` and `trailingActions` in `TextFieldConfiguration`. Also, provide a way to add

lib/src/models/chat_bubble.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ class ChatBubble {
3636
this.senderNameTextStyle,
3737
this.receiptsWidgetConfig,
3838
this.onMessageRead,
39+
this.isSelectable = true,
3940
this.border,
41+
this.selectionHighlightColor,
42+
this.selectionCursorColor,
4043
});
4144

4245
/// Used for giving color of chat bubble.
@@ -70,4 +73,13 @@ class ChatBubble {
7073

7174
/// Used for giving border of chat bubble.
7275
final Border? border;
76+
77+
/// Used to determine whether the text can be selected.
78+
final bool isSelectable;
79+
80+
/// Color used to paint the selected text highlight background. If null, falls back to theme.
81+
final Color? selectionHighlightColor;
82+
83+
/// Color for the drag handles. If null, falls back to theme.
84+
final Color? selectionCursorColor;
7385
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import 'package:flutter/material.dart';
2+
3+
/// A convenience wrapper around [SelectionArea] that lets you locally
4+
/// customize selection highlight, handle, and colors
5+
/// without changing the global app [Theme].
6+
7+
class CustomSelectionArea extends StatelessWidget {
8+
const CustomSelectionArea({
9+
super.key,
10+
required this.child,
11+
this.selectionColor,
12+
this.selectionHandleColor,
13+
this.selectionControls,
14+
this.cursorColor,
15+
});
16+
17+
/// The subtree whose text becomes selectable.
18+
final Widget child;
19+
20+
/// Color used to paint the selected text highlight background.
21+
final Color? selectionColor;
22+
23+
/// Color for the drag handles. If null, falls back to theme.
24+
final Color? selectionHandleColor;
25+
26+
/// Optional custom selection controls (toolbar / handles). If you just need
27+
/// color tweaks, you usually do not need to supply this.
28+
final TextSelectionControls? selectionControls;
29+
30+
/// Cursor color for any text.
31+
final Color? cursorColor;
32+
33+
@override
34+
Widget build(BuildContext context) {
35+
final theme = Theme.of(context);
36+
final baseTextSelectionTheme = theme.textSelectionTheme;
37+
38+
final mergedTextSelectionTheme = baseTextSelectionTheme.copyWith(
39+
selectionColor: selectionColor ?? baseTextSelectionTheme.selectionColor,
40+
selectionHandleColor:
41+
selectionHandleColor ?? baseTextSelectionTheme.selectionHandleColor,
42+
cursorColor: cursorColor ?? baseTextSelectionTheme.cursorColor,
43+
);
44+
45+
return Theme(
46+
data: theme.copyWith(textSelectionTheme: mergedTextSelectionTheme),
47+
child: SelectionArea(selectionControls: selectionControls, child: child),
48+
);
49+
}
50+
}
51+
52+
class ColoredTextSelectionControls extends MaterialTextSelectionControls {
53+
ColoredTextSelectionControls(this.handleColor);
54+
55+
/// Color for the drag handles.
56+
final Color handleColor;
57+
58+
@override
59+
Widget buildHandle(
60+
BuildContext context,
61+
TextSelectionHandleType type,
62+
double textHeight, [
63+
VoidCallback? onTap,
64+
]) {
65+
final handle = super.buildHandle(context, type, textHeight, onTap);
66+
return IconTheme.merge(
67+
data: IconThemeData(color: handleColor),
68+
child: handle,
69+
);
70+
}
71+
}

lib/src/widgets/text_message_view.dart

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2020
* SOFTWARE.
2121
*/
22+
import 'package:chatview/src/widgets/custom_selection_area.dart';
2223
import 'package:chatview_utils/chatview_utils.dart';
2324
import 'package:flutter/material.dart';
2425

@@ -74,6 +75,23 @@ class TextMessageView extends StatelessWidget {
7475
final border = isMessageBySender
7576
? outgoingChatBubbleConfig?.border
7677
: inComingChatBubbleConfig?.border;
78+
final isSelectable = isMessageBySender
79+
? outgoingChatBubbleConfig?.isSelectable ?? false
80+
: inComingChatBubbleConfig?.isSelectable ?? false;
81+
final selectionHighlightColor = isMessageBySender
82+
? outgoingChatBubbleConfig?.selectionHighlightColor
83+
: inComingChatBubbleConfig?.selectionHighlightColor;
84+
final selectionCursorColor = isMessageBySender
85+
? outgoingChatBubbleConfig?.selectionCursorColor
86+
: inComingChatBubbleConfig?.selectionCursorColor;
87+
final baseWidget = Text(
88+
textMessage,
89+
style: _textStyle ??
90+
textTheme.bodyMedium!.copyWith(
91+
color: Colors.white,
92+
fontSize: 16,
93+
),
94+
);
7795
return Stack(
7896
clipBehavior: Clip.none,
7997
children: [
@@ -99,14 +117,15 @@ class TextMessageView extends StatelessWidget {
99117
linkPreviewConfig: _linkPreviewConfig,
100118
url: textMessage,
101119
)
102-
: Text(
103-
textMessage,
104-
style: _textStyle ??
105-
textTheme.bodyMedium!.copyWith(
106-
color: Colors.white,
107-
fontSize: 16,
108-
),
109-
),
120+
: isSelectable
121+
? CustomSelectionArea(
122+
selectionColor: selectionHighlightColor,
123+
selectionHandleColor: selectionCursorColor,
124+
selectionControls: ColoredTextSelectionControls(
125+
selectionCursorColor ?? Colors.black),
126+
child: baseWidget,
127+
)
128+
: baseWidget,
110129
),
111130
if (message.reaction.reactions.isNotEmpty)
112131
ReactionWidget(

0 commit comments

Comments
 (0)