mirror of
https://github.com/Myzel394/quid_faciam_hodie.git
synced 2025-06-18 23:35:25 +02:00
added record button behavior to settings
This commit is contained in:
parent
b8ad3b8d43
commit
ecfe71cfa9
15
lib/enum_mapping/record_button_behavior/texts.dart
Normal file
15
lib/enum_mapping/record_button_behavior/texts.dart
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
import 'package:quid_faciam_hodie/enums/record_button_behavior.dart';
|
||||||
|
|
||||||
|
Map<RecordButtonBehavior, String> getRecordButtonBehaviorTextMapping(
|
||||||
|
final BuildContext context) {
|
||||||
|
final localizations = AppLocalizations.of(context)!;
|
||||||
|
|
||||||
|
return {
|
||||||
|
RecordButtonBehavior.holdRecording:
|
||||||
|
localizations.enumMapping_RecordButtonBehavior_holdRecording,
|
||||||
|
RecordButtonBehavior.switchRecording:
|
||||||
|
localizations.enumMapping_RecordButtonBehavior_switchRecording,
|
||||||
|
};
|
||||||
|
}
|
4
lib/enums/record_button_behavior.dart
Normal file
4
lib/enums/record_button_behavior.dart
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
enum RecordButtonBehavior {
|
||||||
|
holdRecording,
|
||||||
|
switchRecording,
|
||||||
|
}
|
@ -159,6 +159,7 @@
|
|||||||
"settingsScreenDeleteAccountConfirmLabel": "Delete Account now",
|
"settingsScreenDeleteAccountConfirmLabel": "Delete Account now",
|
||||||
"settingsScreenGeneralSectionTitle": "General",
|
"settingsScreenGeneralSectionTitle": "General",
|
||||||
"settingsScreenGeneralSectionQualityLabel": "Quality",
|
"settingsScreenGeneralSectionQualityLabel": "Quality",
|
||||||
|
"settingsScreenGeneralSectionRecordButtonBehaviorLabel": "Record Behavior",
|
||||||
"settingsScreenGeneralSectionAskForMemoryAnnotationsLabel": "Ask for memory annotations",
|
"settingsScreenGeneralSectionAskForMemoryAnnotationsLabel": "Ask for memory annotations",
|
||||||
"settingsScreenGeneralSectionStartRecordingOnStartupLabel": "Automatically start recording on startup",
|
"settingsScreenGeneralSectionStartRecordingOnStartupLabel": "Automatically start recording on startup",
|
||||||
"settingsScreenResetHelpSheetsLabel": "Reset Help Sheets",
|
"settingsScreenResetHelpSheetsLabel": "Reset Help Sheets",
|
||||||
@ -194,5 +195,8 @@
|
|||||||
"enumMapping_ResolutionPreset_high": "High",
|
"enumMapping_ResolutionPreset_high": "High",
|
||||||
"enumMapping_ResolutionPreset_veryHigh": "Very High",
|
"enumMapping_ResolutionPreset_veryHigh": "Very High",
|
||||||
"enumMapping_ResolutionPreset_ultraHigh": "Ultra High",
|
"enumMapping_ResolutionPreset_ultraHigh": "Ultra High",
|
||||||
"enumMapping_ResolutionPreset_max": "Max"
|
"enumMapping_ResolutionPreset_max": "Max",
|
||||||
|
|
||||||
|
"enumMapping_RecordButtonBehavior_holdRecording": "Hold to record",
|
||||||
|
"enumMapping_RecordButtonBehavior_switchRecording": "Tap to start recording, tap again to stop "
|
||||||
}
|
}
|
@ -5,29 +5,37 @@ 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/enums/record_button_behavior.dart';
|
||||||
import 'package:quid_faciam_hodie/utils/string_to_bool.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;
|
||||||
|
RecordButtonBehavior _recordButtonBehavior =
|
||||||
|
RecordButtonBehavior.holdRecording;
|
||||||
bool _askForMemoryAnnotations = false;
|
bool _askForMemoryAnnotations = false;
|
||||||
bool _recordOnStartup = false;
|
bool _recordOnStartup = false;
|
||||||
|
|
||||||
Settings(
|
Settings({
|
||||||
{final ResolutionPreset? resolution,
|
final ResolutionPreset? resolution,
|
||||||
final bool? askForMemoryAnnotations,
|
final RecordButtonBehavior? recordButtonBehavior,
|
||||||
final bool? recordOnStartup})
|
final bool? askForMemoryAnnotations,
|
||||||
: _resolution = resolution ?? ResolutionPreset.max,
|
final bool? recordOnStartup,
|
||||||
|
}) : _resolution = resolution ?? ResolutionPreset.max,
|
||||||
_askForMemoryAnnotations = askForMemoryAnnotations ?? true,
|
_askForMemoryAnnotations = askForMemoryAnnotations ?? true,
|
||||||
_recordOnStartup = recordOnStartup ?? false;
|
_recordOnStartup = recordOnStartup ?? false,
|
||||||
|
_recordButtonBehavior =
|
||||||
|
recordButtonBehavior ?? RecordButtonBehavior.holdRecording;
|
||||||
|
|
||||||
ResolutionPreset get resolution => _resolution;
|
ResolutionPreset get resolution => _resolution;
|
||||||
|
RecordButtonBehavior get recordButtonBehavior => _recordButtonBehavior;
|
||||||
bool get askForMemoryAnnotations => _askForMemoryAnnotations;
|
bool get askForMemoryAnnotations => _askForMemoryAnnotations;
|
||||||
bool get recordOnStartup => _recordOnStartup;
|
bool get recordOnStartup => _recordOnStartup;
|
||||||
|
|
||||||
Map<String, dynamic> toJSONData() => {
|
Map<String, dynamic> toJSONData() => {
|
||||||
'resolution': _resolution.toString(),
|
'resolution': _resolution.toString(),
|
||||||
|
'recordButtonBehavior': _recordButtonBehavior.toString(),
|
||||||
'askForMemoryAnnotations': _askForMemoryAnnotations ? 'true' : 'false',
|
'askForMemoryAnnotations': _askForMemoryAnnotations ? 'true' : 'false',
|
||||||
'recordOnStartup': _recordOnStartup ? 'true' : 'false',
|
'recordOnStartup': _recordOnStartup ? 'true' : 'false',
|
||||||
};
|
};
|
||||||
@ -52,6 +60,9 @@ 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 recordButtonBehavior = RecordButtonBehavior.values.firstWhereOrNull(
|
||||||
|
(preset) => preset.toString() == data['recordButtonBehavior'],
|
||||||
|
);
|
||||||
final askForMemoryAnnotations =
|
final askForMemoryAnnotations =
|
||||||
stringToBool(data['askForMemoryAnnotations']);
|
stringToBool(data['askForMemoryAnnotations']);
|
||||||
final recordOnStartup = stringToBool(data['recordOnStartup']);
|
final recordOnStartup = stringToBool(data['recordOnStartup']);
|
||||||
@ -60,6 +71,7 @@ class Settings extends ChangeNotifier {
|
|||||||
resolution: resolution,
|
resolution: resolution,
|
||||||
askForMemoryAnnotations: askForMemoryAnnotations,
|
askForMemoryAnnotations: askForMemoryAnnotations,
|
||||||
recordOnStartup: recordOnStartup,
|
recordOnStartup: recordOnStartup,
|
||||||
|
recordButtonBehavior: recordButtonBehavior,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,6 +81,12 @@ class Settings extends ChangeNotifier {
|
|||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setRecordButtonBehavior(final RecordButtonBehavior behavior) {
|
||||||
|
_recordButtonBehavior = behavior;
|
||||||
|
notifyListeners();
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
|
||||||
void setAskForMemoryAnnotations(final bool askForMemoryAnnotations) {
|
void setAskForMemoryAnnotations(final bool askForMemoryAnnotations) {
|
||||||
_askForMemoryAnnotations = askForMemoryAnnotations;
|
_askForMemoryAnnotations = askForMemoryAnnotations;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
@ -7,7 +7,9 @@ import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
|
|||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:quid_faciam_hodie/constants/spacing.dart';
|
import 'package:quid_faciam_hodie/constants/spacing.dart';
|
||||||
|
import 'package:quid_faciam_hodie/enum_mapping/record_button_behavior/texts.dart';
|
||||||
import 'package:quid_faciam_hodie/enum_mapping/resolution_preset/texts.dart';
|
import 'package:quid_faciam_hodie/enum_mapping/resolution_preset/texts.dart';
|
||||||
|
import 'package:quid_faciam_hodie/enums/record_button_behavior.dart';
|
||||||
import 'package:quid_faciam_hodie/extensions/snackbar.dart';
|
import 'package:quid_faciam_hodie/extensions/snackbar.dart';
|
||||||
import 'package:quid_faciam_hodie/managers/global_values_manager.dart';
|
import 'package:quid_faciam_hodie/managers/global_values_manager.dart';
|
||||||
import 'package:quid_faciam_hodie/managers/user_help_sheets_manager.dart';
|
import 'package:quid_faciam_hodie/managers/user_help_sheets_manager.dart';
|
||||||
@ -15,10 +17,11 @@ import 'package:quid_faciam_hodie/screens/welcome_screen.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';
|
||||||
import 'package:quid_faciam_hodie/utils/theme.dart';
|
import 'package:quid_faciam_hodie/utils/theme.dart';
|
||||||
import 'package:quid_faciam_hodie/widgets/cupertino_dropdown.dart';
|
|
||||||
import 'package:settings_ui/settings_ui.dart';
|
import 'package:settings_ui/settings_ui.dart';
|
||||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||||
|
|
||||||
|
import 'settings_screen/dropdown_tile.dart';
|
||||||
|
|
||||||
final supabase = Supabase.instance.client;
|
final supabase = Supabase.instance.client;
|
||||||
|
|
||||||
const storage = FlutterSecureStorage();
|
const storage = FlutterSecureStorage();
|
||||||
@ -84,46 +87,6 @@ class _SettingsScreenState extends AuthRequiredState<SettingsScreen>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget getQualityPicker() {
|
|
||||||
final settings = GlobalValuesManager.settings!;
|
|
||||||
final resolutionTextMapping = getResolutionTextMapping(context);
|
|
||||||
final items = ResolutionPreset.values
|
|
||||||
.map(
|
|
||||||
(value) => DropdownMenuItem<ResolutionPreset>(
|
|
||||||
value: value,
|
|
||||||
child: Text(resolutionTextMapping[value]!),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
if (isMaterial(context)) {
|
|
||||||
return DropdownButtonFormField<ResolutionPreset>(
|
|
||||||
value: settings.resolution,
|
|
||||||
onChanged: (value) {
|
|
||||||
if (value == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
settings.setResolution(value);
|
|
||||||
},
|
|
||||||
items: items,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return CupertinoDropdownButton<ResolutionPreset>(
|
|
||||||
itemExtent: 30,
|
|
||||||
onChanged: (value) {
|
|
||||||
if (value == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
settings.setResolution(value);
|
|
||||||
},
|
|
||||||
value: settings.resolution,
|
|
||||||
items: items,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final settings = GlobalValuesManager.settings!;
|
final settings = GlobalValuesManager.settings!;
|
||||||
@ -202,13 +165,29 @@ class _SettingsScreenState extends AuthRequiredState<SettingsScreen>
|
|||||||
title: Text(
|
title: Text(
|
||||||
localizations.settingsScreenGeneralSectionTitle,
|
localizations.settingsScreenGeneralSectionTitle,
|
||||||
),
|
),
|
||||||
tiles: <SettingsTile>[
|
tiles: [
|
||||||
SettingsTile(
|
SettingsDropdownTile<ResolutionPreset>(
|
||||||
leading: Text(
|
leading: const Icon(Icons.high_quality),
|
||||||
|
title: Text(
|
||||||
localizations
|
localizations
|
||||||
.settingsScreenGeneralSectionQualityLabel,
|
.settingsScreenGeneralSectionQualityLabel,
|
||||||
),
|
),
|
||||||
title: getQualityPicker(),
|
onUpdate: settings.setResolution,
|
||||||
|
textMapping: getResolutionTextMapping(context),
|
||||||
|
value: settings.resolution,
|
||||||
|
values: ResolutionPreset.values,
|
||||||
|
),
|
||||||
|
SettingsDropdownTile<RecordButtonBehavior>(
|
||||||
|
leading: const Icon(Icons.fiber_manual_record),
|
||||||
|
title: Text(
|
||||||
|
localizations
|
||||||
|
.settingsScreenGeneralSectionRecordButtonBehaviorLabel,
|
||||||
|
),
|
||||||
|
onUpdate: settings.setRecordButtonBehavior,
|
||||||
|
textMapping:
|
||||||
|
getRecordButtonBehaviorTextMapping(context),
|
||||||
|
value: settings.recordButtonBehavior,
|
||||||
|
values: RecordButtonBehavior.values,
|
||||||
),
|
),
|
||||||
SettingsTile.switchTile(
|
SettingsTile.switchTile(
|
||||||
initialValue: settings.askForMemoryAnnotations,
|
initialValue: settings.askForMemoryAnnotations,
|
||||||
@ -221,8 +200,10 @@ class _SettingsScreenState extends AuthRequiredState<SettingsScreen>
|
|||||||
SettingsTile.switchTile(
|
SettingsTile.switchTile(
|
||||||
initialValue: settings.recordOnStartup,
|
initialValue: settings.recordOnStartup,
|
||||||
onToggle: settings.setRecordOnStartup,
|
onToggle: settings.setRecordOnStartup,
|
||||||
title: Text(localizations
|
title: Text(
|
||||||
.settingsScreenGeneralSectionStartRecordingOnStartupLabel),
|
localizations
|
||||||
|
.settingsScreenGeneralSectionStartRecordingOnStartupLabel,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SettingsTile(
|
SettingsTile(
|
||||||
leading: Icon(context.platformIcons.help),
|
leading: Icon(context.platformIcons.help),
|
||||||
|
168
lib/screens/settings_screen/dropdown_tile.dart
Normal file
168
lib/screens/settings_screen/dropdown_tile.dart
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:settings_ui/settings_ui.dart';
|
||||||
|
|
||||||
|
const IN_DURATION = Duration(seconds: 1);
|
||||||
|
const OUT_DURATION = Duration(milliseconds: 300);
|
||||||
|
|
||||||
|
class DropdownTile extends StatefulWidget {
|
||||||
|
final Widget title;
|
||||||
|
final Iterable values;
|
||||||
|
final dynamic value;
|
||||||
|
final Map<dynamic, String> textMapping;
|
||||||
|
final void Function(dynamic newValue) onUpdate;
|
||||||
|
|
||||||
|
final bool enabled;
|
||||||
|
final Widget? leading;
|
||||||
|
final Widget? description;
|
||||||
|
|
||||||
|
const DropdownTile({
|
||||||
|
Key? key,
|
||||||
|
required this.title,
|
||||||
|
required this.values,
|
||||||
|
required this.value,
|
||||||
|
required this.textMapping,
|
||||||
|
required this.onUpdate,
|
||||||
|
this.enabled = true,
|
||||||
|
this.leading,
|
||||||
|
this.description,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<DropdownTile> createState() => _DropdownTileState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DropdownTileState<T> extends State<DropdownTile>
|
||||||
|
with TickerProviderStateMixin {
|
||||||
|
late final AnimationController controller;
|
||||||
|
late final Animation<double> animation;
|
||||||
|
|
||||||
|
bool get isExpanding =>
|
||||||
|
animation.status == AnimationStatus.forward ||
|
||||||
|
animation.status == AnimationStatus.completed;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
controller = AnimationController(
|
||||||
|
duration: IN_DURATION,
|
||||||
|
vsync: this,
|
||||||
|
);
|
||||||
|
animation = CurvedAnimation(
|
||||||
|
parent: controller,
|
||||||
|
curve: Curves.fastLinearToSlowEaseIn,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
expand() {
|
||||||
|
controller.forward();
|
||||||
|
}
|
||||||
|
|
||||||
|
contract() {
|
||||||
|
controller.animateBack(
|
||||||
|
0.0,
|
||||||
|
duration: OUT_DURATION,
|
||||||
|
curve: Curves.decelerate,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleContainer() {
|
||||||
|
if (isExpanding) {
|
||||||
|
contract();
|
||||||
|
} else {
|
||||||
|
expand();
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
controller.dispose();
|
||||||
|
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
children: <Widget>[
|
||||||
|
SettingsTile(
|
||||||
|
leading: widget.leading,
|
||||||
|
description: widget.description,
|
||||||
|
enabled: widget.enabled,
|
||||||
|
title: widget.title,
|
||||||
|
value: Text(widget.textMapping[widget.value]!),
|
||||||
|
trailing: AnimatedRotation(
|
||||||
|
duration: kThemeChangeDuration,
|
||||||
|
turns: isExpanding ? .5 : 0,
|
||||||
|
child: const Icon(Icons.arrow_drop_down),
|
||||||
|
),
|
||||||
|
onPressed: (_) => toggleContainer(),
|
||||||
|
),
|
||||||
|
SizeTransition(
|
||||||
|
sizeFactor: animation,
|
||||||
|
axis: Axis.vertical,
|
||||||
|
child: Column(
|
||||||
|
children: widget.values
|
||||||
|
.map(
|
||||||
|
(value) => RadioListTile<dynamic>(
|
||||||
|
title: Text(widget.textMapping[value]!),
|
||||||
|
value: value,
|
||||||
|
groupValue: widget.value,
|
||||||
|
onChanged: (value) {
|
||||||
|
if (value == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
widget.onUpdate(value);
|
||||||
|
|
||||||
|
contract();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SettingsDropdownTile<T> extends AbstractSettingsTile {
|
||||||
|
final Widget title;
|
||||||
|
final Iterable<T> values;
|
||||||
|
final T value;
|
||||||
|
final Map<T, String> textMapping;
|
||||||
|
final void Function(T newValue) onUpdate;
|
||||||
|
|
||||||
|
final bool enabled;
|
||||||
|
final Widget? leading;
|
||||||
|
final Widget? description;
|
||||||
|
|
||||||
|
const SettingsDropdownTile({
|
||||||
|
Key? key,
|
||||||
|
required this.title,
|
||||||
|
required this.values,
|
||||||
|
required this.value,
|
||||||
|
required this.textMapping,
|
||||||
|
required this.onUpdate,
|
||||||
|
this.enabled = true,
|
||||||
|
this.leading,
|
||||||
|
this.description,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return DropdownTile(
|
||||||
|
title: title,
|
||||||
|
values: values,
|
||||||
|
value: value,
|
||||||
|
textMapping: textMapping,
|
||||||
|
onUpdate: (value) => onUpdate(value as T),
|
||||||
|
enabled: enabled,
|
||||||
|
leading: leading,
|
||||||
|
description: description,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user