import 'dart:async'; import 'dart:io'; import 'package:extended_image/extended_image.dart'; import 'package:flutter/painting.dart'; import 'package:yumi/app/constants/sc_global_config.dart'; import 'package:yumi/shared/data_sources/sources/local/user_manager.dart'; bool _requiresAuthenticatedImageHeaders(String url) { return url.contains("/external/oss/local/"); } Map? buildNetworkImageHeaders(String url) { if (!_requiresAuthenticatedImageHeaders(url)) { return null; } final uri = Uri.tryParse(url); final headers = { "req-lang": SCGlobalConfig.lang, "X-Forwarded-Proto": "http", "User-Agent": "Dart/3.7.2(dart:io)", "req-imei": SCGlobalConfig.imei, "req-app-intel": "version=${SCGlobalConfig.version};build=${SCGlobalConfig.build};model=${SCGlobalConfig.model};sysVersion=${SCGlobalConfig.sysVersion};channel=${SCGlobalConfig.channel}", "req-client": Platform.isAndroid ? "Android" : "iOS", "req-sys-origin": "origin=${SCGlobalConfig.origin};originChild=${SCGlobalConfig.originChild}", }; if ((uri?.host ?? "").isNotEmpty) { headers["Host"] = uri!.host; } final token = AccountStorage().getToken(); if (token.isNotEmpty) { headers["Authorization"] = "Bearer $token"; } headers.removeWhere((key, value) => value.trim().isEmpty); return headers; } ImageProvider buildCachedImageProvider(String url) { if (url.startsWith("http")) { return ExtendedNetworkImageProvider( url, headers: buildNetworkImageHeaders(url), cache: true, cacheMaxAge: const Duration(days: 7), ); } return FileImage(File(url)); } Future warmNetworkImage( String url, { Duration timeout = const Duration(seconds: 6), }) async { if (url.isEmpty) { return false; } final provider = buildCachedImageProvider(url); final stream = provider.resolve(ImageConfiguration.empty); final completer = Completer(); late final ImageStreamListener listener; listener = ImageStreamListener( (image, synchronousCall) { if (!completer.isCompleted) { completer.complete(true); } stream.removeListener(listener); }, onError: (Object error, StackTrace? stackTrace) { if (!completer.isCompleted) { completer.complete(false); } stream.removeListener(listener); }, ); stream.addListener(listener); return completer.future.timeout( timeout, onTimeout: () { stream.removeListener(listener); return false; }, ); }