This commit is contained in:
otsmr 2025-07-18 23:03:33 +02:00
parent 6d1643848f
commit 9f45a461a2
4 changed files with 54 additions and 26 deletions

View file

@ -1,21 +1,28 @@
// ignore_for_file: avoid_dynamic_calls // ignore_for_file: avoid_dynamic_calls
import 'dart:io';
import 'dart:math'; import 'dart:math';
import 'package:camera/camera.dart'; import 'package:camera/camera.dart';
import 'package:flutter/material.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 { class CameraZoomButtons extends StatefulWidget {
const CameraZoomButtons({ const CameraZoomButtons({
required this.controller, required this.controller,
required this.updateScaleFactor, required this.updateScaleFactor,
required this.scaleFactor, required this.scaleFactor,
required this.selectedCameraDetails,
required this.selectCamera,
super.key, super.key,
}); });
final CameraController controller; final CameraController controller;
final double scaleFactor; final double scaleFactor;
final Function updateScaleFactor; final Function updateScaleFactor;
final SelectedCameraDetails selectedCameraDetails;
final void Function(int sCameraId, bool init, bool enableAudio) selectCamera;
@override @override
State<CameraZoomButtons> createState() => _CameraZoomButtonsState(); State<CameraZoomButtons> createState() => _CameraZoomButtonsState();
@ -31,6 +38,7 @@ String beautifulZoomScale(double scale) {
class _CameraZoomButtonsState extends State<CameraZoomButtons> { class _CameraZoomButtonsState extends State<CameraZoomButtons> {
bool showWideAngleZoom = false; bool showWideAngleZoom = false;
bool showWideAngleZoomIOS = false;
bool _isDisposed = false; bool _isDisposed = false;
@override @override
@ -41,6 +49,9 @@ class _CameraZoomButtonsState extends State<CameraZoomButtons> {
Future<void> initAsync() async { Future<void> initAsync() async {
showWideAngleZoom = (await widget.controller.getMinZoomLevel()) < 1; showWideAngleZoom = (await widget.controller.getMinZoomLevel()) < 1;
if (!showWideAngleZoom && Platform.isIOS && gCameras.length == 3) {
showWideAngleZoomIOS = true;
}
if (_isDisposed) return; if (_isDisposed) return;
setState(() {}); setState(() {});
} }
@ -62,7 +73,11 @@ class _CameraZoomButtonsState extends State<CameraZoomButtons> {
); );
const zoomTextStyle = TextStyle(fontSize: 13); 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( return Center(
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.circular(40), borderRadius: BorderRadius.circular(40),
@ -71,35 +86,41 @@ class _CameraZoomButtonsState extends State<CameraZoomButtons> {
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
if (showWideAngleZoom) if (showWideAngleZoom || showWideAngleZoomIOS)
TextButton( TextButton(
style: zoomButtonStyle.copyWith( style: zoomButtonStyle.copyWith(
foregroundColor: WidgetStateProperty.all( foregroundColor: WidgetStateProperty.all(
(widget.scaleFactor < 1) ? Colors.yellow : Colors.white, isSmallerFocused ? Colors.yellow : Colors.white,
), ),
), ),
onPressed: () async { onPressed: () async {
final level = await widget.controller.getMinZoomLevel(); if (showWideAngleZoomIOS) {
widget.updateScaleFactor(level); widget.selectCamera(2, true, false);
} else {
final level = await widget.controller.getMinZoomLevel();
widget.updateScaleFactor(level);
}
}, },
child: FutureBuilder( child: showWideAngleZoomIOS
future: widget.controller.getMinZoomLevel(), ? const Text('0.5')
builder: (context, snap) { : FutureBuilder(
if (snap.hasData) { future: widget.controller.getMinZoomLevel(),
final minLevel = beautifulZoomScale(snap.data!); builder: (context, snap) {
final currentLevel = if (snap.hasData) {
beautifulZoomScale(widget.scaleFactor); final minLevel = beautifulZoomScale(snap.data!);
return Text( final currentLevel =
widget.scaleFactor < 1 beautifulZoomScale(widget.scaleFactor);
? '${currentLevel}x' return Text(
: '${minLevel}x', widget.scaleFactor < 1
style: zoomTextStyle, ? '${currentLevel}x'
); : '${minLevel}x',
} else { style: zoomTextStyle,
return const Text(''); );
} } else {
}, return const Text('');
), }
},
),
), ),
TextButton( TextButton(
style: zoomButtonStyle.copyWith( style: zoomButtonStyle.copyWith(
@ -108,7 +129,12 @@ class _CameraZoomButtonsState extends State<CameraZoomButtons> {
), ),
), ),
onPressed: () { onPressed: () {
widget.updateScaleFactor(1.0); if (showWideAngleZoomIOS &&
widget.selectedCameraDetails.cameraId == 2) {
widget.selectCamera(0, true, false);
} else {
widget.updateScaleFactor(1.0);
}
}, },
child: Text( child: Text(
isMiddleFocused isMiddleFocused

View file

@ -164,7 +164,6 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
// selectCamera(0, init: true);
initAsync(); initAsync();
} }
@ -614,6 +613,8 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
scaleFactor: scaleFactor:
widget.selectedCameraDetails.scaleFactor, widget.selectedCameraDetails.scaleFactor,
updateScaleFactor: updateScaleFactor, updateScaleFactor: updateScaleFactor,
selectCamera: widget.selectCamera,
selectedCameraDetails: widget.selectedCameraDetails,
controller: widget.cameraController!, controller: widget.cameraController!,
), ),
), ),

View file

@ -83,6 +83,7 @@ class _ShareImageView extends State<ShareImageView> {
await encryptMediaFiles( await encryptMediaFiles(
widget.mediaUploadId, imageHandler, widget.videoUploadHandler); widget.mediaUploadId, imageHandler, widget.videoUploadHandler);
} }
if (!mounted) return;
setState(() {}); setState(() {});
} }

View file

@ -132,7 +132,7 @@ class _ResponsePreviewState extends State<ResponsePreview> {
Future<void> initAsync() async { Future<void> initAsync() async {
final items = await MemoryItem.convertFromMessages([widget.message]); final items = await MemoryItem.convertFromMessages([widget.message]);
if (items.length == 1) { if (items.length == 1 && mounted) {
setState(() { setState(() {
thumbnailPath = items.values.first.thumbnailPath; thumbnailPath = items.values.first.thumbnailPath;
}); });