|
18 | 18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | 19 | */ |
20 | 20 | import 'dart:async'; |
| 21 | +import 'dart:convert'; |
21 | 22 | import 'dart:ui'; |
22 | 23 |
|
| 24 | +import 'package:collection/collection.dart'; |
23 | 25 | import 'package:exceptions/exceptions.dart'; |
24 | 26 | import 'package:flutter/foundation.dart'; |
25 | 27 | import 'package:flutter_mozilla_components/flutter_mozilla_components.dart'; |
26 | 28 | import 'package:html/dom.dart'; |
27 | 29 | import 'package:html/parser.dart' as html_parser; |
28 | | -import 'package:http/io_client.dart'; |
29 | 30 | import 'package:nullability/nullability.dart'; |
30 | 31 | import 'package:riverpod_annotation/riverpod_annotation.dart'; |
31 | | -import 'package:socks5_proxy/socks_client.dart'; |
32 | | -import 'package:universal_io/io.dart'; |
33 | 32 | import 'package:weblibre/core/http_error_handler.dart'; |
| 33 | +import 'package:weblibre/core/logger.dart'; |
34 | 34 | import 'package:weblibre/data/models/web_page_info.dart'; |
35 | | -import 'package:weblibre/extensions/http_encoding.dart'; |
36 | 35 | import 'package:weblibre/features/geckoview/domain/entities/browser_icon.dart'; |
37 | 36 | import 'package:weblibre/features/user/domain/repositories/cache.dart'; |
38 | 37 | import 'package:weblibre/features/web_feed/utils/feed_finder.dart'; |
@@ -211,54 +210,42 @@ class GenericWebsiteService extends _$GenericWebsiteService { |
211 | 210 | Future<Result<WebPageInfo>> fetchPageInfo({ |
212 | 211 | required Uri url, |
213 | 212 | required bool isImageRequest, |
214 | | - required int? proxyPort, |
215 | 213 | }) { |
216 | 214 | return Result.fromAsync(() async { |
217 | | - final result = await compute((args) async { |
218 | | - final [String urlString, bool isImageRequest, int? proxyPort] = args; |
219 | | - |
220 | | - final httpClient = HttpClient(); |
221 | | - if (proxyPort != null) { |
222 | | - SocksTCPClient.assignToHttpClient(httpClient, [ |
223 | | - ProxySettings(InternetAddress.loopbackIPv4, proxyPort), |
224 | | - ]); |
| 215 | + late final Map<String, Object?> result; |
| 216 | + final client = GeckoFetchService(); |
| 217 | + try { |
| 218 | + final response = await client |
| 219 | + .fetch(url: url) |
| 220 | + .timeout(const Duration(seconds: 15)); |
| 221 | + |
| 222 | + //When this is a request for an icon and we hit an image, directly return it |
| 223 | + if (isImageRequest) { |
| 224 | + final contentType = response.headers |
| 225 | + .firstWhereOrNull((header) => header.key == 'content-type') |
| 226 | + ?.value; |
| 227 | + if (contentType?.contains('image/') == true) { |
| 228 | + result = { |
| 229 | + 'imageBytes': [response.body], |
| 230 | + }; |
| 231 | + } |
225 | 232 | } |
226 | 233 |
|
227 | | - final client = IOClient(httpClient); |
228 | | - try { |
229 | | - final baseUri = Uri.parse(urlString); |
230 | | - final response = await client |
231 | | - .get(baseUri) |
232 | | - .timeout(const Duration(seconds: 15)); |
233 | | - |
234 | | - //When this is a request for an icon and we hit an image, directly return it |
235 | | - if (isImageRequest) { |
236 | | - final contentType = response.headers['content-type']; |
237 | | - if (contentType?.contains('image/') == true) { |
238 | | - return { |
239 | | - 'imageBytes': [response.bodyBytes], |
240 | | - }; |
241 | | - } |
242 | | - } |
| 234 | + final document = html_parser.parse(utf8.decode(response.body)); |
243 | 235 |
|
244 | | - final document = html_parser.parse(response.bodyUnicodeFallback); |
245 | | - |
246 | | - final title = document.querySelector('title')?.text; |
247 | | - final resources = _extractIcons(baseUri, document); |
248 | | - final feeds = await FeedFinder( |
249 | | - url: baseUri, |
250 | | - document: document, |
251 | | - ).parse(); |
252 | | - |
253 | | - return { |
254 | | - 'title': title, |
255 | | - 'resources': resources.map(_serializeResource).toList(), |
256 | | - 'feeds': feeds.map((uri) => uri.toString()).toList(), |
257 | | - }; |
258 | | - } finally { |
259 | | - client.close(); |
260 | | - } |
261 | | - }, <dynamic>[url.toString(), isImageRequest, proxyPort]); |
| 236 | + final title = document.querySelector('title')?.text; |
| 237 | + final resources = _extractIcons(url, document); |
| 238 | + final feeds = await FeedFinder(url: url, document: document).parse(); |
| 239 | + |
| 240 | + result = { |
| 241 | + 'title': title, |
| 242 | + 'resources': resources.map(_serializeResource).toList(), |
| 243 | + 'feeds': feeds.map((uri) => uri.toString()).toList(), |
| 244 | + }; |
| 245 | + } catch (e, s) { |
| 246 | + logger.e('Error fetching page $url', error: e, stackTrace: s); |
| 247 | + result = {}; |
| 248 | + } |
262 | 249 |
|
263 | 250 | if (result['imageBytes'] case final Uint8List imageBytes) { |
264 | 251 | return WebPageInfo( |
|
0 commit comments