Skip to content

Commit

Permalink
Upload indicator for the image viewer
Browse files Browse the repository at this point in the history
  • Loading branch information
g123k committed Jun 20, 2024
1 parent 4deb0b4 commit 753e15c
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -219,23 +219,7 @@ class _PhotoRow extends StatelessWidget {
textDirection: Directionality.of(context),
bottom: VERY_SMALL_SPACE,
end: VERY_SMALL_SPACE,
width: 30.0,
height: 30.0,
child: DecoratedBox(
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.5),
shape: BoxShape.circle,
),
child: const Padding(
padding: EdgeInsetsDirectional.only(
start: SMALL_SPACE,
end: SMALL_SPACE,
top: SMALL_SPACE,
bottom: SMALL_SPACE - 1.0,
),
child: CloudUploadAnimation(),
),
),
child: const CloudUploadAnimation.circle(size: 30.0),
),
],
),
Expand Down
92 changes: 58 additions & 34 deletions packages/smooth_app/lib/pages/product/product_image_viewer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import 'package:smooth_app/data_models/up_to_date_mixin.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/duration_constants.dart';
import 'package:smooth_app/generic_lib/widgets/language_selector.dart';
import 'package:smooth_app/generic_lib/widgets/picture_not_found.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/product_image_button.dart';
import 'package:smooth_app/resources/app_animations.dart';

/// Displays a full-screen image with an "edit" floating button.
class ProductImageViewer extends StatefulWidget {
Expand Down Expand Up @@ -69,8 +71,11 @@ class _ProductImageViewerState extends State<ProductImageViewer>
widget.imageField,
widget.language,
);
final ImageProvider? imageProvider = _getTransientFile().getImageProvider();
final TransientFile transientFile = _getTransientFile();
final ImageProvider? imageProvider = transientFile.getImageProvider();
final bool imageExists = imageProvider != null;
final bool isLoading =
transientFile.isImageAvailable() && !transientFile.isServerImage();
final Iterable<OpenFoodFactsLanguage> selectedLanguages =
getProductImageLanguages(
upToDateProduct,
Expand Down Expand Up @@ -124,40 +129,59 @@ class _ProductImageViewerState extends State<ProductImageViewer>
),
],
)
: PhotoView(
minScale: 0.2,
imageProvider: imageProvider,
heroAttributes: PhotoViewHeroAttributes(
tag: 'photo_${widget.imageField.offTag}',
flightShuttleBuilder: (
_,
Animation<double> animation,
HeroFlightDirection flightDirection,
BuildContext fromHeroContext,
BuildContext toHeroContext,
) {
return AnimatedBuilder(
animation: animation,
builder: (_, __) {
Widget widget;
if (flightDirection ==
HeroFlightDirection.push) {
widget = fromHeroContext.widget;
} else {
widget = toHeroContext.widget;
}
: SizedBox.expand(
child: Stack(
children: <Widget>[
Positioned.fill(
child: AnimatedOpacity(
opacity: isLoading ? 0.5 : 1.0,
duration: SmoothAnimationsDuration.short,
child: PhotoView(
minScale: 0.2,
imageProvider: imageProvider,
heroAttributes: PhotoViewHeroAttributes(
tag: 'photo_${widget.imageField.offTag}',
flightShuttleBuilder: (
_,
Animation<double> animation,
HeroFlightDirection flightDirection,
BuildContext fromHeroContext,
BuildContext toHeroContext,
) {
return AnimatedBuilder(
animation: animation,
builder: (_, __) {
Widget widget;
if (flightDirection ==
HeroFlightDirection.push) {
widget = fromHeroContext.widget;
} else {
widget = toHeroContext.widget;
}

return ClipRRect(
borderRadius: BorderRadius.circular(
1 - animation.value) *
ROUNDED_RADIUS.x,
child: widget,
);
},
);
}),
backgroundDecoration: const BoxDecoration(
color: Colors.black,
return ClipRRect(
borderRadius: BorderRadius.circular(
1 - animation.value) *
ROUNDED_RADIUS.x,
child: widget,
);
},
);
}),
backgroundDecoration: const BoxDecoration(
color: Colors.black,
),
),
),
),
if (isLoading)
Center(
child: CloudUploadAnimation.circle(
size: MediaQuery.sizeOf(context).longestSide *
0.2,
),
),
],
),
),
),
Expand Down
46 changes: 41 additions & 5 deletions packages/smooth_app/lib/resources/app_animations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,51 @@ class BarcodeAnimation extends StatelessWidget {

class CloudUploadAnimation extends StatelessWidget {
const CloudUploadAnimation({
required this.size,
super.key,
});
}) : _circleColor = null;

const CloudUploadAnimation.circle({
required this.size,
Color? circleColor,
super.key,
}) : _circleColor = circleColor ?? Colors.black54;

final double size;
final Color? _circleColor;

@override
Widget build(BuildContext context) {
return RiveAnimation.direct(
AnimationsLoader.of(context),
artboard: 'Cloud upload',
animations: const <String>['Animation'],
Widget widget = SizedBox.square(
dimension: size,
child: RiveAnimation.direct(
AnimationsLoader.of(context),
artboard: 'Cloud upload',
animations: const <String>['Animation'],
),
);

if (_circleColor != null) {
widget = DecoratedBox(
decoration: BoxDecoration(
color: _circleColor,
shape: BoxShape.circle,
),
child: Padding(
padding: EdgeInsetsDirectional.only(
top: size * 0.2,
start: size * 0.2,
end: size * 0.2,
bottom: size * 0.13,
),
child: widget,
),
);
}

return SizedBox.square(
dimension: size,
child: widget,
);
}
}
Expand Down

0 comments on commit 753e15c

Please sign in to comment.