refactor tabs
This commit is contained in:
+73
-100
@@ -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,
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user