mirror of
https://github.com/samsonjs/immich.git
synced 2026-04-27 15:07:45 +00:00
fix: incorrect asset viewer scale on image frame update (#25430)
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
parent
dd72c32c60
commit
bccad2940e
3 changed files with 27 additions and 16 deletions
|
|
@ -118,7 +118,6 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
|
||||||
bool dragInProgress = false;
|
bool dragInProgress = false;
|
||||||
bool shouldPopOnDrag = false;
|
bool shouldPopOnDrag = false;
|
||||||
bool assetReloadRequested = false;
|
bool assetReloadRequested = false;
|
||||||
double? initialScale;
|
|
||||||
double previousExtent = _kBottomSheetMinimumExtent;
|
double previousExtent = _kBottomSheetMinimumExtent;
|
||||||
Offset dragDownPosition = Offset.zero;
|
Offset dragDownPosition = Offset.zero;
|
||||||
int totalAssets = 0;
|
int totalAssets = 0;
|
||||||
|
|
@ -264,7 +263,6 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
|
||||||
(context.height * bottomSheetController.size) - (context.height * _kBottomSheetMinimumExtent);
|
(context.height * bottomSheetController.size) - (context.height * _kBottomSheetMinimumExtent);
|
||||||
controller.position = Offset(0, -verticalOffset);
|
controller.position = Offset(0, -verticalOffset);
|
||||||
// Apply the zoom effect when the bottom sheet is showing
|
// Apply the zoom effect when the bottom sheet is showing
|
||||||
initialScale = controller.scale;
|
|
||||||
controller.scale = (controller.scale ?? 1.0) + 0.01;
|
controller.scale = (controller.scale ?? 1.0) + 0.01;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -316,7 +314,7 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
|
||||||
hasDraggedDown = null;
|
hasDraggedDown = null;
|
||||||
viewController?.animateMultiple(
|
viewController?.animateMultiple(
|
||||||
position: initialPhotoViewState.position,
|
position: initialPhotoViewState.position,
|
||||||
scale: initialPhotoViewState.scale,
|
scale: viewController?.initialScale ?? initialPhotoViewState.scale,
|
||||||
rotation: initialPhotoViewState.rotation,
|
rotation: initialPhotoViewState.rotation,
|
||||||
);
|
);
|
||||||
ref.read(assetViewerProvider.notifier).setOpacity(255);
|
ref.read(assetViewerProvider.notifier).setOpacity(255);
|
||||||
|
|
@ -366,8 +364,9 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
|
||||||
final maxScaleDistance = ctx.height * 0.5;
|
final maxScaleDistance = ctx.height * 0.5;
|
||||||
final scaleReduction = (distance / maxScaleDistance).clamp(0.0, dragRatio);
|
final scaleReduction = (distance / maxScaleDistance).clamp(0.0, dragRatio);
|
||||||
double? updatedScale;
|
double? updatedScale;
|
||||||
if (initialPhotoViewState.scale != null) {
|
double? initialScale = viewController?.initialScale ?? initialPhotoViewState.scale;
|
||||||
updatedScale = initialPhotoViewState.scale! * (1.0 - scaleReduction);
|
if (initialScale != null) {
|
||||||
|
updatedScale = initialScale * (1.0 - scaleReduction);
|
||||||
}
|
}
|
||||||
|
|
||||||
final backgroundOpacity = (255 * (1.0 - (scaleReduction / dragRatio))).round();
|
final backgroundOpacity = (255 * (1.0 - (scaleReduction / dragRatio))).round();
|
||||||
|
|
@ -481,8 +480,6 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
|
||||||
|
|
||||||
void _openBottomSheet(BuildContext ctx, {double extent = _kBottomSheetMinimumExtent, bool activitiesMode = false}) {
|
void _openBottomSheet(BuildContext ctx, {double extent = _kBottomSheetMinimumExtent, bool activitiesMode = false}) {
|
||||||
ref.read(assetViewerProvider.notifier).setBottomSheet(true);
|
ref.read(assetViewerProvider.notifier).setBottomSheet(true);
|
||||||
initialScale = viewController?.scale;
|
|
||||||
// viewController?.updateMultiple(scale: (viewController?.scale ?? 1.0) + 0.01);
|
|
||||||
previousExtent = _kBottomSheetMinimumExtent;
|
previousExtent = _kBottomSheetMinimumExtent;
|
||||||
sheetCloseController = showBottomSheet(
|
sheetCloseController = showBottomSheet(
|
||||||
context: ctx,
|
context: ctx,
|
||||||
|
|
@ -504,7 +501,7 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
|
||||||
|
|
||||||
void _handleSheetClose() {
|
void _handleSheetClose() {
|
||||||
viewController?.animateMultiple(position: Offset.zero);
|
viewController?.animateMultiple(position: Offset.zero);
|
||||||
viewController?.updateMultiple(scale: initialScale);
|
viewController?.updateMultiple(scale: viewController?.initialScale);
|
||||||
ref.read(assetViewerProvider.notifier).setBottomSheet(false);
|
ref.read(assetViewerProvider.notifier).setBottomSheet(false);
|
||||||
sheetCloseController = null;
|
sheetCloseController = null;
|
||||||
shouldPopOnDrag = false;
|
shouldPopOnDrag = false;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:immich_mobile/widgets/photo_view/src/utils/ignorable_change_notifier.dart';
|
import 'package:immich_mobile/widgets/photo_view/src/utils/ignorable_change_notifier.dart';
|
||||||
|
import 'package:immich_mobile/widgets/photo_view/src/utils/photo_view_utils.dart';
|
||||||
|
|
||||||
/// The interface in which controllers will be implemented.
|
/// The interface in which controllers will be implemented.
|
||||||
///
|
///
|
||||||
|
|
@ -62,6 +63,9 @@ abstract class PhotoViewControllerBase<T extends PhotoViewControllerValue> {
|
||||||
/// The scale factor to transform the child (image or a customChild).
|
/// The scale factor to transform the child (image or a customChild).
|
||||||
late double? scale;
|
late double? scale;
|
||||||
|
|
||||||
|
double? get initialScale;
|
||||||
|
ScaleBoundaries? scaleBoundaries;
|
||||||
|
|
||||||
/// Nevermind this method :D, look away
|
/// Nevermind this method :D, look away
|
||||||
void setScaleInvisibly(double? scale);
|
void setScaleInvisibly(double? scale);
|
||||||
|
|
||||||
|
|
@ -141,6 +145,9 @@ class PhotoViewController implements PhotoViewControllerBase<PhotoViewController
|
||||||
|
|
||||||
late StreamController<PhotoViewControllerValue> _outputCtrl;
|
late StreamController<PhotoViewControllerValue> _outputCtrl;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ScaleBoundaries? scaleBoundaries;
|
||||||
|
|
||||||
late void Function(Offset)? _animatePosition;
|
late void Function(Offset)? _animatePosition;
|
||||||
late void Function(double)? _animateScale;
|
late void Function(double)? _animateScale;
|
||||||
late void Function(double)? _animateRotation;
|
late void Function(double)? _animateRotation;
|
||||||
|
|
@ -311,4 +318,7 @@ class PhotoViewController implements PhotoViewControllerBase<PhotoViewController
|
||||||
}
|
}
|
||||||
_valueNotifier.value = newValue;
|
_valueNotifier.value = newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
double? get initialScale => scaleBoundaries?.initialScale ?? initial.scale;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,17 @@ class _ImageWrapperState extends State<ImageWrapper> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Should be called only when _imageSize is not null
|
||||||
|
ScaleBoundaries get scaleBoundaries {
|
||||||
|
return ScaleBoundaries(
|
||||||
|
widget.minScale ?? 0.0,
|
||||||
|
widget.maxScale ?? double.infinity,
|
||||||
|
widget.initialScale ?? PhotoViewComputedScale.contained,
|
||||||
|
widget.outerSize,
|
||||||
|
_imageSize!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// retrieve image from the provider
|
// retrieve image from the provider
|
||||||
void _resolveImage() {
|
void _resolveImage() {
|
||||||
final ImageStream newStream = widget.imageProvider.resolve(const ImageConfiguration());
|
final ImageStream newStream = widget.imageProvider.resolve(const ImageConfiguration());
|
||||||
|
|
@ -133,6 +144,7 @@ class _ImageWrapperState extends State<ImageWrapper> {
|
||||||
_lastStack = null;
|
_lastStack = null;
|
||||||
|
|
||||||
_didLoadSynchronously = synchronousCall;
|
_didLoadSynchronously = synchronousCall;
|
||||||
|
widget.controller.scaleBoundaries = scaleBoundaries;
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronousCall && !_didLoadSynchronously ? setupCB() : setState(setupCB);
|
synchronousCall && !_didLoadSynchronously ? setupCB() : setState(setupCB);
|
||||||
|
|
@ -204,14 +216,6 @@ class _ImageWrapperState extends State<ImageWrapper> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final scaleBoundaries = ScaleBoundaries(
|
|
||||||
widget.minScale ?? 0.0,
|
|
||||||
widget.maxScale ?? double.infinity,
|
|
||||||
widget.initialScale ?? PhotoViewComputedScale.contained,
|
|
||||||
widget.outerSize,
|
|
||||||
_imageSize!,
|
|
||||||
);
|
|
||||||
|
|
||||||
return PhotoViewCore(
|
return PhotoViewCore(
|
||||||
imageProvider: widget.imageProvider,
|
imageProvider: widget.imageProvider,
|
||||||
backgroundDecoration: widget.backgroundDecoration,
|
backgroundDecoration: widget.backgroundDecoration,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue