Skip to content

Commit eef5e8b

Browse files
committed
added translation for tweets and PreviewData type
1 parent 510da4b commit eef5e8b

File tree

6 files changed

+226
-60
lines changed

6 files changed

+226
-60
lines changed

lib/helper/utility.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,4 +283,8 @@ class Utility {
283283
Clipboard.setData(data);
284284
customSnackBar(scaffoldKey, message);
285285
}
286+
287+
static Locale getLocale(BuildContext context) {
288+
return Localizations.localeOf(context);
289+
}
286290
}

lib/state/feedState.dart

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import 'package:flutter_twitter_clone/model/user.dart';
1111
import 'package:flutter_twitter_clone/state/appState.dart';
1212
import 'package:flutter_twitter_clone/ui/page/common/locator.dart';
1313
import 'package:path/path.dart' as path;
14+
import 'package:translator/translator.dart';
15+
import 'package:flutter_chat_types/flutter_chat_types.dart' show PreviewData;
1416
// import 'authState.dart';
1517

1618
class FeedState extends AppState {
@@ -74,20 +76,20 @@ class FeedState extends AppState {
7476
return list;
7577
}
7678

77-
//TODO
78-
// Map<String, PreviewData>? _linkDataPreviews = {};
79-
// Map<String, PreviewData>? get linkDataPreviews => _linkDataPreviews;
80-
// void addPreviewData(String url, PreviewData previewData) {
81-
// _linkDataPreviews.addAll({url: previewData});
82-
// notifyListeners();
83-
// }
84-
Map<String, dynamic> _linkDataPreviews = {};
85-
Map<String, dynamic> get linkDataPreviews => _linkDataPreviews;
86-
void addPreviewData(String url, dynamic previewData) {
79+
Map<String, PreviewData> _linkDataPreviews = {};
80+
Map<String, PreviewData> get linkDataPreviews => _linkDataPreviews;
81+
void addPreviewData(String url, PreviewData previewData) {
8782
_linkDataPreviews.addAll({url: previewData});
8883
notifyListeners();
8984
}
9085

86+
Map<String, Translation?> _tweetsTranslations = {};
87+
Map<String, Translation?> get tweetsTranslations => _tweetsTranslations;
88+
void addTweetTranslation(String tweet, Translation? translation) {
89+
_tweetsTranslations.addAll({tweet: translation});
90+
notifyListeners();
91+
}
92+
9193
/// set tweet for detail tweet page
9294
/// Setter call when tweet is tapped to view detail
9395
/// Add Tweet detail is added in _tweetDetailModelList

lib/widgets/tweet/tweet.dart

Lines changed: 51 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import 'package:flutter_twitter_clone/ui/theme/theme.dart';
1010
import 'package:flutter_twitter_clone/widgets/newWidget/title_text.dart';
1111
import 'package:flutter_twitter_clone/widgets/tweet/widgets/parentTweet.dart';
1212
import 'package:flutter_twitter_clone/widgets/tweet/widgets/tweetIconsRow.dart';
13+
import 'package:flutter_twitter_clone/widgets/tweet/widgets/tweetTranslation.dart';
1314
import 'package:flutter_twitter_clone/widgets/url_text/customUrlText.dart';
1415
import 'package:flutter_twitter_clone/widgets/url_text/custom_link_media_info.dart';
1516
import 'package:provider/provider.dart';
@@ -168,6 +169,14 @@ class _TweetBody extends StatelessWidget {
168169
type == TweetType.Tweet || type == TweetType.Tweet
169170
? FontWeight.w400
170171
: FontWeight.w400;
172+
TextStyle textStyle = TextStyle(
173+
color: Colors.black,
174+
fontSize: descriptionFontSize,
175+
fontWeight: descriptionFontWeight);
176+
TextStyle urlStyle = TextStyle(
177+
color: Colors.blue,
178+
fontSize: descriptionFontSize,
179+
fontWeight: descriptionFontWeight);
171180
return Row(
172181
crossAxisAlignment: CrossAxisAlignment.start,
173182
children: <Widget>[
@@ -240,19 +249,24 @@ class _TweetBody extends StatelessWidget {
240249
),
241250
model.description == null
242251
? const SizedBox()
243-
: UrlText(
244-
text: model.description!.removeSpaces,
245-
onHashTagPressed: (tag) {
246-
cprint(tag);
247-
},
248-
style: TextStyle(
249-
color: Colors.black,
250-
fontSize: descriptionFontSize,
251-
fontWeight: descriptionFontWeight),
252-
urlStyle: TextStyle(
253-
color: Colors.blue,
254-
fontSize: descriptionFontSize,
255-
fontWeight: descriptionFontWeight),
252+
: Column(
253+
crossAxisAlignment: CrossAxisAlignment.start,
254+
children: [
255+
UrlText(
256+
text: model.description!.removeSpaces,
257+
onHashTagPressed: (tag) {
258+
cprint(tag);
259+
},
260+
style: textStyle,
261+
urlStyle: urlStyle,
262+
),
263+
TweetTranslation(
264+
tweetKey: model.key!,
265+
description: model.description!,
266+
textStyle: textStyle,
267+
urlStyle: urlStyle,
268+
),
269+
],
256270
),
257271
if (model.imagePath == null && model.description != null)
258272
CustomLinkMediaInfo(text: model.description!),
@@ -292,7 +306,14 @@ class _TweetDetailBody extends StatelessWidget {
292306
type == TweetType.Tweet || type == TweetType.Tweet
293307
? FontWeight.w300
294308
: FontWeight.w400;
295-
309+
TextStyle textStyle = TextStyle(
310+
color: Colors.black,
311+
fontSize: descriptionFontSize,
312+
fontWeight: descriptionFontWeight);
313+
TextStyle urlStyle = TextStyle(
314+
color: Colors.blue,
315+
fontSize: descriptionFontSize,
316+
fontWeight: descriptionFontWeight);
296317
return Column(
297318
crossAxisAlignment: CrossAxisAlignment.start,
298319
children: <Widget>[
@@ -356,21 +377,22 @@ class _TweetDetailBody extends StatelessWidget {
356377
padding: type == TweetType.ParentTweet
357378
? const EdgeInsets.only(left: 80, right: 16)
358379
: const EdgeInsets.symmetric(horizontal: 16),
359-
child: UrlText(
360-
text: model.description!.removeSpaces,
361-
onHashTagPressed: (tag) {
362-
cprint(tag);
363-
},
364-
style: TextStyle(
365-
color: Colors.black,
366-
fontSize: descriptionFontSize,
367-
fontWeight: descriptionFontWeight,
368-
),
369-
urlStyle: TextStyle(
370-
color: Colors.blue,
371-
fontSize: descriptionFontSize,
372-
fontWeight: descriptionFontWeight,
373-
),
380+
child: Column(
381+
children: [
382+
UrlText(
383+
text: model.description!.removeSpaces,
384+
onHashTagPressed: (tag) {
385+
cprint(tag);
386+
},
387+
style: textStyle,
388+
urlStyle: urlStyle),
389+
TweetTranslation(
390+
tweetKey: model.key!,
391+
description: model.description!,
392+
textStyle: textStyle,
393+
urlStyle: urlStyle,
394+
),
395+
],
374396
),
375397
),
376398
if (model.imagePath == null && model.description != null)
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_twitter_clone/state/feedState.dart';
3+
import 'package:flutter_twitter_clone/ui/theme/theme.dart';
4+
import 'package:flutter_twitter_clone/widgets/customWidgets.dart';
5+
import 'package:flutter_twitter_clone/widgets/url_text/customUrlText.dart';
6+
import 'package:provider/provider.dart';
7+
import 'package:translator/translator.dart';
8+
import 'package:flutter_twitter_clone/helper/utility.dart';
9+
10+
class TweetTranslation extends StatelessWidget {
11+
final String description;
12+
final String tweetKey;
13+
final TextStyle? textStyle;
14+
final TextStyle? urlStyle;
15+
const TweetTranslation(
16+
{Key? key,
17+
required this.tweetKey,
18+
required this.description,
19+
this.textStyle,
20+
this.urlStyle})
21+
: super(key: key);
22+
23+
@override
24+
Widget build(BuildContext context) {
25+
String lan = Utility.getLocale(context).toLanguageTag();
26+
var state = Provider.of<FeedState>(context, listen: false);
27+
28+
try {
29+
if (state.tweetsTranslations.containsKey(tweetKey)) {
30+
if (state.tweetsTranslations[tweetKey] != null) {
31+
return _translation(state.tweetsTranslations[tweetKey]!, context,
32+
textStyle, urlStyle);
33+
} else {
34+
return SizedBox.shrink();
35+
}
36+
} else {
37+
return FutureBuilder<Translation>(
38+
future: GoogleTranslator()
39+
.translate(description.removeSpaces, to: lan.split('-')[0]),
40+
builder: (BuildContext context, AsyncSnapshot<Translation> snapshot) {
41+
if (snapshot.hasData) {
42+
if (snapshot.data!.text == snapshot.data!.source.trim()) {
43+
state.tweetsTranslations[tweetKey] = null;
44+
return SizedBox.shrink();
45+
}
46+
state.tweetsTranslations[tweetKey] = snapshot.data!;
47+
48+
return _translation(snapshot.data!, context, textStyle, urlStyle);
49+
}
50+
if (snapshot.hasError) {
51+
return Text("${snapshot.error}");
52+
}
53+
return SizedBox.shrink();
54+
},
55+
);
56+
}
57+
} catch (e) {
58+
cprint(e);
59+
return SizedBox.shrink();
60+
}
61+
}
62+
}
63+
64+
Widget _translation(Translation translation, BuildContext context,
65+
TextStyle? textStyle, TextStyle? urlStyle) {
66+
return Column(
67+
crossAxisAlignment: CrossAxisAlignment.start,
68+
children: [
69+
Padding(
70+
padding: const EdgeInsets.symmetric(vertical: 5.0),
71+
child: Column(
72+
crossAxisAlignment: CrossAxisAlignment.center,
73+
children: [
74+
const Divider(
75+
thickness: 1,
76+
),
77+
Row(
78+
children: [
79+
Text(
80+
"Translated from ${translation.sourceLanguage} by ",
81+
style: TextStyle(
82+
fontSize: 11,
83+
color: AppColor.lightGrey,
84+
fontWeight: FontWeight.bold),
85+
),
86+
customIcon(context,
87+
icon: Icons.g_translate,
88+
paddingIcon: 0,
89+
iconColor: AppColor.lightGrey),
90+
],
91+
),
92+
],
93+
),
94+
),
95+
UrlText(
96+
text: translation.text,
97+
onHashTagPressed: (tag) {
98+
cprint(tag);
99+
},
100+
style: textStyle,
101+
urlStyle: urlStyle,
102+
),
103+
],
104+
);
105+
}
106+
107+
// Padding(
108+
// padding: const EdgeInsets.symmetric(vertical: 10.0),
109+
// child: Row(
110+
// children: [
111+
// Expanded(
112+
// child: const Divider(
113+
// thickness: 1,
114+
// )),
115+
// Text(
116+
// "Translated from ${snapshot.data!.sourceLanguage} by ",
117+
// style: TextStyle(
118+
// color: AppColor.lightGrey,
119+
// fontWeight: FontWeight.bold),
120+
// ),
121+
// customIcon(context,
122+
// icon: Icons.g_translate,
123+
// paddingIcon: 0,
124+
// iconColor: AppColor.lightGrey),
125+
// Expanded(
126+
// child: const Divider(
127+
// thickness: 1,
128+
// )),
129+
// ],
130+
// ),
131+
// ),

lib/widgets/url_text/link_preview.dart

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -42,26 +42,31 @@ class LinkPreviewer extends StatelessWidget {
4242
fontSize: 0,
4343
);
4444

45-
return LinkPreview(
46-
enableAnimation: false,
47-
onPreviewDataFetched: (data) {
48-
state.addPreviewData(uri, data);
49-
},
50-
imageBuilder: (image) {
51-
return ClipRRect(
52-
borderRadius: BorderRadius.circular(10.0),
53-
child: CachedNetworkImage(
54-
imageUrl: image,
55-
),
56-
).ripple(() {
57-
Utility.launchURL(uri);
58-
});
59-
},
60-
linkStyle: style,
61-
previewData:
62-
state.linkDataPreviews[uri], // Pass the preview data from the state
63-
text: uri,
64-
width: MediaQuery.of(context).size.width,
65-
);
45+
try {
46+
return LinkPreview(
47+
enableAnimation: false,
48+
onPreviewDataFetched: (data) {
49+
state.addPreviewData(uri, data);
50+
},
51+
imageBuilder: (image) {
52+
return ClipRRect(
53+
borderRadius: BorderRadius.circular(10.0),
54+
child: CachedNetworkImage(
55+
imageUrl: image,
56+
),
57+
).ripple(() {
58+
Utility.launchURL(uri);
59+
});
60+
},
61+
linkStyle: style,
62+
previewData:
63+
state.linkDataPreviews[uri], // Pass the preview data from the state
64+
text: uri,
65+
width: MediaQuery.of(context).size.width,
66+
);
67+
} catch (e) {
68+
cprint(e);
69+
return SizedBox.shrink();
70+
}
6671
}
6772
}

pubspec.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ dependencies:
5151
qr_flutter: ^4.0.0
5252
rxdart: ^0.27.2
5353
flutter_link_previewer: ^2.5.2
54+
translator: ^0.1.7
55+
flutter_chat_types: ^3.1.4
5456

5557
dev_dependencies:
5658
test: ^1.17.10

0 commit comments

Comments
 (0)