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