-
Notifications
You must be signed in to change notification settings - Fork 250
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DocumentLayout.getRectForPosition fails on Flutter Hot Reload #1568
Comments
@craigdfoster can you please provide a runnable minimal reproduction so that we can paste it in and repro the bug? |
Hi @matthew-carroll, Thanks for getting back! I've pulled together a project for you... Once it's up and running just run a hot reload and you should see the exception in the debug console. Try changing the text on line 30 of Note that the issue is avoided if I don't use a document underlay. You can see this by commenting out line 98 of Cheers! |
@craigdfoster the repro code should be small enough to paste in this issue ticket. It should be nothing but the necessary |
OK, I've paired it down further. Please use the macosui package Note that the issue appears to go away without the call to
|
@craigdfoster is this a SuperEditor issue, or a Mac OS package issue? One of the reasons that we ask for a truly isolated reproduction is so that it's clear that this is our problem, and not a problem caused by other packages. Can you please try to reproduce your issue exclusively with SuperEditor without any external packages? |
Truthfully, I don't think I can go any further without your help. This is a very weird bug. I have super_editor working in a complex app with no issues under normal testing except for this one very specific problem where it fails only in a Dev context, after Hot Reload. I've not seen anything else like it. The exact same code will execute without issue after a fresh start or restart. This btw makes it a very time consuming problem because the app will ALWAYS fail after Hot Reload which really impacts development productivity. I've already used a great deal of trial and error removing other parts of the configuration superfluous to this issue and I have already tried recreating it with Material but to no avail. I'm not sure what else to try in my code. There's no obvious connection between the macOS package and super_editor that would guide further trials. But what I do know is that the error is originating from the super_editor code base and that the I feel I can progress this no further without help from someone who has a good working knowledge of the super_editor code. Would you mind at least tracing it and seeing what you find? |
@angelosilvestre can you try the provided example code with the Mac OS ui package and see if you can root cause this? My initial guess is something related to content layers. |
@matthew-carroll The issue seems that calling As an @override
bool updateShouldNotify(_InheritedMacosTheme old) => theme.data != old.theme.data; So, it rebuilds the dependent widgets when its As a test, I changed It seems it isn't safe to use class MyStatefulDocumentLayer extends DocumentLayoutLayerStatefulWidget {
const MyStatefulDocumentLayer(this.document, {super.key});
final Document document;
@override
DocumentLayoutLayerState<ContentLayerStatefulWidget, dynamic> createState() {
return MyStatefulDocumentLayerState();
}
}
class MyStatefulDocumentLayerState extends DocumentLayoutLayerState<MyStatefulDocumentLayer, List<LayoutInfo>> {
@override
List<LayoutInfo>? computeLayoutDataWithDocumentLayout(BuildContext context, DocumentLayout documentLayout) {
final layoutData = <LayoutInfo>[
for (var node in widget.document.nodes) ...[
LayoutInfo(
nodeId: node.id,
top: documentLayout
.getRectForPosition(DocumentPosition(nodeId: node.id, nodePosition: node.beginningPosition))!
.top,
)
]
];
return layoutData;
}
@override
Widget doBuild(BuildContext context, List<LayoutInfo>? layoutData) {
if (layoutData == null) {
return const SizedBox();
}
return Stack(
children: [
for (var item in layoutData) ...[
Positioned(
top: item.top,
left: 0,
child: Text(
item.nodeId,
style: MacosTheme.of(context).typography.body,
),
),
]
],
);
}
}
class LayoutInfo {
LayoutInfo({
required this.nodeId,
required this.top,
});
final String nodeId;
final double top;
} @craigdfoster Could you please try this sample code and see if it works for you? |
If this is the case, why does a stateful layer work but a stateless layer doesn't? Also, if this is happening during hot reload, the document layout should already be built and cached. So why are we having a problem building a layer, even if the document layout rebuild out of order? |
@matthew-carroll I looked into the stateful layer and we have this: if (contentLayers != null && !contentLayers.renderObject.contentNeedsLayout) {
_layoutData = computeLayoutData(contentElement, contentLayout);
} So the method that access the document layout isn't called when we the layout is dirty. We could do something similar in the stateless build method, returning a What do you think? |
I don't know what this means. What is "the method that access the document layout" and where does your snippet show something related to "when the layout is dirty"? |
Yes @angelosilvestre, that all works as you've described on my end. FYI, capitalising on your observation about
Thank you both very much for your help! |
In the stateless version, In the original sample code we have: Positioned(
top: documentLayout
// NOTE: the Null Check error is thrown from within getRectForPosition
.getRectForPosition(DocumentPosition(
nodeId: node.id, nodePosition: node.beginningPosition))!
.top,
left: 0,
child: Text(
node.id,
// BUT: The issue goes away without the theme call which occurs after
style: MacosTheme.of(context).typography.body,
),
),
final renderTextLayout = key.currentContext?.findRenderObject() as RenderSuperTextLayout?;
if (renderTextLayout == null || renderTextLayout.state._paragraph == null) {
return null;
}
|
I'm not sure why the issue happens for stateless and not stateful, but I think it's likely that the root problem is in the In the |
@matthew-carroll I tried that but we get the same error. |
Ok. I'll need to take a look at this. |
I'm getting a null check error in super_text.dart line 73 every time I do a flutter Hot Reload. (Even for utterly minor code changes)
ProseTextLayout get textLayout => RenderSuperTextLayout.textLayoutFrom(_textLayoutKey)!;
I'm using SuperReader and have a document underlay that renders using a subclassed DocumentLayoutLayerStatelessWidget.
The underlay calls DocumentLayout.getRectForPosition which then leads to the failure above.
Tracing it in debugger reveals that
renderTextLayout.state._paragraph
is null which forcestextLayoutFrom
to return null on line 190I'm using the latest code from the stable branch
The text was updated successfully, but these errors were encountered: