Skip to content

Commit 1519eff

Browse files
committed
✨ Enable copy tweet link to clipboard
1 parent 556cca0 commit 1519eff

File tree

7 files changed

+127
-55
lines changed

7 files changed

+127
-55
lines changed

lib/helper/utility.dart

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'package:firebase_database/firebase_database.dart';
55
import 'package:firebase_dynamic_links/firebase_dynamic_links.dart';
66
import 'package:flutter/foundation.dart';
77
import 'package:flutter/material.dart';
8+
import 'package:flutter/services.dart';
89
import 'package:flutter_twitter_clone/widgets/customWidgets.dart';
910
import 'package:flutter_twitter_clone/widgets/newWidget/customLoader.dart';
1011
import 'package:intl/intl.dart';
@@ -215,7 +216,7 @@ bool validateEmal(String email) {
215216
return status;
216217
}
217218

218-
createLinkAndShare(BuildContext context, String id,
219+
Future<Uri> createLinkToShare(BuildContext context, String id,
219220
{SocialMetaTagParameters socialMetaTagParameters}) async {
220221
final DynamicLinkParameters parameters = DynamicLinkParameters(
221222
uriPrefix: 'https://fwitterdev.page.link',
@@ -232,9 +233,28 @@ createLinkAndShare(BuildContext context, String id,
232233
if (true) {
233234
final ShortDynamicLink shortLink = await parameters.buildShortLink();
234235
url = shortLink.shortUrl;
236+
return url;
235237
} else {
236238
url = await parameters.buildUrl();
237239
}
240+
}
241+
242+
createLinkAndShare(BuildContext context, String id,
243+
{SocialMetaTagParameters socialMetaTagParameters}) async {
244+
var url = createLinkToShare(context, id,
245+
socialMetaTagParameters: socialMetaTagParameters);
238246

239247
share(url.toString(), subject: "Tweet");
240248
}
249+
250+
void copyToClipBoard({
251+
GlobalKey<ScaffoldState> scaffoldKey,
252+
String text,
253+
String message,
254+
}) {
255+
assert(message != null);
256+
assert(text != null);
257+
var data = ClipboardData(text: text);
258+
Clipboard.setData(data);
259+
customSnackBar(scaffoldKey, message);
260+
}

lib/page/feed/feedPage.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,10 @@ class _FeedPageBody extends StatelessWidget {
123123
child: Tweet(
124124
model: model,
125125
trailing: TweetBottomSheet().tweetOptionIcon(
126-
context,
127-
model,
128-
TweetType.Tweet,
129-
),
126+
context,
127+
model: model,
128+
type: TweetType.Tweet,
129+
scaffoldKey: scaffoldKey),
130130
),
131131
);
132132
},

lib/page/feed/feedPostDetail.dart

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class FeedPostDetail extends StatefulWidget {
1919

2020
class _FeedPostDetailState extends State<FeedPostDetail> {
2121
String postId;
22+
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
2223
@override
2324
void initState() {
2425
postId = widget.postId;
@@ -42,17 +43,17 @@ class _FeedPostDetailState extends State<FeedPostDetail> {
4243
return Tweet(
4344
model: model,
4445
type: TweetType.Reply,
45-
trailing:
46-
TweetBottomSheet().tweetOptionIcon(context, model, TweetType.Reply),
46+
trailing: TweetBottomSheet().tweetOptionIcon(context,
47+
scaffoldKey: scaffoldKey, model: model, type: TweetType.Reply),
4748
);
4849
}
4950

5051
Widget _tweetDetail(FeedModel model) {
5152
return Tweet(
5253
model: model,
5354
type: TweetType.Detail,
54-
trailing:
55-
TweetBottomSheet().tweetOptionIcon(context, model, TweetType.Detail),
55+
trailing: TweetBottomSheet().tweetOptionIcon(context,
56+
scaffoldKey: scaffoldKey, model: model, type: TweetType.Detail),
5657
);
5758
}
5859

@@ -83,6 +84,7 @@ class _FeedPostDetailState extends State<FeedPostDetail> {
8384
return Future.value(true);
8485
},
8586
child: Scaffold(
87+
key: scaffoldKey,
8688
floatingActionButton: _floatingActionButton(),
8789
backgroundColor: Theme.of(context).backgroundColor,
8890
body: CustomScrollView(

lib/page/profile/profilePage.dart

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class _ProfilePageState extends State<ProfilePage>
3131
with SingleTickerProviderStateMixin {
3232
bool isMyProfile = false;
3333
int pageIndex = 0;
34-
34+
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
3535
@override
3636
void initState() {
3737
WidgetsBinding.instance.addPostFrameCallback((_) {
@@ -318,6 +318,7 @@ class _ProfilePageState extends State<ProfilePage>
318318
return WillPopScope(
319319
onWillPop: _onWillPop,
320320
child: Scaffold(
321+
key: scaffoldKey,
321322
floatingActionButton: !isMyProfile ? null : _floatingActionButton(),
322323
backgroundColor: TwitterColor.mystic,
323324
body: NestedScrollView(
@@ -438,8 +439,9 @@ class _ProfilePageState extends State<ProfilePage>
438439
isDisplayOnProfile: true,
439440
trailing: TweetBottomSheet().tweetOptionIcon(
440441
context,
441-
list[index],
442-
TweetType.Tweet,
442+
model: list[index],
443+
type: TweetType.Tweet,
444+
scaffoldKey: scaffoldKey,
443445
),
444446
),
445447
),

lib/widgets/tweet/tweet.dart

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,22 @@ class Tweet extends StatelessWidget {
2121
final Widget trailing;
2222
final TweetType type;
2323
final bool isDisplayOnProfile;
24-
const Tweet(
25-
{Key key,
26-
this.model,
27-
this.trailing,
28-
this.type = TweetType.Tweet,
29-
this.isDisplayOnProfile = false})
30-
: super(key: key);
24+
final GlobalKey<ScaffoldState> scaffoldKey;
25+
const Tweet({
26+
Key key,
27+
this.model,
28+
this.trailing,
29+
this.type = TweetType.Tweet,
30+
this.isDisplayOnProfile = false,
31+
this.scaffoldKey,
32+
}) : super(key: key);
3133

3234
void onLongPressedTweet(BuildContext context) {
3335
if (type == TweetType.Detail || type == TweetType.ParentTweet) {
34-
var text = ClipboardData(text: model.description);
35-
Clipboard.setData(text);
36-
Scaffold.of(context).showSnackBar(
37-
SnackBar(
38-
backgroundColor: TwitterColor.black,
39-
content: Text(
40-
'Tweet copied to clipboard',
41-
),
42-
),
43-
);
36+
copyToClipBoard(
37+
scaffoldKey: scaffoldKey,
38+
text: model.description ?? "",
39+
message: "Tweet copy to clipboard");
4440
}
4541
}
4642

lib/widgets/tweet/widgets/tweetBottomSheet.dart

Lines changed: 73 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
import 'package:firebase_dynamic_links/firebase_dynamic_links.dart';
12
import 'package:flutter/material.dart';
23
import 'package:flutter_twitter_clone/helper/constant.dart';
34
import 'package:flutter_twitter_clone/helper/enum.dart';
45
import 'package:flutter_twitter_clone/helper/theme.dart';
6+
import 'package:flutter_twitter_clone/helper/utility.dart';
57
import 'package:flutter_twitter_clone/model/feedModel.dart';
68
import 'package:flutter_twitter_clone/model/user.dart';
79
import 'package:flutter_twitter_clone/state/authState.dart';
@@ -10,13 +12,14 @@ import 'package:flutter_twitter_clone/widgets/customWidgets.dart';
1012
import 'package:provider/provider.dart';
1113

1214
class TweetBottomSheet {
13-
Widget tweetOptionIcon(
14-
BuildContext context, FeedModel model, TweetType type) {
15+
Widget tweetOptionIcon(BuildContext context,
16+
{FeedModel model, TweetType type, GlobalKey<ScaffoldState> scaffoldKey}) {
1517
return customInkWell(
1618
radius: BorderRadius.circular(20),
1719
context: context,
1820
onPressed: () {
19-
_openbottomSheet(context, type, model);
21+
_openbottomSheet(context,
22+
type: type, model: model, scaffoldKey: scaffoldKey);
2023
},
2124
child: Container(
2225
width: 25,
@@ -31,8 +34,10 @@ class TweetBottomSheet {
3134
));
3235
}
3336

34-
void _openbottomSheet(
35-
BuildContext context, TweetType type, FeedModel model) async {
37+
void _openbottomSheet(BuildContext context,
38+
{TweetType type,
39+
FeedModel model,
40+
GlobalKey<ScaffoldState> scaffoldKey}) async {
3641
var authState = Provider.of<AuthState>(context, listen: false);
3742
bool isMyTweet = authState.userId == model.userId;
3843
await showModalBottomSheet(
@@ -54,14 +59,25 @@ class TweetBottomSheet {
5459
),
5560
),
5661
child: type == TweetType.Tweet
57-
? _tweetOptions(context, isMyTweet, model, type)
58-
: _tweetDetailOptions(context, isMyTweet, model, type));
62+
? _tweetOptions(context,
63+
scaffoldKey: scaffoldKey,
64+
isMyTweet: isMyTweet,
65+
model: model,
66+
type: type)
67+
: _tweetDetailOptions(context,
68+
scaffoldKey: scaffoldKey,
69+
isMyTweet: isMyTweet,
70+
model: model,
71+
type: type));
5972
},
6073
);
6174
}
6275

63-
Widget _tweetDetailOptions(
64-
BuildContext context, bool isMyTweet, FeedModel model, TweetType type) {
76+
Widget _tweetDetailOptions(BuildContext context,
77+
{bool isMyTweet,
78+
FeedModel model,
79+
TweetType type,
80+
GlobalKey<ScaffoldState> scaffoldKey}) {
6581
return Column(
6682
children: <Widget>[
6783
Container(
@@ -74,11 +90,25 @@ class TweetBottomSheet {
7490
),
7591
),
7692
),
77-
_widgetBottomSheetRow(
78-
context,
79-
AppIcon.link,
80-
text: 'Copy link to tweet',
81-
),
93+
_widgetBottomSheetRow(context, AppIcon.link,
94+
text: 'Copy link to tweet', isEnable: true, onPressed: () async {
95+
var uri = await createLinkToShare(
96+
context,
97+
"tweet/${model.key}",
98+
socialMetaTagParameters: SocialMetaTagParameters(
99+
description: model.description ??
100+
"${model.user.displayName} posted a tweet on Fwitter.",
101+
title: "Tweet on Fwitter app",
102+
imageUrl: Uri.parse(
103+
"https://play-lh.googleusercontent.com/e66XMuvW5hZ7HnFf8R_lcA3TFgkxm0SuyaMsBs3KENijNHZlogUAjxeu9COqsejV5w=s180-rw")),
104+
);
105+
106+
Navigator.pop(context);
107+
copyToClipBoard(
108+
scaffoldKey: scaffoldKey,
109+
text: uri.toString(),
110+
message: "Tweet link copy to clipboard");
111+
}),
82112
isMyTweet
83113
? _widgetBottomSheetRow(
84114
context,
@@ -141,8 +171,11 @@ class TweetBottomSheet {
141171
);
142172
}
143173

144-
Widget _tweetOptions(
145-
BuildContext context, bool isMyTweet, FeedModel model, TweetType type) {
174+
Widget _tweetOptions(BuildContext context,
175+
{bool isMyTweet,
176+
FeedModel model,
177+
TweetType type,
178+
GlobalKey<ScaffoldState> scaffoldKey}) {
146179
return Column(
147180
children: <Widget>[
148181
Container(
@@ -155,11 +188,24 @@ class TweetBottomSheet {
155188
),
156189
),
157190
),
158-
_widgetBottomSheetRow(
159-
context,
160-
AppIcon.link,
161-
text: 'Copy link to tweet',
162-
),
191+
_widgetBottomSheetRow(context, AppIcon.link,
192+
text: 'Copy link to tweet', isEnable: true, onPressed: () async {
193+
var uri = await createLinkToShare(
194+
context,
195+
"tweet/${model.key}",
196+
socialMetaTagParameters: SocialMetaTagParameters(
197+
description: model.description ??
198+
"${model.user.displayName} posted a tweet on Fwitter.",
199+
title: "Tweet on Fwitter app",
200+
imageUrl: Uri.parse(
201+
"https://play-lh.googleusercontent.com/e66XMuvW5hZ7HnFf8R_lcA3TFgkxm0SuyaMsBs3KENijNHZlogUAjxeu9COqsejV5w=s180-rw")),
202+
);
203+
Navigator.pop(context);
204+
copyToClipBoard(
205+
scaffoldKey: scaffoldKey,
206+
text: uri.toString(),
207+
message: "Tweet link copy to clipboard");
208+
}),
163209
isMyTweet
164210
? _widgetBottomSheetRow(
165211
context,
@@ -241,7 +287,8 @@ class TweetBottomSheet {
241287
istwitterIcon: true,
242288
size: 25,
243289
paddingIcon: 8,
244-
iconColor: isEnable ? AppColor.darkGrey : AppColor.lightGrey,
290+
iconColor:
291+
onPressed != null ? AppColor.darkGrey : AppColor.lightGrey,
245292
),
246293
SizedBox(
247294
width: 15,
@@ -276,8 +323,10 @@ class TweetBottomSheet {
276323
}
277324
}
278325

279-
void openRetweetbottomSheet(
280-
BuildContext context, TweetType type, FeedModel model) async {
326+
void openRetweetbottomSheet(BuildContext context,
327+
{TweetType type,
328+
FeedModel model,
329+
GlobalKey<ScaffoldState> scaffoldKey}) async {
281330
await showModalBottomSheet(
282331
backgroundColor: Colors.transparent,
283332
context: context,

lib/widgets/tweet/widgets/tweetIconsRow.dart

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,16 @@ class TweetIconsRow extends StatelessWidget {
2020
final double size;
2121
final bool isTweetDetail;
2222
final TweetType type;
23+
final GlobalKey<ScaffoldState> scaffoldKey;
2324
const TweetIconsRow(
2425
{Key key,
2526
this.model,
2627
this.iconColor,
2728
this.iconEnableColor,
2829
this.size,
2930
this.isTweetDetail = false,
30-
this.type})
31+
this.type,
32+
this.scaffoldKey})
3133
: super(key: key);
3234

3335
Widget _likeCommentsIcons(BuildContext context, FeedModel model) {
@@ -59,7 +61,8 @@ class TweetIconsRow extends StatelessWidget {
5961
icon: AppIcon.retweet,
6062
iconColor: iconColor,
6163
size: size ?? 20, onPressed: () {
62-
TweetBottomSheet().openRetweetbottomSheet(context, type, model);
64+
TweetBottomSheet().openRetweetbottomSheet(context,
65+
type: type, model: model, scaffoldKey: scaffoldKey);
6366
}),
6467
_iconWidget(
6568
context,

0 commit comments

Comments
 (0)