Add haptic feedback
This commit is contained in:
@@ -186,7 +186,8 @@
|
||||
"openWorkingDir": "Open Working Directory",
|
||||
"ignoreBatteryOptimizations": "Disable Battery Optimization",
|
||||
"ignoreBatteryOptimizationsMsg": "Remove restrictions for optimal VPN performance",
|
||||
"dynamicNotification": "Display speed in notification"
|
||||
"dynamicNotification": "Display speed in notification",
|
||||
"hapticFeedback": "Haptic Feedback"
|
||||
},
|
||||
"advanced": {
|
||||
"sectionTitle": "Advanced",
|
||||
|
||||
35
lib/core/haptic/haptic_service.dart
Normal file
35
lib/core/haptic/haptic_service.dart
Normal file
@@ -0,0 +1,35 @@
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:hiddify/core/preferences/preferences_provider.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
part 'haptic_service.g.dart';
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
class HapticService extends _$HapticService {
|
||||
@override
|
||||
bool build() {
|
||||
return _preferences.getBool(hapticFeedbackPrefKey) ?? true;
|
||||
}
|
||||
|
||||
static const String hapticFeedbackPrefKey = "haptic_feedback";
|
||||
SharedPreferences get _preferences =>
|
||||
ref.read(sharedPreferencesProvider).requireValue;
|
||||
|
||||
Future<void> updatePreference(bool value) async {
|
||||
state = value;
|
||||
await _preferences.setBool(hapticFeedbackPrefKey, value);
|
||||
}
|
||||
|
||||
Future<void> lightImpact() async {
|
||||
if (state) {
|
||||
await HapticFeedback.lightImpact();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> mediumImpact() async {
|
||||
if (state) {
|
||||
await HapticFeedback.mediumImpact();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:hiddify/core/haptic/haptic_service.dart';
|
||||
import 'package:hiddify/core/preferences/general_preferences.dart';
|
||||
import 'package:hiddify/core/preferences/service_preferences.dart';
|
||||
import 'package:hiddify/features/connection/data/connection_data_providers.dart';
|
||||
@@ -53,14 +54,18 @@ class ConnectionNotifier extends _$ConnectionNotifier with AppLogger {
|
||||
}
|
||||
|
||||
Future<void> toggleConnection() async {
|
||||
final haptic = ref.read(hapticServiceProvider.notifier);
|
||||
if (state case AsyncError()) {
|
||||
await haptic.lightImpact();
|
||||
await _connect();
|
||||
} else if (state case AsyncData(:final value)) {
|
||||
switch (value) {
|
||||
case Disconnected():
|
||||
await haptic.lightImpact();
|
||||
await ref.read(startedByUserProvider.notifier).update(true);
|
||||
await _connect();
|
||||
case Connected():
|
||||
await haptic.mediumImpact();
|
||||
await ref.read(startedByUserProvider.notifier).update(false);
|
||||
await _disconnect();
|
||||
default:
|
||||
@@ -111,7 +116,8 @@ class ConnectionNotifier extends _$ConnectionNotifier with AppLogger {
|
||||
)
|
||||
.mapLeft((err) async {
|
||||
loggy.warning("error connecting", err);
|
||||
loggy.warning(err);//Go err is not normal object to see the go errors are string and need to be dumped
|
||||
loggy.warning(
|
||||
err); //Go err is not normal object to see the go errors are string and need to be dumped
|
||||
if (err.toString().contains("panic")) {
|
||||
await Sentry.captureException(Exception(err.toString()));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:fpdart/fpdart.dart';
|
||||
import 'package:hiddify/core/haptic/haptic_service.dart';
|
||||
import 'package:hiddify/core/localization/translations.dart';
|
||||
import 'package:hiddify/core/model/failures.dart';
|
||||
import 'package:hiddify/core/notification/in_app_notification_controller.dart';
|
||||
@@ -127,6 +128,7 @@ class UpdateProfile extends _$UpdateProfile with AppLogger {
|
||||
Future<void> updateProfile(RemoteProfileEntity profile) async {
|
||||
if (state.isLoading) return;
|
||||
state = const AsyncLoading();
|
||||
await ref.read(hapticServiceProvider.notifier).lightImpact();
|
||||
state = await AsyncValue.guard(
|
||||
() async {
|
||||
return await _profilesRepo.updateSubscription(profile).match(
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:hiddify/core/haptic/haptic_service.dart';
|
||||
import 'package:hiddify/core/utils/throttler.dart';
|
||||
import 'package:hiddify/features/connection/notifier/connection_notifier.dart';
|
||||
import 'package:hiddify/features/proxy/data/proxy_data_providers.dart';
|
||||
@@ -40,6 +41,7 @@ class IpInfoNotifier extends _$IpInfoNotifier with AppLogger {
|
||||
|
||||
Future<void> refresh() async {
|
||||
loggy.debug("refreshing");
|
||||
await ref.read(hapticServiceProvider.notifier).lightImpact();
|
||||
ref.invalidateSelf();
|
||||
}
|
||||
}
|
||||
@@ -69,6 +71,7 @@ class ActiveProxyNotifier extends _$ActiveProxyNotifier with AppLogger {
|
||||
() async {
|
||||
loggy.debug("testing group: [$groupTag]");
|
||||
if (state case AsyncData()) {
|
||||
await ref.read(hapticServiceProvider.notifier).lightImpact();
|
||||
await ref
|
||||
.read(proxyRepositoryProvider)
|
||||
.urlTest(groupTag)
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'dart:async';
|
||||
|
||||
import 'package:combine/combine.dart';
|
||||
import 'package:dartx/dartx.dart';
|
||||
import 'package:hiddify/core/haptic/haptic_service.dart';
|
||||
import 'package:hiddify/core/localization/translations.dart';
|
||||
import 'package:hiddify/core/preferences/preferences_provider.dart';
|
||||
import 'package:hiddify/features/connection/notifier/connection_notifier.dart';
|
||||
@@ -131,6 +132,7 @@ class ProxiesOverviewNotifier extends _$ProxiesOverviewNotifier with AppLogger {
|
||||
"changing proxy, group: [$groupTag] - outbound: [$outboundTag]",
|
||||
);
|
||||
if (state case AsyncData(value: final outbounds)) {
|
||||
await ref.read(hapticServiceProvider.notifier).lightImpact();
|
||||
await ref
|
||||
.read(proxyRepositoryProvider)
|
||||
.selectProxy(groupTag, outboundTag)
|
||||
@@ -151,6 +153,7 @@ class ProxiesOverviewNotifier extends _$ProxiesOverviewNotifier with AppLogger {
|
||||
Future<void> urlTest(String groupTag) async {
|
||||
loggy.debug("testing group: [$groupTag]");
|
||||
if (state case AsyncData()) {
|
||||
await ref.read(hapticServiceProvider.notifier).lightImpact();
|
||||
await ref
|
||||
.read(proxyRepositoryProvider)
|
||||
.urlTest(groupTag)
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'dart:io';
|
||||
|
||||
import 'package:fluentui_system_icons/fluentui_system_icons.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hiddify/core/haptic/haptic_service.dart';
|
||||
import 'package:hiddify/core/localization/translations.dart';
|
||||
import 'package:hiddify/core/preferences/general_preferences.dart';
|
||||
import 'package:hiddify/core/theme/app_theme_mode.dart';
|
||||
@@ -54,7 +55,7 @@ class GeneralSettingTiles extends HookConsumerWidget {
|
||||
},
|
||||
),
|
||||
const EnableAnalyticsPrefTile(),
|
||||
if (Platform.isAndroid)
|
||||
if (Platform.isAndroid) ...[
|
||||
SwitchListTile(
|
||||
title: Text(t.settings.general.dynamicNotification),
|
||||
secondary: const Icon(FluentIcons.top_speed_24_regular),
|
||||
@@ -65,6 +66,14 @@ class GeneralSettingTiles extends HookConsumerWidget {
|
||||
.update(value);
|
||||
},
|
||||
),
|
||||
SwitchListTile(
|
||||
title: Text(t.settings.general.hapticFeedback),
|
||||
secondary: const Icon(FluentIcons.phone_vibrate_24_regular),
|
||||
value: ref.watch(hapticServiceProvider),
|
||||
onChanged:
|
||||
ref.read(hapticServiceProvider.notifier).updatePreference,
|
||||
),
|
||||
],
|
||||
if (PlatformUtils.isDesktop) ...[
|
||||
SwitchListTile(
|
||||
title: Text(t.settings.general.autoStart),
|
||||
|
||||
Reference in New Issue
Block a user