122 lines
5.0 KiB
Dart
122 lines
5.0 KiB
Dart
import 'package:auto_size_text/auto_size_text.dart';
|
|
import 'package:cached_network_image/cached_network_image.dart';
|
|
import 'package:carousel_slider/carousel_slider.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_markdown/flutter_markdown.dart';
|
|
import 'package:mc_gallery/features/home/data/models/image_model.dart';
|
|
|
|
import '/features/core/data/constants/const_colors.dart';
|
|
import '/features/core/data/constants/const_text.dart';
|
|
import '/features/core/widgets/gap.dart';
|
|
import '/features/core/widgets/mcg_scaffold.dart';
|
|
import '/features/home/views/image_carousel/image_carousel_view_model.dart';
|
|
import '../../../core/widgets/state/view_model_builder.dart';
|
|
|
|
class ImageCarouselViewArguments {
|
|
const ImageCarouselViewArguments({required this.imageIndexKey});
|
|
final int imageIndexKey;
|
|
}
|
|
|
|
class ImageCarouselView extends StatelessWidget {
|
|
const ImageCarouselView({
|
|
required this.imageCarouselViewArguments,
|
|
super.key,
|
|
});
|
|
|
|
final ImageCarouselViewArguments imageCarouselViewArguments;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return ViewModelBuilder<ImageCarouselViewModel>(
|
|
viewModelBuilder: () => ImageCarouselViewModel.locate,
|
|
argumentBuilder: () => imageCarouselViewArguments,
|
|
builder: (context, final model) => McgScaffold(
|
|
bodyBuilderWaiter: model.isInitialised,
|
|
forceInternetCheck: true,
|
|
appBar: AppBar(
|
|
title: Text(model.strings.imageCarousel),
|
|
),
|
|
body: Column(
|
|
children: [
|
|
Expanded(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Card(
|
|
elevation: 8,
|
|
surfaceTintColor: ConstColours.transparent,
|
|
child: CarouselSlider.builder(
|
|
itemCount: model.numberOfImages,
|
|
carouselController: model.carouselController,
|
|
options: CarouselOptions(
|
|
enlargeFactor: 1,
|
|
enlargeCenterPage: true,
|
|
enlargeStrategy: CenterPageEnlargeStrategy.scale,
|
|
disableCenter: true,
|
|
viewportFraction: 1,
|
|
initialPage: model.currentImageIndex,
|
|
enableInfiniteScroll: false,
|
|
onPageChanged: (final index, _) => model.swipedTo(newIndex: index),
|
|
),
|
|
itemBuilder: (context, _, __) => Stack(
|
|
fit: StackFit.expand,
|
|
children: [
|
|
ValueListenableBuilder<ImageModel>(
|
|
valueListenable: model.currentImageModelListenable,
|
|
builder: (context, _, __) => CachedNetworkImage(
|
|
imageUrl: model.currentImageUrl,
|
|
cacheKey: model.currentImageKey,
|
|
fit: BoxFit.contain,
|
|
progressIndicatorBuilder: (_, __, final progress) =>
|
|
CircularProgressIndicator(
|
|
value: model.downloadProgressValue(progress: progress),
|
|
),
|
|
),
|
|
),
|
|
ValueListenableBuilder<ImageModel>(
|
|
valueListenable: model.currentImageModelListenable,
|
|
builder: (context, _, __) => Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
IconButton(
|
|
icon: Icon(
|
|
Icons.chevron_left,
|
|
color: model.hasPreviousImage
|
|
? ConstColours.white
|
|
: ConstColours.black,
|
|
),
|
|
onPressed: model.onPreviousPressed,
|
|
),
|
|
AutoSizeText(
|
|
model.currentImageName,
|
|
style: ConstText.imageOverlayTextStyle(context),
|
|
),
|
|
IconButton(
|
|
icon: Icon(
|
|
Icons.chevron_right,
|
|
color:
|
|
model.hasNextImage ? ConstColours.white : ConstColours.black,
|
|
),
|
|
onPressed: model.onNextPressed,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
const Gap(24),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 24),
|
|
child: MarkdownBody(data: model.strings.imageDetails),
|
|
),
|
|
const Gap(16),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|