tab tree initial scroll
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:fast_equatable/fast_equatable.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
@@ -11,6 +12,55 @@ import 'package:weblibre/features/geckoview/domain/controllers/bottom_sheet.dart
|
||||
import 'package:weblibre/features/geckoview/domain/providers/selected_tab.dart';
|
||||
import 'package:weblibre/features/geckoview/features/browser/presentation/widgets/tab_preview.dart';
|
||||
import 'package:weblibre/features/geckoview/features/tabs/domain/providers.dart';
|
||||
import 'package:weblibre/utils/ui_helper.dart';
|
||||
|
||||
class BuchheimWalkerAlgorithmWithFocus extends BuchheimWalkerAlgorithm {
|
||||
bool _hasScrolled = false;
|
||||
|
||||
final Size childSize;
|
||||
final TransformationController transforamtionController;
|
||||
final dynamic initialNodeId;
|
||||
|
||||
BuchheimWalkerAlgorithmWithFocus(
|
||||
super.configuration,
|
||||
super.renderer, {
|
||||
required this.childSize,
|
||||
required this.transforamtionController,
|
||||
this.initialNodeId,
|
||||
});
|
||||
|
||||
@override
|
||||
void setFocusedNode(Node node) {
|
||||
final scale = transforamtionController.value.getMaxScaleOnAxis();
|
||||
final newPosition =
|
||||
(node.position - Offset(childSize.width / 2, childSize.height / 2)) *
|
||||
scale;
|
||||
|
||||
transforamtionController.value = transforamtionController.value.clone()
|
||||
..setTranslation(Vector3(-newPosition.dx, -newPosition.dy, 0));
|
||||
}
|
||||
|
||||
@override
|
||||
Size run(Graph? graph, double shiftX, double shiftY) {
|
||||
final size = super.run(graph, shiftX, shiftY);
|
||||
|
||||
if (initialNodeId != null && !_hasScrolled) {
|
||||
final node = graph?.nodes.firstWhereOrNull(
|
||||
(element) => element.key?.value == initialNodeId,
|
||||
);
|
||||
|
||||
if (node != null && node.position != Offset.zero) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
setFocusedNode(node);
|
||||
});
|
||||
|
||||
_hasScrolled = true;
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
class TabTreeDialog extends HookConsumerWidget {
|
||||
final String tabId;
|
||||
@@ -26,22 +76,11 @@ class TabTreeDialog extends HookConsumerWidget {
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final transforamtionController = useTransformationController();
|
||||
|
||||
final builder = useMemoized(() {
|
||||
final config = BuchheimWalkerConfiguration()
|
||||
..siblingSeparation = 100
|
||||
..levelSeparation = 150
|
||||
..subtreeSeparation = 150
|
||||
..orientation = BuchheimWalkerConfiguration.ORIENTATION_TOP_BOTTOM;
|
||||
|
||||
return BuchheimWalkerAlgorithm(config, TreeEdgeRenderer(config));
|
||||
});
|
||||
|
||||
final selectedTabId = ref.watch(selectedTabProvider);
|
||||
final tabs = ref.watch(tabDescendantsProvider(tabId));
|
||||
|
||||
final graph = useMemoized(() {
|
||||
final graph = Graph();
|
||||
graph.isTree = true;
|
||||
final graph = Graph()..isTree = true;
|
||||
|
||||
if (tabs.hasValue) {
|
||||
for (final MapEntry(:key, :value) in tabs.valueOrNull!.entries) {
|
||||
@@ -55,7 +94,23 @@ class TabTreeDialog extends HookConsumerWidget {
|
||||
}
|
||||
|
||||
return graph;
|
||||
}, [EquatableValue(tabs.valueOrNull)]);
|
||||
}, [EquatableValue(tabs.valueOrNull), selectedTabId]);
|
||||
|
||||
final graphAlgo = useMemoized(() {
|
||||
final config = BuchheimWalkerConfiguration()
|
||||
..siblingSeparation = 100
|
||||
..levelSeparation = 150
|
||||
..subtreeSeparation = 150
|
||||
..orientation = BuchheimWalkerConfiguration.ORIENTATION_TOP_BOTTOM;
|
||||
|
||||
return BuchheimWalkerAlgorithmWithFocus(
|
||||
config,
|
||||
TreeEdgeRenderer(config),
|
||||
childSize: childSize,
|
||||
transforamtionController: transforamtionController,
|
||||
initialNodeId: selectedTabId,
|
||||
);
|
||||
}, [selectedTabId]);
|
||||
|
||||
return Dialog.fullscreen(
|
||||
child: Scaffold(
|
||||
@@ -72,17 +127,18 @@ class TabTreeDialog extends HookConsumerWidget {
|
||||
floatingActionButton: FloatingActionButton(
|
||||
child: const Icon(MdiIcons.target),
|
||||
onPressed: () {
|
||||
final node = graph.getNodeUsingId(selectedTabId);
|
||||
final scale = transforamtionController.value.getMaxScaleOnAxis();
|
||||
final newPosition =
|
||||
(node.position -
|
||||
Offset(childSize.width / 2, childSize.height / 2)) *
|
||||
scale;
|
||||
final node = graph.nodes.firstWhereOrNull(
|
||||
(element) => element.key?.value == selectedTabId,
|
||||
);
|
||||
|
||||
transforamtionController.value =
|
||||
transforamtionController.value.clone()..setTranslation(
|
||||
Vector3(-newPosition.dx, -newPosition.dy, 0),
|
||||
);
|
||||
if (node != null) {
|
||||
graphAlgo.setFocusedNode(node);
|
||||
} else {
|
||||
showErrorMessage(
|
||||
context,
|
||||
'The current tab is not part of this tree',
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
extendBodyBehindAppBar: true,
|
||||
@@ -98,7 +154,7 @@ class TabTreeDialog extends HookConsumerWidget {
|
||||
replacement: const Bone.square(),
|
||||
child: GraphView(
|
||||
graph: graph,
|
||||
algorithm: builder,
|
||||
algorithm: graphAlgo,
|
||||
paint: Paint()
|
||||
..color = Theme.of(context).colorScheme.outline
|
||||
..strokeWidth = 1
|
||||
|
||||
Reference in New Issue
Block a user