Skip to content

Commit

Permalink
feat: 3129 (New PR) Allow to swipe between product images on the full…
Browse files Browse the repository at this point in the history
… screen image (#3363)

* feat : 3129 (New PR) Allow to swipe between product images on the full screen image

* Resolved formatting issues

* Made the changes suggested in PR review

* Resolved formatting issues

Co-authored-by: monsieurtanuki <fabrice_fontaine@hotmail.com>
  • Loading branch information
omkarChend1kar and monsieurtanuki authored Nov 27, 2022
1 parent 2621b3a commit bc91d43
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,11 @@ class SmoothImagesSliverGrid extends SmoothImagesView {
image: imageProvider,
onTap: onTap == null
? null
: () => onTap!(entry.key, entry.value),
: () => onTap!(
entry.key,
entry.value,
null,
),
),
);
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ class SmoothImagesSliverList extends SmoothImagesView {
),
onTap: onTap == null
? null
: () => onTap!(imageList[index].key, imageList[index].value),
: () => onTap!(
imageList[index].key,
imageList[index].value,
index,
),
),
),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ abstract class SmoothImagesView extends StatelessWidget {
});

final Map<ProductImageData, ImageProvider?> imagesData;
final void Function(ProductImageData, ImageProvider?)? onTap;
final void Function(ProductImageData, ImageProvider?, int?)? onTap;
final bool loading;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import 'package:smooth_app/generic_lib/widgets/smooth_back_button.dart';
import 'package:smooth_app/helpers/product_cards_helper.dart';
import 'package:smooth_app/pages/image_crop_page.dart';
import 'package:smooth_app/pages/product/common/product_refresher.dart';
import 'package:smooth_app/pages/product/product_image_viewer.dart';
import 'package:smooth_app/pages/product/product_image_swipeable_view.dart';
import 'package:smooth_app/widgets/smooth_app_bar.dart';
import 'package:smooth_app/widgets/smooth_scaffold.dart';

Expand Down Expand Up @@ -97,9 +97,16 @@ class _ProductImageGalleryViewState extends State<ProductImageGalleryView> {
),
SmoothImagesSliverList(
imagesData: _selectedImages,
onTap: (ProductImageData data, _) =>
onTap: (
ProductImageData data,
_,
int? initialImageIndex,
) =>
TransientFile.isImageAvailable(data, _barcode)
? _openImage(data)
? _openImage(
imageData: data,
initialImageIndex: initialImageIndex ?? 0,
)
: _newImage(data),
),
],
Expand All @@ -120,13 +127,16 @@ class _ProductImageGalleryViewState extends State<ProductImageGalleryView> {
),
);

