setting to show close button on new/edit tab screen

This commit is contained in:
Fabian Freund
2026-06-06 08:26:03 +02:00
parent b0ac6c97b0
commit 69aad79b93
6 changed files with 95 additions and 2 deletions
@@ -22,6 +22,7 @@ import 'dart:async';
import 'package:fading_scroll/fading_scroll.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:weblibre/core/design/app_colors.dart';
import 'package:weblibre/core/routing/routes.dart';
@@ -627,6 +628,12 @@ class SearchScreen extends HookConsumerWidget {
};
}
// Whether to surface an in-app close button so the page can be dismissed
// without a system back button/gesture (opt-in, e.g. for e-ink devices).
// Only meaningful when there is a route to pop back to.
final showCloseButton =
context.canPop() && settings.showSearchCloseButton;
return Scaffold(
body: SafeArea(
child: Form(
@@ -638,11 +645,22 @@ class SearchScreen extends HookConsumerWidget {
floating: true,
pinned: true,
automaticallyImplyLeading: false,
leading: showCloseButton
? IconButton(
tooltip: 'Close',
icon: const Icon(Icons.close),
onPressed: () => context.pop(),
)
: null,
backgroundColor: colorScheme.surface,
scrolledUnderElevation: 0,
shadowColor: Colors.transparent,
surfaceTintColor: Colors.transparent,
toolbarHeight: isEditMode ? 0 : kToolbarHeight,
// Collapse the toolbar in edit mode (no tab-type switcher), but
// keep it when the close button needs somewhere to render.
toolbarHeight: (isEditMode && !showCloseButton)
? 0
: kToolbarHeight,
titleSpacing: 0.0,
title: isEditMode
? null
@@ -76,6 +76,21 @@ const List<SettingsSectionDefinition> generalSettingsSections = [
keywords: ['dialogs', 'bottom sheets', 'overlay'],
child: _ShowModalBarrierTile(),
),
SettingsEntryDefinition(
title: 'Show Close Button',
subtitle: 'Add a button to dismiss the search / new-tab page without '
'a back gesture',
keywords: [
'back',
'close',
'dismiss',
'e-ink',
'eink',
'accessibility',
'new tab',
],
child: _ShowSearchCloseButtonTile(),
),
],
),
SettingsSectionDefinition(
@@ -282,6 +297,37 @@ class _ShowModalBarrierTile extends HookConsumerWidget {
}
}
class _ShowSearchCloseButtonTile extends HookConsumerWidget {
const _ShowSearchCloseButtonTile();
@override
Widget build(BuildContext context, WidgetRef ref) {
final showSearchCloseButton = ref.watch(
generalSettingsWithDefaultsProvider.select(
(s) => s.showSearchCloseButton,
),
);
return SwitchListTile.adaptive(
title: const Text('Show Close Button'),
subtitle: const Text(
'Add a button to dismiss the search / new-tab page without a back '
'gesture, useful on devices without a back button',
),
secondary: const Icon(Icons.close),
value: showSearchCloseButton,
onChanged: (value) async {
await ref
.read(saveGeneralSettingsControllerProvider.notifier)
.save(
(currentSettings) =>
currentSettings.copyWith.showSearchCloseButton(value),
);
},
);
}
}
class _PureBlackTile extends HookConsumerWidget {
const _PureBlackTile();
@@ -91,6 +91,11 @@ class GeneralSettings with FastEquatable {
final bool enableLocalAiFeatures;
final bool showContainerUi;
final bool showIsolatedTabUi;
/// Whether the search / new-tab page shows a leading close button so it can
/// be dismissed without a system back button or back gesture (e.g. on e-ink
/// devices). Defaults to false. Only shown when the route can be popped.
final bool showSearchCloseButton;
@JsonKey(name: 'defaultCreateTabType')
final TabType storedDefaultCreateTabType;
final TabDirection tabListDirection;
@@ -164,6 +169,7 @@ class GeneralSettings with FastEquatable {
required this.enableLocalAiFeatures,
required this.showContainerUi,
required this.showIsolatedTabUi,
required this.showSearchCloseButton,
required this.storedDefaultCreateTabType,
required this.tabListDirection,
required this.tabBarDirection,
@@ -225,6 +231,7 @@ class GeneralSettings with FastEquatable {
bool? enableLocalAiFeatures,
bool? showContainerUi,
bool? showIsolatedTabUi,
bool? showSearchCloseButton,
TabType? storedDefaultCreateTabType,
TabDirection? tabListDirection,
TabDirection? tabBarDirection,
@@ -283,6 +290,7 @@ class GeneralSettings with FastEquatable {
enableLocalAiFeatures = enableLocalAiFeatures ?? true,
showContainerUi = showContainerUi ?? true,
showIsolatedTabUi = showIsolatedTabUi ?? true,
showSearchCloseButton = showSearchCloseButton ?? false,
storedDefaultCreateTabType =
storedDefaultCreateTabType ?? TabType.regular,
tabListDirection = tabListDirection ?? TabDirection.newestFirst,
@@ -406,6 +414,7 @@ class GeneralSettings with FastEquatable {
enableLocalAiFeatures,
showContainerUi,
showIsolatedTabUi,
showSearchCloseButton,
storedDefaultCreateTabType,
tabListDirection,
tabBarDirection,
@@ -39,6 +39,8 @@ abstract class _$GeneralSettingsCWProxy {
GeneralSettings showIsolatedTabUi(bool showIsolatedTabUi);
GeneralSettings showSearchCloseButton(bool showSearchCloseButton);
GeneralSettings storedDefaultCreateTabType(
TabType storedDefaultCreateTabType,
);
@@ -167,6 +169,7 @@ abstract class _$GeneralSettingsCWProxy {
bool enableLocalAiFeatures,
bool showContainerUi,
bool showIsolatedTabUi,
bool showSearchCloseButton,
TabType storedDefaultCreateTabType,
TabDirection tabListDirection,
TabDirection tabBarDirection,
@@ -279,6 +282,10 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy {
GeneralSettings showIsolatedTabUi(bool showIsolatedTabUi) =>
call(showIsolatedTabUi: showIsolatedTabUi);
@override
GeneralSettings showSearchCloseButton(bool showSearchCloseButton) =>
call(showSearchCloseButton: showSearchCloseButton);
@override
GeneralSettings storedDefaultCreateTabType(
TabType storedDefaultCreateTabType,
@@ -490,6 +497,7 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy {
Object? enableLocalAiFeatures = const $CopyWithPlaceholder(),
Object? showContainerUi = const $CopyWithPlaceholder(),
Object? showIsolatedTabUi = const $CopyWithPlaceholder(),
Object? showSearchCloseButton = const $CopyWithPlaceholder(),
Object? storedDefaultCreateTabType = const $CopyWithPlaceholder(),
Object? tabListDirection = const $CopyWithPlaceholder(),
Object? tabBarDirection = const $CopyWithPlaceholder(),
@@ -616,6 +624,12 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy {
? _value.showIsolatedTabUi
// ignore: cast_nullable_to_non_nullable
: showIsolatedTabUi as bool,
showSearchCloseButton:
showSearchCloseButton == const $CopyWithPlaceholder() ||
showSearchCloseButton == null
? _value.showSearchCloseButton
// ignore: cast_nullable_to_non_nullable
: showSearchCloseButton as bool,
storedDefaultCreateTabType:
storedDefaultCreateTabType == const $CopyWithPlaceholder() ||
storedDefaultCreateTabType == null
@@ -916,6 +930,7 @@ GeneralSettings _$GeneralSettingsFromJson(
enableLocalAiFeatures: json['enableLocalAiFeatures'] as bool?,
showContainerUi: json['showContainerUi'] as bool?,
showIsolatedTabUi: json['showIsolatedTabUi'] as bool?,
showSearchCloseButton: json['showSearchCloseButton'] as bool?,
storedDefaultCreateTabType: $enumDecodeNullable(
_$TabTypeEnumMap,
json['defaultCreateTabType'],
@@ -1029,6 +1044,7 @@ Map<String, dynamic> _$GeneralSettingsToJson(
'enableLocalAiFeatures': instance.enableLocalAiFeatures,
'showContainerUi': instance.showContainerUi,
'showIsolatedTabUi': instance.showIsolatedTabUi,
'showSearchCloseButton': instance.showSearchCloseButton,
'defaultCreateTabType':
_$TabTypeEnumMap[instance.storedDefaultCreateTabType]!,
'tabListDirection': _$TabDirectionEnumMap[instance.tabListDirection]!,
@@ -269,6 +269,10 @@ class GeneralSettingsRepository extends _$GeneralSettingsRepository {
DriftSqlType.bool,
db.typeMapping,
),
'showSearchCloseButton': settings['showSearchCloseButton']?.readAs(
DriftSqlType.bool,
db.typeMapping,
),
});
}
@@ -35,7 +35,7 @@ final class GeneralSettingsRepositoryProvider
}
String _$generalSettingsRepositoryHash() =>
r'5036124c086e35c0e4616a0fd3b2276adb66dd5f';
r'6cf0832a8497c94a813e06556c048a1010be74e1';
abstract class _$GeneralSettingsRepository
extends $StreamNotifier<GeneralSettings> {