Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add haptic feedback #1459

Merged
merged 12 commits into from
Jan 14, 2024
3 changes: 2 additions & 1 deletion android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />

<uses-permission android:name="android.permission.VIBRATE" />

<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
Expand Down
3 changes: 2 additions & 1 deletion lib/services/manager_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import 'package:revanced_manager/services/patcher_api.dart';
import 'package:revanced_manager/services/revanced_api.dart';
import 'package:revanced_manager/services/root_api.dart';
import 'package:revanced_manager/services/toast.dart';
import 'package:revanced_manager/ui/widgets/shared/haptics/haptic_checkbox_list_tile.dart';
import 'package:revanced_manager/utils/check_for_supported_patch.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:timeago/timeago.dart';
Expand Down Expand Up @@ -617,7 +618,7 @@ class ManagerAPI {
),
),
const SizedBox(height: 8),
CheckboxListTile(
HapticCheckboxListTile(
value: value,
contentPadding: EdgeInsets.zero,
title: I18nText(
Expand Down
3 changes: 2 additions & 1 deletion lib/ui/views/app_selector/app_selector_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:revanced_manager/ui/views/app_selector/app_selector_viewmodel.da
import 'package:revanced_manager/ui/widgets/appSelectorView/app_skeleton_loader.dart';
import 'package:revanced_manager/ui/widgets/appSelectorView/installed_app_item.dart';
import 'package:revanced_manager/ui/widgets/appSelectorView/not_installed_app_item.dart';
import 'package:revanced_manager/ui/widgets/shared/haptics/haptic_floating_action_button_extended.dart';
import 'package:revanced_manager/ui/widgets/shared/search_bar.dart';
import 'package:stacked/stacked.dart' hide SkeletonLoader;

Expand All @@ -23,7 +24,7 @@ class _AppSelectorViewState extends State<AppSelectorView> {
onViewModelReady: (model) => model.initialize(),
viewModelBuilder: () => AppSelectorViewModel(),
builder: (context, model, child) => Scaffold(
floatingActionButton: FloatingActionButton.extended(
floatingActionButton: HapticFloatingActionButtonExtended(
label: I18nText('appSelectorView.storageButton'),
icon: const Icon(Icons.sd_storage),
onPressed: () {
Expand Down
3 changes: 2 additions & 1 deletion lib/ui/views/home/home_viewmodel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import 'package:revanced_manager/services/toast.dart';
import 'package:revanced_manager/ui/views/navigation/navigation_viewmodel.dart';
import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart';
import 'package:revanced_manager/ui/widgets/homeView/update_confirmation_dialog.dart';
import 'package:revanced_manager/ui/widgets/shared/haptics/haptic_checkbox_list_tile.dart';
import 'package:stacked/stacked.dart';
import 'package:stacked_services/stacked_services.dart';

Expand Down Expand Up @@ -207,7 +208,7 @@ class HomeViewModel extends BaseViewModel {
),
),
),
CheckboxListTile(
HapticCheckboxListTile(
value: value,
contentPadding: EdgeInsets.zero,
title: I18nText(
Expand Down
3 changes: 2 additions & 1 deletion lib/ui/views/installer/installer_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:revanced_manager/ui/views/installer/installer_viewmodel.dart';
import 'package:revanced_manager/ui/widgets/installerView/gradient_progress_indicator.dart';
import 'package:revanced_manager/ui/widgets/shared/custom_card.dart';
import 'package:revanced_manager/ui/widgets/shared/custom_sliver_app_bar.dart';
import 'package:revanced_manager/ui/widgets/shared/haptics/haptic_floating_action_button_extended.dart';
import 'package:stacked/stacked.dart';

class InstallerView extends StatelessWidget {
Expand All @@ -22,7 +23,7 @@ class InstallerView extends StatelessWidget {
child: Scaffold(
floatingActionButton: Visibility(
visible: !model.isPatching && !model.hasErrors,
child: FloatingActionButton.extended(
child: HapticFloatingActionButtonExtended(
label: I18nText(
model.isInstalled
? 'installerView.openButton'
Expand Down
3 changes: 2 additions & 1 deletion lib/ui/views/patch_options/patch_options_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:google_fonts/google_fonts.dart';
import 'package:revanced_manager/models/patch.dart';
import 'package:revanced_manager/ui/views/patch_options/patch_options_viewmodel.dart';
import 'package:revanced_manager/ui/widgets/patchesSelectorView/patch_options_fields.dart';
import 'package:revanced_manager/ui/widgets/shared/haptics/haptic_floating_action_button_extended.dart';
import 'package:stacked/stacked.dart';

class PatchOptionsView extends StatelessWidget {
Expand All @@ -17,7 +18,7 @@ class PatchOptionsView extends StatelessWidget {
builder: (context, model, child) => GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Scaffold(
floatingActionButton: FloatingActionButton.extended(
floatingActionButton: HapticFloatingActionButtonExtended(
onPressed: () async {
final bool saved = model.saveOptions(context);
if (saved && context.mounted) {
Expand Down
3 changes: 2 additions & 1 deletion lib/ui/views/patcher/patcher_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart';
import 'package:revanced_manager/ui/widgets/patcherView/app_selector_card.dart';
import 'package:revanced_manager/ui/widgets/patcherView/patch_selector_card.dart';
import 'package:revanced_manager/ui/widgets/shared/custom_sliver_app_bar.dart';
import 'package:revanced_manager/ui/widgets/shared/haptics/haptic_floating_action_button_extended.dart';
import 'package:stacked/stacked.dart';

class PatcherView extends StatelessWidget {
Expand All @@ -19,7 +20,7 @@ class PatcherView extends StatelessWidget {
builder: (context, model, child) => Scaffold(
floatingActionButton: Visibility(
visible: model.showPatchButton(),
child: FloatingActionButton.extended(
child: HapticFloatingActionButtonExtended(
label: I18nText('patcherView.patchButton'),
icon: const Icon(Icons.build),
onPressed: () async {
Expand Down
3 changes: 2 additions & 1 deletion lib/ui/views/patches_selector/patches_selector_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:revanced_manager/app/app.locator.dart';
import 'package:revanced_manager/services/manager_api.dart';
import 'package:revanced_manager/ui/views/patches_selector/patches_selector_viewmodel.dart';
import 'package:revanced_manager/ui/widgets/shared/haptics/haptic_floating_action_button_extended.dart';
import 'package:revanced_manager/ui/widgets/shared/search_bar.dart';
import 'package:stacked/stacked.dart';

Expand Down Expand Up @@ -36,7 +37,7 @@ class _PatchesSelectorViewState extends State<PatchesSelectorView> {
builder: (context, model, child) => Scaffold(
floatingActionButton: Visibility(
visible: model.patches.isNotEmpty,
child: FloatingActionButton.extended(
child: HapticFloatingActionButtonExtended(
label: Row(
children: <Widget>[
I18nText('patchesSelectorView.doneButton'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import 'package:flutter_i18n/widgets/I18nText.dart';
import 'package:revanced_manager/app/app.locator.dart';
import 'package:revanced_manager/services/manager_api.dart';
import 'package:revanced_manager/ui/widgets/settingsView/settings_section.dart';
import 'package:revanced_manager/ui/widgets/shared/haptics/haptic_radio_list_tile.dart';
import 'package:revanced_manager/ui/widgets/shared/haptics/haptic_switch_list_tile.dart';

class SUpdateThemeUI extends StatefulWidget {
const SUpdateThemeUI({super.key});
Expand Down Expand Up @@ -42,7 +44,7 @@ class _SUpdateThemeUIState extends State<SUpdateThemeUI> {
onTap: () => {showThemeDialog(context)},
),
if (managerAPI.isDynamicThemeAvailable)
SwitchListTile(
HapticSwitchListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 20.0),
title: I18nText(
'settingsView.dynamicThemeLabel',
Expand Down Expand Up @@ -129,7 +131,7 @@ class _SUpdateThemeUIState extends State<SUpdateThemeUI> {
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
RadioListTile(
HapticRadioListTile(
title: I18nText('settingsView.systemThemeLabel'),
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
value: 0,
Expand All @@ -138,7 +140,7 @@ class _SUpdateThemeUIState extends State<SUpdateThemeUI> {
newTheme.value = value!;
},
),
RadioListTile(
HapticRadioListTile(
title: I18nText('settingsView.lightThemeLabel'),
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
value: 1,
Expand All @@ -147,7 +149,7 @@ class _SUpdateThemeUIState extends State<SUpdateThemeUI> {
newTheme.value = value!;
},
),
RadioListTile(
HapticRadioListTile(
title: I18nText('settingsView.darkThemeLabel'),
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
value: 2,
Expand Down
6 changes: 4 additions & 2 deletions lib/ui/widgets/patchesSelectorView/patch_item.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import 'package:revanced_manager/models/patch.dart';
import 'package:revanced_manager/services/manager_api.dart';
import 'package:revanced_manager/services/toast.dart';
import 'package:revanced_manager/ui/widgets/shared/custom_card.dart';
import 'package:revanced_manager/ui/widgets/shared/haptics/haptic_checkbox.dart';
import 'package:revanced_manager/ui/widgets/shared/haptics/haptic_custom_card.dart';

// ignore: must_be_immutable
class PatchItem extends StatefulWidget {
Expand Down Expand Up @@ -56,7 +58,7 @@ class _PatchItemState extends State<PatchItem> {
widget._managerAPI.isVersionCompatibilityCheckEnabled() == true
? 0.5
: 1,
child: CustomCard(
child: HapticCustomCard(
padding: EdgeInsets.only(
top: 12,
bottom: 16,
Expand Down Expand Up @@ -88,7 +90,7 @@ class _PatchItemState extends State<PatchItem> {
children: [
Transform.scale(
scale: 1.2,
child: Checkbox(
child: HapticCheckbox(
value: widget.isSelected,
activeColor: Theme.of(context).colorScheme.primary,
checkColor: Theme.of(context).colorScheme.secondaryContainer,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_i18n/widgets/I18nText.dart';
import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart';
import 'package:revanced_manager/ui/widgets/shared/haptics/haptic_switch_list_tile.dart';

class SAutoUpdatePatches extends StatefulWidget {
const SAutoUpdatePatches({super.key});
Expand All @@ -14,7 +15,7 @@ final _settingsViewModel = SettingsViewModel();
class _SAutoUpdatePatchesState extends State<SAutoUpdatePatches> {
@override
Widget build(BuildContext context) {
return SwitchListTile(
return HapticSwitchListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 20.0),
title: I18nText(
'settingsView.autoUpdatePatchesLabel',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_i18n/widgets/I18nText.dart';
import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart';
import 'package:revanced_manager/ui/widgets/shared/haptics/haptic_switch_list_tile.dart';

class SEnablePatchesSelection extends StatefulWidget {
const SEnablePatchesSelection({super.key});
Expand All @@ -15,7 +16,7 @@ final _settingsViewModel = SettingsViewModel();
class _SEnablePatchesSelectionState extends State<SEnablePatchesSelection> {
@override
Widget build(BuildContext context) {
return SwitchListTile(
return HapticSwitchListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 20.0),
title: I18nText(
'settingsView.enablePatchesSelectionLabel',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_i18n/widgets/I18nText.dart';
import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart';
import 'package:revanced_manager/ui/widgets/shared/haptics/haptic_switch_list_tile.dart';

class SRequireSuggestedAppVersion extends StatefulWidget {
const SRequireSuggestedAppVersion({super.key});
Expand All @@ -16,7 +17,7 @@ class _SRequireSuggestedAppVersionState
extends State<SRequireSuggestedAppVersion> {
@override
Widget build(BuildContext context) {
return SwitchListTile(
return HapticSwitchListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 20.0),
title: I18nText(
'settingsView.requireSuggestedAppVersionLabel',
Expand Down
3 changes: 2 additions & 1 deletion lib/ui/widgets/settingsView/settings_universal_patches.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:flutter_i18n/widgets/I18nText.dart';
import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart';
import 'package:revanced_manager/ui/views/patches_selector/patches_selector_viewmodel.dart';
import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart';
import 'package:revanced_manager/ui/widgets/shared/haptics/haptic_switch_list_tile.dart';

class SUniversalPatches extends StatefulWidget {
const SUniversalPatches({super.key});
Expand All @@ -18,7 +19,7 @@ final _patcherViewModel = PatcherViewModel();
class _SUniversalPatchesState extends State<SUniversalPatches> {
@override
Widget build(BuildContext context) {
return SwitchListTile(
return HapticSwitchListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 20.0),
title: I18nText(
'settingsView.universalPatchesLabel',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:flutter_i18n/widgets/I18nText.dart';
import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart';
import 'package:revanced_manager/ui/views/patches_selector/patches_selector_viewmodel.dart';
import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart';
import 'package:revanced_manager/ui/widgets/shared/haptics/haptic_switch_list_tile.dart';
import 'package:revanced_manager/utils/check_for_supported_patch.dart';

class SVersionCompatibilityCheck extends StatefulWidget {
Expand All @@ -21,7 +22,7 @@ class _SVersionCompatibilityCheckState
extends State<SVersionCompatibilityCheck> {
@override
Widget build(BuildContext context) {
return SwitchListTile(
return HapticSwitchListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 20.0),
title: I18nText(
'settingsView.versionCompatibilityCheckLabel',
Expand Down
32 changes: 32 additions & 0 deletions lib/ui/widgets/shared/haptics/haptic_checkbox.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class HapticCheckbox extends StatelessWidget {
const HapticCheckbox({
super.key,
required this.value,
required this.onChanged,
this.activeColor,
this.checkColor,
this.side,
});
final bool value;
final Function(bool?)? onChanged;
final Color? activeColor;
final Color? checkColor;
final BorderSide? side;

@override
Widget build(BuildContext context) {
return Checkbox(
value: value,
onChanged: (value) => {
HapticFeedback.selectionClick(),
if (onChanged != null) onChanged!(value),
},
activeColor: activeColor,
checkColor: checkColor,
side: side,
);
}
}
32 changes: 32 additions & 0 deletions lib/ui/widgets/shared/haptics/haptic_checkbox_list_tile.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class HapticCheckboxListTile extends StatelessWidget {
const HapticCheckboxListTile({
super.key,
required this.value,
required this.onChanged,
this.title,
this.subtitle,
this.contentPadding,
});
final bool value;
final Function(bool?)? onChanged;
final Widget? title;
final Widget? subtitle;
final EdgeInsetsGeometry? contentPadding;

@override
Widget build(BuildContext context) {
return CheckboxListTile(
contentPadding: contentPadding ?? EdgeInsets.zero,
title: title,
subtitle: subtitle,
value: value,
onChanged: (value) => {
HapticFeedback.lightImpact(),
if (onChanged != null) onChanged!(value),
},
);
}
}
33 changes: 33 additions & 0 deletions lib/ui/widgets/shared/haptics/haptic_custom_card.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:revanced_manager/ui/widgets/shared/custom_card.dart';

class HapticCustomCard extends StatelessWidget {
const HapticCustomCard({
super.key,
this.isFilled = true,
required this.child,
this.onTap,
this.padding,
this.backgroundColor,
});
final bool isFilled;
final Widget child;
final Function()? onTap;
final EdgeInsetsGeometry? padding;
final Color? backgroundColor;

@override
Widget build(BuildContext context) {
return CustomCard(
isFilled: isFilled,
onTap: () => {
HapticFeedback.selectionClick(),
if (onTap != null) onTap!(),
},
padding: padding,
backgroundColor: backgroundColor,
child: child,
);
}
}
Loading