diff --git a/lib/constants/values.dart b/lib/constants/values.dart index c7caaef..c20ca67 100644 --- a/lib/constants/values.dart +++ b/lib/constants/values.dart @@ -1,3 +1,7 @@ +import 'dart:collection'; + const DURATION_INFINITY = Duration(days: 999); const SECONDARY_BUTTONS_DURATION_MULTIPLIER = 1.8; const PHOTO_SHOW_AFTER_CREATION_DURATION = Duration(milliseconds: 500); +final UnmodifiableSetView DEFAULT_ZOOM_LEVELS = + UnmodifiableSetView({0.6, 1, 2, 5, 10, 20, 50, 100}); diff --git a/lib/screens/main_screen.dart b/lib/screens/main_screen.dart index 86b0d66..6bf0382 100644 --- a/lib/screens/main_screen.dart +++ b/lib/screens/main_screen.dart @@ -29,6 +29,9 @@ class MainScreen extends StatefulWidget { } class _MainScreenState extends AuthRequiredState with Loadable { + final List zoomLevels = [1.0]; + int currentZoomLevelIndex = 0; + bool isRecording = false; bool lockCamera = false; bool isTorchEnabled = false; @@ -39,6 +42,17 @@ class _MainScreenState extends AuthRequiredState with Loadable { CameraController? controller; + static String formatZoomLevel(double zoomLevel) { + if (zoomLevel.floor() == zoomLevel) { + // Zoom level is a whole number + return '${zoomLevel.floor()}x'; + } else { + return '${zoomLevel.toStringAsFixed(1)}x'; + } + } + + double get currentZoomLevel => zoomLevels[currentZoomLevelIndex]; + @override bool get isLoading => super.isLoading || controller == null || !controller!.value.isInitialized; @@ -113,12 +127,34 @@ class _MainScreenState extends AuthRequiredState with Loadable { if (mounted) setState(() {}); }); - controller!.initialize().then((_) { - if (!mounted) { - return; - } + await controller!.initialize(); - setState(() {}); + await determineZoomLevels(); + + if (!mounted) { + return; + } + + setState(() {}); + } + + Future determineZoomLevels() async { + final minZoomLevel = await controller!.getMinZoomLevel(); + final maxZoomLevel = await controller!.getMaxZoomLevel(); + + final availableZoomLevels = List.from( + DEFAULT_ZOOM_LEVELS + .where((zoomLevel) => + zoomLevel >= minZoomLevel && zoomLevel <= maxZoomLevel) + .toSet(), + ) + ..add(minZoomLevel) + ..add(maxZoomLevel) + ..toList() + ..sort(); + + setState(() { + zoomLevels.addAll(availableZoomLevels); }); } @@ -328,6 +364,7 @@ class _MainScreenState extends AuthRequiredState with Loadable { expandableContent: Padding( padding: const EdgeInsets.all(LARGE_SPACE), child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ ElevatedButton.icon( icon: const Icon(Icons.flashlight_on_rounded), @@ -352,6 +389,31 @@ class _MainScreenState extends AuthRequiredState with Loadable { }); }, ), + ElevatedButton( + style: ButtonStyle( + backgroundColor: MaterialStateProperty.resolveWith( + (_) => Colors.white10, + ), + foregroundColor: MaterialStateProperty.resolveWith( + (_) => Colors.white, + ), + ), + onPressed: () { + final newZoomLevelIndex = + ((currentZoomLevel + 1) % zoomLevels.length).toInt(); + print(newZoomLevelIndex); + print(zoomLevels); + + controller!.setZoomLevel(zoomLevels[newZoomLevelIndex]); + + setState(() { + currentZoomLevelIndex = newZoomLevelIndex; + }); + }, + child: Text( + formatZoomLevel(currentZoomLevel), + ), + ), ], ), ),