Compare commits

..

2 Commits

View File

@@ -406,10 +406,11 @@ class _DocumentViewerModalState extends State<DocumentViewerModal> {
// Build Collabora Online viewer URL with WOPISrc // Build Collabora Online viewer URL with WOPISrc
// The WOPISrc must be URL-encoded and kept encoded // The WOPISrc must be URL-encoded and kept encoded
// We use a double-encoding approach: encodeComponent keeps it encoded through iframe.src // We use a double-encoding approach: encodeComponent keeps it encoded through iframe.src
final baseUrl = 'https://of.b0esche.cloud/loleaflet/dist/loleaflet.html'; final baseUrl =
final collaboraUrl = Uri.parse(baseUrl) 'https://of.b0esche.cloud/loleaflet/dist/loleaflet.html';
.replace(queryParameters: {'WOPISrc': wopiSession.wopisrc}) final collaboraUrl = Uri.parse(
.toString(); baseUrl,
).replace(queryParameters: {'WOPISrc': wopiSession.wopisrc}).toString();
// Use WebView to display Collabora Online // Use WebView to display Collabora Online
return _buildWebView(collaboraUrl); return _buildWebView(collaboraUrl);
@@ -457,15 +458,26 @@ class _DocumentViewerModalState extends State<DocumentViewerModal> {
} }
Widget _buildCollaboraIframe(String collaboraUrl) { Widget _buildCollaboraIframe(String collaboraUrl) {
// For Collabora Online, create an iframe that loads the editor directly // For Collabora Online, we need to POST the WOPISrc, not GET it
const String viewType = 'collabora-iframe'; // Create an iframe and submit a form to load the document
const String viewType = 'collabora-form';
ui.platformViewRegistry.registerViewFactory( ui.platformViewRegistry.registerViewFactory(viewType, (int viewId) {
viewType, // Extract the WOPISrc from the URL
(int viewId) { final uri = Uri.parse(collaboraUrl);
// Create the iframe with the properly encoded Collabora URL final wopisrc = uri.queryParameters['WOPISrc'] ?? '';
// Create a container for the form and iframe
final container = html.DivElement()
..style.width = '100%'
..style.height = '100%'
..style.margin = '0'
..style.padding = '0'
..style.overflow = 'hidden';
// Create the iframe first
final iframe = html.IFrameElement() final iframe = html.IFrameElement()
..src = collaboraUrl ..name = 'collabora-iframe'
..style.border = 'none' ..style.border = 'none'
..style.width = '100%' ..style.width = '100%'
..style.height = '100%' ..style.height = '100%'
@@ -475,15 +487,36 @@ class _DocumentViewerModalState extends State<DocumentViewerModal> {
'allow', 'allow',
'microphone; camera; usb; autoplay; clipboard-read; clipboard-write', 'microphone; camera; usb; autoplay; clipboard-read; clipboard-write',
) )
// Remove allow-same-origin for security, add allow-popups-to-escape-sandbox
..setAttribute( ..setAttribute(
'sandbox', 'sandbox',
'allow-scripts allow-popups allow-forms allow-pointer-lock allow-presentation allow-modals allow-downloads allow-popups-to-escape-sandbox', 'allow-scripts allow-popups allow-forms allow-pointer-lock allow-presentation allow-modals allow-downloads allow-popups-to-escape-sandbox',
); );
return iframe; 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';
// 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();
});
return container;
});
return HtmlElementView(viewType: viewType); return HtmlElementView(viewType: viewType);
} }