feat: add haptic feedback for various user interactions
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:tallee/core/adaptive_page_route.dart';
|
||||
import 'package:tallee/core/custom_theme.dart';
|
||||
import 'package:tallee/l10n/generated/app_localizations.dart';
|
||||
@@ -55,8 +56,9 @@ class _CustomNavigationBarState extends State<CustomNavigationBar>
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
await Navigator.push(
|
||||
context,
|
||||
final navigator = Navigator.of(context);
|
||||
await HapticFeedback.selectionClick();
|
||||
await navigator.push(
|
||||
adaptivePageRoute(builder: (_) => const SettingsView()),
|
||||
);
|
||||
setState(() {
|
||||
@@ -125,7 +127,8 @@ class _CustomNavigationBarState extends State<CustomNavigationBar>
|
||||
}
|
||||
|
||||
/// Handles tab tap events. Updates the current [index] state.
|
||||
void onTabTapped(int index) {
|
||||
void onTabTapped(int index) async {
|
||||
await HapticFeedback.selectionClick();
|
||||
setState(() {
|
||||
currentIndex = index;
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tallee/core/constants.dart';
|
||||
import 'package:tallee/core/custom_theme.dart';
|
||||
@@ -133,8 +134,10 @@ class _CreateGroupViewState extends State<CreateGroupView> {
|
||||
if (!mounted) return;
|
||||
|
||||
if (success) {
|
||||
await HapticFeedback.successNotification();
|
||||
Navigator.pop(context, updatedGroup);
|
||||
} else {
|
||||
await HapticFeedback.errorNotification();
|
||||
showSnackbar(
|
||||
message: widget.groupToEdit == null
|
||||
? loc.error_creating_group
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tallee/core/adaptive_page_route.dart';
|
||||
@@ -68,6 +69,7 @@ class _GroupDetailViewState extends State<GroupDetailView> {
|
||||
IconButton(
|
||||
icon: const Icon(Icons.delete),
|
||||
onPressed: () async {
|
||||
await HapticFeedback.selectionClick();
|
||||
showDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) => CustomAlertDialog(
|
||||
@@ -75,11 +77,17 @@ class _GroupDetailViewState extends State<GroupDetailView> {
|
||||
content: Text(loc.this_cannot_be_undone),
|
||||
actions: [
|
||||
CustomDialogAction(
|
||||
onPressed: () => Navigator.of(context).pop(true),
|
||||
onPressed: () async {
|
||||
await HapticFeedback.warningNotification();
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
text: loc.delete,
|
||||
),
|
||||
CustomDialogAction(
|
||||
onPressed: () => Navigator.of(context).pop(false),
|
||||
onPressed: () async {
|
||||
await HapticFeedback.selectionClick();
|
||||
Navigator.of(context).pop(false);
|
||||
},
|
||||
buttonType: ButtonType.secondary,
|
||||
text: loc.cancel,
|
||||
),
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tallee/core/adaptive_page_route.dart';
|
||||
import 'package:tallee/core/constants.dart';
|
||||
@@ -102,6 +103,7 @@ class _GroupViewState extends State<GroupView> {
|
||||
text: loc.create_group,
|
||||
icon: Icons.group_add,
|
||||
onPressed: () async {
|
||||
await HapticFeedback.selectionClick();
|
||||
await Navigator.push(
|
||||
context,
|
||||
adaptivePageRoute(
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'dart:io';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
@@ -201,7 +202,8 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
children: [
|
||||
GestureDetector(
|
||||
child: const Icon(Icons.language),
|
||||
onTap: () => {
|
||||
onTap: () async => {
|
||||
await HapticFeedback.lightImpact(),
|
||||
launchUrl(
|
||||
Uri.parse('https://liquid-dev.de'),
|
||||
),
|
||||
@@ -209,7 +211,8 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
),
|
||||
GestureDetector(
|
||||
child: const FaIcon(FontAwesomeIcons.github),
|
||||
onTap: () => {
|
||||
onTap: () async => {
|
||||
await HapticFeedback.lightImpact(),
|
||||
launchUrl(
|
||||
Uri.parse(
|
||||
'https://github.com/liquiddevelopmentde',
|
||||
@@ -223,9 +226,12 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
? CupertinoIcons.mail_solid
|
||||
: Icons.email,
|
||||
),
|
||||
onTap: () => launchUrl(
|
||||
Uri.parse('mailto:hi@liquid-dev.de'),
|
||||
),
|
||||
onTap: () async => {
|
||||
await HapticFeedback.lightImpact(),
|
||||
launchUrl(
|
||||
Uri.parse('mailto:hi@liquid-dev.de'),
|
||||
),
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -266,20 +272,38 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
void showImportSnackBar({
|
||||
required BuildContext context,
|
||||
required ImportResult result,
|
||||
}) {
|
||||
}) async {
|
||||
final loc = AppLocalizations.of(context);
|
||||
switch (result) {
|
||||
case ImportResult.success:
|
||||
if (context.mounted) {
|
||||
await HapticFeedback.successNotification();
|
||||
}
|
||||
showSnackbar(context: context, message: loc.data_successfully_imported);
|
||||
case ImportResult.invalidSchema:
|
||||
if (context.mounted) {
|
||||
await HapticFeedback.errorNotification();
|
||||
}
|
||||
showSnackbar(context: context, message: loc.invalid_schema);
|
||||
case ImportResult.fileReadError:
|
||||
if (context.mounted) {
|
||||
await HapticFeedback.errorNotification();
|
||||
}
|
||||
showSnackbar(context: context, message: loc.error_reading_file);
|
||||
case ImportResult.canceled:
|
||||
if (context.mounted) {
|
||||
await HapticFeedback.errorNotification();
|
||||
}
|
||||
showSnackbar(context: context, message: loc.import_canceled);
|
||||
case ImportResult.formatException:
|
||||
if (context.mounted) {
|
||||
await HapticFeedback.errorNotification();
|
||||
}
|
||||
showSnackbar(context: context, message: loc.format_exception);
|
||||
case ImportResult.unknownException:
|
||||
if (context.mounted) {
|
||||
await HapticFeedback.errorNotification();
|
||||
}
|
||||
showSnackbar(context: context, message: loc.unknown_exception);
|
||||
}
|
||||
}
|
||||
@@ -291,13 +315,16 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
void showExportSnackBar({
|
||||
required BuildContext context,
|
||||
required ExportResult result,
|
||||
}) {
|
||||
}) async {
|
||||
final loc = AppLocalizations.of(context);
|
||||
switch (result) {
|
||||
case ExportResult.success:
|
||||
await HapticFeedback.successNotification();
|
||||
showSnackbar(context: context, message: loc.data_successfully_exported);
|
||||
case ExportResult.canceled:
|
||||
await HapticFeedback.errorNotification();
|
||||
showSnackbar(context: context, message: loc.export_canceled);
|
||||
await HapticFeedback.errorNotification();
|
||||
case ExportResult.unknownException:
|
||||
showSnackbar(context: context, message: loc.unknown_exception);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user