auto hide add new tab button

This commit is contained in:
Fabian Freund
2026-01-01 08:12:39 +01:00
parent 01d5f70ad0
commit 5495d0c1cd
4 changed files with 170 additions and 45 deletions
@@ -27,6 +27,7 @@ import 'package:weblibre/features/geckoview/features/browser/presentation/widget
import 'package:weblibre/features/geckoview/features/browser/presentation/widgets/tab_view/tab_list_view.dart';
import 'package:weblibre/features/geckoview/features/browser/presentation/widgets/tab_view/tab_tree_view.dart';
import 'package:weblibre/features/user/domain/repositories/general_settings.dart';
import 'package:weblibre/presentation/hooks/scroll_visibility.dart';
class TabViewScreen extends HookConsumerWidget {
const TabViewScreen();
@@ -38,6 +39,9 @@ class TabViewScreen extends HookConsumerWidget {
final scrollController = useScrollController(keys: [tabsReorderable]);
// Track FAB visibility based on scroll direction
final isFabVisible = useScrollVisibility(scrollController);
return Dialog.fullscreen(
child: Scaffold(
body: SafeArea(
@@ -69,21 +73,30 @@ class TabViewScreen extends HookConsumerWidget {
),
},
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
final settings = ref.read(generalSettingsWithDefaultsProvider);
floatingActionButton: AnimatedSlide(
duration: const Duration(milliseconds: 200),
offset: isFabVisible.value ? Offset.zero : const Offset(0, 2),
curve: Curves.easeInOut,
child: AnimatedOpacity(
duration: const Duration(milliseconds: 200),
opacity: isFabVisible.value ? 1.0 : 0.0,
child: FloatingActionButton(
onPressed: () async {
final settings = ref.read(generalSettingsWithDefaultsProvider);
await SearchRoute(
tabType:
ref.read(selectedTabTypeProvider) ??
settings.defaultCreateTabType,
).push(context);
await SearchRoute(
tabType:
ref.read(selectedTabTypeProvider) ??
settings.defaultCreateTabType,
).push(context);
if (context.mounted) {
const BrowserRoute().go(context);
}
},
child: const Icon(Icons.add),
if (context.mounted) {
const BrowserRoute().go(context);
}
},
child: const Icon(Icons.add),
),
),
),
),
);
@@ -27,6 +27,7 @@ import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/co
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/tab.dart';
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/tab_search.dart';
import 'package:weblibre/features/user/domain/repositories/general_settings.dart';
import 'package:weblibre/presentation/hooks/scroll_visibility.dart';
class _TabDraggable extends HookConsumerWidget {
final TabEntity entity;
@@ -400,6 +401,9 @@ class ViewTabGridWidget extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
// Track FAB visibility based on scroll direction
final isFabVisible = useScrollVisibility(scrollController);
return Stack(
alignment: Alignment.bottomRight,
children: [
@@ -431,24 +435,33 @@ class ViewTabGridWidget extends HookConsumerWidget {
),
),
if (showNewTabFab)
Padding(
padding: const EdgeInsets.only(
top: TabViewHeader.headerSize + 4,
right: 4,
),
child: FloatingActionButton.small(
onPressed: () async {
final settings = ref.read(generalSettingsWithDefaultsProvider);
AnimatedSlide(
duration: const Duration(milliseconds: 200),
offset: isFabVisible.value ? Offset.zero : const Offset(0, 2),
curve: Curves.easeInOut,
child: AnimatedOpacity(
duration: const Duration(milliseconds: 200),
opacity: isFabVisible.value ? 1.0 : 0.0,
child: Padding(
padding: const EdgeInsets.only(
top: TabViewHeader.headerSize + 4,
right: 4,
),
child: FloatingActionButton.small(
onPressed: () async {
final settings = ref.read(generalSettingsWithDefaultsProvider);
await SearchRoute(
tabType:
ref.read(selectedTabTypeProvider) ??
settings.defaultCreateTabType,
).push(context);
await SearchRoute(
tabType:
ref.read(selectedTabTypeProvider) ??
settings.defaultCreateTabType,
).push(context);
onClose();
},
child: const Icon(Icons.add),
onClose();
},
child: const Icon(Icons.add),
),
),
),
),
],
@@ -25,6 +25,7 @@ import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/co
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/tab.dart';
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/tab_search.dart';
import 'package:weblibre/features/user/domain/repositories/general_settings.dart';
import 'package:weblibre/presentation/hooks/scroll_visibility.dart';
class _TabDraggable extends HookConsumerWidget {
final TabEntity entity;
@@ -369,6 +370,9 @@ class ViewTabListWidget extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
// Track FAB visibility based on scroll direction
final isFabVisible = useScrollVisibility(scrollController);
return Stack(
alignment: Alignment.bottomRight,
children: [
@@ -400,24 +404,33 @@ class ViewTabListWidget extends HookConsumerWidget {
),
),
if (showNewTabFab)
Padding(
padding: const EdgeInsets.only(
top: TabViewHeader.headerSize + 4,
right: 4,
),
child: FloatingActionButton.small(
onPressed: () async {
final settings = ref.read(generalSettingsWithDefaultsProvider);
AnimatedSlide(
duration: const Duration(milliseconds: 200),
offset: isFabVisible.value ? Offset.zero : const Offset(0, 2),
curve: Curves.easeInOut,
child: AnimatedOpacity(
duration: const Duration(milliseconds: 200),
opacity: isFabVisible.value ? 1.0 : 0.0,
child: Padding(
padding: const EdgeInsets.only(
top: TabViewHeader.headerSize + 4,
right: 4,
),
child: FloatingActionButton.small(
onPressed: () async {
final settings = ref.read(generalSettingsWithDefaultsProvider);
await SearchRoute(
tabType:
ref.read(selectedTabTypeProvider) ??
settings.defaultCreateTabType,
).push(context);
await SearchRoute(
tabType:
ref.read(selectedTabTypeProvider) ??
settings.defaultCreateTabType,
).push(context);
onClose();
},
child: const Icon(Icons.add),
onClose();
},
child: const Icon(Icons.add),
),
),
),
),
],