优化编辑新增界面

This commit is contained in:
DelLevin-Home
2026-07-13 23:57:08 +08:00
parent b4793a8d01
commit be72fd1286
22 changed files with 4241 additions and 45 deletions

View File

@@ -77,11 +77,17 @@ class ReaderRendererController {
.toList();
final propertiesParam = encodedPropertiesList.map((p) => '"$p"').join(',');
final propertiesJson = '[$propertiesParam]';
if (Platform.isWindows) {
final result = await _rendererState?._readHtmlForUrl(url);
if (result != null) {
return await webViewController?.loadFrameSrcdoc(
'curr', result.$1, result.$2, anchorsJson, propertiesJson,
);
}
}
return await webViewController?.loadFrame(
'curr',
url,
anchorsJson,
propertiesJson,
'curr', url, anchorsJson, propertiesJson,
);
}
@@ -98,11 +104,17 @@ class ReaderRendererController {
.toList();
final propertiesParam = encodedPropertiesList.map((p) => '"$p"').join(',');
final propertiesJson = '[$propertiesParam]';
if (Platform.isWindows) {
final result = await _rendererState?._readHtmlForUrl(url);
if (result != null) {
return await webViewController?.loadFrameSrcdoc(
'next', result.$1, result.$2, anchorsJson, propertiesJson,
);
}
}
return await webViewController?.loadFrame(
'next',
url,
anchorsJson,
propertiesJson,
'next', url, anchorsJson, propertiesJson,
);
}
@@ -119,11 +131,17 @@ class ReaderRendererController {
.toList();
final propertiesParam = encodedPropertiesList.map((p) => '"$p"').join(',');
final propertiesJson = '[$propertiesParam]';
if (Platform.isWindows) {
final result = await _rendererState?._readHtmlForUrl(url);
if (result != null) {
return await webViewController?.loadFrameSrcdoc(
'prev', result.$1, result.$2, anchorsJson, propertiesJson,
);
}
}
return await webViewController?.loadFrame(
'prev',
url,
anchorsJson,
propertiesJson,
'prev', url, anchorsJson, propertiesJson,
);
}
@@ -237,6 +255,16 @@ class _ReaderRendererState extends State<ReaderRenderer>
);
}
/// Read HTML content from EPUB for a given virtual URL (Windows srcdoc approach).
/// Returns (htmlContent, baseUrl) or null.
Future<(String, String)?> _readHtmlForUrl(String url) async {
return await widget.webViewHandler.readHtmlContentWithBaseUrl(
epubPath: widget.bookSession.book['file_path'] as String,
fileHash: widget.fileHash,
url: url,
);
}
@override
void initState() {
super.initState();

View File

@@ -200,7 +200,18 @@ class _ReaderScreenState extends State<ReaderScreen>
final route = ModalRoute.of(context);
if (route != null && route.animation != null) {
routeAnimation = route.animation!;
routeAnimation?.addStatusListener(handleRouteAnimationStatus);
if (routeAnimation!.isCompleted) {
shouldShowWebView = true;
} else {
routeAnimation?.addStatusListener(handleRouteAnimationStatus);
// 安全超时:桌面端路由动画可能不触发 completed500ms后强制显示
Future.delayed(const Duration(milliseconds: 500), () {
if (mounted && !shouldShowWebView) {
debugPrint('[EPUB-Reader] animation timeout, forcing WebView visible');
setState(() { shouldShowWebView = true; });
}
});
}
} else {
shouldShowWebView = true;
}
@@ -268,6 +279,7 @@ class _ReaderScreenState extends State<ReaderScreen>
}
void handleRouteAnimationStatus(AnimationStatus status) {
debugPrint('[EPUB-Reader] animation status: $status');
if (status == AnimationStatus.completed) {
setState(() {
shouldShowWebView = true;

View File

@@ -5,6 +5,7 @@ import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import '../../main.dart';
import '../../services/epub/epub_theme.dart';
import 'book_session.dart';
import '../../services/epub/epub_webview_handler.dart';
@@ -44,6 +45,16 @@ class ReaderWebViewController {
return await _webViewState?._loadFrame(frame, url, anchors, properties);
}
Future<int?> loadFrameSrcdoc(
String frame,
String htmlContent,
String baseUrl,
String anchors,
String properties,
) async {
return await _webViewState?._loadFrameSrcdoc(frame, htmlContent, baseUrl, anchors, properties);
}
Future<void> jumpToPage(int pageIndex) async {
await _webViewState?._jumpToPage(pageIndex);
}
@@ -327,6 +338,7 @@ class _ReaderWebViewState extends State<ReaderWebView> {
if (_isHeadlessInitialized) return;
_headlessWebView = HeadlessInAppWebView(
webViewEnvironment: windowsWebViewEnvironment,
initialData: _generateInitialData(width, height),
initialSettings: defaultSettings,
shouldInterceptRequest: _shouldInterceptRequest,
@@ -364,6 +376,14 @@ class _ReaderWebViewState extends State<ReaderWebView> {
String properties,
) => _api.loadFrame(frame, url, anchors, properties);
Future<int> _loadFrameSrcdoc(
String frame,
String htmlContent,
String baseUrl,
String anchors,
String properties,
) => _api.loadFrameSrcdoc(frame, htmlContent, baseUrl, anchors, properties);
Future<void> _jumpToPage(int pageIndex) => _api.jumpToPage(pageIndex);
Future<void> _restoreScrollPosition(double ratio) =>
@@ -1113,6 +1133,7 @@ class _ReaderWebViewState extends State<ReaderWebView> {
child: AbsorbPointer(
child: widget.shouldShowWebView
? InAppWebView(
webViewEnvironment: windowsWebViewEnvironment,
headlessWebView: _headlessWebView,
initialData: _generateInitialData(width, height),
initialSettings: defaultSettings,