Future<void> _openImage(ProductImageData imageData) async =>
Navigator.push<void>(
Future<void> _openImage({
required ProductImageData imageData,
required int initialImageIndex,
}) async =>
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (_) => ProductImageViewer(
builder: (_) => ProductImageSwipeableView(
initialImageIndex: initialImageIndex,
product: _product,
imageField: imageData.imageField,
),
),
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:openfoodfacts/model/Product.dart';
import 'package:provider/provider.dart';
import 'package:smooth_app/data_models/product_image_data.dart';
import 'package:smooth_app/database/local_database.dart';
import 'package:smooth_app/database/transient_file.dart';
import 'package:smooth_app/generic_lib/design_constants.dart';
import 'package:smooth_app/generic_lib/widgets/smooth_back_button.dart';
import 'package:smooth_app/helpers/product_cards_helper.dart';
import 'package:smooth_app/pages/product/product_image_viewer.dart';
import 'package:smooth_app/widgets/smooth_scaffold.dart';

///Widget to display swipeable product images of particular category,
///Opens product image with [initialImageIndex].
class ProductImageSwipeableView extends StatefulWidget {
const ProductImageSwipeableView({
super.key,
required this.product,
required this.initialImageIndex,
});
final Product product;
final int initialImageIndex;
@override
State<ProductImageSwipeableView> createState() =>
_ProductImageSwipeableViewState();
}

class _ProductImageSwipeableViewState extends State<ProductImageSwipeableView> {
late final LocalDatabase _localDatabase;
//Making use of [ValueNotifier] such that to avoid performance issues
//while swipping between pages by making sure only [Text] widget for product title is rebuilt
final ValueNotifier<int> _currentImageDataIndex = ValueNotifier<int>(0);
late Map<ProductImageData, ImageProvider?> _selectedImages;
late List<ProductImageData> _imageDataList;
late PageController _controller;
late final Product _initialProduct;
late Product _product;

ImageProvider? _provideImage(ProductImageData imageData) =>
TransientFile.getImageProvider(imageData, _barcode);

String get _barcode => _initialProduct.barcode!;

@override
void initState() {
super.initState();
_initialProduct = widget.product;
_localDatabase = context.read<LocalDatabase>();
_localDatabase.upToDate.showInterest(_barcode);
_controller = PageController(
initialPage: widget.initialImageIndex,
);
}

@override
void dispose() {
_localDatabase.upToDate.loseInterest(_barcode);
super.dispose();
}

@override
Widget build(BuildContext context) {
final AppLocalizations appLocalizations = AppLocalizations.of(context);
context.watch<LocalDatabase>();
_product = _localDatabase.upToDate.getLocalUpToDate(_initialProduct);
final List<ProductImageData> allProductImagesData =
getProductMainImagesData(
_product,
appLocalizations,
includeOther: false,
);
_selectedImages = Map<ProductImageData, ImageProvider?>.fromIterables(
allProductImagesData,
allProductImagesData.map(_provideImage),
);
_imageDataList = List<ProductImageData>.from(_selectedImages.keys);
return SmoothScaffold(
appBar: AppBar(
backgroundColor: Colors.black,
foregroundColor: WHITE_COLOR,
elevation: 0,
title: ValueListenableBuilder<int>(
valueListenable: _currentImageDataIndex,
builder: (_, int index, __) {
return Text(
_imageDataList[index].title,
);
},
),
leading: SmoothBackButton(
iconColor: Colors.white,
onPressed: () => Navigator.maybePop(context),
),
),
body: PageView.builder(
onPageChanged: (int index) {
_currentImageDataIndex.value = index;
},
controller: _controller,
itemCount: _selectedImages.keys.length,
itemBuilder: (BuildContext context, int index) {
return ProductImageViewer(
product: widget.product,
imageField: _imageDataList[index].imageField,
);
},
),
);
}
}
47 changes: 21 additions & 26 deletions packages/smooth_app/lib/pages/product/product_image_viewer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ import 'package:smooth_app/data_models/product_image_data.dart';
import 'package:smooth_app/database/dao_int.dart';
import 'package:smooth_app/database/local_database.dart';
import 'package:smooth_app/database/transient_file.dart';
import 'package:smooth_app/generic_lib/design_constants.dart';
import 'package:smooth_app/generic_lib/loading_dialog.dart';
import 'package:smooth_app/generic_lib/widgets/smooth_back_button.dart';
import 'package:smooth_app/generic_lib/widgets/picture_not_found.dart';
import 'package:smooth_app/helpers/database_helper.dart';
import 'package:smooth_app/helpers/product_cards_helper.dart';
import 'package:smooth_app/pages/image_crop_page.dart';
Expand Down Expand Up @@ -75,40 +74,36 @@ class _ProductImageViewerState extends State<ProductImageViewer> {
extendBodyBehindAppBar: true,
backgroundColor: Colors.black,
floatingActionButton: FloatingActionButton.extended(
label: Text(appLocalizations.edit_photo_button_label),
icon: const Icon(Icons.edit),
label: Text(
imageProvider == null
? appLocalizations.add
: appLocalizations.edit_photo_button_label,
),
icon: Icon(
imageProvider == null ? Icons.add : Icons.edit,
),
backgroundColor: Theme.of(context).colorScheme.primary,
onPressed: () async => _editImage(),
),
appBar: AppBar(
backgroundColor: Colors.black,
foregroundColor: WHITE_COLOR,
elevation: 0,
title: Text(_imageData.title),
leading: SmoothBackButton(
iconColor: Colors.white,
onPressed: () => Navigator.maybePop(context),
),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ConstrainedBox(
constraints: BoxConstraints.tight(
Size(double.infinity, MediaQuery.of(context).size.height / 2),
),
child: PhotoView(
minScale: 0.2,
imageProvider:
imageProvider, // TODO(monsieurtanuki): what if null?
heroAttributes: PhotoViewHeroAttributes(
tag: imageProvider ??
Object(), // TODO(monsieurtanuki): what if null?
),
backgroundDecoration: const BoxDecoration(
color: Colors.black,
),
),
child: imageProvider == null
? const PictureNotFound()
: PhotoView(
minScale: 0.2,
imageProvider: imageProvider,
heroAttributes: PhotoViewHeroAttributes(
tag: imageProvider,
),
backgroundDecoration: const BoxDecoration(
color: Colors.black,
),
),
),
],
),
Expand Down

0 comments on commit bc91d43

Please sign in to comment.