Fix: Use JavaScript form submission for Collabora POST request

- Collabora expects POST to loleaflet.html with WOPISrc in body, not GET
- Previous Dart form.submit() wasn't executing reliably
- Use ScriptElement to inject and execute form submission JavaScript
- This bypasses Dart's HTML layer limitations and ensures form POSTs properly
- Unique viewType names with timestamp to avoid registration conflicts
This commit is contained in:
Leon Bösche
2026-01-12 15:22:40 +01:00
parent ef60983534
commit 89f55471ce

View File

@@ -459,8 +459,8 @@ class _DocumentViewerModalState extends State<DocumentViewerModal> {
Widget _buildCollaboraIframe(String collaboraUrl) {
// For Collabora Online, we need to POST the WOPISrc, not GET it
// Create an iframe and submit a form to load the document
const String viewType = 'collabora-form';
// Use JavaScript to create and submit the form properly
final String viewType = 'collabora-form-${DateTime.now().millisecondsSinceEpoch}';
ui.platformViewRegistry.registerViewFactory(viewType, (int viewId) {
// Extract the WOPISrc from the URL
@@ -477,7 +477,7 @@ class _DocumentViewerModalState extends State<DocumentViewerModal> {
// Create the iframe first
final iframe = html.IFrameElement()
..name = 'collabora-iframe'
..name = 'collabora-iframe-$viewId'
..style.border = 'none'
..style.width = '100%'
..style.height = '100%'
@@ -494,26 +494,36 @@ class _DocumentViewerModalState extends State<DocumentViewerModal> {
container.append(iframe);
// Create a hidden form that will POST to Collabora
final form = html.FormElement()
..method = 'POST'
..action = 'https://of.b0esche.cloud/loleaflet/dist/loleaflet.html'
..target = 'collabora-iframe'
..style.display = 'none';
// Use JavaScript to create and submit the form
// This is more reliable than Dart's form.submit()
final jsCode = '''
(function() {
var form = document.createElement('form');
form.method = 'POST';
form.action = 'https://of.b0esche.cloud/loleaflet/dist/loleaflet.html';
form.target = 'collabora-iframe-$viewId';
form.style.display = 'none';
var input = document.createElement('input');
input.type = 'hidden';
input.name = 'WOPISrc';
input.value = '$wopisrc';
form.appendChild(input);
document.body.appendChild(form);
// Submit the form
setTimeout(function() {
form.submit();
}, 50);
})();
''';
// Add WOPISrc as a hidden input
final wopisrcInput = html.InputElement()
..type = 'hidden'
..name = 'WOPISrc'
..value = wopisrc;
form.append(wopisrcInput);
container.append(form);
// Use a timer to submit the form after the iframe is fully loaded
Future.delayed(const Duration(milliseconds: 100), () {
form.submit();
});
final script = html.ScriptElement()
..type = 'text/javascript'
..text = jsCode;
html.document.body!.append(script);
return container;
});