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