Implement Collabora Online viewer for Office documents (DOCX, XLSX, etc)

This commit is contained in:
Leon Bösche
2026-01-12 00:46:45 +01:00
parent d9c8c1e1f3
commit f0fe439c3b
4 changed files with 106 additions and 92 deletions

View File

@@ -11,6 +11,7 @@ import '../injection.dart';
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
import 'package:go_router/go_router.dart';
import 'package:http/http.dart' as http;
import 'package:webview_flutter/webview_flutter.dart';
// Modal version for overlay display
class DocumentViewerModal extends StatefulWidget {
@@ -253,52 +254,10 @@ class _DocumentViewerModalState extends State<DocumentViewerModal> {
},
);
} else if (state.caps.isOffice) {
// Office document viewer - show placeholder with download option
return Container(
color: AppTheme.primaryBackground,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
state.caps.mimeType.contains('word')
? Icons.description
: state.caps.mimeType.contains('sheet')
? Icons.table_chart
: Icons.folder_open,
size: 64,
color: AppTheme.accentColor,
),
const SizedBox(height: 16),
Text(
'Office Document',
style: TextStyle(
color: AppTheme.primaryText,
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
Text(
'Download to view in your office application',
style: TextStyle(
color: AppTheme.secondaryText,
fontSize: 14,
),
),
const SizedBox(height: 24),
ElevatedButton.icon(
icon: const Icon(Icons.download),
label: const Text('Download File'),
onPressed: () {
// Open file download
// In a real implementation, you'd use url_launcher
// launchUrl(state.viewUrl);
},
),
],
),
),
// Office document viewer using Collabora Online
return _buildCollaboraViewer(
state.viewUrl.toString(),
state.token,
);
} else {
// Unknown file type
@@ -366,6 +325,37 @@ class _DocumentViewerModalState extends State<DocumentViewerModal> {
}
}
Widget _buildCollaboraViewer(String documentUrl, String token) {
// Collabora Online viewer URL format
// Pass document URL and token to Collabora
final Uri collaboraUri = Uri.parse('https://of.b0esche.cloud/browser/dist/index.html').replace(
queryParameters: {
'url': documentUrl,
'token': token,
},
);
return WebViewWidget(
controller: WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setNavigationDelegate(
NavigationDelegate(
onPageStarted: (String url) {
// Page started loading
},
onPageFinished: (String url) {
// Page finished loading
},
onWebResourceError: (WebResourceError error) {
// Handle errors
debugPrint('WebView error: ${error.description}');
},
),
)
..loadRequest(collaboraUri),
);
}
@override
void dispose() {
_viewerBloc.close();
@@ -582,52 +572,10 @@ class _DocumentViewerState extends State<DocumentViewer> {
},
);
} else if (state.caps.isOffice) {
// Office document viewer - show placeholder with download option
return Container(
color: AppTheme.primaryBackground,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
state.caps.mimeType.contains('word')
? Icons.description
: state.caps.mimeType.contains('sheet')
? Icons.table_chart
: Icons.folder_open,
size: 64,
color: AppTheme.accentColor,
),
const SizedBox(height: 16),
Text(
'Office Document',
style: TextStyle(
color: AppTheme.primaryText,
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
Text(
'Download to view in your office application',
style: TextStyle(
color: AppTheme.secondaryText,
fontSize: 14,
),
),
const SizedBox(height: 24),
ElevatedButton.icon(
icon: const Icon(Icons.download),
label: const Text('Download File'),
onPressed: () {
// Open file download
// In a real implementation, you'd use url_launcher
// launchUrl(state.viewUrl);
},
),
],
),
),
// Office document viewer using Collabora Online
return _buildCollaboraViewerPage(
state.viewUrl.toString(),
token ?? '',
);
} else {
// Unknown file type
@@ -690,6 +638,37 @@ class _DocumentViewerState extends State<DocumentViewer> {
}
}
Widget _buildCollaboraViewerPage(String documentUrl, String token) {
// Collabora Online viewer URL format
// Pass document URL and token to Collabora
final Uri collaboraUri = Uri.parse('https://of.b0esche.cloud/browser/dist/index.html').replace(
queryParameters: {
'url': documentUrl,
'token': token,
},
);
return WebViewWidget(
controller: WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setNavigationDelegate(
NavigationDelegate(
onPageStarted: (String url) {
// Page started loading
},
onPageFinished: (String url) {
// Page finished loading
},
onWebResourceError: (WebResourceError error) {
// Handle errors
debugPrint('WebView error: ${error.description}');
},
),
)
..loadRequest(collaboraUri),
);
}
@override
void dispose() {
_viewerBloc.close();

View File

@@ -17,6 +17,7 @@ import sqflite_darwin
import super_native_extensions
import syncfusion_pdfviewer_macos
import url_launcher_macos
import webview_flutter_wkwebview
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin"))
@@ -31,4 +32,5 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
SuperNativeExtensionsPlugin.register(with: registry.registrar(forPlugin: "SuperNativeExtensionsPlugin"))
SyncfusionFlutterPdfViewerPlugin.register(with: registry.registrar(forPlugin: "SyncfusionFlutterPdfViewerPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
WebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "WebViewFlutterPlugin"))
}

View File

@@ -1453,6 +1453,38 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.2.1"
webview_flutter:
dependency: "direct main"
description:
name: webview_flutter
sha256: a3da219916aba44947d3a5478b1927876a09781174b5a2b67fa5be0555154bf9
url: "https://pub.dev"
source: hosted
version: "4.13.1"
webview_flutter_android:
dependency: transitive
description:
name: webview_flutter_android
sha256: eeeb3fcd5f0ff9f8446c9f4bbc18a99b809e40297528a3395597d03aafb9f510
url: "https://pub.dev"
source: hosted
version: "4.10.11"
webview_flutter_platform_interface:
dependency: transitive
description:
name: webview_flutter_platform_interface
sha256: "63d26ee3aca7256a83ccb576a50272edd7cfc80573a4305caa98985feb493ee0"
url: "https://pub.dev"
source: hosted
version: "2.14.0"
webview_flutter_wkwebview:
dependency: transitive
description:
name: webview_flutter_wkwebview
sha256: e49f378ed066efb13fc36186bbe0bd2425630d4ea0dbc71a18fdd0e4d8ed8ebc
url: "https://pub.dev"
source: hosted
version: "3.23.5"
win32:
dependency: transitive
description:

View File

@@ -55,6 +55,7 @@ dependencies:
infinite_scroll_pagination: ^5.1.1
collection: ^1.18.0
syncfusion_flutter_pdfviewer: ^31.1.21
webview_flutter: ^4.10.0
dev_dependencies:
flutter_test: