Skip to content

Commit 0a6fdfe

Browse files
committed
fixed preview with link_preview_generator package
1 parent e5d7873 commit 0a6fdfe

File tree

3 files changed

+128
-34
lines changed

3 files changed

+128
-34
lines changed

lib/state/feedState.dart

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ import 'package:flutter_twitter_clone/helper/utility.dart';
1010
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';
13+
import 'package:link_preview_generator/link_preview_generator.dart'
14+
show WebInfo;
1315
import 'package:path/path.dart' as path;
1416
import 'package:translator/translator.dart';
15-
import 'package:flutter_chat_types/flutter_chat_types.dart' show PreviewData;
17+
// import 'package:flutter_chat_types/flutter_chat_types.dart' show PreviewData;
1618
// import 'authState.dart';
1719

1820
class FeedState extends AppState {
@@ -76,11 +78,10 @@ class FeedState extends AppState {
7678
return list;
7779
}
7880

79-
Map<String, PreviewData> _linkDataPreviews = {};
80-
Map<String, PreviewData> get linkDataPreviews => _linkDataPreviews;
81-
void addPreviewData(String url, PreviewData previewData) {
82-
_linkDataPreviews.addAll({url: previewData});
83-
notifyListeners();
81+
Map<String, WebInfo> _linkWebInfos = {};
82+
Map<String, WebInfo> get linkWebInfos => _linkWebInfos;
83+
void addWebInfo(String url, WebInfo webInfo) {
84+
_linkWebInfos.addAll({url: webInfo});
8485
}
8586

8687
Map<String, Translation?> _tweetsTranslations = {};
Lines changed: 120 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import 'package:cached_network_image/cached_network_image.dart';
22
import 'package:flutter/material.dart';
3-
import 'package:flutter_link_previewer/flutter_link_previewer.dart';
3+
import 'package:link_preview_generator/link_preview_generator.dart';
44

55
import 'package:flutter_twitter_clone/helper/utility.dart';
66
import 'package:flutter_twitter_clone/state/feedState.dart';
77
import 'package:flutter_twitter_clone/ui/theme/theme.dart';
8+
import 'package:link_preview_generator/src/utils/analyzer.dart'
9+
show
10+
LinkPreviewAnalyzer; //FIXME Don't import implementation files from another package.
811
import 'package:provider/provider.dart';
912

1013
class LinkPreviewer extends StatelessWidget {
@@ -31,42 +34,132 @@ class LinkPreviewer extends StatelessWidget {
3134
@override
3235
Widget build(BuildContext context) {
3336
var state = Provider.of<FeedState>(context, listen: false);
37+
3438
var uri = url ?? getUrl();
3539
if (uri == null) {
3640
return const SizedBox.shrink();
3741
} else if (uri.contains("page.link/")) {
3842
/// `flutter_link_preview` package is unable to fetch firebase dynamic link meta data
3943
return const SizedBox.shrink();
4044
}
41-
final style = TextStyle(
42-
fontSize: 0,
43-
);
44-
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,
45+
if (state.linkWebInfos.containsKey(uri))
46+
return _buildLinkPreview(
47+
state.linkWebInfos[uri]!, uri, Theme.of(context));
48+
return FutureBuilder(
49+
builder: (BuildContext context, AsyncSnapshot<InfoBase?> snapshot) {
50+
if (snapshot.hasData) {
51+
state.addWebInfo(uri, snapshot.data! as WebInfo);
52+
return _buildLinkPreview(
53+
snapshot.data! as WebInfo, uri, Theme.of(context));
54+
}
55+
if (snapshot.hasError) {
56+
return SizedBox.shrink();
57+
}
58+
return Container(
59+
width: MediaQuery.of(context).size.width,
60+
decoration: BoxDecoration(
61+
borderRadius: BorderRadius.circular(8),
62+
color: const Color.fromRGBO(248, 248, 248, 1.0),
5663
),
57-
).ripple(() {
58-
Utility.launchURL(uri);
59-
});
64+
alignment: Alignment.center,
65+
child: const Text('Fetching data...'),
66+
);
6067
},
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,
68+
future: LinkPreviewAnalyzer.getInfo(uri,
69+
cacheDuration: Duration(hours: 24), multimedia: true));
70+
}
71+
72+
Widget _buildLinkPreview(WebInfo info, String uri, ThemeData theme) {
73+
var image = LinkPreviewAnalyzer.isNotEmpty(info.image)
74+
? info.image
75+
: LinkPreviewAnalyzer.isNotEmpty(info.icon)
76+
? info.icon
77+
: ""; //TODO Placeholder/error image
78+
if (!LinkPreviewAnalyzer.isNotEmpty(info.title) &&
79+
LinkPreviewAnalyzer.isNotEmpty(info.image)) {
80+
return CachedNetworkImage(
81+
imageUrl: image,
82+
fit: BoxFit.contain,
83+
).ripple(
84+
() {
85+
Utility.launchURL(uri);
86+
},
87+
borderRadius: BorderRadius.circular(10),
6688
);
67-
} catch (e) {
68-
cprint(e);
69-
return SizedBox.shrink();
7089
}
90+
if (!LinkPreviewAnalyzer.isNotEmpty(info.title)) return const SizedBox();
91+
92+
return Padding(
93+
padding: const EdgeInsets.only(top: 8),
94+
child: Container(
95+
decoration: BoxDecoration(
96+
borderRadius: BorderRadius.circular(10),
97+
border: Border.all(color: AppColor.extraLightGrey),
98+
color: theme.colorScheme.onPrimary),
99+
child: Column(
100+
crossAxisAlignment: CrossAxisAlignment.start,
101+
mainAxisAlignment: MainAxisAlignment.center,
102+
children: <Widget>[
103+
if (LinkPreviewAnalyzer.isNotEmpty(image))
104+
ClipRRect(
105+
borderRadius: BorderRadius.vertical(top: Radius.circular(10)),
106+
child: Container(
107+
height: 140,
108+
width: double.infinity,
109+
decoration: BoxDecoration(
110+
border: Border(
111+
bottom: BorderSide(color: theme.dividerColor, width: 1),
112+
),
113+
),
114+
child: CachedNetworkImage(
115+
imageUrl: image,
116+
fit: BoxFit.cover,
117+
),
118+
),
119+
),
120+
const SizedBox(height: 4),
121+
if (LinkPreviewAnalyzer.isNotEmpty(info.title))
122+
Padding(
123+
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
124+
child: Text(
125+
info.title.trim(),
126+
maxLines: 1,
127+
overflow: TextOverflow.ellipsis,
128+
style: TextStyles.titleStyle.copyWith(
129+
fontSize: 14,
130+
fontWeight: FontWeight.bold,
131+
color: Colors.black87),
132+
),
133+
),
134+
if (LinkPreviewAnalyzer.isNotEmpty(info.description))
135+
Padding(
136+
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
137+
child: Text(
138+
info.description.trim(),
139+
maxLines: 2,
140+
overflow: TextOverflow.ellipsis,
141+
style: TextStyles.subtitleStyle.copyWith(fontSize: 12),
142+
),
143+
),
144+
Padding(
145+
padding: EdgeInsets.only(bottom: 5, left: 8, right: 8),
146+
child: Text(
147+
Uri.tryParse(uri)!.authority,
148+
maxLines: 1,
149+
overflow: TextOverflow.ellipsis,
150+
style: TextStyles.subtitleStyle.copyWith(
151+
fontWeight: FontWeight.w400,
152+
fontSize: info.title.isNotEmpty ? 14 : 16),
153+
),
154+
),
155+
],
156+
),
157+
).ripple(
158+
() {
159+
Utility.launchURL(uri);
160+
},
161+
borderRadius: BorderRadius.circular(8),
162+
),
163+
);
71164
}
72165
}

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ dependencies:
5050
qr_code_scanner: ^0.5.2
5151
qr_flutter: ^4.0.0
5252
rxdart: ^0.27.2
53-
flutter_link_previewer: ^2.5.2
5453
translator: ^0.1.7
5554
flutter_chat_types: ^3.1.4
55+
link_preview_generator: ^1.2.0
5656

5757
dev_dependencies:
5858
test: ^1.17.10

0 commit comments

Comments
 (0)