mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-01-22 16:56:19 +01:00
290 lines
10 KiB
Dart
290 lines
10 KiB
Dart
import 'package:cached_network_image/cached_network_image.dart';
|
|
import 'package:cached_network_image_platform_interface/cached_network_image_platform_interface.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/widgets.dart';
|
|
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
|
import 'package:octo_image/octo_image.dart';
|
|
|
|
/// Builder function to create an image widget. The function is called after
|
|
/// the ImageProvider completes the image loading.
|
|
typedef ImageWidgetBuilder = Widget Function(
|
|
BuildContext context,
|
|
Widget child,
|
|
ImageProvider imageProvider,
|
|
);
|
|
|
|
/// Image widget to show NetworkImage with caching functionality.
|
|
class CachedNetworkImage extends StatelessWidget {
|
|
/// Evict an image from both the disk file based caching system of the
|
|
/// [BaseCacheManager] as the in memory [ImageCache] of the [ImageProvider].
|
|
/// [url] is used by both the disk and memory cache. The scale is only used
|
|
/// to clear the image from the [ImageCache].
|
|
static Future evictFromCache(
|
|
String url, {
|
|
String? cacheKey,
|
|
BaseCacheManager? cacheManager,
|
|
double scale = 1.0,
|
|
}) async {
|
|
cacheManager = cacheManager ?? DefaultCacheManager();
|
|
await cacheManager.removeFile(cacheKey ?? url);
|
|
return CachedNetworkImageProvider(url, scale: scale).evict();
|
|
}
|
|
|
|
final CachedNetworkImageProvider _image;
|
|
|
|
/// Option to use cachemanager with other settings
|
|
final BaseCacheManager? cacheManager;
|
|
|
|
/// The target image that is displayed.
|
|
final String imageUrl;
|
|
|
|
/// The target image's cache key.
|
|
final String? cacheKey;
|
|
|
|
/// Optional builder to further customize the display of the image.
|
|
final ImageWidgetBuilder? imageBuilder;
|
|
|
|
/// Widget displayed while the target [imageUrl] is loading.
|
|
final PlaceholderWidgetBuilder? placeholder;
|
|
|
|
/// Widget displayed while the target [imageUrl] is loading.
|
|
final ProgressIndicatorBuilder? progressIndicatorBuilder;
|
|
|
|
/// Widget displayed while the target [imageUrl] failed loading.
|
|
final LoadingErrorWidgetBuilder? errorWidget;
|
|
|
|
/// The duration of the fade-in animation for the [placeholder].
|
|
final Duration? placeholderFadeInDuration;
|
|
|
|
/// The duration of the fade-out animation for the [placeholder].
|
|
final Duration? fadeOutDuration;
|
|
|
|
/// The curve of the fade-out animation for the [placeholder].
|
|
final Curve fadeOutCurve;
|
|
|
|
/// The duration of the fade-in animation for the [imageUrl].
|
|
final Duration fadeInDuration;
|
|
|
|
/// The curve of the fade-in animation for the [imageUrl].
|
|
final Curve fadeInCurve;
|
|
|
|
/// If non-null, require the image to have this width.
|
|
///
|
|
/// If null, the image will pick a size that best preserves its intrinsic
|
|
/// aspect ratio. This may result in a sudden change if the size of the
|
|
/// placeholder widget does not match that of the target image. The size is
|
|
/// also affected by the scale factor.
|
|
final double? width;
|
|
|
|
/// If non-null, require the image to have this height.
|
|
///
|
|
/// If null, the image will pick a size that best preserves its intrinsic
|
|
/// aspect ratio. This may result in a sudden change if the size of the
|
|
/// placeholder widget does not match that of the target image. The size is
|
|
/// also affected by the scale factor.
|
|
final double? height;
|
|
|
|
/// How to inscribe the image into the space allocated during layout.
|
|
///
|
|
/// The default varies based on the other fields. See the discussion at
|
|
/// [paintImage].
|
|
final BoxFit? fit;
|
|
|
|
/// How to align the image within its bounds.
|
|
///
|
|
/// The alignment aligns the given position in the image to the given position
|
|
/// in the layout bounds. For example, a [Alignment] alignment of (-1.0,
|
|
/// -1.0) aligns the image to the top-left corner of its layout bounds, while a
|
|
/// [Alignment] alignment of (1.0, 1.0) aligns the bottom right of the
|
|
/// image with the bottom right corner of its layout bounds. Similarly, an
|
|
/// alignment of (0.0, 1.0) aligns the bottom middle of the image with the
|
|
/// middle of the bottom edge of its layout bounds.
|
|
///
|
|
/// If the [alignment] is [TextDirection]-dependent (i.e. if it is a
|
|
/// [AlignmentDirectional]), then an ambient [Directionality] widget
|
|
/// must be in scope.
|
|
///
|
|
/// Defaults to [Alignment.center].
|
|
///
|
|
/// See also:
|
|
///
|
|
/// * [Alignment], a class with convenient constants typically used to
|
|
/// specify an [AlignmentGeometry].
|
|
/// * [AlignmentDirectional], like [Alignment] for specifying alignments
|
|
/// relative to text direction.
|
|
final Alignment alignment;
|
|
|
|
/// How to paint any portions of the layout bounds not covered by the image.
|
|
final ImageRepeat repeat;
|
|
|
|
/// Whether to paint the image in the direction of the [TextDirection].
|
|
///
|
|
/// If this is true, then in [TextDirection.ltr] contexts, the image will be
|
|
/// drawn with its origin in the top left (the "normal" painting direction for
|
|
/// children); and in [TextDirection.rtl] contexts, the image will be drawn with
|
|
/// a scaling factor of -1 in the horizontal direction so that the origin is
|
|
/// in the top right.
|
|
///
|
|
/// This is occasionally used with children in right-to-left environments, for
|
|
/// children that were designed for left-to-right locales. Be careful, when
|
|
/// using this, to not flip children with integral shadows, text, or other
|
|
/// effects that will look incorrect when flipped.
|
|
///
|
|
/// If this is true, there must be an ambient [Directionality] widget in
|
|
/// scope.
|
|
final bool matchTextDirection;
|
|
|
|
/// Optional headers for the http request of the image url
|
|
final Map<String, String>? httpHeaders;
|
|
|
|
/// When set to true it will animate from the old image to the new image
|
|
/// if the url changes.
|
|
final bool useOldImageOnUrlChange;
|
|
|
|
/// If non-null, this color is blended with each image pixel using [colorBlendMode].
|
|
final Color? color;
|
|
|
|
/// Used to combine [color] with this image.
|
|
///
|
|
/// The default is [BlendMode.srcIn]. In terms of the blend mode, [color] is
|
|
/// the source and this image is the destination.
|
|
///
|
|
/// See also:
|
|
///
|
|
/// * [BlendMode], which includes an illustration of the effect of each blend mode.
|
|
final BlendMode? colorBlendMode;
|
|
|
|
/// Target the interpolation quality for image scaling.
|
|
///
|
|
/// If not given a value, defaults to FilterQuality.low.
|
|
final FilterQuality filterQuality;
|
|
|
|
/// Will resize the image in memory to have a certain width using [ResizeImage]
|
|
final int? memCacheWidth;
|
|
|
|
/// Will resize the image in memory to have a certain height using [ResizeImage]
|
|
final int? memCacheHeight;
|
|
|
|
/// Will resize the image and store the resized image in the disk cache.
|
|
final int? maxWidthDiskCache;
|
|
|
|
/// Will resize the image and store the resized image in the disk cache.
|
|
final int? maxHeightDiskCache;
|
|
|
|
/// CachedNetworkImage shows a network image using a caching mechanism. It also
|
|
/// provides support for a placeholder, showing an error and fading into the
|
|
/// loaded image. Next to that it supports most features of a default Image
|
|
/// widget.
|
|
CachedNetworkImage({
|
|
Key? key,
|
|
required this.imageUrl,
|
|
this.httpHeaders,
|
|
this.imageBuilder,
|
|
this.placeholder,
|
|
this.progressIndicatorBuilder,
|
|
this.errorWidget,
|
|
this.fadeOutDuration = const Duration(milliseconds: 1000),
|
|
this.fadeOutCurve = Curves.easeOut,
|
|
this.fadeInDuration = const Duration(milliseconds: 500),
|
|
this.fadeInCurve = Curves.easeIn,
|
|
this.width,
|
|
this.height,
|
|
this.fit,
|
|
this.alignment = Alignment.center,
|
|
this.repeat = ImageRepeat.noRepeat,
|
|
this.matchTextDirection = false,
|
|
this.cacheManager,
|
|
this.useOldImageOnUrlChange = false,
|
|
this.color,
|
|
this.filterQuality = FilterQuality.low,
|
|
this.colorBlendMode,
|
|
this.placeholderFadeInDuration,
|
|
this.memCacheWidth,
|
|
this.memCacheHeight,
|
|
this.cacheKey,
|
|
this.maxWidthDiskCache,
|
|
this.maxHeightDiskCache,
|
|
ImageRenderMethodForWeb imageRenderMethodForWeb =
|
|
ImageRenderMethodForWeb.HtmlImage,
|
|
}) : _image = CachedNetworkImageProvider(
|
|
imageUrl,
|
|
headers: httpHeaders,
|
|
cacheManager: cacheManager,
|
|
cacheKey: cacheKey,
|
|
imageRenderMethodForWeb: imageRenderMethodForWeb,
|
|
maxWidth: maxWidthDiskCache,
|
|
maxHeight: maxHeightDiskCache,
|
|
),
|
|
super(key: key);
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
var octoPlaceholderBuilder =
|
|
placeholder != null ? _octoPlaceholderBuilder : null;
|
|
var octoProgressIndicatorBuilder =
|
|
progressIndicatorBuilder != null ? _octoProgressIndicatorBuilder : null;
|
|
|
|
///If there is no placeholer OctoImage does not fade, so always set an
|
|
///(empty) placeholder as this always used to be the behaviour of
|
|
///CachedNetworkImage.
|
|
if (octoPlaceholderBuilder == null &&
|
|
octoProgressIndicatorBuilder == null) {
|
|
octoPlaceholderBuilder = (context) => Container();
|
|
}
|
|
|
|
return OctoImage(
|
|
image: _image,
|
|
imageBuilder: imageBuilder != null ? _octoImageBuilder : null,
|
|
placeholderBuilder: octoPlaceholderBuilder,
|
|
progressIndicatorBuilder: octoProgressIndicatorBuilder,
|
|
errorBuilder: errorWidget != null ? _octoErrorBuilder : null,
|
|
fadeOutDuration: fadeOutDuration,
|
|
fadeOutCurve: fadeOutCurve,
|
|
fadeInDuration: fadeInDuration,
|
|
fadeInCurve: fadeInCurve,
|
|
width: width,
|
|
height: height,
|
|
fit: fit,
|
|
alignment: alignment,
|
|
repeat: repeat,
|
|
matchTextDirection: matchTextDirection,
|
|
color: color,
|
|
filterQuality: filterQuality,
|
|
colorBlendMode: colorBlendMode,
|
|
placeholderFadeInDuration: placeholderFadeInDuration,
|
|
gaplessPlayback: useOldImageOnUrlChange,
|
|
memCacheWidth: memCacheWidth,
|
|
memCacheHeight: memCacheHeight,
|
|
);
|
|
}
|
|
|
|
Widget _octoImageBuilder(BuildContext context, Widget child) {
|
|
return imageBuilder!(context, child, _image);
|
|
}
|
|
|
|
Widget _octoPlaceholderBuilder(BuildContext context) {
|
|
return placeholder!(context, imageUrl);
|
|
}
|
|
|
|
Widget _octoProgressIndicatorBuilder(
|
|
BuildContext context,
|
|
ImageChunkEvent? progress,
|
|
) {
|
|
int? totalSize;
|
|
var downloaded = 0;
|
|
if (progress != null) {
|
|
totalSize = progress.expectedTotalBytes;
|
|
downloaded = progress.cumulativeBytesLoaded;
|
|
}
|
|
return progressIndicatorBuilder!(
|
|
context, imageUrl, DownloadProgress(imageUrl, totalSize, downloaded));
|
|
}
|
|
|
|
Widget _octoErrorBuilder(
|
|
BuildContext context,
|
|
Object error,
|
|
StackTrace? stackTrace,
|
|
) {
|
|
return errorWidget!(context, imageUrl, error);
|
|
}
|
|
}
|