minor fixes
This commit is contained in:
parent
fdd9e00939
commit
093b967e26
7 changed files with 125 additions and 77 deletions
|
@ -96,7 +96,7 @@ class ActivityResultStreamHandler(private val activity: Activity, arguments: Any
|
|||
val granted = PermissionManager.requestMediaFileAccess(activity, uris, mimeTypes)
|
||||
success(granted)
|
||||
} catch (e: Exception) {
|
||||
error("requestMediaFileAccess-request", "failed to request access to uris=$uris", e.message)
|
||||
error("requestMediaFileAccess-request", "failed to request access to ${uris.size} uris=$uris", e.message)
|
||||
}
|
||||
endOfStream()
|
||||
}
|
||||
|
|
|
@ -52,7 +52,9 @@ class MimeTypes {
|
|||
static const v3gpp = 'video/3gpp';
|
||||
static const asf = 'video/x-ms-asf';
|
||||
static const avi = 'video/avi';
|
||||
static const aviMSVideo = 'video/msvideo';
|
||||
static const aviVnd = 'video/vnd.avi';
|
||||
static const aviXMSVideo = 'video/x-msvideo';
|
||||
static const flv = 'video/flv';
|
||||
static const flvX = 'video/x-flv';
|
||||
static const mkv = 'video/mkv';
|
||||
|
@ -87,7 +89,7 @@ class MimeTypes {
|
|||
|
||||
static const Set<String> _knownOpaqueImages = {jpeg};
|
||||
|
||||
static const Set<String> _knownVideos = {v3gpp, asf, avi, aviVnd, flv, flvX, mkv, mkvX, mov, mp2p, mp2t, mp2ts, mp4, mpeg, ogv, realVideo, webm, wmv};
|
||||
static const Set<String> _knownVideos = {v3gpp, asf, avi, aviMSVideo, aviVnd, aviXMSVideo, flv, flvX, mkv, mkvX, mov, mp2p, mp2t, mp2ts, mp4, mpeg, ogv, realVideo, webm, wmv};
|
||||
|
||||
static final Set<String> knownMediaTypes = {
|
||||
anyImage,
|
||||
|
@ -108,7 +110,9 @@ class MimeTypes {
|
|||
static bool refersToSameType(String a, b) {
|
||||
switch (a) {
|
||||
case avi:
|
||||
case aviMSVideo:
|
||||
case aviVnd:
|
||||
case aviXMSVideo:
|
||||
return [avi, aviVnd].contains(b);
|
||||
case bmp:
|
||||
case bmpX:
|
||||
|
|
|
@ -113,8 +113,11 @@ class _EntryPageViewState extends State<EntryPageView> with SingleTickerProvider
|
|||
viewerController.startAutopilotAnimation(
|
||||
vsync: this,
|
||||
onUpdate: ({required scaleLevel}) {
|
||||
final scale = _magnifierController.scaleBoundaries.scaleForLevel(scaleLevel);
|
||||
_magnifierController.update(scale: scale, source: ChangeSource.animation);
|
||||
final boundaries = _magnifierController.scaleBoundaries;
|
||||
if (boundaries != null) {
|
||||
final scale = boundaries.scaleForLevel(scaleLevel);
|
||||
_magnifierController.update(scale: scale, source: ChangeSource.animation);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -318,11 +321,14 @@ class _EntryPageViewState extends State<EntryPageView> with SingleTickerProvider
|
|||
// while cover is fading out, the same controller is used for both the cover and the video,
|
||||
// and both fire scale boundaries events, so we make sure that in the end
|
||||
// the scale boundaries from the video are used after the cover is gone
|
||||
_magnifierController.setScaleBoundaries(
|
||||
_magnifierController.scaleBoundaries.copyWith(
|
||||
childSize: videoDisplaySize,
|
||||
),
|
||||
);
|
||||
final boundaries = _magnifierController.scaleBoundaries;
|
||||
if (boundaries != null) {
|
||||
_magnifierController.setScaleBoundaries(
|
||||
boundaries.copyWith(
|
||||
childSize: videoDisplaySize,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: ValueListenableBuilder<ImageInfo?>(
|
||||
valueListenable: _videoCoverInfoNotifier,
|
||||
|
|
|
@ -48,7 +48,7 @@ class AvesMagnifierController {
|
|||
|
||||
double? get scale => currentState.scale;
|
||||
|
||||
ScaleBoundaries get scaleBoundaries => _scaleBoundaries!;
|
||||
ScaleBoundaries? get scaleBoundaries => _scaleBoundaries;
|
||||
|
||||
ScaleStateChange get scaleState => _currentScaleState;
|
||||
|
||||
|
@ -118,17 +118,20 @@ class AvesMagnifierController {
|
|||
}
|
||||
|
||||
double? getScaleForScaleState(ScaleState scaleState) {
|
||||
double _clamp(double scale) => scale.clamp(scaleBoundaries.minScale, scaleBoundaries.maxScale);
|
||||
final boundaries = scaleBoundaries;
|
||||
if (boundaries == null) return null;
|
||||
|
||||
double _clamp(double scale) => scale.clamp(boundaries.minScale, boundaries.maxScale);
|
||||
|
||||
switch (scaleState) {
|
||||
case ScaleState.initial:
|
||||
case ScaleState.zoomedIn:
|
||||
case ScaleState.zoomedOut:
|
||||
return _clamp(scaleBoundaries.initialScale);
|
||||
return _clamp(boundaries.initialScale);
|
||||
case ScaleState.covering:
|
||||
return _clamp(ScaleLevel.scaleForCovering(scaleBoundaries.viewportSize, scaleBoundaries.childSize));
|
||||
return _clamp(ScaleLevel.scaleForCovering(boundaries.viewportSize, boundaries.childSize));
|
||||
case ScaleState.originalSize:
|
||||
return _clamp(scaleBoundaries.originalScale);
|
||||
return _clamp(boundaries.originalScale);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -13,11 +13,7 @@ import 'package:flutter/widgets.dart';
|
|||
mixin AvesMagnifierControllerDelegate on State<MagnifierCore> {
|
||||
AvesMagnifierController get controller => widget.controller;
|
||||
|
||||
ScaleBoundaries get scaleBoundaries => controller.scaleBoundaries;
|
||||
|
||||
Size get childSize => scaleBoundaries.childSize;
|
||||
|
||||
Size get viewportSize => scaleBoundaries.viewportSize;
|
||||
ScaleBoundaries? get scaleBoundaries => controller.scaleBoundaries;
|
||||
|
||||
ScaleStateCycle get scaleStateCycle => widget.scaleStateCycle;
|
||||
|
||||
|
@ -56,8 +52,9 @@ mixin AvesMagnifierControllerDelegate on State<MagnifierCore> {
|
|||
var nextPosition = Offset.zero;
|
||||
if (nextScaleState == ScaleState.covering || nextScaleState == ScaleState.originalSize) {
|
||||
final childFocalPoint = scaleStateChange.childFocalPoint;
|
||||
if (childFocalPoint != null) {
|
||||
nextPosition = scaleBoundaries.childToStatePosition(nextScale!, childFocalPoint);
|
||||
final boundaries = scaleBoundaries;
|
||||
if (childFocalPoint != null && boundaries != null) {
|
||||
nextPosition = boundaries.childToStatePosition(nextScale!, childFocalPoint);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,11 +67,14 @@ mixin AvesMagnifierControllerDelegate on State<MagnifierCore> {
|
|||
}
|
||||
|
||||
void _onMagnifierStateChange(MagnifierState state) {
|
||||
final boundaries = scaleBoundaries;
|
||||
if (boundaries == null) return;
|
||||
|
||||
controller.update(position: clampPosition(), source: state.source);
|
||||
if (controller.scale == controller.previousState.scale) return;
|
||||
|
||||
if (state.source == ChangeSource.internal || state.source == ChangeSource.animation) return;
|
||||
final newScaleState = (scale! > scaleBoundaries.initialScale) ? ScaleState.zoomedIn : ScaleState.zoomedOut;
|
||||
final newScaleState = (scale! > boundaries.initialScale) ? ScaleState.zoomedIn : ScaleState.zoomedOut;
|
||||
controller.setScaleState(newScaleState, state.source);
|
||||
}
|
||||
|
||||
|
@ -104,9 +104,12 @@ mixin AvesMagnifierControllerDelegate on State<MagnifierCore> {
|
|||
}
|
||||
|
||||
void updateScaleStateFromNewScale(double newScale, ChangeSource source) {
|
||||
final boundaries = scaleBoundaries;
|
||||
if (boundaries == null) return;
|
||||
|
||||
var newScaleState = ScaleState.initial;
|
||||
if (scale != scaleBoundaries.initialScale) {
|
||||
newScaleState = (newScale > scaleBoundaries.initialScale) ? ScaleState.zoomedIn : ScaleState.zoomedOut;
|
||||
if (scale != boundaries.initialScale) {
|
||||
newScaleState = (newScale > boundaries.initialScale) ? ScaleState.zoomedIn : ScaleState.zoomedOut;
|
||||
}
|
||||
controller.setScaleState(newScaleState, source);
|
||||
}
|
||||
|
@ -136,10 +139,13 @@ mixin AvesMagnifierControllerDelegate on State<MagnifierCore> {
|
|||
}
|
||||
|
||||
CornersRange cornersX({double? scale}) {
|
||||
final boundaries = scaleBoundaries;
|
||||
if (boundaries == null) return const CornersRange(0, 0);
|
||||
|
||||
final _scale = scale ?? this.scale!;
|
||||
|
||||
final computedWidth = childSize.width * _scale;
|
||||
final screenWidth = viewportSize.width;
|
||||
final computedWidth = boundaries.childSize.width * _scale;
|
||||
final screenWidth = boundaries.viewportSize.width;
|
||||
|
||||
final positionX = basePosition.x;
|
||||
final widthDiff = computedWidth - screenWidth;
|
||||
|
@ -150,10 +156,13 @@ mixin AvesMagnifierControllerDelegate on State<MagnifierCore> {
|
|||
}
|
||||
|
||||
CornersRange cornersY({double? scale}) {
|
||||
final boundaries = scaleBoundaries;
|
||||
if (boundaries == null) return const CornersRange(0, 0);
|
||||
|
||||
final _scale = scale ?? this.scale!;
|
||||
|
||||
final computedHeight = childSize.height * _scale;
|
||||
final screenHeight = viewportSize.height;
|
||||
final computedHeight = boundaries.childSize.height * _scale;
|
||||
final screenHeight = boundaries.viewportSize.height;
|
||||
|
||||
final positionY = basePosition.y;
|
||||
final heightDiff = computedHeight - screenHeight;
|
||||
|
@ -164,14 +173,17 @@ mixin AvesMagnifierControllerDelegate on State<MagnifierCore> {
|
|||
}
|
||||
|
||||
Offset clampPosition({Offset? position, double? scale}) {
|
||||
final boundaries = scaleBoundaries;
|
||||
if (boundaries == null) return Offset.zero;
|
||||
|
||||
final _scale = scale ?? this.scale!;
|
||||
final _position = position ?? this.position;
|
||||
|
||||
final computedWidth = childSize.width * _scale;
|
||||
final computedHeight = childSize.height * _scale;
|
||||
final computedWidth = boundaries.childSize.width * _scale;
|
||||
final computedHeight = boundaries.childSize.height * _scale;
|
||||
|
||||
final screenWidth = viewportSize.width;
|
||||
final screenHeight = viewportSize.height;
|
||||
final screenWidth = boundaries.viewportSize.width;
|
||||
final screenHeight = boundaries.viewportSize.height;
|
||||
|
||||
var finalX = 0.0;
|
||||
if (screenWidth < computedWidth) {
|
||||
|
|
|
@ -112,6 +112,9 @@ class _MagnifierCoreState extends State<MagnifierCore> with TickerProviderStateM
|
|||
}
|
||||
|
||||
void onScaleUpdate(ScaleUpdateDetails details) {
|
||||
final boundaries = scaleBoundaries;
|
||||
if (boundaries == null) return;
|
||||
|
||||
double newScale;
|
||||
if (_doubleTap) {
|
||||
// quick scale, aka one finger zoom
|
||||
|
@ -131,7 +134,7 @@ class _MagnifierCoreState extends State<MagnifierCore> with TickerProviderStateM
|
|||
final scaleFocalPoint = _doubleTap ? _startFocalPoint! : details.focalPoint;
|
||||
|
||||
final panPositionDelta = scaleFocalPoint - _lastViewportFocalPosition!;
|
||||
final scalePositionDelta = scaleBoundaries.viewportToStatePosition(controller, scaleFocalPoint) * (scale! / newScale - 1);
|
||||
final scalePositionDelta = boundaries.viewportToStatePosition(controller, scaleFocalPoint) * (scale! / newScale - 1);
|
||||
final newPosition = position + panPositionDelta + scalePositionDelta;
|
||||
|
||||
updateScaleStateFromNewScale(newScale, ChangeSource.gesture);
|
||||
|
@ -145,10 +148,13 @@ class _MagnifierCoreState extends State<MagnifierCore> with TickerProviderStateM
|
|||
}
|
||||
|
||||
void onScaleEnd(ScaleEndDetails details) {
|
||||
final boundaries = scaleBoundaries;
|
||||
if (boundaries == null) return;
|
||||
|
||||
final _position = controller.position;
|
||||
final _scale = controller.scale!;
|
||||
final maxScale = scaleBoundaries.maxScale;
|
||||
final minScale = scaleBoundaries.minScale;
|
||||
final maxScale = boundaries.maxScale;
|
||||
final minScale = boundaries.minScale;
|
||||
|
||||
// animate back to min/max scale if gesture yielded a scale exceeding them
|
||||
if (_scale > maxScale || _scale < minScale) {
|
||||
|
@ -202,21 +208,30 @@ class _MagnifierCoreState extends State<MagnifierCore> with TickerProviderStateM
|
|||
final onTap = widget.onTap;
|
||||
if (onTap == null) return;
|
||||
|
||||
final boundaries = scaleBoundaries;
|
||||
if (boundaries == null) return;
|
||||
|
||||
final viewportTapPosition = details.localPosition;
|
||||
final viewportSize = boundaries.viewportSize;
|
||||
final alignment = Alignment(viewportTapPosition.dx / viewportSize.width, viewportTapPosition.dy / viewportSize.height);
|
||||
final childTapPosition = scaleBoundaries.viewportToChildPosition(controller, viewportTapPosition);
|
||||
final childTapPosition = boundaries.viewportToChildPosition(controller, viewportTapPosition);
|
||||
|
||||
onTap(context, controller.currentState, alignment, childTapPosition);
|
||||
}
|
||||
|
||||
void onDoubleTap(TapDownDetails details) {
|
||||
final boundaries = scaleBoundaries;
|
||||
if (boundaries == null) return;
|
||||
|
||||
final viewportTapPosition = details.localPosition;
|
||||
if (widget.onDoubleTap != null) {
|
||||
final viewportSize = scaleBoundaries.viewportSize;
|
||||
final onDoubleTap = widget.onDoubleTap;
|
||||
if (onDoubleTap != null) {
|
||||
final viewportSize = boundaries.viewportSize;
|
||||
final alignment = Alignment(viewportTapPosition.dx / viewportSize.width, viewportTapPosition.dy / viewportSize.height);
|
||||
if (widget.onDoubleTap?.call(alignment) == true) return;
|
||||
if (onDoubleTap.call(alignment) == true) return;
|
||||
}
|
||||
|
||||
final childTapPosition = scaleBoundaries.viewportToChildPosition(controller, viewportTapPosition);
|
||||
final childTapPosition = boundaries.viewportToChildPosition(controller, viewportTapPosition);
|
||||
nextScaleState(ChangeSource.gesture, childFocalPoint: childTapPosition);
|
||||
}
|
||||
|
||||
|
@ -245,7 +260,7 @@ class _MagnifierCoreState extends State<MagnifierCore> with TickerProviderStateM
|
|||
|
||||
/// Check if scale is equal to initial after scale animation update
|
||||
void onAnimationStatusCompleted() {
|
||||
if (controller.scaleState.state != ScaleState.initial && scale == scaleBoundaries.initialScale) {
|
||||
if (controller.scaleState.state != ScaleState.initial && scale == scaleBoundaries?.initialScale) {
|
||||
controller.setScaleState(ScaleState.initial, ChangeSource.animation);
|
||||
}
|
||||
}
|
||||
|
@ -264,42 +279,44 @@ class _MagnifierCoreState extends State<MagnifierCore> with TickerProviderStateM
|
|||
}
|
||||
|
||||
return StreamBuilder<MagnifierState>(
|
||||
stream: controller.stateStream,
|
||||
initialData: controller.previousState,
|
||||
builder: (context, snapshot) {
|
||||
if (!snapshot.hasData) return Container();
|
||||
stream: controller.stateStream,
|
||||
initialData: controller.previousState,
|
||||
builder: (context, snapshot) {
|
||||
final boundaries = scaleBoundaries;
|
||||
if (!snapshot.hasData || boundaries == null) return const SizedBox();
|
||||
|
||||
final magnifierState = snapshot.data!;
|
||||
final position = magnifierState.position;
|
||||
final applyScale = widget.applyScale;
|
||||
final magnifierState = snapshot.data!;
|
||||
final position = magnifierState.position;
|
||||
final applyScale = widget.applyScale;
|
||||
|
||||
Widget child = CustomSingleChildLayout(
|
||||
delegate: _CenterWithOriginalSizeDelegate(
|
||||
scaleBoundaries.childSize,
|
||||
basePosition,
|
||||
applyScale,
|
||||
),
|
||||
child: widget.child,
|
||||
);
|
||||
Widget child = CustomSingleChildLayout(
|
||||
delegate: _CenterWithOriginalSizeDelegate(
|
||||
boundaries.childSize,
|
||||
basePosition,
|
||||
applyScale,
|
||||
),
|
||||
child: widget.child,
|
||||
);
|
||||
|
||||
child = Transform(
|
||||
transform: Matrix4.identity()
|
||||
..translate(position.dx, position.dy)
|
||||
..scale(applyScale ? scale : 1.0),
|
||||
alignment: basePosition,
|
||||
child: child,
|
||||
);
|
||||
child = Transform(
|
||||
transform: Matrix4.identity()
|
||||
..translate(position.dx, position.dy)
|
||||
..scale(applyScale ? scale : 1.0),
|
||||
alignment: basePosition,
|
||||
child: child,
|
||||
);
|
||||
|
||||
return MagnifierGestureDetector(
|
||||
onDoubleTap: onDoubleTap,
|
||||
onScaleStart: onScaleStart,
|
||||
onScaleUpdate: onScaleUpdate,
|
||||
onScaleEnd: onScaleEnd,
|
||||
hitDetector: this,
|
||||
onTapUp: widget.onTap == null ? null : onTap,
|
||||
child: child,
|
||||
);
|
||||
});
|
||||
return MagnifierGestureDetector(
|
||||
onDoubleTap: onDoubleTap,
|
||||
onScaleStart: onScaleStart,
|
||||
onScaleUpdate: onScaleUpdate,
|
||||
onScaleEnd: onScaleEnd,
|
||||
hitDetector: this,
|
||||
onTapUp: widget.onTap == null ? null : onTap,
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,8 +9,11 @@ mixin CornerHitDetector on AvesMagnifierControllerDelegate {
|
|||
// so be sure to compare with `precisionErrorTolerance`
|
||||
|
||||
_CornerHit _hitCornersX() {
|
||||
final childWidth = scaleBoundaries.childSize.width * scale!;
|
||||
final viewportWidth = scaleBoundaries.viewportSize.width;
|
||||
final boundaries = scaleBoundaries;
|
||||
if (boundaries == null) return const _CornerHit(false, false);
|
||||
|
||||
final childWidth = boundaries.childSize.width * scale!;
|
||||
final viewportWidth = boundaries.viewportSize.width;
|
||||
if (viewportWidth + precisionErrorTolerance >= childWidth) {
|
||||
return const _CornerHit(true, true);
|
||||
}
|
||||
|
@ -20,8 +23,11 @@ mixin CornerHitDetector on AvesMagnifierControllerDelegate {
|
|||
}
|
||||
|
||||
_CornerHit _hitCornersY() {
|
||||
final childHeight = scaleBoundaries.childSize.height * scale!;
|
||||
final viewportHeight = scaleBoundaries.viewportSize.height;
|
||||
final boundaries = scaleBoundaries;
|
||||
if (boundaries == null) return const _CornerHit(false, false);
|
||||
|
||||
final childHeight = boundaries.childSize.height * scale!;
|
||||
final viewportHeight = boundaries.viewportSize.height;
|
||||
if (viewportHeight + precisionErrorTolerance >= childHeight) {
|
||||
return const _CornerHit(true, true);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue