Skip to content

Commit

Permalink
# 优化
Browse files Browse the repository at this point in the history
- 优化漫画阅读界面图片预览的体验
- 优化同步的体验,把压缩解压加密解密的过程放在后台线程中,提升用户体验
- 添加坚果云webdav的适配
# 修复
- 修复历史记录界面页数跳转逻辑出错的问题
  • Loading branch information
deretame committed Jan 24, 2025
1 parent 9d007fd commit 6bbbb20
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 40 deletions.
109 changes: 73 additions & 36 deletions lib/network/webdav.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@ Future<void> testWebDavServer() async {
));

try {
// 发送 HEAD 请求测试服务是否可用
final response = await dio.head('/');
// 发送 OPTIONS 请求测试服务是否可用
final response = await dio.request(
'/',
options: Options(method: 'OPTIONS'),
);

// 检查状态码
if (response.statusCode == 200) {
Expand Down Expand Up @@ -248,15 +251,20 @@ Future<void> checkOrCreateFixedDirectory() async {
}

// 判断是否是文件夹
bool xmlIsDirectory(xml.XmlElement prop) {
// 检查 <D:resourcetype> 节点下是否有 <D:collection />
var resourceType = prop.findElements('D:resourcetype').firstOrNull;
bool xmlIsDirectory(xml.XmlElement prop, String namespacePrefix) {
// 动态构建元素名称
var resourceTypeElement = '$namespacePrefix:resourcetype';
var collectionElement = '$namespacePrefix:collection';

// 检查 <resourcetype> 节点下是否有 <collection />
var resourceType = prop.findElements(resourceTypeElement).firstOrNull;
if (resourceType != null) {
return resourceType.findElements('D:collection').isNotEmpty;
return resourceType.findElements(collectionElement).isNotEmpty;
}
return false;
}

// 获取 WebDAV 文件列表
Future<List<String>> fetchWebDAVFiles() async {
List<String> urlList = [];

Expand All @@ -279,17 +287,27 @@ Future<List<String>> fetchWebDAVFiles() async {
xml.XmlDocument xmlDoc = xml.XmlDocument.parse(response.data);

try {
var elements = xmlDoc.findAllElements('D:response');
// 获取命名空间前缀
var namespacePrefix = _getNamespacePrefix(xmlDoc);

// 动态构建元素名称
var responseElement = '$namespacePrefix:response';
var propstatElement = '$namespacePrefix:propstat';
var propElement = '$namespacePrefix:prop';
var displayNameElement = '$namespacePrefix:displayname';

var elements = xmlDoc.findAllElements(responseElement);

for (var element in elements) {
var href = element.findElements('D:href').first.innerText;
var propstat = element.findElements('D:propstat').first;
var prop = propstat.findElements('D:prop').first;
var propstat = element.findElements(propstatElement).first;
var prop = propstat.findElements(propElement).first;

var isDir = xmlIsDirectory(prop); // 判断是否是文件夹
// 获取 displayname
var displayName =
prop.findElements(displayNameElement).firstOrNull?.innerText;

if (!isDir) {
urlList.add(href);
if (displayName != null && !xmlIsDirectory(prop, namespacePrefix)) {
urlList.add("/Breeze/$displayName");
}
}
} catch (e) {
Expand All @@ -305,6 +323,15 @@ Future<List<String>> fetchWebDAVFiles() async {
return urlList;
}

// 获取命名空间前缀
String _getNamespacePrefix(xml.XmlDocument xmlDoc) {
var rootElement = xmlDoc.rootElement;
var namespacePrefix = rootElement.name.prefix;

// 如果未找到前缀,默认使用 'd'
return namespacePrefix ?? 'd';
}

Future<void> uploadFile2WebDav() async {
var allHistory = await objectbox.bikaHistoryBox.getAllAsync();
allHistory.sort((a, b) => b.history.compareTo(a.history));
Expand Down Expand Up @@ -477,32 +504,42 @@ Future<List<int>> _downloadFromWebDav(String remotePath) async {
throw Exception('WebDAV 配置不完整');
}

try {
// 发送 GET 请求下载文件
final response = await dio.get(
remotePath,
options: Options(
responseType: ResponseType.bytes, // 以字节数组形式接收数据
),
);
const maxRetries = 3;
const retryDelay = Duration(seconds: 2);

// 检查状态码
if (response.statusCode == 200) {
debugPrint('文件下载成功');
return response.data as List<int>;
} else {
throw Exception('文件下载失败,状态码: ${response.statusCode}');
}
} on DioException catch (e) {
if (e.response != null) {
throw Exception(
'文件下载失败: ${e.message}\n${e.response?.statusCode}\n${e.response?.data}');
} else {
throw Exception('文件下载失败: ${e.message}');
for (var i = 0; i < maxRetries; i++) {
try {
final response = await dio.get(
remotePath,
options: Options(
responseType: ResponseType.bytes,
),
);

if (response.statusCode == 200) {
debugPrint('文件下载成功');
return response.data as List<int>;
} else if (response.statusCode == 409) {
debugPrint('冲突,重试中...');
await Future.delayed(retryDelay);
continue;
} else {
throw Exception('文件下载失败,状态码: ${response.statusCode}');
}
} on DioException catch (e) {
if (e.response?.statusCode == 409) {
debugPrint('冲突,重试中...');
await Future.delayed(retryDelay);
continue;
} else {
throw Exception('文件下载失败: ${e.message}');
}
} catch (e) {
throw Exception('未知错误: $e');
}
} catch (e) {
throw Exception('未知错误: $e');
}

throw Exception('文件下载失败,重试次数用尽');
}

Future<void> updateHistory(List<BikaComicHistory> comicHistories) async {
Expand Down
17 changes: 14 additions & 3 deletions lib/page/webdav_sync/method/method.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,30 @@ Future<void> testWebDavServer(
));

try {
// 发送 HEAD 请求测试服务是否可用
final response = await dio.head('/');
// 打印请求信息
debugPrint('请求 URL: ${dio.options.baseUrl}');
debugPrint('请求头: ${dio.options.headers}');

// 发送 OPTIONS 请求测试服务是否可用
final response = await dio.request(
'/',
options: Options(method: 'OPTIONS'),
);

// 检查状态码
if (response.statusCode == 200) {
debugPrint('WebDAV 服务可用');
debugPrint('支持的 HTTP 方法: ${response.headers['allow']}');
} else {
throw Exception('WebDAV 服务返回异常状态码: ${response.statusCode}');
}
} on DioException catch (e) {
// 捕获 Dio 的错误
if (e.response != null) {
// 如果服务器返回了响应
// 打印完整响应信息
debugPrint('响应状态码: ${e.response?.statusCode}');
debugPrint('响应头: ${e.response?.headers}');
debugPrint('响应体: ${e.response?.data}');
throw Exception('WebDAV 服务返回错误: ${e.response?.statusCode}');
} else {
// 如果只是 Dio 的错误(如网络连接失败、超时等)
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: zephyr
description: "使用Flutter开发的三方哔咔应用。"
version: 1.24.1+69
version: 1.24.2+70

environment:
sdk: ">=3.0.0"
Expand Down

0 comments on commit 6bbbb20

Please sign in to comment.