mirror of
https://github.com/Myzel394/quid_faciam_hodie.git
synced 2025-06-18 15:25:27 +02:00
added startup recording settings
This commit is contained in:
parent
684de568b3
commit
696d43d67f
@ -111,6 +111,7 @@
|
||||
"settingsScreenGeneralSectionTitle": "General",
|
||||
"settingsScreenGeneralSectionQualityLabel": "Qualität",
|
||||
"settingsScreenGeneralSectionAskForMemoryAnnotationsLabel": "Nach Anmerkungen für Erinnerungen fragen",
|
||||
"settingsScreenGeneralSectionStartRecordingOnStartupLabel": "Aufnahme automatisch beim Öffnen der App starten",
|
||||
"settingsScreenResetHelpSheetsLabel": "Hilf-Sheets zurücksetzen",
|
||||
"settingsScreenResetHelpSheetsResetSuccessfully": "Hilf-Sheets wurden zurückgesetzt.",
|
||||
|
||||
|
@ -161,6 +161,7 @@
|
||||
"settingsScreenGeneralSectionTitle": "General",
|
||||
"settingsScreenGeneralSectionQualityLabel": "Quality",
|
||||
"settingsScreenGeneralSectionAskForMemoryAnnotationsLabel": "Ask for memory annotations",
|
||||
"settingsScreenGeneralSectionStartRecordingOnStartupLabel": "Automatically start recording on startup",
|
||||
"settingsScreenResetHelpSheetsLabel": "Reset Help Sheets",
|
||||
"settingsScreenResetHelpSheetsResetSuccessfully": "Help Sheets reset successfully.",
|
||||
|
||||
|
@ -5,25 +5,31 @@ import 'package:collection/collection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:quid_faciam_hodie/constants/storage_keys.dart';
|
||||
import 'package:quid_faciam_hodie/utils/string_to_bool.dart';
|
||||
|
||||
const secure = FlutterSecureStorage();
|
||||
|
||||
class Settings extends ChangeNotifier {
|
||||
ResolutionPreset _resolution = ResolutionPreset.max;
|
||||
bool _askForMemoryAnnotations = false;
|
||||
bool _recordOnStartup = false;
|
||||
|
||||
Settings({
|
||||
final ResolutionPreset? resolution,
|
||||
final bool? askForMemoryAnnotations,
|
||||
}) : _resolution = resolution ?? ResolutionPreset.max,
|
||||
_askForMemoryAnnotations = askForMemoryAnnotations ?? true;
|
||||
Settings(
|
||||
{final ResolutionPreset? resolution,
|
||||
final bool? askForMemoryAnnotations,
|
||||
final bool? recordOnStartup})
|
||||
: _resolution = resolution ?? ResolutionPreset.max,
|
||||
_askForMemoryAnnotations = askForMemoryAnnotations ?? true,
|
||||
_recordOnStartup = recordOnStartup ?? false;
|
||||
|
||||
ResolutionPreset get resolution => _resolution;
|
||||
bool get askForMemoryAnnotations => _askForMemoryAnnotations;
|
||||
bool get recordOnStartup => _recordOnStartup;
|
||||
|
||||
Map<String, dynamic> toJSONData() => {
|
||||
'resolution': _resolution.toString(),
|
||||
'askForMemoryAnnotations': _askForMemoryAnnotations ? 'true' : 'false',
|
||||
'recordOnStartup': _recordOnStartup ? 'true' : 'false',
|
||||
};
|
||||
|
||||
Future<void> save() async {
|
||||
@ -46,20 +52,14 @@ class Settings extends ChangeNotifier {
|
||||
final resolution = ResolutionPreset.values.firstWhereOrNull(
|
||||
(preset) => preset.toString() == data['resolution'],
|
||||
);
|
||||
final askForMemoryAnnotations = () {
|
||||
switch (data['askForMemoryAnnotations']) {
|
||||
case 'true':
|
||||
return true;
|
||||
case 'false':
|
||||
return false;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}();
|
||||
final askForMemoryAnnotations =
|
||||
stringToBool(data['askForMemoryAnnotations']);
|
||||
final recordOnStartup = stringToBool(data['recordOnStartup']);
|
||||
|
||||
return Settings(
|
||||
resolution: resolution,
|
||||
askForMemoryAnnotations: askForMemoryAnnotations,
|
||||
recordOnStartup: recordOnStartup,
|
||||
);
|
||||
}
|
||||
|
||||
@ -74,4 +74,10 @@ class Settings extends ChangeNotifier {
|
||||
notifyListeners();
|
||||
save();
|
||||
}
|
||||
|
||||
void setRecordOnStartup(final bool recordOnStartup) {
|
||||
_recordOnStartup = recordOnStartup;
|
||||
notifyListeners();
|
||||
save();
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import 'package:quid_faciam_hodie/managers/global_values_manager.dart';
|
||||
import 'package:quid_faciam_hodie/models/memories.dart';
|
||||
import 'package:quid_faciam_hodie/screens/main_screen/annotation_dialog.dart';
|
||||
import 'package:quid_faciam_hodie/screens/main_screen/camera_help_content.dart';
|
||||
import 'package:quid_faciam_hodie/screens/main_screen/cancel_recording_button.dart';
|
||||
import 'package:quid_faciam_hodie/screens/main_screen/settings_button_overlay.dart';
|
||||
import 'package:quid_faciam_hodie/utils/auth_required.dart';
|
||||
import 'package:quid_faciam_hodie/utils/loadable.dart';
|
||||
@ -49,6 +50,7 @@ class MainScreen extends StatefulWidget {
|
||||
class _MainScreenState extends AuthRequiredState<MainScreen> with Loadable {
|
||||
int currentZoomLevelIndex = 0;
|
||||
|
||||
bool hasRecordedOnStartup = false;
|
||||
bool isRecording = false;
|
||||
bool lockCamera = false;
|
||||
bool isTorchEnabled = false;
|
||||
@ -148,6 +150,19 @@ class _MainScreenState extends AuthRequiredState<MainScreen> with Loadable {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> startRecording() async {
|
||||
setState(() {
|
||||
isRecording = true;
|
||||
});
|
||||
|
||||
if (controller!.value.isRecordingVideo) {
|
||||
// A recording has already started, do nothing.
|
||||
return;
|
||||
}
|
||||
|
||||
await controller!.startVideoRecording();
|
||||
}
|
||||
|
||||
void onNewCameraSelected(final CameraDescription cameraDescription) async {
|
||||
final settings = GlobalValuesManager.settings!;
|
||||
final previousCameraController = controller;
|
||||
@ -179,6 +194,12 @@ class _MainScreenState extends AuthRequiredState<MainScreen> with Loadable {
|
||||
await controller!.initialize();
|
||||
await controller!.prepareForVideoRecording();
|
||||
|
||||
if (settings.recordOnStartup && !hasRecordedOnStartup) {
|
||||
startRecording();
|
||||
|
||||
hasRecordedOnStartup = true;
|
||||
}
|
||||
|
||||
await determineZoomLevels();
|
||||
|
||||
if (!mounted) {
|
||||
@ -420,7 +441,7 @@ class _MainScreenState extends AuthRequiredState<MainScreen> with Loadable {
|
||||
controller!.buildPreview(),
|
||||
if (isRecording)
|
||||
RecordingOverlay(controller: controller!),
|
||||
if (!isRecording) SettingsButtonOverlay(),
|
||||
if (!isRecording) const SettingsButtonOverlay(),
|
||||
if (uploadingPhotoAnimation != null)
|
||||
UploadingPhoto(
|
||||
data: uploadingPhotoAnimation!,
|
||||
@ -465,22 +486,34 @@ class _MainScreenState extends AuthRequiredState<MainScreen> with Loadable {
|
||||
SECONDARY_BUTTONS_DURATION_MULTIPLIER,
|
||||
opacityDuration: DEFAULT_OPACITY_DURATION *
|
||||
SECONDARY_BUTTONS_DURATION_MULTIPLIER,
|
||||
child: ChangeCameraButton(
|
||||
disabled: lockCamera || isRecording,
|
||||
onChangeCamera: () {
|
||||
final currentCameraIndex =
|
||||
GlobalValuesManager.cameras
|
||||
.indexOf(controller!.description);
|
||||
final availableCameras =
|
||||
GlobalValuesManager.cameras.length;
|
||||
child: isRecording
|
||||
? CancelRecordingButton(
|
||||
onCancel: () {
|
||||
setState(() {
|
||||
isRecording = false;
|
||||
});
|
||||
|
||||
onNewCameraSelected(
|
||||
GlobalValuesManager.cameras[
|
||||
(currentCameraIndex + 1) %
|
||||
availableCameras],
|
||||
);
|
||||
},
|
||||
),
|
||||
controller!.stopVideoRecording();
|
||||
},
|
||||
)
|
||||
: ChangeCameraButton(
|
||||
disabled: lockCamera || isRecording,
|
||||
onChangeCamera: () {
|
||||
final currentCameraIndex =
|
||||
GlobalValuesManager.cameras
|
||||
.indexOf(
|
||||
controller!.description);
|
||||
final availableCameras =
|
||||
GlobalValuesManager
|
||||
.cameras.length;
|
||||
|
||||
onNewCameraSelected(
|
||||
GlobalValuesManager.cameras[
|
||||
(currentCameraIndex + 1) %
|
||||
availableCameras],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
@ -488,18 +521,7 @@ class _MainScreenState extends AuthRequiredState<MainScreen> with Loadable {
|
||||
child: RecordButton(
|
||||
disabled: lockCamera,
|
||||
active: isRecording,
|
||||
onVideoBegin: () async {
|
||||
setState(() {
|
||||
isRecording = true;
|
||||
});
|
||||
|
||||
if (controller!.value.isRecordingVideo) {
|
||||
// A recording has already started, do nothing.
|
||||
return;
|
||||
}
|
||||
|
||||
await controller!.startVideoRecording();
|
||||
},
|
||||
onVideoBegin: startRecording,
|
||||
onVideoEnd: takeVideo,
|
||||
onPhotoShot: takePhoto,
|
||||
),
|
||||
|
37
lib/screens/main_screen/cancel_recording_button.dart
Normal file
37
lib/screens/main_screen/cancel_recording_button.dart
Normal file
@ -0,0 +1,37 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
|
||||
|
||||
class CancelRecordingButton extends StatelessWidget {
|
||||
final VoidCallback onCancel;
|
||||
|
||||
const CancelRecordingButton({
|
||||
Key? key,
|
||||
required this.onCancel,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
HapticFeedback.heavyImpact();
|
||||
onCancel();
|
||||
},
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: <Widget>[
|
||||
Icon(
|
||||
Icons.circle,
|
||||
size: 60,
|
||||
color: Colors.white.withOpacity(.2),
|
||||
),
|
||||
Icon(
|
||||
context.platformIcons.clear,
|
||||
size: 25,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -26,15 +26,12 @@ const OUT_DURATION = Duration(milliseconds: 300);
|
||||
|
||||
class _RecordButtonState extends State<RecordButton> {
|
||||
bool animateToVideoIcon = false;
|
||||
bool videoInAnimationActive = false;
|
||||
|
||||
void cancelAnimation() {
|
||||
if (videoInAnimationActive) {
|
||||
if (widget.active) {
|
||||
return;
|
||||
}
|
||||
|
||||
setState(() {
|
||||
videoInAnimationActive = false;
|
||||
animateToVideoIcon = false;
|
||||
});
|
||||
}
|
||||
@ -49,7 +46,6 @@ class _RecordButtonState extends State<RecordButton> {
|
||||
}
|
||||
|
||||
setState(() {
|
||||
videoInAnimationActive = false;
|
||||
animateToVideoIcon = false;
|
||||
});
|
||||
|
||||
@ -69,7 +65,6 @@ class _RecordButtonState extends State<RecordButton> {
|
||||
|
||||
setState(() {
|
||||
animateToVideoIcon = false;
|
||||
videoInAnimationActive = true;
|
||||
});
|
||||
|
||||
HapticFeedback.heavyImpact();
|
||||
@ -87,7 +82,6 @@ class _RecordButtonState extends State<RecordButton> {
|
||||
}
|
||||
|
||||
setState(() {
|
||||
videoInAnimationActive = false;
|
||||
animateToVideoIcon = false;
|
||||
});
|
||||
|
||||
@ -117,19 +111,18 @@ class _RecordButtonState extends State<RecordButton> {
|
||||
alignment: Alignment.center,
|
||||
children: <Widget>[
|
||||
AnimatedContainer(
|
||||
duration: videoInAnimationActive ? Duration.zero : OUT_DURATION,
|
||||
duration: widget.active ? Duration.zero : OUT_DURATION,
|
||||
width: 60,
|
||||
height: 60,
|
||||
decoration: BoxDecoration(
|
||||
color: videoInAnimationActive
|
||||
? Colors.white
|
||||
: Colors.white.withOpacity(.2),
|
||||
color:
|
||||
widget.active ? Colors.white : Colors.white.withOpacity(.2),
|
||||
borderRadius: BorderRadius.circular(30),
|
||||
),
|
||||
),
|
||||
AnimatedScale(
|
||||
duration: () {
|
||||
if (videoInAnimationActive) {
|
||||
if (widget.active) {
|
||||
return Duration(milliseconds: 400);
|
||||
}
|
||||
|
||||
@ -141,7 +134,7 @@ class _RecordButtonState extends State<RecordButton> {
|
||||
}(),
|
||||
curve: Curves.easeInOut,
|
||||
scale: () {
|
||||
if (videoInAnimationActive) {
|
||||
if (widget.active) {
|
||||
return .6;
|
||||
}
|
||||
|
||||
@ -153,7 +146,7 @@ class _RecordButtonState extends State<RecordButton> {
|
||||
}(),
|
||||
child: AnimatedContainer(
|
||||
duration: () {
|
||||
if (videoInAnimationActive) {
|
||||
if (widget.active) {
|
||||
return Duration(milliseconds: 400);
|
||||
}
|
||||
|
||||
@ -166,8 +159,8 @@ class _RecordButtonState extends State<RecordButton> {
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: videoInAnimationActive ? Colors.red : Colors.white,
|
||||
borderRadius: videoInAnimationActive
|
||||
color: widget.active ? Colors.red : Colors.white,
|
||||
borderRadius: widget.active
|
||||
? BorderRadius.circular(8)
|
||||
: BorderRadius.circular(50),
|
||||
),
|
||||
|
@ -218,6 +218,12 @@ class _SettingsScreenState extends AuthRequiredState<SettingsScreen>
|
||||
.settingsScreenGeneralSectionAskForMemoryAnnotationsLabel,
|
||||
),
|
||||
),
|
||||
SettingsTile.switchTile(
|
||||
initialValue: settings.recordOnStartup,
|
||||
onToggle: settings.setRecordOnStartup,
|
||||
title: Text(localizations
|
||||
.settingsScreenGeneralSectionStartRecordingOnStartupLabel),
|
||||
),
|
||||
SettingsTile(
|
||||
leading: Icon(context.platformIcons.help),
|
||||
title: Text(
|
||||
|
10
lib/utils/string_to_bool.dart
Normal file
10
lib/utils/string_to_bool.dart
Normal file
@ -0,0 +1,10 @@
|
||||
bool? stringToBool(final String value) {
|
||||
switch (value) {
|
||||
case 'true':
|
||||
return true;
|
||||
case 'false':
|
||||
return false;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user