From 9f45a461a2e46d9864e30ea7f76ec8beca1a243c Mon Sep 17 00:00:00 2001 From: otsmr Date: Fri, 18 Jul 2025 23:03:33 +0200 Subject: [PATCH] fix #246 --- .../zoom_selector.dart | 74 +++++++++++++------ .../camera_preview_controller_view.dart | 3 +- lib/src/views/camera/share_image_view.dart | 1 + .../response_container.dart | 2 +- 4 files changed, 54 insertions(+), 26 deletions(-) diff --git a/lib/src/views/camera/camera_preview_components/zoom_selector.dart b/lib/src/views/camera/camera_preview_components/zoom_selector.dart index c4c7e19..1f9d526 100644 --- a/lib/src/views/camera/camera_preview_components/zoom_selector.dart +++ b/lib/src/views/camera/camera_preview_components/zoom_selector.dart @@ -1,21 +1,28 @@ // ignore_for_file: avoid_dynamic_calls +import 'dart:io'; import 'dart:math'; import 'package:camera/camera.dart'; import 'package:flutter/material.dart'; +import 'package:twonly/globals.dart'; +import 'package:twonly/src/views/camera/camera_preview_controller_view.dart'; class CameraZoomButtons extends StatefulWidget { const CameraZoomButtons({ required this.controller, required this.updateScaleFactor, required this.scaleFactor, + required this.selectedCameraDetails, + required this.selectCamera, super.key, }); final CameraController controller; final double scaleFactor; final Function updateScaleFactor; + final SelectedCameraDetails selectedCameraDetails; + final void Function(int sCameraId, bool init, bool enableAudio) selectCamera; @override State createState() => _CameraZoomButtonsState(); @@ -31,6 +38,7 @@ String beautifulZoomScale(double scale) { class _CameraZoomButtonsState extends State { bool showWideAngleZoom = false; + bool showWideAngleZoomIOS = false; bool _isDisposed = false; @override @@ -41,6 +49,9 @@ class _CameraZoomButtonsState extends State { Future initAsync() async { showWideAngleZoom = (await widget.controller.getMinZoomLevel()) < 1; + if (!showWideAngleZoom && Platform.isIOS && gCameras.length == 3) { + showWideAngleZoomIOS = true; + } if (_isDisposed) return; setState(() {}); } @@ -62,7 +73,11 @@ class _CameraZoomButtonsState extends State { ); const zoomTextStyle = TextStyle(fontSize: 13); - final isMiddleFocused = widget.scaleFactor >= 1 && widget.scaleFactor < 2; + final isSmallerFocused = widget.scaleFactor < 1 || + (showWideAngleZoomIOS && widget.selectedCameraDetails.cameraId == 2); + final isMiddleFocused = widget.scaleFactor >= 1 && + widget.scaleFactor < 2 && + !(showWideAngleZoomIOS && widget.selectedCameraDetails.cameraId == 2); return Center( child: ClipRRect( borderRadius: BorderRadius.circular(40), @@ -71,35 +86,41 @@ class _CameraZoomButtonsState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - if (showWideAngleZoom) + if (showWideAngleZoom || showWideAngleZoomIOS) TextButton( style: zoomButtonStyle.copyWith( foregroundColor: WidgetStateProperty.all( - (widget.scaleFactor < 1) ? Colors.yellow : Colors.white, + isSmallerFocused ? Colors.yellow : Colors.white, ), ), onPressed: () async { - final level = await widget.controller.getMinZoomLevel(); - widget.updateScaleFactor(level); + if (showWideAngleZoomIOS) { + widget.selectCamera(2, true, false); + } else { + final level = await widget.controller.getMinZoomLevel(); + widget.updateScaleFactor(level); + } }, - child: FutureBuilder( - future: widget.controller.getMinZoomLevel(), - builder: (context, snap) { - if (snap.hasData) { - final minLevel = beautifulZoomScale(snap.data!); - final currentLevel = - beautifulZoomScale(widget.scaleFactor); - return Text( - widget.scaleFactor < 1 - ? '${currentLevel}x' - : '${minLevel}x', - style: zoomTextStyle, - ); - } else { - return const Text(''); - } - }, - ), + child: showWideAngleZoomIOS + ? const Text('0.5') + : FutureBuilder( + future: widget.controller.getMinZoomLevel(), + builder: (context, snap) { + if (snap.hasData) { + final minLevel = beautifulZoomScale(snap.data!); + final currentLevel = + beautifulZoomScale(widget.scaleFactor); + return Text( + widget.scaleFactor < 1 + ? '${currentLevel}x' + : '${minLevel}x', + style: zoomTextStyle, + ); + } else { + return const Text(''); + } + }, + ), ), TextButton( style: zoomButtonStyle.copyWith( @@ -108,7 +129,12 @@ class _CameraZoomButtonsState extends State { ), ), onPressed: () { - widget.updateScaleFactor(1.0); + if (showWideAngleZoomIOS && + widget.selectedCameraDetails.cameraId == 2) { + widget.selectCamera(0, true, false); + } else { + widget.updateScaleFactor(1.0); + } }, child: Text( isMiddleFocused diff --git a/lib/src/views/camera/camera_preview_controller_view.dart b/lib/src/views/camera/camera_preview_controller_view.dart index 125a619..44705e6 100644 --- a/lib/src/views/camera/camera_preview_controller_view.dart +++ b/lib/src/views/camera/camera_preview_controller_view.dart @@ -164,7 +164,6 @@ class _CameraPreviewViewState extends State { @override void initState() { super.initState(); - // selectCamera(0, init: true); initAsync(); } @@ -614,6 +613,8 @@ class _CameraPreviewViewState extends State { scaleFactor: widget.selectedCameraDetails.scaleFactor, updateScaleFactor: updateScaleFactor, + selectCamera: widget.selectCamera, + selectedCameraDetails: widget.selectedCameraDetails, controller: widget.cameraController!, ), ), diff --git a/lib/src/views/camera/share_image_view.dart b/lib/src/views/camera/share_image_view.dart index 35a2d0b..018dbb9 100644 --- a/lib/src/views/camera/share_image_view.dart +++ b/lib/src/views/camera/share_image_view.dart @@ -83,6 +83,7 @@ class _ShareImageView extends State { await encryptMediaFiles( widget.mediaUploadId, imageHandler, widget.videoUploadHandler); } + if (!mounted) return; setState(() {}); } diff --git a/lib/src/views/chats/chat_messages_components/response_container.dart b/lib/src/views/chats/chat_messages_components/response_container.dart index c05463a..322fde3 100644 --- a/lib/src/views/chats/chat_messages_components/response_container.dart +++ b/lib/src/views/chats/chat_messages_components/response_container.dart @@ -132,7 +132,7 @@ class _ResponsePreviewState extends State { Future initAsync() async { final items = await MemoryItem.convertFromMessages([widget.message]); - if (items.length == 1) { + if (items.length == 1 && mounted) { setState(() { thumbnailPath = items.values.first.thumbnailPath; });