refactor(images): replace flutter cache manager
This commit is contained in:
@@ -332,7 +332,7 @@ abstract class MediaServerClient {
|
||||
|
||||
// ── Images ───────────────────────────────────────────────────────
|
||||
/// Resolve a backend-relative thumbnail path to a fully-qualified URL ready
|
||||
/// for `cached_network_image`. Returns an empty string for null/empty
|
||||
/// for cached image providers. Returns an empty string for null/empty
|
||||
/// inputs.
|
||||
///
|
||||
/// When [width]/[height] are provided, the implementation should request
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:cached_network_image_ce/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
|
||||
import '../services/image_cache_service.dart';
|
||||
import '../utils/initials_palette.dart';
|
||||
import '../widgets/app_icon.dart';
|
||||
import 'profile.dart';
|
||||
@@ -67,9 +68,10 @@ class ProfileAvatar extends StatelessWidget {
|
||||
if (thumb != null && thumb.isNotEmpty) {
|
||||
return CachedNetworkImage(
|
||||
imageUrl: thumb,
|
||||
cacheManager: PlexImageCacheManager.instance,
|
||||
fit: BoxFit.cover,
|
||||
placeholder: (_, _) => _initialFallback(theme, p),
|
||||
errorWidget: (_, _, _) => _initialFallback(theme, p),
|
||||
errorBuilder: (_, _, _) => _initialFallback(theme, p),
|
||||
);
|
||||
}
|
||||
return _initialFallback(theme, p);
|
||||
|
||||
@@ -10,7 +10,7 @@ import '../focus/focusable_action_bar.dart';
|
||||
import '../focus/input_mode_tracker.dart';
|
||||
import '../focus/key_event_utils.dart';
|
||||
import '../utils/global_key_utils.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:cached_network_image_ce/cached_network_image.dart';
|
||||
|
||||
import '../services/image_cache_service.dart';
|
||||
import '../media/media_item.dart';
|
||||
@@ -1498,7 +1498,7 @@ class _DiscoverScreenState extends State<DiscoverScreen>
|
||||
memCacheHeight: memHeight,
|
||||
placeholder: (context, url) =>
|
||||
ColoredBox(color: Theme.of(context).colorScheme.surfaceContainerHighest),
|
||||
errorWidget: (context, url, error) =>
|
||||
errorBuilder: (context, error, stackTrace) =>
|
||||
ColoredBox(color: Theme.of(context).colorScheme.surfaceContainerHighest),
|
||||
),
|
||||
);
|
||||
@@ -1572,7 +1572,7 @@ class _DiscoverScreenState extends State<DiscoverScreen>
|
||||
memCacheWidth: (400 * dpr).clamp(200, 800).round(),
|
||||
alignment: isLargeScreen ? Alignment.bottomLeft : Alignment.bottomCenter,
|
||||
placeholder: (context, url) => const SizedBox.shrink(),
|
||||
errorWidget: (context, url, error) {
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
// Fallback to text if logo fails to load
|
||||
final theme = Theme.of(context);
|
||||
final colorScheme = theme.colorScheme;
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:cached_network_image_ce/cached_network_image.dart';
|
||||
import '../../../media/library_first_character.dart';
|
||||
import '../../../media/library_query.dart';
|
||||
import '../../../media/media_item.dart';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:cached_network_image_ce/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
|
||||
@@ -168,7 +168,7 @@ class _ProgramDetailsSheetContentState extends State<_ProgramDetailsSheetContent
|
||||
height: 120,
|
||||
fit: BoxFit.cover,
|
||||
memCacheHeight: (120 * MediaQuery.devicePixelRatioOf(context)).round(),
|
||||
errorWidget: (_, _, _) => const SizedBox.shrink(),
|
||||
errorBuilder: (_, _, _) => const SizedBox.shrink(),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:cached_network_image_ce/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../services/image_cache_service.dart';
|
||||
@@ -822,7 +822,7 @@ class _MediaDetailScreenState extends State<MediaDetailScreen>
|
||||
fit: BoxFit.cover,
|
||||
memCacheHeight: memCacheHeight,
|
||||
placeholder: (context, url) => const PlaceholderContainer(),
|
||||
errorWidget: (context, url, error) => _buildHeroNetworkArtwork(
|
||||
errorBuilder: (context, error, stackTrace) => _buildHeroNetworkArtwork(
|
||||
context,
|
||||
client: client,
|
||||
artworkPaths: artworkPaths,
|
||||
@@ -1571,7 +1571,7 @@ class _MediaDetailScreenState extends State<MediaDetailScreen>
|
||||
fit: BoxFit.cover,
|
||||
memCacheWidth: memWidth,
|
||||
placeholder: (context, url) => const PlaceholderContainer(),
|
||||
errorWidget: (context, url, error) => const PlaceholderContainer(),
|
||||
errorBuilder: (context, error, stackTrace) => const PlaceholderContainer(),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -2528,7 +2528,8 @@ class _MediaDetailScreenState extends State<MediaDetailScreen>
|
||||
alignment: Alignment.centerLeft,
|
||||
memCacheWidth: (400 * dpr).clamp(200, 800).round(),
|
||||
placeholder: (context, url) => const SizedBox.shrink(),
|
||||
errorWidget: (context, url, error) => _buildTitleText(context, metadata.displayTitle),
|
||||
errorBuilder: (context, error, stackTrace) =>
|
||||
_buildTitleText(context, metadata.displayTitle),
|
||||
),
|
||||
sigma: 10,
|
||||
clip: false,
|
||||
|
||||
@@ -1,102 +1,41 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
||||
// CE's public conditional export hides the IO-only httpClientFactory parameter
|
||||
// behind a narrower unsupported-platform stub.
|
||||
// ignore: implementation_imports
|
||||
import 'package:cached_network_image_ce/src/cache/default_cache_manager.dart' as ce_cache;
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import '../utils/platform_detector.dart';
|
||||
import '../utils/media_server_http_client.dart';
|
||||
|
||||
/// Custom cache manager for media-server image transcoding with HTTP/2
|
||||
/// multiplexing. Used for both Plex and Jellyfin artwork (the class name
|
||||
/// predates Jellyfin support — it's backend-neutral).
|
||||
/// Shared cache manager for media-server image artwork. Used for both Plex and
|
||||
/// Jellyfin artwork (the class name predates Jellyfin support — it's
|
||||
/// backend-neutral).
|
||||
///
|
||||
/// Uses the platform-native HTTP client so iOS/macOS (CupertinoClient) and
|
||||
/// Android (CronetClient) benefit from HTTP/2 connection multiplexing —
|
||||
/// many concurrent image downloads over a single connection instead of
|
||||
/// being limited to a handful of HTTP/1.1 connections.
|
||||
class PlexImageCacheManager extends CacheManager with ImageCacheManager {
|
||||
static const _key = 'plexImageCache';
|
||||
|
||||
class PlexImageCacheManager extends ce_cache.DefaultCacheManager {
|
||||
static final PlexImageCacheManager instance = PlexImageCacheManager._();
|
||||
|
||||
PlexImageCacheManager._() : super(_buildConfig());
|
||||
|
||||
static Config _buildConfig() {
|
||||
final fileService = _HttpFileService(httpClient.inner);
|
||||
// tvOS has no sqflite plugin, so force the JSON cache-info repo there.
|
||||
// On other platforms we let flutter_cache_manager pick its default repo.
|
||||
if (PlatformDetector.isAppleTV()) {
|
||||
return Config(
|
||||
_key,
|
||||
PlexImageCacheManager._()
|
||||
: super(
|
||||
stalePeriod: const Duration(days: 14),
|
||||
maxNrOfCacheObjects: 3000,
|
||||
fileService: fileService,
|
||||
repo: JsonCacheInfoRepository(databaseName: _key),
|
||||
httpClientFactory: () => _SharedHttpClient(httpClient.inner),
|
||||
);
|
||||
}
|
||||
return Config(_key, stalePeriod: const Duration(days: 14), maxNrOfCacheObjects: 3000, fileService: fileService);
|
||||
}
|
||||
}
|
||||
|
||||
class _HttpFileService extends FileService {
|
||||
final http.Client _client;
|
||||
/// CE closes each factory-created client after a download. Wrap the app-wide
|
||||
/// shared client so image requests reuse its platform transport without
|
||||
/// transferring ownership of its lifecycle.
|
||||
class _SharedHttpClient extends http.BaseClient {
|
||||
final http.Client _inner;
|
||||
|
||||
_HttpFileService(this._client);
|
||||
_SharedHttpClient(this._inner);
|
||||
|
||||
@override
|
||||
Future<FileServiceResponse> get(String url, {Map<String, String>? headers}) async {
|
||||
final request = http.Request('GET', Uri.parse(url));
|
||||
if (headers != null) request.headers.addAll(headers);
|
||||
final response = await _client.send(request);
|
||||
return _HttpGetResponse(response);
|
||||
}
|
||||
}
|
||||
Future<http.StreamedResponse> send(http.BaseRequest request) => _inner.send(request);
|
||||
|
||||
class _HttpGetResponse implements FileServiceResponse {
|
||||
final http.StreamedResponse _response;
|
||||
final DateTime _receivedTime = DateTime.now();
|
||||
|
||||
_HttpGetResponse(this._response);
|
||||
|
||||
@override
|
||||
Stream<List<int>> get content => _response.stream;
|
||||
|
||||
@override
|
||||
int? get contentLength {
|
||||
final value = _response.headers[HttpHeaders.contentLengthHeader];
|
||||
return value != null ? int.tryParse(value) : null;
|
||||
}
|
||||
|
||||
@override
|
||||
int get statusCode => _response.statusCode;
|
||||
|
||||
@override
|
||||
DateTime get validTill {
|
||||
var ageDuration = const Duration(days: 7);
|
||||
final controlHeader = _response.headers[HttpHeaders.cacheControlHeader];
|
||||
if (controlHeader != null) {
|
||||
for (final setting in controlHeader.split(',')) {
|
||||
final s = setting.trim().toLowerCase();
|
||||
if (s == 'no-cache') ageDuration = Duration.zero;
|
||||
if (s.startsWith('max-age=')) {
|
||||
final secs = int.tryParse(s.split('=')[1]) ?? 0;
|
||||
if (secs > 0) ageDuration = Duration(seconds: secs);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _receivedTime.add(ageDuration);
|
||||
}
|
||||
|
||||
@override
|
||||
String? get eTag => _response.headers[HttpHeaders.etagHeader];
|
||||
|
||||
@override
|
||||
String get fileExtension {
|
||||
final contentTypeHeader = _response.headers[HttpHeaders.contentTypeHeader];
|
||||
if (contentTypeHeader != null) {
|
||||
final ct = ContentType.parse(contentTypeHeader);
|
||||
return '.${ct.subType}';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
void close() {}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'dart:math' as math;
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:cached_network_image_ce/cached_network_image.dart';
|
||||
import 'package:flutter/painting.dart' show ImageConfiguration, ImageProvider, ImageStreamListener;
|
||||
|
||||
import '../media/media_source_info.dart';
|
||||
@@ -36,7 +36,7 @@ class JellyfinTrickplayService implements ScrubPreviewSource {
|
||||
|
||||
/// Provider cache by sheet index: scrubbing typically dwells on one sheet
|
||||
/// for many hover events, so we reuse the same wrapper rather than
|
||||
/// reallocating each frame. cached_network_image's own cache is keyed by
|
||||
/// reallocating each frame. The image cache itself is keyed by
|
||||
/// URL, but the wrapper object itself isn't free.
|
||||
final Map<int, ImageProvider> _providerCache = {};
|
||||
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:cached_network_image_ce/cached_network_image.dart';
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:plezy/widgets/app_icon.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import '../services/image_cache_service.dart';
|
||||
import 'package:plezy/widgets/app_icon.dart';
|
||||
|
||||
import '../media/media_server_client.dart';
|
||||
import '../services/image_cache_service.dart';
|
||||
import '../utils/app_logger.dart';
|
||||
import '../utils/media_image_helper.dart';
|
||||
import '../utils/obfuscation_utils.dart';
|
||||
@@ -356,6 +360,6 @@ class OptimizedMediaImage extends StatelessWidget {
|
||||
// so the URL hash alone uniquely identifies the bytes on disk. Including
|
||||
// mem-cache dimensions here would re-introduce churn on every pixel of
|
||||
// window resize and defeat getMemCacheDimensions' bucketing.
|
||||
return 'plex_optimized_${imageUrl.hashCode}';
|
||||
return 'plex_optimized_${sha1.convert(utf8.encode(imageUrl))}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import package_info_plus
|
||||
import screen_retriever_macos
|
||||
import sentry_flutter
|
||||
import shared_preferences_foundation
|
||||
import sqflite_darwin
|
||||
import sqlite3_flutter_libs
|
||||
import universal_gamepad
|
||||
import url_launcher_macos
|
||||
@@ -33,7 +32,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
ScreenRetrieverMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverMacosPlugin"))
|
||||
SentryFlutterPlugin.register(with: registry.registrar(forPlugin: "SentryFlutterPlugin"))
|
||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||
Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin"))
|
||||
GamepadPlugin.register(with: registry.registrar(forPlugin: "GamepadPlugin"))
|
||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||
|
||||
@@ -29,9 +29,6 @@ PODS:
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- Sparkle (2.9.0)
|
||||
- sqflite_darwin (0.0.4):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- sqlite3 (3.52.0):
|
||||
- sqlite3/common (= 3.52.0)
|
||||
- sqlite3/common (3.52.0)
|
||||
@@ -79,7 +76,6 @@ DEPENDENCIES:
|
||||
- screen_retriever_macos (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever_macos/macos`)
|
||||
- sentry_flutter (from `Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos`)
|
||||
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`)
|
||||
- sqlite3_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/darwin`)
|
||||
- universal_gamepad (from `Flutter/ephemeral/.symlinks/plugins/universal_gamepad/macos`)
|
||||
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
||||
@@ -117,8 +113,6 @@ EXTERNAL SOURCES:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/sentry_flutter/macos
|
||||
shared_preferences_foundation:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
|
||||
sqflite_darwin:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin
|
||||
sqlite3_flutter_libs:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/sqlite3_flutter_libs/darwin
|
||||
universal_gamepad:
|
||||
@@ -145,7 +139,6 @@ SPEC CHECKSUMS:
|
||||
sentry_flutter: 31101687061fb85211ebab09ce6eb8db4e9ba74f
|
||||
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
|
||||
Sparkle: f4355f9ebbe9b7d932df4980d70f13922ac97b2a
|
||||
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
||||
sqlite3: a51c07cf16e023d6c48abd5e5791a61a47354921
|
||||
sqlite3_flutter_libs: b3e120efe9a82017e5552a620f696589ed4f62ab
|
||||
universal_gamepad: 8922f1f238f62d6847de887228976d5b572b57da
|
||||
|
||||
+28
-76
@@ -150,30 +150,30 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.12.4"
|
||||
cached_network_image:
|
||||
cached_network_image_ce:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: cached_network_image
|
||||
sha256: "7c1183e361e5c8b0a0f21a28401eecdbde252441106a9816400dd4c2b2424916"
|
||||
name: cached_network_image_ce
|
||||
sha256: d4701fbbdf508de831e847fd1d49c644ffa6191c6018c416ab6f66bbe1ad5fff
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.4.1"
|
||||
cached_network_image_platform_interface:
|
||||
version: "4.6.4"
|
||||
cached_network_image_platform_interface_ce:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cached_network_image_platform_interface
|
||||
sha256: "35814b016e37fbdc91f7ae18c8caf49ba5c88501813f73ce8a07027a395e2829"
|
||||
name: cached_network_image_platform_interface_ce
|
||||
sha256: "95343645becaeac01dd6eeb9f3a85448b6076d211010ff1973e8bbfd840b571d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.1"
|
||||
cached_network_image_web:
|
||||
version: "5.2.0"
|
||||
cached_network_image_web_ce:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cached_network_image_web
|
||||
sha256: "980842f4e8e2535b8dbd3d5ca0b1f0ba66bf61d14cc3a17a9b4788a3685ba062"
|
||||
name: cached_network_image_web_ce
|
||||
sha256: "6bcd8608d4ace7c35625f09d971ce68c7a6581a4631b0fb6ceb2909b2c2e17a8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
version: "2.1.1"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -443,14 +443,6 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_cache_manager:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_cache_manager
|
||||
sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.4.1"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
@@ -506,6 +498,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.2"
|
||||
hive_ce:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: hive_ce
|
||||
sha256: "8e9980e68643afb1e765d3af32b47996552a64e190d03faf622cea07c1294418"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.19.3"
|
||||
hooks:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -586,6 +586,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.5"
|
||||
isolate_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: isolate_channel
|
||||
sha256: a9d3d620695bc984244dafae00b95e4319d6974b2d77f4b9e1eb4f2efe099094
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.1"
|
||||
jni:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -940,14 +948,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.0"
|
||||
rxdart:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: rxdart
|
||||
sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.28.0"
|
||||
saf_stream:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -1155,46 +1155,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.2"
|
||||
sqflite:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite
|
||||
sha256: e2297b1da52f127bc7a3da11439985d9b536f75070f3325e62ada69a5c585d03
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.2"
|
||||
sqflite_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite_android
|
||||
sha256: "881e28efdcc9950fd8e9bb42713dcf1103e62a2e7168f23c9338d82db13dec40"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.2+3"
|
||||
sqflite_common:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite_common
|
||||
sha256: "6ef422a4525ecc601db6c0a2233ff448c731307906e92cabc9ba292afaae16a6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.6"
|
||||
sqflite_darwin:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite_darwin
|
||||
sha256: "279832e5cde3fe99e8571879498c9211f3ca6391b0d818df4e17d9fff5c6ccb3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.2"
|
||||
sqflite_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite_platform_interface
|
||||
sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
sqlite3:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1251,14 +1211,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
synchronized:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: synchronized
|
||||
sha256: c254ade258ec8282947a0acbbc90b9575b4f19673533ee46f2f6e9b3aeefd7c0
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.4.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
+1
-2
@@ -13,8 +13,7 @@ dependencies:
|
||||
intl: ^0.20.2
|
||||
json_annotation: ^4.9.0
|
||||
shared_preferences: ^2.5.4
|
||||
cached_network_image: ^3.4.1
|
||||
flutter_cache_manager: ^3.4.1
|
||||
cached_network_image_ce: 4.6.4
|
||||
http: ^1.2.0
|
||||
url_launcher: ^6.3.0
|
||||
uuid: ^4.4.0
|
||||
|
||||
@@ -40,7 +40,7 @@ TrickplayInfo _info({
|
||||
);
|
||||
|
||||
/// Stub that returns a constant 1×1 transparent image for any URL — keeps
|
||||
/// tests off path_provider / cached_network_image's disk cache.
|
||||
/// tests off path_provider / the image disk cache.
|
||||
ImageProvider _fakeSheet(String _) => MemoryImage(Uint8List.fromList(const [0]));
|
||||
|
||||
void main() {
|
||||
|
||||
Reference in New Issue
Block a user