samsung tap scroll setting

This commit is contained in:
Fabian Freund
2026-05-06 18:18:07 +02:00
parent 581a5b662b
commit d5f977a3d2
14 changed files with 3364 additions and 2204 deletions
@@ -141,6 +141,23 @@ class EngineSettingsReplicationService
},
);
ref.listen(
fireImmediately: true,
generalSettingsWithDefaultsProvider.select(
(settings) => settings.browserHandlingScrollEnabled,
),
(previous, next) async {
await _service.setBrowserHandlingScrollEnabled(next);
},
onError: (error, stackTrace) {
logger.e(
'Error listening to browserHandlingScrollEnabled',
error: error,
stackTrace: stackTrace,
);
},
);
ref.listen(
fireImmediately: true,
generalSettingsWithDefaultsProvider.select(
@@ -44,7 +44,7 @@ final class EngineSettingsReplicationServiceProvider
}
String _$engineSettingsReplicationServiceHash() =>
r'8f37476c9beecd6cc70a07b8cd3a51864b077176';
r'f38eb7631e56b3520ea92e82bd6df31ca4234471';
abstract class _$EngineSettingsReplicationService extends $Notifier<void> {
void build();
@@ -25,7 +25,9 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:weblibre/features/settings/presentation/controllers/save_settings.dart';
import 'package:weblibre/features/settings/presentation/widgets/sections.dart';
import 'package:weblibre/features/user/data/models/engine_settings.dart';
import 'package:weblibre/features/user/data/models/general_settings.dart';
import 'package:weblibre/features/user/domain/presentation/dialogs/quit_browser_dialog.dart';
import 'package:weblibre/features/user/domain/repositories/general_settings.dart';
import 'package:weblibre/features/user/domain/repositories/engine_settings.dart';
import 'package:weblibre/utils/exit_app.dart';
@@ -44,6 +46,9 @@ class ExperimentalSettingsScreen extends StatelessWidget {
controller: controller,
padding: const EdgeInsets.symmetric(horizontal: 12.0),
children: const [
SettingSection(name: 'Browser Touch Diagnostics'),
_TouchDiagnosticsInfoTile(),
_BrowserHandlingScrollEnabledTile(),
SettingSection(name: 'Web Push'),
_UnifiedPushDistributorTile(),
SettingSection(name: 'Runtime & Startup'),
@@ -58,6 +63,51 @@ class ExperimentalSettingsScreen extends StatelessWidget {
}
}
class _TouchDiagnosticsInfoTile extends StatelessWidget {
const _TouchDiagnosticsInfoTile();
@override
Widget build(BuildContext context) {
return const ListTile(
leading: Icon(MdiIcons.bugOutline),
title: Text('Samsung tap-scroll checks'),
subtitle: Text(
'For issue #284, test in this order: disable Pull to Refresh, disable Auto-hide Tab Bar, then disable the native scroll detector below.',
),
);
}
}
class _BrowserHandlingScrollEnabledTile extends HookConsumerWidget {
const _BrowserHandlingScrollEnabledTile();
@override
Widget build(BuildContext context, WidgetRef ref) {
final browserHandlingScrollEnabled = ref.watch(
generalSettingsWithDefaultsProvider.select(
(s) => s.browserHandlingScrollEnabled,
),
);
return SwitchListTile.adaptive(
title: const Text('Native Gecko Scroll Detector'),
subtitle: const Text(
'Lets native Gecko touch handling decide when the browser toolbar may react to page scrolling. Turn this off to test Samsung tap-scroll issues.',
),
secondary: const Icon(Icons.touch_app),
value: browserHandlingScrollEnabled,
onChanged: (value) async {
await ref
.read(saveGeneralSettingsControllerProvider.notifier)
.save(
(currentSettings) =>
currentSettings.copyWith.browserHandlingScrollEnabled(value),
);
},
);
}
}
class _UnifiedPushDistributorTile extends StatelessWidget {
const _UnifiedPushDistributorTile();
@@ -99,6 +99,7 @@ class GeneralSettings with FastEquatable {
final TabBarLayout tabBarLayout;
final QuickTabSwitcherMode quickTabSwitcherMode;
final bool pullToRefreshEnabled;
final bool browserHandlingScrollEnabled;
final bool useExternalDownloadManager;
final bool doubleBackCloseTab;
final Duration unassignedTabsAutoCleanInterval;
@@ -154,6 +155,7 @@ class GeneralSettings with FastEquatable {
required this.tabBarLayout,
required this.quickTabSwitcherMode,
required this.pullToRefreshEnabled,
required this.browserHandlingScrollEnabled,
required this.useExternalDownloadManager,
required this.doubleBackCloseTab,
required this.unassignedTabsAutoCleanInterval,
@@ -210,6 +212,7 @@ class GeneralSettings with FastEquatable {
TabBarLayout? tabBarLayout,
QuickTabSwitcherMode? quickTabSwitcherMode,
bool? pullToRefreshEnabled,
bool? browserHandlingScrollEnabled,
bool? useExternalDownloadManager,
bool? doubleBackCloseTab,
Duration? unassignedTabsAutoCleanInterval,
@@ -267,6 +270,7 @@ class GeneralSettings with FastEquatable {
quickTabSwitcherMode =
quickTabSwitcherMode ?? QuickTabSwitcherMode.lastUsedTabs,
pullToRefreshEnabled = pullToRefreshEnabled ?? true,
browserHandlingScrollEnabled = browserHandlingScrollEnabled ?? true,
useExternalDownloadManager = useExternalDownloadManager ?? false,
doubleBackCloseTab = doubleBackCloseTab ?? true,
unassignedTabsAutoCleanInterval =
@@ -379,6 +383,7 @@ class GeneralSettings with FastEquatable {
tabBarLayout,
quickTabSwitcherMode,
pullToRefreshEnabled,
browserHandlingScrollEnabled,
useExternalDownloadManager,
doubleBackCloseTab,
unassignedTabsAutoCleanInterval,
@@ -75,6 +75,10 @@ abstract class _$GeneralSettingsCWProxy {
GeneralSettings pullToRefreshEnabled(bool pullToRefreshEnabled);
GeneralSettings browserHandlingScrollEnabled(
bool browserHandlingScrollEnabled,
);
GeneralSettings useExternalDownloadManager(bool useExternalDownloadManager);
GeneralSettings doubleBackCloseTab(bool doubleBackCloseTab);
@@ -169,6 +173,7 @@ abstract class _$GeneralSettingsCWProxy {
TabBarLayout tabBarLayout,
QuickTabSwitcherMode quickTabSwitcherMode,
bool pullToRefreshEnabled,
bool browserHandlingScrollEnabled,
bool useExternalDownloadManager,
bool doubleBackCloseTab,
Duration unassignedTabsAutoCleanInterval,
@@ -322,6 +327,11 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy {
GeneralSettings pullToRefreshEnabled(bool pullToRefreshEnabled) =>
call(pullToRefreshEnabled: pullToRefreshEnabled);
@override
GeneralSettings browserHandlingScrollEnabled(
bool browserHandlingScrollEnabled,
) => call(browserHandlingScrollEnabled: browserHandlingScrollEnabled);
@override
GeneralSettings useExternalDownloadManager(bool useExternalDownloadManager) =>
call(useExternalDownloadManager: useExternalDownloadManager);
@@ -467,6 +477,7 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy {
Object? tabBarLayout = const $CopyWithPlaceholder(),
Object? quickTabSwitcherMode = const $CopyWithPlaceholder(),
Object? pullToRefreshEnabled = const $CopyWithPlaceholder(),
Object? browserHandlingScrollEnabled = const $CopyWithPlaceholder(),
Object? useExternalDownloadManager = const $CopyWithPlaceholder(),
Object? doubleBackCloseTab = const $CopyWithPlaceholder(),
Object? unassignedTabsAutoCleanInterval = const $CopyWithPlaceholder(),
@@ -657,6 +668,12 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy {
? _value.pullToRefreshEnabled
// ignore: cast_nullable_to_non_nullable
: pullToRefreshEnabled as bool,
browserHandlingScrollEnabled:
browserHandlingScrollEnabled == const $CopyWithPlaceholder() ||
browserHandlingScrollEnabled == null
? _value.browserHandlingScrollEnabled
// ignore: cast_nullable_to_non_nullable
: browserHandlingScrollEnabled as bool,
useExternalDownloadManager:
useExternalDownloadManager == const $CopyWithPlaceholder() ||
useExternalDownloadManager == null
@@ -888,6 +905,7 @@ GeneralSettings _$GeneralSettingsFromJson(
json['quickTabSwitcherMode'],
),
pullToRefreshEnabled: json['pullToRefreshEnabled'] as bool?,
browserHandlingScrollEnabled: json['browserHandlingScrollEnabled'] as bool?,
useExternalDownloadManager: json['useExternalDownloadManager'] as bool?,
doubleBackCloseTab: json['doubleBackCloseTab'] as bool?,
unassignedTabsAutoCleanInterval:
@@ -970,6 +988,7 @@ Map<String, dynamic> _$GeneralSettingsToJson(
'quickTabSwitcherMode':
_$QuickTabSwitcherModeEnumMap[instance.quickTabSwitcherMode]!,
'pullToRefreshEnabled': instance.pullToRefreshEnabled,
'browserHandlingScrollEnabled': instance.browserHandlingScrollEnabled,
'useExternalDownloadManager': instance.useExternalDownloadManager,
'doubleBackCloseTab': instance.doubleBackCloseTab,
'unassignedTabsAutoCleanInterval':
@@ -156,6 +156,8 @@ class GeneralSettingsRepository extends _$GeneralSettingsRepository {
DriftSqlType.bool,
db.typeMapping,
),
'browserHandlingScrollEnabled': settings['browserHandlingScrollEnabled']
?.readAs(DriftSqlType.bool, db.typeMapping),
'useExternalDownloadManager': settings['useExternalDownloadManager']
?.readAs(DriftSqlType.bool, db.typeMapping),
'doubleBackCloseTab': settings['doubleBackCloseTab']?.readAs(
@@ -35,7 +35,7 @@ final class GeneralSettingsRepositoryProvider
}
String _$generalSettingsRepositoryHash() =>
r'5fe717f8bccad163fa0cb8ec3294c4b00847e141';
r'36bbfdce0f33806dd0a73c416f5bf93e87bf74a1';
abstract class _$GeneralSettingsRepository
extends $StreamNotifier<GeneralSettings> {
@@ -569,7 +569,19 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
}
browserHandlingScrollFeature = BrowserHandlingScrollFeature(viewportEvents).also {
it.start()
if (GlobalComponents.browserHandlingScrollEnabled) {
it.start()
}
}
GlobalComponents.onBrowserHandlingScrollEnabledChanged = { enabled ->
browserHandlingScrollFeature?.let {
if (enabled) {
it.start()
} else {
it.stop()
}
}
}
}
@@ -686,6 +698,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
browserHandlingScrollFeature = null
GlobalComponents.onPullToRefreshEnabledChanged = null
GlobalComponents.onBrowserHandlingScrollEnabledChanged = null
GlobalComponents.onScreenshotProtectionEnabledChanged = null
val engineView = fragmentEngineView
engineView?.setActivityContext(null)
@@ -75,6 +75,14 @@ object GlobalComponents {
var onPullToRefreshEnabledChanged: ((Boolean) -> Unit)? = null
var browserHandlingScrollEnabled: Boolean = true
set(value) {
field = value
onBrowserHandlingScrollEnabledChanged?.invoke(value)
}
var onBrowserHandlingScrollEnabledChanged: ((Boolean) -> Unit)? = null
var screenshotProtectionEnabled: Boolean = false
set(value) {
field = value
@@ -419,6 +419,10 @@ class GeckoEngineSettingsApiImpl : GeckoEngineSettingsApi {
GlobalComponents.pullToRefreshEnabled = enabled
}
override fun setBrowserHandlingScrollEnabled(enabled: Boolean) {
GlobalComponents.browserHandlingScrollEnabled = enabled
}
override fun setScreenshotProtectionEnabled(enabled: Boolean) {
GlobalComponents.screenshotProtectionEnabled = enabled
}
@@ -6757,6 +6757,7 @@ interface GeckoEngineSettingsApi {
fun updateRuntimeSettings(settings: GeckoEngineSettings)
fun setScreenshotProtectionEnabled(enabled: Boolean)
fun setPullToRefreshEnabled(enabled: Boolean)
fun setBrowserHandlingScrollEnabled(enabled: Boolean)
/**
* Sets the app links mode preference (stored in SharedPreferences).
* Controls how external app links are handled in the browser.
@@ -6851,6 +6852,24 @@ interface GeckoEngineSettingsApi {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.setBrowserHandlingScrollEnabled$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val enabledArg = args[0] as Boolean
val wrapped: List<Any?> = try {
api.setBrowserHandlingScrollEnabled(enabledArg)
listOf(null)
} catch (exception: Throwable) {
GeckoPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.setAppLinksMode$separatedMessageChannelSuffix", codec)
if (api != null) {
@@ -197,6 +197,10 @@ class GeckoEngineSettingsService {
return _api.setPullToRefreshEnabled(enabled);
}
Future<void> setBrowserHandlingScrollEnabled(bool enabled) {
return _api.setBrowserHandlingScrollEnabled(enabled);
}
/// Sets the app links mode preference.
/// Controls how external app links are handled in browser.
Future<void> setAppLinksMode(AppLinksMode mode) {
File diff suppressed because it is too large Load Diff
@@ -1496,6 +1496,7 @@ abstract class GeckoEngineSettingsApi {
void updateRuntimeSettings(GeckoEngineSettings settings);
void setScreenshotProtectionEnabled(bool enabled);
void setPullToRefreshEnabled(bool enabled);
void setBrowserHandlingScrollEnabled(bool enabled);
/// Sets the app links mode preference (stored in SharedPreferences).
/// Controls how external app links are handled in the browser.