Closed 5hirish closed 1 year ago
Hey @5hirish!
Please do not confuse the childrenProvider
callback with the providers of package:provider
or package:riverpod
. The childrenProvider
callback should behave like a getter as it is called recursively while building the tree, you may do the following:
// Access the children directly
(FileSystemEntity parent) => parent.children;
// Or with a map (the key could also be the id of your nodes)
// The below map could be held by a StateProvider if desired
Map<FileSystemEntity, List<FileSystemEntity>> childrenCache;
(FileSystemEntity parent) => childrenCache[parent] ?? const Iterable.empty();
I don't use package:riverpod
nor package:flutter_hooks
so I wouldn't be capable of helping you out if the issue turns out to be with reading providers in a recursive function.
Interesting so, I will have to store this tree in-memory ? I am actually changing the visibility of this tree based on a toggle but the expanded state wasn't being maintained in the tree. Hence, I was planning to use providers (in my case with riverpod) to store the expanded state even if the widget is recreated on toggling visibility. Any suggestions?
Because I am also using getter but a provider getter, which is fine. The error is more directed in open transition. The collapse transition seems, while collapsing I can see the files. Only on expansion is the error I get.
The following StackOverflowError was thrown building SizeTransition(animation: AnimationController#c4e62(▶ 0.944)➩CurveTween(curve: _Linear)➩0.9444433333333334, state: _AnimatedState#9f563):
Stack Overflow
I'm not sure what is causing the stack overflow error, but if all you need is to preserve the expansion state of your nodes, you can override the [get|set]ExpansionState
methods of the TreeController
class:
class MyTreeController extends TreeController<T> {
TreeController({
// ...
Iterable<Object>? initiallyExpandedNodes,
}) : expandedNodes = {...?initiallyExpandedNodes};
final Set<Object> expandedNodes;
@override
bool getExpansionState(T node) {
return expandedNodes.contains(node.id);
}
@override
void setExpansionState(T node, bool expanded) {
if (expanded) {
expandedNodes.add(node.id);
} else {
expandedNodes.remove(node.id);
}
}
}
With the above implementation you could approach preserving the expansion state by:
expandedNodes
somewhere else when the user interacts with the action that would hide the tree;setExpansionState()
that would update the stored expansion state per node.There is an inconsistent behaviour here too. Where toggling the widget containing the tree in and out of visibility leads to an inconsistent behaviour. After expansion trigger the rebuilding doesn't happen on expansion and the children are not displayed.
isOpen = _treeController.getExpansionState(file);
onPressed = () => _treeController.toggleExpansion(file);
Could you provide a a minimal reproducible example of the issue?
@baumths just try toggling the visibility couple of times and expanding few nodes, you will encounter a scenario where any node doesn't expand. 5hirish/fancy_tree_example. Thanks
I takes me about 4-5 tries to get it to fail.
I haven't added the logic to retain the expanded state after widget rebuild on this yet. I wanted to first investigate the inconsistency before any enhancements.
Should be fixed in https://github.com/5hirish/fancy_tree_example/pull/1.
By the way, this does not seem to be an issue with this library. As my knowledge of package:riverpod
and package:flutter_hooks
is very limited, I wont be able to assist you any further. Hope my PR helps you towards the desired implementation.
I will close this issue for now but feel free to reopen it if you find out there's actually an issue with this library.
Oh perfect I understand the mistake. Thanks a bunch.
I am building an open-source low-code Flutter IDE.
A low-code, low-barrier-to-entry IDE which focuses on productivity by simple drag-n-drop, plug-n-play interface while at the same time offering the control and freedom to build production-grade apps at scale.
Would love to talk about it if you are interested!
@baumths I made a little YouTube live code stream tutorial with your library! Hope it helps for folks who want to use the library! Flutter Code Along: How to display files in a tree | Tonic IDE | EP #1
I have a riverpod
StateNotifierProvider
reading files from a directory asynchronously. I would like to use it in my tree controller to to provide the child nodes which will be fetchedonPressed
. I am unable to read a provider in thechildrenProvider
as it throws aStackOverflow
error.The
AnimatedTreeView
is contained in aHookConsumerWidget
. Reason behind using hooks is to maintain a state of the widget tree's expansion.Stack Trace: