Last active
July 24, 2021 10:26
-
-
Save Turskyi/4d5ea1f5b25b1456a7bf7fff03a6ce3c to your computer and use it in GitHub Desktop.
Fetch data(preview) from provided url.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:html/parser.dart'; | |
import 'package:http/http.dart'; | |
/// Convenient solution for flutter(dart) to fetch data(preview, title etc.) from provided web link. | |
class FetchPreviewHelper { | |
static final titlePreview = 'title'; | |
static final descriptionPreview = 'description'; | |
static final imagePreview = 'image'; | |
static final favIconPreview = 'favIcon'; | |
static final appleIconPreview = 'appleIcon'; | |
Future<Map<String, dynamic>> fetch(url) async { | |
final client = Client(); | |
final response = await client.get(_validateUrl(url)); | |
final document = parse(response.body); | |
String? description, title, image, appleIcon, favIcon; | |
var elements = document.getElementsByTagName('meta'); | |
final linkElements = document.getElementsByTagName('link'); | |
elements.forEach((tmp) { | |
/// fetching title | |
if (tmp.attributes['property'] == 'og:title') { | |
/* fetching seo title */ | |
title = tmp.attributes['content']; | |
} | |
/* if seo title is empty then fetch normal title */ | |
if (title == null || (title != null && title!.isEmpty)) { | |
title = document.getElementsByTagName(titlePreview)[0].text; | |
} | |
/// fetching description | |
if (tmp.attributes['property'] == 'og:description') { | |
/* fetching seo description */ | |
description = tmp.attributes['content']; | |
} | |
/* if seo description is empty then fetch normal description. */ | |
if (description == null || (description != null && description!.isEmpty)) { | |
/* fetching base title */ | |
if (tmp.attributes['name'] == descriptionPreview) { | |
description = tmp.attributes['content']; | |
} | |
} | |
/// fetching image | |
if (tmp.attributes['property'] == 'og:image') { | |
image = tmp.attributes['content']; | |
} | |
}); | |
linkElements.forEach((tmp) { | |
if (tmp.attributes['rel'] == 'apple-touch-icon') { | |
appleIcon = tmp.attributes['href']; | |
} | |
if (tmp.attributes['rel']?.contains('icon') == true) { | |
favIcon = tmp.attributes['href']; | |
} | |
}); | |
return { | |
titlePreview: title ?? '', | |
descriptionPreview: description ?? '', | |
imagePreview: image ?? '', | |
appleIconPreview: appleIcon ?? '', | |
favIconPreview: favIcon ?? '' | |
}; | |
} | |
_validateUrl(String url) { | |
if (url.startsWith('http://') == true || url.startsWith('https://') == true) { | |
return url; | |
} | |
else { | |
return 'http://$url'; | |
} | |
} | |
} | |
//------------------------------------ new file ----------------------------------- | |
//----- some start of the separate StatefulWidget, which is skipped for convenience ----- | |
/// json object of a preview page | |
Map<String, dynamic>? previewData; | |
@override | |
void initState() { | |
FetchPreviewHelper().fetch(widget.suggestion.url).then((resultData) { | |
setState(() { | |
previewData = resultData; | |
}); | |
}); | |
super.initState(); | |
} | |
/* Example of using received data: | |
//--- somewhere in the middle of the widget -- | |
Row( | |
children: <Widget>[ | |
previewData?[FetchPreviewHelper.favIconPreview] != null || | |
previewData?[FetchPreviewHelper.favIconPreview] != | |
'' | |
? Image.network( | |
previewData?[FetchPreviewHelper.favIconPreview], | |
height: AppDimens.sizeFavIcon, | |
width: AppDimens.sizeFavIcon, | |
errorBuilder: (BuildContext context, | |
Object exception, StackTrace? stackTrace) { | |
return LinkIconWidget(); | |
}, | |
) | |
: LinkIconWidget(), | |
Text(widget.suggestion.url!, | |
style: AppStyles.styleCaptionNormal.apply( | |
color: AppConfigs.of(context).colors.blueBright)) | |
], | |
), | |
*/ | |
// ---------------- rest of the StatefulWidget, which is skipped for convenience ----- | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment