diff --git a/CHANGELOG.md b/CHANGELOG.md index 180a2e99..85dca3ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Improved: The blue verification checkmark now displays the total number of verifications. - Fix: Issue with receiving messages when user closed app while decrypting - Fix: Background message fetching reliability. +- Fix: Issue with focus changing when taking a picture ## 0.2.16 diff --git a/lib/src/visual/views/camera/camera_preview_components/main_camera_controller.dart b/lib/src/visual/views/camera/camera_preview_components/main_camera_controller.dart index df665c84..f713585e 100644 --- a/lib/src/visual/views/camera/camera_preview_components/main_camera_controller.dart +++ b/lib/src/visual/views/camera/camera_preview_components/main_camera_controller.dart @@ -85,22 +85,31 @@ class MainCameraController { FaceFilterType _currentFilterType = FaceFilterType.none; FaceFilterType get currentFilterType => _currentFilterType; + Future? _initializeFuture; Future? _pendingDisposal; Future closeCamera() async { contactsVerified = {}; scannedNewProfiles = {}; scannedUrl = null; - try { - await cameraController?.stopImageStream(); - // ignore: empty_catches - } catch (e) {} final cameraControllerTemp = cameraController; cameraController = null; + final initFutureTemp = _initializeFuture; + _initializeFuture = null; // prevents: CameraException(Disposed CameraController, buildPreview() was called on a disposed CameraController.) _pendingDisposal = Future.delayed( const Duration(milliseconds: 100), () async { + try { + if (initFutureTemp != null) { + await initFutureTemp; + } + // ignore: empty_catches + } catch (e) {} + try { + await cameraControllerTemp?.stopImageStream(); + // ignore: empty_catches + } catch (e) {} await cameraControllerTemp?.dispose(); }, ); @@ -126,8 +135,7 @@ class MainCameraController { if (init) { for (; cameraId < AppEnvironment.cameras.length; cameraId++) { - if (AppEnvironment.cameras[cameraId].lensDirection == - CameraLensDirection.back) { + if (AppEnvironment.cameras[cameraId].lensDirection == CameraLensDirection.back) { break; } } @@ -140,12 +148,11 @@ class MainCameraController { AppEnvironment.cameras[cameraId], ResolutionPreset.high, enableAudio: await Permission.microphone.isGranted, - imageFormatGroup: Platform.isAndroid - ? ImageFormatGroup.nv21 - : ImageFormatGroup.bgra8888, + imageFormatGroup: Platform.isAndroid ? ImageFormatGroup.nv21 : ImageFormatGroup.bgra8888, ); try { - await cameraController?.initialize(); + _initializeFuture = cameraController?.initialize(); + await _initializeFuture; await cameraController?.startImageStream(_processCameraImage); await cameraController?.setZoomLevel(selectedCameraDetails.scaleFactor); if (userService.currentUser.videoStabilizationEnabled && !kDebugMode) { @@ -185,14 +192,10 @@ class MainCameraController { await cameraController?.setFlashMode( selectedCameraDetails.isFlashOn ? FlashMode.always : FlashMode.off, ); - selectedCameraDetails.maxAvailableZoom = - await cameraController?.getMaxZoomLevel() ?? 1; - selectedCameraDetails.minAvailableZoom = - await cameraController?.getMinZoomLevel() ?? 1; + selectedCameraDetails.maxAvailableZoom = await cameraController?.getMaxZoomLevel() ?? 1; + selectedCameraDetails.minAvailableZoom = await cameraController?.getMinZoomLevel() ?? 1; selectedCameraDetails - ..isZoomAble = - selectedCameraDetails.maxAvailableZoom != - selectedCameraDetails.minAvailableZoom + ..isZoomAble = selectedCameraDetails.maxAvailableZoom != selectedCameraDetails.minAvailableZoom ..cameraLoaded = true ..cameraId = cameraId; @@ -214,8 +217,7 @@ class MainCameraController { } Future onTapDown(TapDownDetails details) async { - final box = - cameraPreviewKey.currentContext?.findRenderObject() as RenderBox?; + final box = cameraPreviewKey.currentContext?.findRenderObject() as RenderBox?; if (box == null) return; final localPosition = box.globalToLocal(details.globalPosition); @@ -231,8 +233,7 @@ class MainCameraController { await cameraController?.setFocusPoint(Offset(dx, dy)); await cameraController?.setFocusMode(FocusMode.auto); } catch (e) { - if (e is CameraException && - (e.code == 'setFocusPointFailed' || e.code == 'setFocusModeFailed')) { + if (e is CameraException && (e.code == 'setFocusPointFailed' || e.code == 'setFocusModeFailed')) { Log.info('Focus point or mode not supported on this device'); } else { Log.warn(e); @@ -273,8 +274,7 @@ class MainCameraController { if (inputImage == null) return; _processBarcode(inputImage); // check if front camera is selected - if (cameraController?.description.lensDirection == - CameraLensDirection.front) { + if (cameraController?.description.lensDirection == CameraLensDirection.front) { if (_currentFilterType != FaceFilterType.none) { _processFaces(inputImage); } @@ -293,16 +293,14 @@ class MainCameraController { if (Platform.isIOS) { rotation = InputImageRotationValue.fromRawValue(sensorOrientation); } else if (Platform.isAndroid) { - var rotationCompensation = - _orientations[cameraController!.value.deviceOrientation]; + var rotationCompensation = _orientations[cameraController!.value.deviceOrientation]; if (rotationCompensation == null) return null; if (camera.lensDirection == CameraLensDirection.front) { // front-facing rotationCompensation = (sensorOrientation + rotationCompensation) % 360; } else { // back-facing - rotationCompensation = - (sensorOrientation - rotationCompensation + 360) % 360; + rotationCompensation = (sensorOrientation - rotationCompensation + 360) % 360; } rotation = InputImageRotationValue.fromRawValue(rotationCompensation); } @@ -344,9 +342,7 @@ class MainCameraController { if (_isBusy) return; _isBusy = true; final barcodes = await _barcodeScanner.processImage(inputImage); - if (inputImage.metadata?.size != null && - inputImage.metadata?.rotation != null && - cameraController != null) { + if (inputImage.metadata?.size != null && inputImage.metadata?.rotation != null && cameraController != null) { final painter = BarcodeDetectorPainter( barcodes, inputImage.metadata!.size, @@ -430,9 +426,7 @@ class MainCameraController { if (_isBusyFaces) return; _isBusyFaces = true; final faces = await _faceDetector.processImage(inputImage); - if (inputImage.metadata?.size != null && - inputImage.metadata?.rotation != null && - cameraController != null) { + if (inputImage.metadata?.size != null && inputImage.metadata?.rotation != null && cameraController != null) { if (faces.isNotEmpty) { CustomPainter? painter; switch (_currentFilterType) { diff --git a/lib/src/visual/views/camera/camera_qr_scanner.view.dart b/lib/src/visual/views/camera/camera_qr_scanner.view.dart index 1ef5d9e6..d7d01b98 100644 --- a/lib/src/visual/views/camera/camera_qr_scanner.view.dart +++ b/lib/src/visual/views/camera/camera_qr_scanner.view.dart @@ -31,21 +31,24 @@ class QrCodeScannerViewState extends State { @override Widget build(BuildContext context) { return Scaffold( - body: GestureDetector( - onDoubleTap: _mainCameraController.onDoubleTap, - onTapDown: _mainCameraController.onTapDown, - child: Stack( - children: [ - MainCameraPreview( - mainCameraController: _mainCameraController, + body: Stack( + children: [ + MainCameraPreview( + mainCameraController: _mainCameraController, + ), + Positioned.fill( + child: GestureDetector( + behavior: HitTestBehavior.translucent, + onDoubleTap: _mainCameraController.onDoubleTap, + onTapDown: _mainCameraController.onTapDown, ), - CameraPreviewControllerView( - mainController: _mainCameraController, - hideControllers: true, - isVisible: true, - ), - ], - ), + ), + CameraPreviewControllerView( + mainController: _mainCameraController, + hideControllers: true, + isVisible: true, + ), + ], ), ); } diff --git a/lib/src/visual/views/camera/camera_send_to.view.dart b/lib/src/visual/views/camera/camera_send_to.view.dart index 0f53fe8b..e1370f74 100644 --- a/lib/src/visual/views/camera/camera_send_to.view.dart +++ b/lib/src/visual/views/camera/camera_send_to.view.dart @@ -33,21 +33,24 @@ class CameraSendToViewState extends State { @override Widget build(BuildContext context) { return Scaffold( - body: GestureDetector( - onDoubleTap: _mainCameraController.onDoubleTap, - onTapDown: _mainCameraController.onTapDown, - child: Stack( - children: [ - MainCameraPreview( - mainCameraController: _mainCameraController, + body: Stack( + children: [ + MainCameraPreview( + mainCameraController: _mainCameraController, + ), + Positioned.fill( + child: GestureDetector( + behavior: HitTestBehavior.translucent, + onDoubleTap: _mainCameraController.onDoubleTap, + onTapDown: _mainCameraController.onTapDown, ), - CameraPreviewControllerView( - mainController: _mainCameraController, - sendToGroup: widget.sendToGroup, - isVisible: true, - ), - ], - ), + ), + CameraPreviewControllerView( + mainController: _mainCameraController, + sendToGroup: widget.sendToGroup, + isVisible: true, + ), + ], ), ); } diff --git a/lib/src/visual/views/home.view.dart b/lib/src/visual/views/home.view.dart index 7125e9ba..67a02382 100644 --- a/lib/src/visual/views/home.view.dart +++ b/lib/src/visual/views/home.view.dart @@ -237,53 +237,57 @@ class HomeViewState extends State { @override Widget build(BuildContext context) { return Scaffold( - body: GestureDetector( - onDoubleTap: _offsetRatio == 0 ? _mainCameraController.onDoubleTap : null, - onTapDown: _offsetRatio == 0 ? _mainCameraController.onTapDown : null, - child: Stack( - children: [ - MainCameraPreview(mainCameraController: _mainCameraController), + body: Stack( + children: [ + MainCameraPreview(mainCameraController: _mainCameraController), + Positioned.fill( + child: Opacity( + opacity: _offsetRatio, + child: Container( + color: context.color.surface, + ), + ), + ), + NotificationListener( + onNotification: _onPageView, + child: Positioned.fill( + child: PageView( + controller: _homeViewPageController, + onPageChanged: (index) { + setState(() { + _activePageIdx = index; + }); + }, + children: [ + const ChatListView(), + Container(), + const MemoriesView(), + ], + ), + ), + ), + if (_offsetRatio == 0) Positioned.fill( - child: Opacity( - opacity: _offsetRatio, - child: Container( - color: context.color.surface, - ), + child: GestureDetector( + behavior: HitTestBehavior.translucent, + onDoubleTap: _mainCameraController.onDoubleTap, + onTapDown: _mainCameraController.onTapDown, ), ), - NotificationListener( - onNotification: _onPageView, - child: Positioned.fill( - child: PageView( - controller: _homeViewPageController, - onPageChanged: (index) { - setState(() { - _activePageIdx = index; - }); - }, - children: [ - const ChatListView(), - Container(), - const MemoriesView(), - ], - ), + Positioned( + left: 0, + top: 0, + right: 0, + bottom: (_offsetRatio > 0.25) ? MediaQuery.sizeOf(context).height * 2 : 0, + child: Opacity( + opacity: 1 - (_offsetRatio * 4) % 1, + child: CameraPreviewControllerView( + mainController: _mainCameraController, + isVisible: ((1 - (_offsetRatio * 4) % 1) == 1) && _activePageIdx == 1, ), ), - Positioned( - left: 0, - top: 0, - right: 0, - bottom: (_offsetRatio > 0.25) ? MediaQuery.sizeOf(context).height * 2 : 0, - child: Opacity( - opacity: 1 - (_offsetRatio * 4) % 1, - child: CameraPreviewControllerView( - mainController: _mainCameraController, - isVisible: ((1 - (_offsetRatio * 4) % 1) == 1) && _activePageIdx == 1, - ), - ), - ), - ], - ), + ), + ], ), bottomNavigationBar: AnimatedSize( duration: const Duration(milliseconds: 250), diff --git a/lib/src/visual/views/public_profile.view.dart b/lib/src/visual/views/public_profile.view.dart index 5d88abd2..cda31a15 100644 --- a/lib/src/visual/views/public_profile.view.dart +++ b/lib/src/visual/views/public_profile.view.dart @@ -44,7 +44,7 @@ class _PublicProfileViewState extends State { SizedBox(width: 15), ], ), - body: Column( + body: ListView( children: [ Container(width: double.infinity), const SizedBox(height: 10), @@ -75,6 +75,7 @@ class _PublicProfileViewState extends State { Text( userService.currentUser.username, style: const TextStyle(fontSize: 24), + textAlign: TextAlign.center, ), const SizedBox(height: 20), const Divider(),