refactor tabs

This commit is contained in:
Fabian Freund
2025-10-01 12:57:00 +02:00
parent aff82ce4ae
commit 004532d8ae
2 changed files with 80 additions and 124 deletions
@@ -50,6 +50,39 @@ import 'package:weblibre/presentation/hooks/listenable_callback.dart';
import 'package:weblibre/presentation/widgets/speech_to_text_button.dart'; import 'package:weblibre/presentation/widgets/speech_to_text_button.dart';
import 'package:weblibre/utils/ui_helper.dart' as ui_helper; import 'package:weblibre/utils/ui_helper.dart' as ui_helper;
int calculateCrossAxisItemCount({
required double screenWidth,
required double horizontalPadding,
required double crossAxisSpacing,
}) {
final totalHorizontalPadding = horizontalPadding * 2;
final availableWidth =
screenWidth - totalHorizontalPadding - crossAxisSpacing;
final crossAxisCount = availableWidth ~/ 180.0;
return crossAxisCount;
}
double calculateItemHeight({
required double screenWidth,
required double childAspectRatio,
required double horizontalPadding,
required double mainAxisSpacing,
required double crossAxisSpacing,
required int crossAxisCount,
}) {
final totalHorizontalPadding = horizontalPadding * 2;
final totalCrossAxisSpacing = crossAxisSpacing * (crossAxisCount - 1);
final availableWidth =
screenWidth - totalHorizontalPadding - totalCrossAxisSpacing;
final itemWidth = availableWidth / crossAxisCount;
final itemHeight = itemWidth / childAspectRatio;
final totalItemHeight = itemHeight + mainAxisSpacing;
return totalItemHeight;
}
class _TabDraggable extends HookConsumerWidget { class _TabDraggable extends HookConsumerWidget {
final TabEntity entity; final TabEntity entity;
final String? suggestedContainerId; final String? suggestedContainerId;
@@ -84,7 +117,17 @@ class _TabDraggable extends HookConsumerWidget {
key: ValueKey(entity.tabId), key: ValueKey(entity.tabId),
tabId: entity.tabId, tabId: entity.tabId,
activeTabId: activeTab, activeTabId: activeTab,
containerId: suggestedContainerId!, onTap: () async {
final containerData = await ref
.read(containerRepositoryProvider.notifier)
.getContainerData(suggestedContainerId!);
if (containerData != null) {
await ref
.read(tabDataRepositoryProvider.notifier)
.assignContainer(entity.tabId, containerData);
}
},
) )
: SingleTabPreview( : SingleTabPreview(
key: ValueKey(entity.tabId), key: ValueKey(entity.tabId),
@@ -331,39 +374,6 @@ class ViewTabsSheetWidget extends HookConsumerWidget {
super.key, super.key,
}); });
int _calculateCrossAxisItemCount({
required double screenWidth,
required double horizontalPadding,
required double crossAxisSpacing,
}) {
final totalHorizontalPadding = horizontalPadding * 2;
final availableWidth =
screenWidth - totalHorizontalPadding - crossAxisSpacing;
final crossAxisCount = availableWidth ~/ 180.0;
return crossAxisCount;
}
double _calculateItemHeight({
required double screenWidth,
required double childAspectRatio,
required double horizontalPadding,
required double mainAxisSpacing,
required double crossAxisSpacing,
required int crossAxisCount,
}) {
final totalHorizontalPadding = horizontalPadding * 2;
final totalCrossAxisSpacing = crossAxisSpacing * (crossAxisCount - 1);
final availableWidth =
screenWidth - totalHorizontalPadding - totalCrossAxisSpacing;
final itemWidth = availableWidth / crossAxisCount;
final itemHeight = itemWidth / childAspectRatio;
final totalItemHeight = itemHeight + mainAxisSpacing;
return totalItemHeight;
}
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
return Stack( return Stack(
@@ -423,7 +433,7 @@ class ViewTabsSheetWidget extends HookConsumerWidget {
final activeTab = ref.watch(selectedTabProvider); final activeTab = ref.watch(selectedTabProvider);
final crossAxisCount = useMemoized(() { final crossAxisCount = useMemoized(() {
final calculatedCount = _calculateCrossAxisItemCount( final calculatedCount = calculateCrossAxisItemCount(
screenWidth: screenWidth, screenWidth: screenWidth,
horizontalPadding: 4.0, horizontalPadding: 4.0,
crossAxisSpacing: 8.0, crossAxisSpacing: 8.0,
@@ -433,7 +443,7 @@ class ViewTabsSheetWidget extends HookConsumerWidget {
}, [screenWidth, itemCount]); }, [screenWidth, itemCount]);
final itemHeight = useMemoized( final itemHeight = useMemoized(
() => _calculateItemHeight( () => calculateItemHeight(
screenWidth: screenWidth, screenWidth: screenWidth,
childAspectRatio: 0.75, childAspectRatio: 0.75,
horizontalPadding: 4.0, horizontalPadding: 4.0,
@@ -628,37 +638,6 @@ class ViewTabTreesSheetWidget extends HookConsumerWidget {
super.key, super.key,
}); });
int _calculateCrossAxisItemCount({
required double screenWidth,
required double horizontalPadding,
required double crossAxisSpacing,
}) {
final totalHorizontalPadding = horizontalPadding * 2;
final availableWidth =
screenWidth - totalHorizontalPadding - crossAxisSpacing;
final crossAxisCount = availableWidth ~/ 180.0;
return crossAxisCount;
}
Size _calculateItemSize({
required double screenWidth,
required double childAspectRatio,
required double horizontalPadding,
required double crossAxisSpacing,
required int crossAxisCount,
}) {
final totalHorizontalPadding = horizontalPadding * 2;
final totalCrossAxisSpacing = crossAxisSpacing * (crossAxisCount - 1);
final availableWidth =
screenWidth - totalHorizontalPadding - totalCrossAxisSpacing;
final itemWidth = availableWidth / crossAxisCount;
final itemHeight = itemWidth / childAspectRatio;
return Size(itemWidth, itemHeight);
}
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
return Stack( return Stack(
@@ -670,6 +649,8 @@ class ViewTabTreesSheetWidget extends HookConsumerWidget {
Expanded( Expanded(
child: HookConsumer( child: HookConsumer(
builder: (context, ref, child) { builder: (context, ref, child) {
final screenWidth = MediaQuery.of(context).size.width;
final filteredTabEntities = ref.watch( final filteredTabEntities = ref.watch(
seamlessFilteredTabEntitiesProvider( seamlessFilteredTabEntitiesProvider(
searchPartition: TabSearchPartition.preview, searchPartition: TabSearchPartition.preview,
@@ -682,40 +663,32 @@ class ViewTabTreesSheetWidget extends HookConsumerWidget {
final activeTab = ref.watch(selectedTabProvider); final activeTab = ref.watch(selectedTabProvider);
final crossAxisCount = useMemoized( final crossAxisCount = useMemoized(() {
() { final calculatedCount = calculateCrossAxisItemCount(
final calculatedCount = _calculateCrossAxisItemCount( screenWidth: screenWidth,
screenWidth: MediaQuery.of(context).size.width, horizontalPadding: 4.0,
horizontalPadding: 4.0, crossAxisSpacing: 8.0,
crossAxisSpacing: 8.0, );
);
return math.max( return math.max(
math.min( math.min(
calculatedCount, calculatedCount,
filteredTabEntities.value.length, filteredTabEntities.value.length,
), ),
2, 2,
); );
}, }, [screenWidth, filteredTabEntities.value.length]);
[
MediaQuery.of(context).size.width,
filteredTabEntities.value.length,
],
);
final itemSize = useMemoized( final itemHeight = useMemoized(
() => () => calculateItemHeight(
_calculateItemSize( screenWidth: screenWidth,
screenWidth: MediaQuery.of(context).size.width, childAspectRatio: 0.75,
childAspectRatio: 0.75, horizontalPadding: 4.0,
horizontalPadding: 4.0, crossAxisSpacing: 8.0,
crossAxisSpacing: 8.0, crossAxisCount: crossAxisCount,
crossAxisCount: crossAxisCount, mainAxisSpacing: 8.0,
) + ),
//mainAxisSpacing [screenWidth, crossAxisCount],
const Offset(0, 8.0),
[MediaQuery.of(context).size.width, crossAxisCount],
); );
useEffect(() { useEffect(() {
@@ -724,7 +697,7 @@ class ViewTabTreesSheetWidget extends HookConsumerWidget {
); );
if (index > -1) { if (index > -1) {
final offset = (index ~/ 2) * itemSize.height; final offset = (index ~/ 2) * itemHeight;
if (offset != sheetScrollController.offset) { if (offset != sheetScrollController.offset) {
unawaited( unawaited(
@@ -33,7 +33,6 @@ import 'package:weblibre/features/geckoview/features/find_in_page/domain/entitie
import 'package:weblibre/features/geckoview/features/find_in_page/presentation/controllers/find_in_page.dart'; import 'package:weblibre/features/geckoview/features/find_in_page/presentation/controllers/find_in_page.dart';
import 'package:weblibre/features/geckoview/features/tabs/data/entities/tab_entity.dart'; import 'package:weblibre/features/geckoview/features/tabs/data/entities/tab_entity.dart';
import 'package:weblibre/features/geckoview/features/tabs/domain/providers.dart'; 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/tabs/domain/repositories/tab.dart';
import 'package:weblibre/presentation/hooks/menu_controller.dart'; import 'package:weblibre/presentation/hooks/menu_controller.dart';
import 'package:weblibre/utils/ui_helper.dart' as ui_helper; import 'package:weblibre/utils/ui_helper.dart' as ui_helper;
@@ -380,46 +379,30 @@ class SingleTabPreview extends HookConsumerWidget {
} }
} }
class SuggestedSingleTabPreview extends HookConsumerWidget { class SuggestedSingleTabPreview extends StatelessWidget {
final String tabId; final String tabId;
final String containerId;
final String? activeTabId; final String? activeTabId;
final void Function()? onTap;
const SuggestedSingleTabPreview({ const SuggestedSingleTabPreview({
required this.tabId, required this.tabId,
required this.containerId,
required this.activeTabId, required this.activeTabId,
this.onTap,
super.key, super.key,
}); });
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context) {
final hasTabState = ref.watch(
tabStateProvider(tabId).select((value) => value != null),
);
if (!hasTabState) {
return const SizedBox.shrink();
}
return Opacity( return Opacity(
opacity: 0.5, opacity: 0.5,
child: TabPreview( child: TabPreview(
tabId: tabId, tabId: tabId,
isActive: tabId == activeTabId, isActive: tabId == activeTabId,
onTap: () async { onTap: onTap,
final containerData = await ref
.read(containerRepositoryProvider.notifier)
.getContainerData(containerId);
if (containerData != null) {
await ref
.read(tabDataRepositoryProvider.notifier)
.assignContainer(tabId, containerData);
}
},
trailingChild: const IconButton( trailingChild: const IconButton(
visualDensity: VisualDensity(horizontal: -4.0, vertical: -4.0),
icon: Icon(MdiIcons.creation), icon: Icon(MdiIcons.creation),
onPressed: null, onPressed: null,
), ),