From d63c84d4bb426e37c69b0ed06c4741feba85a3c6 Mon Sep 17 00:00:00 2001 From: krawieck Date: Wed, 16 Sep 2020 20:09:09 +0200 Subject: [PATCH 1/2] Make comments selectable --- lib/widgets/comment.dart | 213 ++++++++++++++++++++------------- lib/widgets/markdown_text.dart | 5 +- 2 files changed, 134 insertions(+), 84 deletions(-) diff --git a/lib/widgets/comment.dart b/lib/widgets/comment.dart index 206c9ec..3597861 100644 --- a/lib/widgets/comment.dart +++ b/lib/widgets/comment.dart @@ -1,6 +1,8 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:esys_flutter_share/esys_flutter_share.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:intl/intl.dart'; import 'package:lemmy_api_client/lemmy_api_client.dart'; import 'package:timeago/timeago.dart' as timeago; @@ -13,7 +15,7 @@ import '../util/text_color.dart'; import 'bottom_modal.dart'; import 'markdown_text.dart'; -class Comment extends StatelessWidget { +class Comment extends HookWidget { final int indent; final int postCreatorId; final CommentTree commentTree; @@ -32,57 +34,6 @@ class Comment extends StatelessWidget { @required this.postCreatorId, }); - void _openMoreMenu(BuildContext context) { - final com = commentTree.comment; - showModalBottomSheet( - backgroundColor: Colors.transparent, - context: context, - builder: (context) => BottomModal( - child: Column( - children: [ - ListTile( - leading: Icon(Icons.open_in_browser), - title: Text('Open in browser'), - onTap: () async => await ul.canLaunch(com.apId) - ? ul.launch(com.apId) - : Scaffold.of(context).showSnackBar( - SnackBar(content: Text("can't open in browser"))), - ), - ListTile( - leading: Icon(Icons.share), - title: Text('Share url'), - onTap: () => - Share.text('Share comment url', com.apId, 'text/plain'), - ), - ListTile( - leading: Icon(Icons.share), - title: Text('Share text'), - onTap: () => - Share.text('Share comment text', com.content, 'text/plain'), - ), - ListTile( - leading: Icon(Icons.info_outline), - title: Text('Nerd stuff'), - onTap: () => _showCommentInfo(context), - ), - ], - ), - ), - ); - } - - void _save(bool save) { - print('SAVE COMMENT, $save'); - } - - void _reply() { - print('OPEN REPLY BOX'); - } - - void _vote(VoteType vote) { - print('COMMENT VOTE: ${vote.toString()}'); - } - _showCommentInfo(BuildContext context) { final com = commentTree.comment; showDialog( @@ -141,10 +92,85 @@ class Comment extends StatelessWidget { @override Widget build(BuildContext context) { - final comment = commentTree.comment; + final selectable = useState(false); + final showRaw = useState(false); + final comment = commentTree.comment; final saved = comment.saved ?? false; + void _openMoreMenu(BuildContext context) { + pop() { + Navigator.of(context).pop(); + } + + final com = commentTree.comment; + showModalBottomSheet( + backgroundColor: Colors.transparent, + context: context, + builder: (context) => BottomModal( + child: Column( + children: [ + ListTile( + leading: Icon(Icons.open_in_browser), + title: Text('Open in browser'), + onTap: () async => await ul.canLaunch(com.apId) + ? ul.launch(com.apId) + : Scaffold.of(context).showSnackBar( + SnackBar(content: Text("can't open in browser"))), + ), + ListTile( + leading: Icon(Icons.share), + title: Text('Share url'), + onTap: () => + Share.text('Share comment url', com.apId, 'text/plain'), + ), + ListTile( + leading: Icon(Icons.share), + title: Text('Share text'), + onTap: () => + Share.text('Share comment text', com.content, 'text/plain'), + ), + ListTile( + leading: Icon( + selectable.value ? Icons.assignment : Icons.content_cut), + title: + Text('Make text ${selectable.value ? 'un' : ''}selectable'), + onTap: () { + selectable.value = !selectable.value; + pop(); + }, + ), + ListTile( + leading: Icon(showRaw.value ? Icons.brush : Icons.build), + title: Text('Show ${showRaw.value ? 'fancy' : 'raw'} text'), + onTap: () { + showRaw.value = !showRaw.value; + pop(); + }, + ), + ListTile( + leading: Icon(Icons.info_outline), + title: Text('Nerd stuff'), + onTap: () => _showCommentInfo(context), + ), + ], + ), + ), + ); + } + + void _save(bool save) { + print('SAVE COMMENT, $save'); + } + + void _reply() { + print('OPEN REPLY BOX'); + } + + void _vote(VoteType vote) { + print('COMMENT VOTE: ${vote.toString()}'); + } + // decide which username to use final username = () { if (comment.creatorPreferredUsername != null && @@ -170,11 +196,57 @@ class Comment extends StatelessWidget { )); } else { return Flexible( - child: MarkdownText(commentTree.comment.content, - instanceUrl: commentTree.comment.instanceUrl)); + child: showRaw.value + ? selectable.value + ? SelectableText(commentTree.comment.content) + : Text(commentTree.comment.content) + : MarkdownText( + commentTree.comment.content, + instanceUrl: commentTree.comment.instanceUrl, + selectable: selectable.value, + )); } }(); + final actions = Row(children: [ + if (selectable.value) + _CommentAction( + icon: Icons.content_copy, + tooltip: 'copy', + onPressed: () { + Clipboard.setData( + ClipboardData(text: commentTree.comment.content)) + .then((_) => Scaffold.of(context).showSnackBar( + SnackBar(content: Text('comment copied to clipboard')))); + }), + Spacer(), + _CommentAction( + icon: Icons.more_horiz, + onPressed: () => _openMoreMenu(context), + tooltip: 'more', + ), + _CommentAction( + icon: saved ? Icons.bookmark : Icons.bookmark_border, + onPressed: () => _save(!saved), + tooltip: '${saved ? 'unsave' : 'save'} comment', + ), + _CommentAction( + icon: Icons.reply, + onPressed: _reply, + tooltip: 'reply', + ), + _CommentAction( + icon: Icons.arrow_upward, + onPressed: () => _vote(VoteType.up), + tooltip: 'upvote', + ), + _CommentAction( + icon: Icons.arrow_downward, + onPressed: () => _vote(VoteType.down), + tooltip: 'downvote', + ), + ]); + return Column( children: [ Container( @@ -228,35 +300,10 @@ class Comment extends StatelessWidget { ), ) ]), + SizedBox(height: 10), Row(children: [body]), - Row(children: [ - Spacer(), - _CommentAction( - icon: Icons.more_horiz, - onPressed: () => _openMoreMenu(context), - tooltip: 'more', - ), - _CommentAction( - icon: saved ? Icons.bookmark : Icons.bookmark_border, - onPressed: () => _save(!saved), - tooltip: '${saved ? 'unsave' : 'save'} comment', - ), - _CommentAction( - icon: Icons.reply, - onPressed: _reply, - tooltip: 'reply', - ), - _CommentAction( - icon: Icons.arrow_upward, - onPressed: () => _vote(VoteType.up), - tooltip: 'upvote', - ), - _CommentAction( - icon: Icons.arrow_downward, - onPressed: () => _vote(VoteType.down), - tooltip: 'downvote', - ), - ]) + SizedBox(height: 5), + actions, ], ), padding: EdgeInsets.all(10), diff --git a/lib/widgets/markdown_text.dart b/lib/widgets/markdown_text.dart index d3b4af2..42b4f95 100644 --- a/lib/widgets/markdown_text.dart +++ b/lib/widgets/markdown_text.dart @@ -9,11 +9,14 @@ import 'fullscreenable_image.dart'; class MarkdownText extends StatelessWidget { final String instanceUrl; final String text; - MarkdownText(this.text, {@required this.instanceUrl}) + final bool selectable; + + MarkdownText(this.text, {@required this.instanceUrl, this.selectable = false}) : assert(instanceUrl != null); @override Widget build(BuildContext context) => MarkdownBody( + selectable: selectable, data: text, extensionSet: md.ExtensionSet.gitHubWeb, onTapLink: (href) { From a5eaf784d5741a17e1f72f77569e08f646fd0a16 Mon Sep 17 00:00:00 2001 From: krawieck Date: Wed, 16 Sep 2020 21:21:47 +0200 Subject: [PATCH 2/2] convert pop to arrow function --- lib/widgets/comment.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/widgets/comment.dart b/lib/widgets/comment.dart index 3597861..9d71bb8 100644 --- a/lib/widgets/comment.dart +++ b/lib/widgets/comment.dart @@ -99,9 +99,7 @@ class Comment extends HookWidget { final saved = comment.saved ?? false; void _openMoreMenu(BuildContext context) { - pop() { - Navigator.of(context).pop(); - } + pop() => Navigator.of(context).pop(); final com = commentTree.comment; showModalBottomSheet(