gesture feature initial
This commit is contained in:
@@ -223,6 +223,18 @@ GeckoViewportService viewportService(Ref ref) {
|
||||
return service;
|
||||
}
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
GeckoGestureService gestureService(Ref ref) {
|
||||
final service = GeckoGestureService();
|
||||
service.setUp();
|
||||
|
||||
ref.onDispose(() async {
|
||||
await service.dispose();
|
||||
});
|
||||
|
||||
return service;
|
||||
}
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
class EngineReadyState extends _$EngineReadyState {
|
||||
Future<bool> waitUntilReady({
|
||||
|
||||
@@ -293,6 +293,53 @@ final class ViewportServiceProvider
|
||||
|
||||
String _$viewportServiceHash() => r'bab39db3180bb6a1cf8c055966b7f5910b41b424';
|
||||
|
||||
@ProviderFor(gestureService)
|
||||
final gestureServiceProvider = GestureServiceProvider._();
|
||||
|
||||
final class GestureServiceProvider
|
||||
extends
|
||||
$FunctionalProvider<
|
||||
GeckoGestureService,
|
||||
GeckoGestureService,
|
||||
GeckoGestureService
|
||||
>
|
||||
with $Provider<GeckoGestureService> {
|
||||
GestureServiceProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'gestureServiceProvider',
|
||||
isAutoDispose: false,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$gestureServiceHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
$ProviderElement<GeckoGestureService> $createElement(
|
||||
$ProviderPointer pointer,
|
||||
) => $ProviderElement(pointer);
|
||||
|
||||
@override
|
||||
GeckoGestureService create(Ref ref) {
|
||||
return gestureService(ref);
|
||||
}
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(GeckoGestureService value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<GeckoGestureService>(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$gestureServiceHash() => r'81e90a1adb64f596190b52aba0e2ab9dcab3c5e7';
|
||||
|
||||
@ProviderFor(EngineReadyState)
|
||||
final engineReadyStateProvider = EngineReadyStateProvider._();
|
||||
|
||||
|
||||
+1
@@ -43,5 +43,6 @@ enum ToolbarButtonId {
|
||||
pageDown,
|
||||
font,
|
||||
extensionShortcut,
|
||||
toggleGestures,
|
||||
quit,
|
||||
}
|
||||
|
||||
+6
@@ -169,6 +169,11 @@ const quitToolbarButtonSpec = ToolbarButtonSpec(
|
||||
canBeFallbackTarget: false,
|
||||
);
|
||||
|
||||
const toggleGesturesToolbarButtonSpec = ToolbarButtonSpec(
|
||||
id: ToolbarButtonId.toggleGestures,
|
||||
defaultVisible: false,
|
||||
);
|
||||
|
||||
const toolbarButtonSpecs = [
|
||||
backToolbarButtonSpec,
|
||||
forwardToolbarButtonSpec,
|
||||
@@ -194,6 +199,7 @@ const toolbarButtonSpecs = [
|
||||
pageDownToolbarButtonSpec,
|
||||
fontToolbarButtonSpec,
|
||||
extensionShortcutToolbarButtonSpec,
|
||||
toggleGesturesToolbarButtonSpec,
|
||||
quitToolbarButtonSpec,
|
||||
];
|
||||
|
||||
|
||||
+30
@@ -47,6 +47,8 @@ import 'package:weblibre/features/geckoview/features/find_in_page/presentation/c
|
||||
import 'package:weblibre/features/geckoview/features/readerview/presentation/controllers/readerable.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/data/entities/tab_mode.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/tab.dart';
|
||||
import 'package:weblibre/features/gestures/data/models/gesture_settings.dart';
|
||||
import 'package:weblibre/features/gestures/domain/repositories/gesture_settings.dart';
|
||||
import 'package:weblibre/features/settings/presentation/controllers/save_settings.dart';
|
||||
import 'package:weblibre/features/user/data/models/engine_settings.dart';
|
||||
import 'package:weblibre/features/user/domain/presentation/dialogs/quit_browser_dialog.dart';
|
||||
@@ -399,6 +401,34 @@ final List<ToolbarButtonDefinition> toolbarButtonRegistry = [
|
||||
);
|
||||
},
|
||||
),
|
||||
ToolbarButtonDefinition(
|
||||
spec: toggleGesturesToolbarButtonSpec,
|
||||
label: 'Gestures',
|
||||
icon: MdiIcons.gestureSwipe,
|
||||
builder: (scope, context, ref) {
|
||||
final on = ref.watch(
|
||||
gestureSettingsWithDefaultsProvider.select((s) => s.effectiveEnabled),
|
||||
);
|
||||
return IconButton(
|
||||
isSelected: on,
|
||||
tooltip: on ? 'Disable gestures' : 'Enable gestures',
|
||||
onPressed: scope.isPreview
|
||||
? () {}
|
||||
: () async {
|
||||
final newActive = !on;
|
||||
await ref
|
||||
.read(gestureSettingsRepositoryProvider.notifier)
|
||||
.updateSettings(
|
||||
(s) => s.copyWith(
|
||||
enabled: s.enabled || newActive,
|
||||
active: newActive,
|
||||
),
|
||||
);
|
||||
},
|
||||
icon: Icon(on ? MdiIcons.gestureSwipe : MdiIcons.gestureDoubleTap),
|
||||
);
|
||||
},
|
||||
),
|
||||
ToolbarButtonDefinition(
|
||||
spec: pageUpToolbarButtonSpec,
|
||||
label: 'Page Up',
|
||||
|
||||
+42
@@ -69,6 +69,8 @@ import 'package:weblibre/features/geckoview/features/tabs/domain/providers.dart'
|
||||
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/container.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/tab.dart';
|
||||
import 'package:weblibre/features/geckoview/features/top_sites/domain/repositories/top_site_repository.dart';
|
||||
import 'package:weblibre/features/gestures/data/models/gesture_settings.dart';
|
||||
import 'package:weblibre/features/gestures/domain/repositories/gesture_settings.dart';
|
||||
import 'package:weblibre/features/proxy/data/models/singbox_proxy_profile.dart';
|
||||
import 'package:weblibre/features/proxy/domain/providers/assigned_proxy_profiles.dart';
|
||||
import 'package:weblibre/features/proxy/domain/repositories/singbox_proxy_runtime.dart';
|
||||
@@ -173,6 +175,16 @@ class _BrowserMenuSheet extends HookConsumerWidget {
|
||||
_ProfileCard(),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Gestures quick toggle (only when the master switch is on)
|
||||
if (ref.watch(
|
||||
gestureSettingsWithDefaultsProvider.select(
|
||||
(s) => s.enabled,
|
||||
),
|
||||
)) ...[
|
||||
const _GestureToggleTile(),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
|
||||
// App
|
||||
const _SettingsCard(),
|
||||
const SizedBox(height: 24),
|
||||
@@ -930,6 +942,36 @@ class _FetchFeedsTile extends HookConsumerWidget {
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Gestures Quick Toggle ───
|
||||
|
||||
class _GestureToggleTile extends ConsumerWidget {
|
||||
const _GestureToggleTile();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final active = ref.watch(
|
||||
gestureSettingsWithDefaultsProvider.select((s) => s.active),
|
||||
);
|
||||
|
||||
return _buildMenuCard(
|
||||
context,
|
||||
children: [
|
||||
SwitchListTile.adaptive(
|
||||
secondary: const Icon(MdiIcons.gestureSwipe),
|
||||
title: const Text('Gestures'),
|
||||
subtitle: Text(active ? 'Active' : 'Suspended'),
|
||||
value: active,
|
||||
onChanged: (value) async {
|
||||
await ref
|
||||
.read(gestureSettingsRepositoryProvider.notifier)
|
||||
.updateSettings((s) => s.copyWith(active: value));
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Tab Actions Card ───
|
||||
|
||||
class _TabActionsCard extends HookConsumerWidget {
|
||||
|
||||
+16
@@ -55,6 +55,8 @@ import 'package:weblibre/features/geckoview/features/tabs/domain/providers/selec
|
||||
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/container.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/tab.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/domain/services/local_index_pruner.dart';
|
||||
import 'package:weblibre/features/gestures/domain/services/gesture_control.dart';
|
||||
import 'package:weblibre/features/gestures/presentation/widgets/gesture_feedback_overlay.dart';
|
||||
import 'package:weblibre/features/intent_gatekeeper/domain/entities/intent_source_policy.dart';
|
||||
import 'package:weblibre/features/intent_gatekeeper/domain/entities/pending_intent_decision.dart';
|
||||
import 'package:weblibre/features/intent_gatekeeper/domain/services/intent_gatekeeper.dart';
|
||||
@@ -304,6 +306,7 @@ class _BrowserViewState extends ConsumerState<BrowserView>
|
||||
),
|
||||
),
|
||||
if (showHome) const Positioned.fill(child: BrowserHome()),
|
||||
const Positioned.fill(child: GestureFeedbackOverlay()),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -610,6 +613,19 @@ class _BrowserViewState extends ConsumerState<BrowserView>
|
||||
},
|
||||
);
|
||||
|
||||
ref.listenManual(
|
||||
fireImmediately: true,
|
||||
gestureControlServiceProvider,
|
||||
(previous, next) {},
|
||||
onError: (error, stackTrace) {
|
||||
logger.e(
|
||||
'Error listening to gestureControlServiceProvider',
|
||||
error: error,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
ref.listenManual(
|
||||
fireImmediately: true,
|
||||
proxySettingsReplicationProvider,
|
||||
|
||||
+2
-2
@@ -42,7 +42,7 @@ final class GeckoInferenceRepositoryProvider
|
||||
}
|
||||
|
||||
String _$geckoInferenceRepositoryHash() =>
|
||||
r'c4f52d2edfb8c5763577a17697202016645177da';
|
||||
r'cd6d47ccb5aa8d64aba81ac1d982b1df8cf64d14';
|
||||
|
||||
abstract class _$GeckoInferenceRepository extends $Notifier<void> {
|
||||
void build();
|
||||
@@ -389,7 +389,7 @@ final class ContainerTabSuggestionsProvider
|
||||
}
|
||||
|
||||
String _$containerTabSuggestionsHash() =>
|
||||
r'958c7432aa5c2a2828fcccd0127e0110d0a008cf';
|
||||
r'a29a43773000b415f3e8a23db281078c30c3b10d';
|
||||
|
||||
final class ContainerTabSuggestionsFamily extends $Family
|
||||
with $FunctionalFamilyOverride<FutureOr<List<String>?>, String?> {
|
||||
|
||||
Reference in New Issue
Block a user