feat: zoom widget de imagem

This commit is contained in:
2026-09-25 14:41:13 -03:00
parent 9382a1f946
commit a31a88f87a
3 changed files with 179 additions and 76 deletions

View File

@@ -25,7 +25,7 @@ class ImageViewerView extends StatelessWidget {
foregroundColor: Colors.white,
);
return GestureDetector(
onTap: () => Navigator.of(context).pop(),
onTap: controller.closeAction,
child: Scaffold(
backgroundColor: Colors.black.withAlpha(128),
extendBodyBehindAppBar: true,
@@ -34,7 +34,7 @@ class ImageViewerView extends StatelessWidget {
leading: IconButton(
style: iconButtonStyle,
icon: const Icon(Icons.close),
onPressed: Navigator.of(context).pop,
onPressed: controller.closeAction,
color: Colors.white,
tooltip: L10n.of(context).close,
),
@@ -78,50 +78,60 @@ class ImageViewerView extends StatelessWidget {
KeyboardListener(
focusNode: controller.focusNode,
onKeyEvent: controller.onKeyEvent,
child: PageView.builder(
scrollDirection: Axis.vertical,
controller: controller.pageController,
itemCount: controller.allEvents.length,
itemBuilder: (context, i) {
final event = controller.allEvents[i];
switch (event.messageType) {
case MessageTypes.Video:
return Padding(
padding: const EdgeInsets.only(top: 52.0),
child: Center(
child: GestureDetector(
// Ignore taps to not go back here:
onTap: () {},
child: EventVideoPlayer(event),
),
),
);
case MessageTypes.Image:
case MessageTypes.Sticker:
default:
return InteractiveViewer(
minScale: 1.0,
maxScale: 10.0,
onInteractionEnd: controller.onInteractionEnds,
child: Center(
child: Hero(
tag: event.eventId,
child: Listener(
onPointerDown: (_) => controller.onPointerDown(),
onPointerUp: (_) => controller.onPointerUp(),
onPointerCancel: (_) => controller.onPointerUp(),
child: PageView.builder(
scrollDirection: Axis.vertical,
controller: controller.pageController,
physics: controller.canSwipeToNextImage
? const PageScrollPhysics()
: const NeverScrollableScrollPhysics(),
itemCount: controller.allEvents.length,
itemBuilder: (context, i) {
final event = controller.allEvents[i];
switch (event.messageType) {
case MessageTypes.Video:
return Padding(
padding: const EdgeInsets.only(top: 52.0),
child: Center(
child: GestureDetector(
// Ignore taps to not go back here:
onTap: () {},
child: MxcImage(
key: ValueKey(event.eventId),
event: event,
fit: BoxFit.contain,
isThumbnail: false,
animated: true,
child: EventVideoPlayer(event),
),
),
);
case MessageTypes.Image:
case MessageTypes.Sticker:
default:
return InteractiveViewer(
transformationController: controller
.transformationControllerFor(event),
minScale: 1.0,
maxScale: 10.0,
onInteractionEnd: controller.onInteractionEnds,
child: Center(
child: Hero(
tag: event.eventId,
child: GestureDetector(
// Ignore taps to not go back here:
onTap: () {},
child: MxcImage(
key: ValueKey(event.eventId),
event: event,
fit: BoxFit.contain,
isThumbnail: false,
animated: true,
),
),
),
),
),
);
}
},
);
}
},
),
),
),
if (hovered)