didvan-app/lib/widgets/skeleton_image.dart

109 lines
3.0 KiB
Dart

import 'dart:typed_data';
import 'package:didvan/widgets/shimmer_placeholder.dart';
import 'package:http/http.dart' as http;
import 'package:cached_network_image/cached_network_image.dart';
import 'package:didvan/config/design_config.dart';
import 'package:didvan/services/network/request.dart';
import 'package:didvan/services/network/request_helper.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class SkeletonImage extends StatefulWidget {
final String imageUrl;
final double width;
final double height;
final BorderRadius? borderRadius;
final double? aspectRatio;
const SkeletonImage({
Key? key,
required this.imageUrl,
this.width = 300,
this.height = 140,
this.borderRadius = DesignConfig.lowBorderRadius,
this.aspectRatio,
}) : super(key: key);
@override
State<SkeletonImage> createState() => _SkeletonImageState();
}
class _SkeletonImageState extends State<SkeletonImage> {
late Uint8List _bytes;
bool _isLoading = true;
@override
void initState() {
if (kIsWeb) _getImage();
super.initState();
}
Future<void> _getImage() async {
final url = RequestHelper.baseUrl + widget.imageUrl;
_bytes = (await http.get(
Uri.parse(url),
headers: {'Authorization': 'Bearer ${RequestService.token}'},
))
.bodyBytes;
if (mounted) {
setState(() {
_isLoading = false;
});
}
}
@override
Widget build(BuildContext context) {
if (kIsWeb) {
if (_isLoading) {
return _aspectRatioGenerator(
child: ShimmerPlaceholder(
borderRadius: widget.borderRadius,
width: widget.aspectRatio == null ? widget.width : null,
height: widget.aspectRatio == null ? widget.height : null,
),
);
}
return _aspectRatioGenerator(
child: ClipRRect(
borderRadius: widget.borderRadius,
child: Image.memory(
_bytes,
fit: BoxFit.cover,
width: widget.width,
height: widget.height,
),
),
);
}
return _aspectRatioGenerator(
child: CachedNetworkImage(
httpHeaders: {'Authorization': 'Bearer ${RequestService.token}'},
width: widget.width,
height: widget.height,
imageUrl: RequestHelper.baseUrl + widget.imageUrl,
imageBuilder: (context, imageProvider) => Container(
decoration: BoxDecoration(
borderRadius: widget.borderRadius ?? DesignConfig.lowBorderRadius,
image: DecorationImage(
image: imageProvider,
fit: BoxFit.cover,
),
),
),
progressIndicatorBuilder: (context, url, progress) =>
ShimmerPlaceholder(
borderRadius: widget.borderRadius,
),
),
);
}
Widget _aspectRatioGenerator({required Widget child}) =>
widget.aspectRatio == null
? SizedBox(child: child)
: AspectRatio(
aspectRatio: widget.aspectRatio!,
child: child,
);
}