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,33 +458,65 @@ 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(
viewType, ui.platformViewRegistry.registerViewFactory(viewType, (int viewId) {
(int viewId) { // Extract the WOPISrc from the URL
// Create the iframe with the properly encoded Collabora URL final uri = Uri.parse(collaboraUrl);
final iframe = html.IFrameElement() final wopisrc = uri.queryParameters['WOPISrc'] ?? '';
..src = collaboraUrl
..style.border = 'none' // Create a container for the form and iframe
..style.width = '100%' final container = html.DivElement()
..style.height = '100%' ..style.width = '100%'
..style.margin = '0' ..style.height = '100%'
..style.padding = '0' ..style.margin = '0'
..setAttribute( ..style.padding = '0'
'allow', ..style.overflow = 'hidden';
'microphone; camera; usb; autoplay; clipboard-read; clipboard-write',
) // Create the iframe first
// Remove allow-same-origin for security, add allow-popups-to-escape-sandbox final iframe = html.IFrameElement()
..setAttribute( ..name = 'collabora-iframe'
'sandbox', ..style.border = 'none'
'allow-scripts allow-popups allow-forms allow-pointer-lock allow-presentation allow-modals allow-downloads allow-popups-to-escape-sandbox', ..style.width = '100%'
); ..style.height = '100%'
..style.margin = '0'
return iframe; ..style.padding = '0'
}, ..setAttribute(
); 'allow',
'microphone; camera; usb; autoplay; clipboard-read; clipboard-write',
)
..setAttribute(
'sandbox',
'allow-scripts allow-popups allow-forms allow-pointer-lock allow-presentation allow-modals allow-downloads allow-popups-to-escape-sandbox',
);
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);
} }