💄 Optimize embed view renderer loading logic

This commit is contained in:
2025-09-08 15:48:10 +08:00
parent 7cd10118cc
commit edb0a25f34

View File

@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/post.dart'; import 'package:island/models/post.dart';
@@ -22,6 +23,10 @@ class EmbedViewRenderer extends HookConsumerWidget {
final theme = Theme.of(context); final theme = Theme.of(context);
final colorScheme = theme.colorScheme; final colorScheme = theme.colorScheme;
// State management for lazy loading
final shouldLoad = useState(false);
final isLoading = useState(false);
return Container( return Container(
constraints: BoxConstraints(maxHeight: maxHeight ?? 400), constraints: BoxConstraints(maxHeight: maxHeight ?? 400),
decoration: BoxDecoration( decoration: BoxDecoration(
@@ -93,11 +98,17 @@ class EmbedViewRenderer extends HookConsumerWidget {
), ),
), ),
// WebView content // WebView content with lazy loading
AspectRatio( AspectRatio(
aspectRatio: embedView.aspectRatio ?? 1, aspectRatio: embedView.aspectRatio ?? 1,
child: InAppWebView( child:
initialUrlRequest: URLRequest(url: WebUri(embedView.uri)), shouldLoad.value
? Stack(
children: [
InAppWebView(
initialUrlRequest: URLRequest(
url: WebUri(embedView.uri),
),
initialSettings: InAppWebViewSettings( initialSettings: InAppWebViewSettings(
javaScriptEnabled: true, javaScriptEnabled: true,
mediaPlaybackRequiresUserGesture: false, mediaPlaybackRequiresUserGesture: false,
@@ -110,7 +121,8 @@ class EmbedViewRenderer extends HookConsumerWidget {
builtInZoomControls: false, builtInZoomControls: false,
displayZoomControls: false, displayZoomControls: false,
minimumFontSize: 12, minimumFontSize: 12,
preferredContentMode: UserPreferredContentMode.RECOMMENDED, preferredContentMode:
UserPreferredContentMode.RECOMMENDED,
allowsBackForwardNavigationGestures: false, allowsBackForwardNavigationGestures: false,
allowsLinkPreview: false, allowsLinkPreview: false,
isInspectable: false, isInspectable: false,
@@ -125,9 +137,10 @@ class EmbedViewRenderer extends HookConsumerWidget {
); );
}, },
onLoadStart: (controller, url) { onLoadStart: (controller, url) {
// Handle load start isLoading.value = true;
}, },
onLoadStop: (controller, url) async { onLoadStop: (controller, url) async {
isLoading.value = false;
// Inject CSS to improve mobile display and remove borders // Inject CSS to improve mobile display and remove borders
await controller.evaluateJavascript( await controller.evaluateJavascript(
source: ''' source: '''
@@ -190,14 +203,23 @@ class EmbedViewRenderer extends HookConsumerWidget {
); );
}, },
onLoadError: (controller, url, code, message) { onLoadError: (controller, url, code, message) {
// Handle load errors isLoading.value = false;
}, },
onLoadHttpError: (controller, url, statusCode, description) { onLoadHttpError: (
// Handle HTTP errors controller,
url,
statusCode,
description,
) {
isLoading.value = false;
}, },
shouldOverrideUrlLoading: (controller, navigationAction) async { shouldOverrideUrlLoading: (
controller,
navigationAction,
) async {
final uri = navigationAction.request.url; final uri = navigationAction.request.url;
if (uri != null && uri.toString() != embedView.uri) { if (uri != null &&
uri.toString() != embedView.uri) {
// Open external links in browser // Open external links in browser
// You might want to use url_launcher here // You might want to use url_launcher here
return NavigationActionPolicy.CANCEL; return NavigationActionPolicy.CANCEL;
@@ -209,9 +231,48 @@ class EmbedViewRenderer extends HookConsumerWidget {
}, },
onConsoleMessage: (controller, consoleMessage) { onConsoleMessage: (controller, consoleMessage) {
// Handle console messages for debugging // Handle console messages for debugging
debugPrint('WebView Console: ${consoleMessage.message}'); debugPrint(
'WebView Console: ${consoleMessage.message}',
);
}, },
), ),
if (isLoading.value)
Container(
color: colorScheme.surfaceContainerLowest,
child: const Center(
child: CircularProgressIndicator(),
),
),
],
)
: GestureDetector(
onTap: () {
shouldLoad.value = true;
},
child: Container(
color: colorScheme.surfaceContainerLowest,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Symbols.play_arrow,
size: 48,
color: colorScheme.onSurfaceVariant.withOpacity(
0.6,
),
),
const SizedBox(height: 8),
Text(
'Tap to load content',
style: theme.textTheme.bodyMedium?.copyWith(
color: colorScheme.onSurfaceVariant
.withOpacity(0.6),
),
),
],
),
),
),
), ),
], ],
), ),