mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
feat: webdav
Closes #432 Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -7,12 +7,14 @@ import 'package:PiliPlus/pages/setting/privacy_setting.dart';
|
||||
import 'package:PiliPlus/pages/setting/recommend_setting.dart';
|
||||
import 'package:PiliPlus/pages/setting/style_setting.dart';
|
||||
import 'package:PiliPlus/pages/setting/video_setting.dart';
|
||||
import 'package:PiliPlus/pages/webdav/view.dart';
|
||||
import 'package:PiliPlus/utils/accounts/account.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:PiliPlus/utils/storage.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||
|
||||
import 'widgets/multi_select_dialog.dart';
|
||||
|
||||
@@ -84,6 +86,11 @@ class _SettingPageState extends State<SettingPage> {
|
||||
subtitle: '震动、搜索、收藏、ai、评论、动态、代理、更新检查等',
|
||||
icon: Icons.extension_outlined,
|
||||
),
|
||||
_SettingsModel(
|
||||
name: 'webdavSetting',
|
||||
title: 'WebDAV 设置',
|
||||
icon: MdiIcons.databaseCogOutline,
|
||||
),
|
||||
_SettingsModel(
|
||||
name: 'about',
|
||||
title: '关于',
|
||||
@@ -104,6 +111,7 @@ class _SettingPageState extends State<SettingPage> {
|
||||
'playSetting' => '播放器设置',
|
||||
'styleSetting' => '外观设置',
|
||||
'extraSetting' => '其它设置',
|
||||
'webdavSetting' => 'WebDAV 设置',
|
||||
'about' => '关于',
|
||||
_ => '设置',
|
||||
}),
|
||||
@@ -127,6 +135,7 @@ class _SettingPageState extends State<SettingPage> {
|
||||
'playSetting' => PlaySetting(showAppBar: false),
|
||||
'styleSetting' => StyleSetting(showAppBar: false),
|
||||
'extraSetting' => ExtraSetting(showAppBar: false),
|
||||
'webdavSetting' => WebDavSettingPage(showAppBar: false),
|
||||
'about' => AboutPage(showAppBar: false),
|
||||
_ => const SizedBox.shrink(),
|
||||
},
|
||||
|
||||
134
lib/pages/webdav/view.dart
Normal file
134
lib/pages/webdav/view.dart
Normal file
@@ -0,0 +1,134 @@
|
||||
import 'package:PiliPlus/pages/webdav/webdav.dart';
|
||||
import 'package:PiliPlus/utils/storage.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
|
||||
class WebDavSettingPage extends StatefulWidget {
|
||||
const WebDavSettingPage({
|
||||
super.key,
|
||||
this.showAppBar,
|
||||
});
|
||||
|
||||
final bool? showAppBar;
|
||||
|
||||
@override
|
||||
State<WebDavSettingPage> createState() => _WebDavSettingPageState();
|
||||
}
|
||||
|
||||
class _WebDavSettingPageState extends State<WebDavSettingPage> {
|
||||
final _uriCtr = TextEditingController(text: GStorage.webdavUri);
|
||||
final _usernameCtr = TextEditingController(text: GStorage.webdavUsername);
|
||||
final _passwordCtr = TextEditingController(text: GStorage.webdavPassword);
|
||||
final _directoryCtr = TextEditingController(text: GStorage.webdavDirectory);
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_uriCtr.dispose();
|
||||
_usernameCtr.dispose();
|
||||
_passwordCtr.dispose();
|
||||
_directoryCtr.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
EdgeInsets padding = MediaQuery.paddingOf(context);
|
||||
return Scaffold(
|
||||
appBar: widget.showAppBar == false
|
||||
? null
|
||||
: AppBar(title: const Text('WebDAV 设置')),
|
||||
body: ListView(
|
||||
padding: padding.copyWith(
|
||||
top: 20,
|
||||
left: padding.left + 20,
|
||||
right: padding.right + 20,
|
||||
bottom: padding.bottom + 90,
|
||||
),
|
||||
children: [
|
||||
TextField(
|
||||
controller: _uriCtr,
|
||||
decoration: const InputDecoration(
|
||||
labelText: '地址',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
TextField(
|
||||
controller: _usernameCtr,
|
||||
decoration: const InputDecoration(
|
||||
labelText: '用户',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
TextField(
|
||||
controller: _passwordCtr,
|
||||
decoration: const InputDecoration(
|
||||
labelText: '密码',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
TextField(
|
||||
controller: _directoryCtr,
|
||||
decoration: const InputDecoration(
|
||||
labelText: '路径',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: FilledButton.tonal(
|
||||
style: FilledButton.styleFrom(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
),
|
||||
onPressed: WebDav().backup,
|
||||
child: const Text('备份设置'),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 20),
|
||||
Expanded(
|
||||
child: FilledButton.tonal(
|
||||
style: FilledButton.styleFrom(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
),
|
||||
onPressed: WebDav().restore,
|
||||
child: const Text('恢复设置'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
child: const Icon(Icons.save),
|
||||
onPressed: () async {
|
||||
if (_uriCtr.text.isEmpty) {
|
||||
SmartDialog.showToast('地址不能为空');
|
||||
return;
|
||||
}
|
||||
await GStorage.setting.put(SettingBoxKey.webdavUri, _uriCtr.text);
|
||||
await GStorage.setting
|
||||
.put(SettingBoxKey.webdavUsername, _usernameCtr.text);
|
||||
await GStorage.setting
|
||||
.put(SettingBoxKey.webdavPassword, _passwordCtr.text);
|
||||
await GStorage.setting
|
||||
.put(SettingBoxKey.webdavDirectory, _directoryCtr.text);
|
||||
try {
|
||||
final res = await WebDav().init();
|
||||
SmartDialog.showToast('配置${res ? '成功' : '失败'}');
|
||||
} catch (e) {
|
||||
SmartDialog.showToast('配置失败: ${e.toString()}');
|
||||
return;
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
88
lib/pages/webdav/webdav.dart
Normal file
88
lib/pages/webdav/webdav.dart
Normal file
@@ -0,0 +1,88 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:PiliPlus/utils/storage.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:webdav_client/webdav_client.dart' as webdav;
|
||||
|
||||
class WebDav {
|
||||
late String _webDavUri;
|
||||
late String _webDavUsername;
|
||||
late String _webDavPassword;
|
||||
late String _webdavDirectory;
|
||||
|
||||
webdav.Client? _client;
|
||||
|
||||
WebDav._internal();
|
||||
static final WebDav _instance = WebDav._internal();
|
||||
factory WebDav() => _instance;
|
||||
|
||||
Future<bool> init() async {
|
||||
_webDavUri = GStorage.webdavUri;
|
||||
_webDavUsername = GStorage.webdavUsername;
|
||||
_webDavPassword = GStorage.webdavPassword;
|
||||
_webdavDirectory = GStorage.webdavDirectory;
|
||||
if (_webdavDirectory.endsWith('/').not) {
|
||||
_webdavDirectory += '/';
|
||||
}
|
||||
_webdavDirectory += 'PiliPlus';
|
||||
|
||||
try {
|
||||
_client = null;
|
||||
final client = webdav.newClient(
|
||||
_webDavUri,
|
||||
user: _webDavUsername,
|
||||
password: _webDavPassword,
|
||||
)
|
||||
..setHeaders({'accept-charset': 'utf-8'})
|
||||
..setConnectTimeout(4000)
|
||||
..setReceiveTimeout(4000)
|
||||
..setSendTimeout(4000);
|
||||
|
||||
await client.mkdirAll(_webdavDirectory);
|
||||
|
||||
_client = client;
|
||||
return true;
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future backup() async {
|
||||
if (_client == null) {
|
||||
if (await init() == false) {
|
||||
SmartDialog.showToast('备份失败,请检查配置');
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
final path = '$_webdavDirectory/piliplus_settings.json';
|
||||
final file = File(path);
|
||||
if (await file.exists()) {
|
||||
await file.delete();
|
||||
}
|
||||
String data = await GStorage.exportAllSettings();
|
||||
await _client!.write(path, utf8.encode(data));
|
||||
SmartDialog.showToast('备份成功');
|
||||
} catch (e) {
|
||||
SmartDialog.showToast('备份失败: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future restore() async {
|
||||
if (_client == null) {
|
||||
if (await init() == false) {
|
||||
SmartDialog.showToast('恢复失败,请检查配置');
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
final path = '$_webdavDirectory/piliplus_settings.json';
|
||||
final data = await _client!.read(path);
|
||||
await GStorage.importAllSettings(utf8.decode(data));
|
||||
SmartDialog.showToast('恢复成功');
|
||||
} catch (e) {
|
||||
SmartDialog.showToast('恢复失败: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user