mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
opt.: backup & titlebar
This commit is contained in:
4
.vscode/launch.json
vendored
4
.vscode/launch.json
vendored
@@ -5,7 +5,7 @@
|
|||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "toolbox",
|
"name": "debug",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"type": "dart",
|
"type": "dart",
|
||||||
// "args": [
|
// "args": [
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
// ]
|
// ]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "toolbox (profile mode)",
|
"name": "profile",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"type": "dart",
|
"type": "dart",
|
||||||
"flutterMode": "profile",
|
"flutterMode": "profile",
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ EXTERNAL SOURCES:
|
|||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
countly_flutter: d880b352f212d4f6453a87c85f0455f3b4b9c611
|
countly_flutter: d880b352f212d4f6453a87c85f0455f3b4b9c611
|
||||||
file_picker: 1d63c4949e05e386da864365f8c13e1e64787675
|
file_picker: 880e54928ebe4aa405aaf4577f29a76a078341c6
|
||||||
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
||||||
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
|
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
|
||||||
icloud_storage: d9ac7a33ced81df08ba7ea1bf3099cc0ee58f60a
|
icloud_storage: d9ac7a33ced81df08ba7ea1bf3099cc0ee58f60a
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ import 'package:toolbox/data/model/app/backup.dart';
|
|||||||
import 'package:toolbox/data/model/app/error.dart';
|
import 'package:toolbox/data/model/app/error.dart';
|
||||||
import 'package:toolbox/data/res/path.dart';
|
import 'package:toolbox/data/res/path.dart';
|
||||||
import 'package:toolbox/data/res/store.dart';
|
import 'package:toolbox/data/res/store.dart';
|
||||||
// ignore: implementation_imports
|
import 'package:webdav_client/webdav_client.dart';
|
||||||
import 'package:webdav_client/src/client.dart';
|
|
||||||
|
|
||||||
abstract final class Webdav {
|
abstract final class Webdav {
|
||||||
static var _client = WebdavClient(
|
static var _client = WebdavClient(
|
||||||
@@ -73,6 +72,9 @@ abstract final class Webdav {
|
|||||||
|
|
||||||
static void changeClient(String url, String user, String pwd) {
|
static void changeClient(String url, String user, String pwd) {
|
||||||
_client = WebdavClient(url: url, user: user, pwd: pwd);
|
_client = WebdavClient(url: url, user: user, pwd: pwd);
|
||||||
|
Stores.setting.webdavUrl.put(url);
|
||||||
|
Stores.setting.webdavUser.put(user);
|
||||||
|
Stores.setting.webdavPwd.put(pwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> sync() async {
|
static Future<void> sync() async {
|
||||||
|
|||||||
@@ -315,7 +315,7 @@ class ServerProvider extends ChangeNotifier {
|
|||||||
final completer = Completer();
|
final completer = Completer();
|
||||||
final homePath = (await s.client?.run('echo \$HOME').string)?.trim();
|
final homePath = (await s.client?.run('echo \$HOME').string)?.trim();
|
||||||
if (homePath == null || homePath.isEmpty) {
|
if (homePath == null || homePath.isEmpty) {
|
||||||
throw Exception('Got home path: $homePath');
|
throw Exception('Got empty home path');
|
||||||
}
|
}
|
||||||
final remotePath = ShellFunc.getShellPath(homePath);
|
final remotePath = ShellFunc.getShellPath(homePath);
|
||||||
final reqId = Pros.sftp.add(
|
final reqId = Pros.sftp.add(
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import 'data/provider/sftp.dart';
|
|||||||
import 'data/provider/snippet.dart';
|
import 'data/provider/snippet.dart';
|
||||||
import 'data/res/color.dart';
|
import 'data/res/color.dart';
|
||||||
import 'locator.dart';
|
import 'locator.dart';
|
||||||
import 'view/widget/custom_appbar.dart';
|
import 'view/widget/appbar.dart';
|
||||||
|
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
_runInZone(() async {
|
_runInZone(() async {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import 'package:toolbox/core/extension/context/common.dart';
|
|||||||
import 'package:toolbox/core/extension/context/dialog.dart';
|
import 'package:toolbox/core/extension/context/dialog.dart';
|
||||||
import 'package:toolbox/core/extension/context/locale.dart';
|
import 'package:toolbox/core/extension/context/locale.dart';
|
||||||
import 'package:toolbox/core/extension/context/snackbar.dart';
|
import 'package:toolbox/core/extension/context/snackbar.dart';
|
||||||
|
import 'package:toolbox/core/utils/misc.dart';
|
||||||
import 'package:toolbox/core/utils/sync/icloud.dart';
|
import 'package:toolbox/core/utils/sync/icloud.dart';
|
||||||
import 'package:toolbox/core/utils/platform/base.dart';
|
import 'package:toolbox/core/utils/platform/base.dart';
|
||||||
import 'package:toolbox/core/utils/share.dart';
|
import 'package:toolbox/core/utils/share.dart';
|
||||||
@@ -14,16 +15,14 @@ import 'package:toolbox/data/model/app/backup.dart';
|
|||||||
import 'package:toolbox/data/res/logger.dart';
|
import 'package:toolbox/data/res/logger.dart';
|
||||||
import 'package:toolbox/data/res/path.dart';
|
import 'package:toolbox/data/res/path.dart';
|
||||||
import 'package:toolbox/data/res/store.dart';
|
import 'package:toolbox/data/res/store.dart';
|
||||||
|
import 'package:toolbox/data/res/ui.dart';
|
||||||
|
import 'package:toolbox/view/widget/appbar.dart';
|
||||||
import 'package:toolbox/view/widget/expand_tile.dart';
|
import 'package:toolbox/view/widget/expand_tile.dart';
|
||||||
import 'package:toolbox/view/widget/cardx.dart';
|
import 'package:toolbox/view/widget/cardx.dart';
|
||||||
import 'package:toolbox/view/widget/input_field.dart';
|
import 'package:toolbox/view/widget/input_field.dart';
|
||||||
import 'package:toolbox/view/widget/store_switch.dart';
|
import 'package:toolbox/view/widget/store_switch.dart';
|
||||||
import 'package:toolbox/view/widget/value_notifier.dart';
|
import 'package:toolbox/view/widget/value_notifier.dart';
|
||||||
|
|
||||||
import '../../core/utils/misc.dart';
|
|
||||||
import '../../data/res/ui.dart';
|
|
||||||
import '../widget/custom_appbar.dart';
|
|
||||||
|
|
||||||
class BackupPage extends StatelessWidget {
|
class BackupPage extends StatelessWidget {
|
||||||
BackupPage({super.key});
|
BackupPage({super.key});
|
||||||
|
|
||||||
@@ -86,57 +85,7 @@ class BackupPage extends StatelessWidget {
|
|||||||
ListTile(
|
ListTile(
|
||||||
trailing: const Icon(Icons.restore),
|
trailing: const Icon(Icons.restore),
|
||||||
title: Text(l10n.restore),
|
title: Text(l10n.restore),
|
||||||
onTap: () async {
|
onTap: () async => _onTapFileRestore(context),
|
||||||
final path = await pickOneFile();
|
|
||||||
if (path == null) return;
|
|
||||||
|
|
||||||
final file = File(path);
|
|
||||||
if (!await file.exists()) {
|
|
||||||
context.showSnackBar(l10n.fileNotExist(path));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final text = await file.readAsString();
|
|
||||||
if (text.isEmpty) {
|
|
||||||
context.showSnackBar(l10n.fieldMustNotEmpty);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
context.showLoadingDialog();
|
|
||||||
final backup =
|
|
||||||
await compute(Backup.fromJsonString, text.trim());
|
|
||||||
if (backupFormatVersion != backup.version) {
|
|
||||||
context.showSnackBar(l10n.backupVersionNotMatch);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await context.showRoundDialog(
|
|
||||||
title: Text(l10n.restore),
|
|
||||||
child: Text(l10n.askContinue(
|
|
||||||
'${l10n.restore} ${l10n.backup}(${backup.date})',
|
|
||||||
)),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () => context.pop(),
|
|
||||||
child: Text(l10n.cancel),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () async {
|
|
||||||
await backup.restore(force: true);
|
|
||||||
context.pop();
|
|
||||||
},
|
|
||||||
child: Text(l10n.ok),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
} catch (e, trace) {
|
|
||||||
Loggers.app.warning('Import backup failed', e, trace);
|
|
||||||
context.showSnackBar(e.toString());
|
|
||||||
} finally {
|
|
||||||
context.pop();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -145,92 +94,25 @@ class BackupPage extends StatelessWidget {
|
|||||||
|
|
||||||
Widget _buildIcloud(BuildContext context) {
|
Widget _buildIcloud(BuildContext context) {
|
||||||
return CardX(
|
return CardX(
|
||||||
ExpandTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.cloud),
|
|
||||||
title: const Text('iCloud'),
|
title: const Text('iCloud'),
|
||||||
initiallyExpanded: true,
|
trailing: StoreSwitch(
|
||||||
children: [
|
prop: Stores.setting.icloudSync,
|
||||||
ListTile(
|
validator: (p0) {
|
||||||
title: Text(l10n.auto),
|
if (p0 && Stores.setting.webdavSync.fetch()) {
|
||||||
trailing: StoreSwitch(
|
context.showSnackBar(l10n.autoBackupConflict);
|
||||||
prop: Stores.setting.icloudSync,
|
return false;
|
||||||
validator: (p0) {
|
}
|
||||||
if (p0 && Stores.setting.webdavSync.fetch()) {
|
return true;
|
||||||
context.showSnackBar(l10n.autoBackupConflict);
|
},
|
||||||
return false;
|
callback: (val) async {
|
||||||
}
|
if (val) {
|
||||||
return true;
|
icloudLoading.value = true;
|
||||||
},
|
await ICloud.sync();
|
||||||
callback: (val) async {
|
icloudLoading.value = false;
|
||||||
if (val) {
|
}
|
||||||
icloudLoading.value = true;
|
},
|
||||||
await ICloud.sync();
|
),
|
||||||
icloudLoading.value = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
ListTile(
|
|
||||||
title: Text(l10n.manual),
|
|
||||||
trailing: ValueBuilder(
|
|
||||||
listenable: icloudLoading,
|
|
||||||
build: () {
|
|
||||||
if (icloudLoading.value) {
|
|
||||||
return UIs.centerSizedLoadingSmall;
|
|
||||||
}
|
|
||||||
return Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () async {
|
|
||||||
icloudLoading.value = true;
|
|
||||||
try {
|
|
||||||
final result = await ICloud.download(
|
|
||||||
relativePath: Paths.bakName,
|
|
||||||
);
|
|
||||||
if (result != null) {
|
|
||||||
Loggers.app
|
|
||||||
.warning('Download backup failed: $result');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch (e, s) {
|
|
||||||
Loggers.app.warning('Download backup failed', e, s);
|
|
||||||
context.showSnackBar(e.toString());
|
|
||||||
icloudLoading.value = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final dlFile =
|
|
||||||
await File(await Paths.bak).readAsString();
|
|
||||||
final dlBak =
|
|
||||||
await compute(Backup.fromJsonString, dlFile);
|
|
||||||
await dlBak.restore(force: true);
|
|
||||||
icloudLoading.value = false;
|
|
||||||
},
|
|
||||||
child: Text(l10n.download),
|
|
||||||
),
|
|
||||||
UIs.width7,
|
|
||||||
TextButton(
|
|
||||||
onPressed: () async {
|
|
||||||
icloudLoading.value = true;
|
|
||||||
await Backup.backup();
|
|
||||||
final uploadResult =
|
|
||||||
await ICloud.upload(relativePath: Paths.bakName);
|
|
||||||
if (uploadResult != null) {
|
|
||||||
Loggers.app.warning(
|
|
||||||
'Upload iCloud backup failed: $uploadResult');
|
|
||||||
} else {
|
|
||||||
Loggers.app.info('Upload iCloud backup success');
|
|
||||||
}
|
|
||||||
icloudLoading.value = false;
|
|
||||||
},
|
|
||||||
child: Text(l10n.upload),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -245,67 +127,7 @@ class BackupPage extends StatelessWidget {
|
|||||||
ListTile(
|
ListTile(
|
||||||
title: Text(l10n.setting),
|
title: Text(l10n.setting),
|
||||||
trailing: const Icon(Icons.settings),
|
trailing: const Icon(Icons.settings),
|
||||||
onTap: () async {
|
onTap: () async => _onTapWebdavSetting(context),
|
||||||
final urlCtrl = TextEditingController(
|
|
||||||
text: Stores.setting.webdavUrl.fetch(),
|
|
||||||
);
|
|
||||||
final userCtrl = TextEditingController(
|
|
||||||
text: Stores.setting.webdavUser.fetch(),
|
|
||||||
);
|
|
||||||
final pwdCtrl = TextEditingController(
|
|
||||||
text: Stores.setting.webdavPwd.fetch(),
|
|
||||||
);
|
|
||||||
final result = await context.showRoundDialog<bool>(
|
|
||||||
title: const Text('WebDAV'),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Input(
|
|
||||||
label: 'URL',
|
|
||||||
hint: 'https://example.com/webdav/',
|
|
||||||
controller: urlCtrl,
|
|
||||||
),
|
|
||||||
Input(
|
|
||||||
label: l10n.user,
|
|
||||||
controller: userCtrl,
|
|
||||||
),
|
|
||||||
Input(
|
|
||||||
label: l10n.pwd,
|
|
||||||
controller: pwdCtrl,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
context.pop(true);
|
|
||||||
},
|
|
||||||
child: Text(l10n.ok),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
if (result == true) {
|
|
||||||
final result = await Webdav.test(
|
|
||||||
urlCtrl.text,
|
|
||||||
userCtrl.text,
|
|
||||||
pwdCtrl.text,
|
|
||||||
);
|
|
||||||
if (result == null) {
|
|
||||||
context.showSnackBar(l10n.success);
|
|
||||||
} else {
|
|
||||||
context.showSnackBar(result);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Webdav.changeClient(
|
|
||||||
urlCtrl.text,
|
|
||||||
userCtrl.text,
|
|
||||||
pwdCtrl.text,
|
|
||||||
);
|
|
||||||
Stores.setting.webdavUrl.put(urlCtrl.text);
|
|
||||||
Stores.setting.webdavUser.put(userCtrl.text);
|
|
||||||
Stores.setting.webdavPwd.put(pwdCtrl.text);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(l10n.auto),
|
title: Text(l10n.auto),
|
||||||
@@ -347,48 +169,12 @@ class BackupPage extends StatelessWidget {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async => _onTapWebdavDl(context),
|
||||||
webdavLoading.value = true;
|
|
||||||
try {
|
|
||||||
final result = await Webdav.download(
|
|
||||||
relativePath: Paths.bakName,
|
|
||||||
);
|
|
||||||
if (result != null) {
|
|
||||||
Loggers.app.warning(
|
|
||||||
'Download webdav backup failed: $result');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch (e, s) {
|
|
||||||
Loggers.app
|
|
||||||
.warning('Download webdav backup failed', e, s);
|
|
||||||
context.showSnackBar(e.toString());
|
|
||||||
webdavLoading.value = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final dlFile =
|
|
||||||
await File(await Paths.bak).readAsString();
|
|
||||||
final dlBak =
|
|
||||||
await compute(Backup.fromJsonString, dlFile);
|
|
||||||
await dlBak.restore(force: true);
|
|
||||||
webdavLoading.value = false;
|
|
||||||
},
|
|
||||||
child: Text(l10n.download),
|
child: Text(l10n.download),
|
||||||
),
|
),
|
||||||
UIs.width7,
|
UIs.width7,
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async => _onTapWebdavUp(context),
|
||||||
webdavLoading.value = true;
|
|
||||||
await Backup.backup();
|
|
||||||
final uploadResult =
|
|
||||||
await Webdav.upload(relativePath: Paths.bakName);
|
|
||||||
if (uploadResult != null) {
|
|
||||||
Loggers.app.warning(
|
|
||||||
'Upload webdav backup failed: $uploadResult');
|
|
||||||
} else {
|
|
||||||
Loggers.app.info('Upload webdav backup success');
|
|
||||||
}
|
|
||||||
webdavLoading.value = false;
|
|
||||||
},
|
|
||||||
child: Text(l10n.upload),
|
child: Text(l10n.upload),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -400,4 +186,141 @@ class BackupPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _onTapFileRestore(BuildContext context) async {
|
||||||
|
final path = await pickOneFile();
|
||||||
|
if (path == null) return;
|
||||||
|
|
||||||
|
final file = File(path);
|
||||||
|
if (!await file.exists()) {
|
||||||
|
context.showSnackBar(l10n.fileNotExist(path));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final text = await file.readAsString();
|
||||||
|
if (text.isEmpty) {
|
||||||
|
context.showSnackBar(l10n.fieldMustNotEmpty);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
context.showLoadingDialog();
|
||||||
|
final backup = await compute(Backup.fromJsonString, text.trim());
|
||||||
|
if (backupFormatVersion != backup.version) {
|
||||||
|
context.showSnackBar(l10n.backupVersionNotMatch);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await context.showRoundDialog(
|
||||||
|
title: Text(l10n.restore),
|
||||||
|
child: Text(l10n.askContinue(
|
||||||
|
'${l10n.restore} ${l10n.backup}(${backup.date})',
|
||||||
|
)),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => context.pop(),
|
||||||
|
child: Text(l10n.cancel),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await backup.restore(force: true);
|
||||||
|
context.pop();
|
||||||
|
},
|
||||||
|
child: Text(l10n.ok),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} catch (e, trace) {
|
||||||
|
Loggers.app.warning('Import backup failed', e, trace);
|
||||||
|
context.showSnackBar(e.toString());
|
||||||
|
} finally {
|
||||||
|
context.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onTapWebdavDl(BuildContext context) async {
|
||||||
|
webdavLoading.value = true;
|
||||||
|
try {
|
||||||
|
final result = await Webdav.download(
|
||||||
|
relativePath: Paths.bakName,
|
||||||
|
);
|
||||||
|
if (result != null) {
|
||||||
|
Loggers.app.warning('Download webdav backup failed: $result');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (e, s) {
|
||||||
|
Loggers.app.warning('Download webdav backup failed', e, s);
|
||||||
|
context.showSnackBar(e.toString());
|
||||||
|
webdavLoading.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final dlFile = await File(await Paths.bak).readAsString();
|
||||||
|
final dlBak = await compute(Backup.fromJsonString, dlFile);
|
||||||
|
await dlBak.restore(force: true);
|
||||||
|
webdavLoading.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onTapWebdavUp(BuildContext context) async {
|
||||||
|
webdavLoading.value = true;
|
||||||
|
await Backup.backup();
|
||||||
|
final uploadResult = await Webdav.upload(relativePath: Paths.bakName);
|
||||||
|
if (uploadResult != null) {
|
||||||
|
Loggers.app.warning('Upload webdav backup failed: $uploadResult');
|
||||||
|
} else {
|
||||||
|
Loggers.app.info('Upload webdav backup success');
|
||||||
|
}
|
||||||
|
webdavLoading.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onTapWebdavSetting(BuildContext context) async {
|
||||||
|
final urlCtrl = TextEditingController(
|
||||||
|
text: Stores.setting.webdavUrl.fetch(),
|
||||||
|
);
|
||||||
|
final userCtrl = TextEditingController(
|
||||||
|
text: Stores.setting.webdavUser.fetch(),
|
||||||
|
);
|
||||||
|
final pwdCtrl = TextEditingController(
|
||||||
|
text: Stores.setting.webdavPwd.fetch(),
|
||||||
|
);
|
||||||
|
final result = await context.showRoundDialog<bool>(
|
||||||
|
title: const Text('WebDAV'),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Input(
|
||||||
|
label: 'URL',
|
||||||
|
hint: 'https://example.com/webdav/',
|
||||||
|
controller: urlCtrl,
|
||||||
|
),
|
||||||
|
Input(
|
||||||
|
label: l10n.user,
|
||||||
|
controller: userCtrl,
|
||||||
|
),
|
||||||
|
Input(
|
||||||
|
label: l10n.pwd,
|
||||||
|
controller: pwdCtrl,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
context.pop(true);
|
||||||
|
},
|
||||||
|
child: Text(l10n.ok),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
if (result == true) {
|
||||||
|
final result =
|
||||||
|
await Webdav.test(urlCtrl.text, userCtrl.text, pwdCtrl.text);
|
||||||
|
if (result == null) {
|
||||||
|
context.showSnackBar(l10n.success);
|
||||||
|
} else {
|
||||||
|
context.showSnackBar(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Webdav.changeClient(urlCtrl.text, userCtrl.text, pwdCtrl.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import 'package:provider/provider.dart';
|
|||||||
import 'package:toolbox/core/extension/context/common.dart';
|
import 'package:toolbox/core/extension/context/common.dart';
|
||||||
import 'package:toolbox/data/provider/debug.dart';
|
import 'package:toolbox/data/provider/debug.dart';
|
||||||
|
|
||||||
import '../widget/custom_appbar.dart';
|
import '../widget/appbar.dart';
|
||||||
|
|
||||||
class DebugPage extends StatefulWidget {
|
class DebugPage extends StatefulWidget {
|
||||||
const DebugPage({super.key});
|
const DebugPage({super.key});
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import '../../data/model/app/error.dart';
|
|||||||
import '../../data/model/app/menu.dart';
|
import '../../data/model/app/menu.dart';
|
||||||
import '../../data/res/ui.dart';
|
import '../../data/res/ui.dart';
|
||||||
import '../../data/res/url.dart';
|
import '../../data/res/url.dart';
|
||||||
import '../widget/custom_appbar.dart';
|
import '../widget/appbar.dart';
|
||||||
import '../widget/popup_menu.dart';
|
import '../widget/popup_menu.dart';
|
||||||
import '../widget/cardx.dart';
|
import '../widget/cardx.dart';
|
||||||
import '../widget/two_line_text.dart';
|
import '../widget/two_line_text.dart';
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import 'package:toolbox/core/utils/misc.dart';
|
|||||||
import 'package:toolbox/data/res/highlight.dart';
|
import 'package:toolbox/data/res/highlight.dart';
|
||||||
import 'package:toolbox/data/res/store.dart';
|
import 'package:toolbox/data/res/store.dart';
|
||||||
|
|
||||||
import '../widget/custom_appbar.dart';
|
import '../widget/appbar.dart';
|
||||||
import '../widget/two_line_text.dart';
|
import '../widget/two_line_text.dart';
|
||||||
|
|
||||||
class EditorPage extends StatefulWidget {
|
class EditorPage extends StatefulWidget {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import '../../data/res/build_data.dart';
|
|||||||
import '../../data/res/misc.dart';
|
import '../../data/res/misc.dart';
|
||||||
import '../../data/res/ui.dart';
|
import '../../data/res/ui.dart';
|
||||||
import '../../data/res/url.dart';
|
import '../../data/res/url.dart';
|
||||||
import '../widget/custom_appbar.dart';
|
import '../widget/appbar.dart';
|
||||||
import '../widget/cardx.dart';
|
import '../widget/cardx.dart';
|
||||||
import '../widget/url_text.dart';
|
import '../widget/url_text.dart';
|
||||||
import '../widget/value_notifier.dart';
|
import '../widget/value_notifier.dart';
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import 'package:toolbox/view/widget/input_field.dart';
|
|||||||
import '../../../core/utils/server.dart';
|
import '../../../core/utils/server.dart';
|
||||||
import '../../../data/model/server/private_key_info.dart';
|
import '../../../data/model/server/private_key_info.dart';
|
||||||
import '../../../data/res/ui.dart';
|
import '../../../data/res/ui.dart';
|
||||||
import '../../widget/custom_appbar.dart';
|
import '../../widget/appbar.dart';
|
||||||
|
|
||||||
const _format = 'text/plain';
|
const _format = 'text/plain';
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import '../../../core/route.dart';
|
|||||||
import '../../../data/model/server/private_key_info.dart';
|
import '../../../data/model/server/private_key_info.dart';
|
||||||
import '../../../data/provider/private_key.dart';
|
import '../../../data/provider/private_key.dart';
|
||||||
import '../../../data/res/ui.dart';
|
import '../../../data/res/ui.dart';
|
||||||
import '../../widget/custom_appbar.dart';
|
import '../../widget/appbar.dart';
|
||||||
import '../../widget/cardx.dart';
|
import '../../widget/cardx.dart';
|
||||||
|
|
||||||
class PrivateKeysListPage extends StatefulWidget {
|
class PrivateKeysListPage extends StatefulWidget {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import '../../data/model/app/shell_func.dart';
|
|||||||
import '../../data/model/server/proc.dart';
|
import '../../data/model/server/proc.dart';
|
||||||
import '../../data/model/server/server_private_info.dart';
|
import '../../data/model/server/server_private_info.dart';
|
||||||
import '../../data/res/ui.dart';
|
import '../../data/res/ui.dart';
|
||||||
import '../widget/custom_appbar.dart';
|
import '../widget/appbar.dart';
|
||||||
import '../widget/cardx.dart';
|
import '../widget/cardx.dart';
|
||||||
import '../widget/two_line_text.dart';
|
import '../widget/two_line_text.dart';
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import '../../../data/provider/server.dart';
|
|||||||
import '../../../data/res/color.dart';
|
import '../../../data/res/color.dart';
|
||||||
import '../../../data/res/default.dart';
|
import '../../../data/res/default.dart';
|
||||||
import '../../../data/res/ui.dart';
|
import '../../../data/res/ui.dart';
|
||||||
import '../../widget/custom_appbar.dart';
|
import '../../widget/appbar.dart';
|
||||||
import '../../widget/cardx.dart';
|
import '../../widget/cardx.dart';
|
||||||
|
|
||||||
class ServerDetailPage extends StatefulWidget {
|
class ServerDetailPage extends StatefulWidget {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import '../../../data/model/server/private_key_info.dart';
|
|||||||
import '../../../data/model/server/server_private_info.dart';
|
import '../../../data/model/server/server_private_info.dart';
|
||||||
import '../../../data/provider/private_key.dart';
|
import '../../../data/provider/private_key.dart';
|
||||||
import '../../../data/res/ui.dart';
|
import '../../../data/res/ui.dart';
|
||||||
import '../../widget/custom_appbar.dart';
|
import '../../widget/appbar.dart';
|
||||||
import '../../widget/input_field.dart';
|
import '../../widget/input_field.dart';
|
||||||
import '../../widget/cardx.dart';
|
import '../../widget/cardx.dart';
|
||||||
import '../../widget/tag.dart';
|
import '../../widget/tag.dart';
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import 'package:toolbox/core/extension/context/snackbar.dart';
|
|||||||
import 'package:toolbox/core/utils/platform/auth.dart';
|
import 'package:toolbox/core/utils/platform/auth.dart';
|
||||||
import 'package:toolbox/data/res/store.dart';
|
import 'package:toolbox/data/res/store.dart';
|
||||||
import 'package:toolbox/view/page/setting/platform_pub.dart';
|
import 'package:toolbox/view/page/setting/platform_pub.dart';
|
||||||
import 'package:toolbox/view/widget/custom_appbar.dart';
|
import 'package:toolbox/view/widget/appbar.dart';
|
||||||
import 'package:toolbox/view/widget/input_field.dart';
|
import 'package:toolbox/view/widget/input_field.dart';
|
||||||
import 'package:toolbox/view/widget/cardx.dart';
|
import 'package:toolbox/view/widget/cardx.dart';
|
||||||
import 'package:toolbox/view/widget/store_switch.dart';
|
import 'package:toolbox/view/widget/store_switch.dart';
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ import '../../../data/res/color.dart';
|
|||||||
import '../../../data/res/path.dart';
|
import '../../../data/res/path.dart';
|
||||||
import '../../../data/res/ui.dart';
|
import '../../../data/res/ui.dart';
|
||||||
import '../../widget/color_picker.dart';
|
import '../../widget/color_picker.dart';
|
||||||
import '../../widget/custom_appbar.dart';
|
import '../../widget/appbar.dart';
|
||||||
import '../../widget/input_field.dart';
|
import '../../widget/input_field.dart';
|
||||||
import '../../widget/cardx.dart';
|
import '../../widget/cardx.dart';
|
||||||
import '../../widget/store_switch.dart';
|
import '../../widget/store_switch.dart';
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import 'package:toolbox/data/res/misc.dart';
|
|||||||
import 'package:toolbox/data/res/store.dart';
|
import 'package:toolbox/data/res/store.dart';
|
||||||
import 'package:toolbox/data/res/ui.dart';
|
import 'package:toolbox/data/res/ui.dart';
|
||||||
import 'package:toolbox/view/page/setting/platform_pub.dart';
|
import 'package:toolbox/view/page/setting/platform_pub.dart';
|
||||||
import 'package:toolbox/view/widget/custom_appbar.dart';
|
import 'package:toolbox/view/widget/appbar.dart';
|
||||||
import 'package:toolbox/view/widget/future_widget.dart';
|
import 'package:toolbox/view/widget/future_widget.dart';
|
||||||
import 'package:toolbox/view/widget/cardx.dart';
|
import 'package:toolbox/view/widget/cardx.dart';
|
||||||
import 'package:toolbox/view/widget/store_switch.dart';
|
import 'package:toolbox/view/widget/store_switch.dart';
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import 'package:toolbox/core/extension/context/locale.dart';
|
|||||||
import 'package:toolbox/data/res/store.dart';
|
import 'package:toolbox/data/res/store.dart';
|
||||||
|
|
||||||
import '../../../core/extension/order.dart';
|
import '../../../core/extension/order.dart';
|
||||||
import '../../widget/custom_appbar.dart';
|
import '../../widget/appbar.dart';
|
||||||
import '../../widget/cardx.dart';
|
import '../../widget/cardx.dart';
|
||||||
|
|
||||||
class ServerDetailOrderPage extends StatefulWidget {
|
class ServerDetailOrderPage extends StatefulWidget {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import 'package:toolbox/data/res/store.dart';
|
|||||||
import 'package:toolbox/data/res/ui.dart';
|
import 'package:toolbox/data/res/ui.dart';
|
||||||
import 'package:toolbox/view/widget/cardx.dart';
|
import 'package:toolbox/view/widget/cardx.dart';
|
||||||
|
|
||||||
import '../../widget/custom_appbar.dart';
|
import '../../widget/appbar.dart';
|
||||||
|
|
||||||
class ServerOrderPage extends StatefulWidget {
|
class ServerOrderPage extends StatefulWidget {
|
||||||
const ServerOrderPage({super.key});
|
const ServerOrderPage({super.key});
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import 'package:toolbox/data/res/store.dart';
|
|||||||
import 'package:toolbox/data/res/ui.dart';
|
import 'package:toolbox/data/res/ui.dart';
|
||||||
import 'package:toolbox/view/widget/cardx.dart';
|
import 'package:toolbox/view/widget/cardx.dart';
|
||||||
|
|
||||||
import '../../widget/custom_appbar.dart';
|
import '../../widget/appbar.dart';
|
||||||
|
|
||||||
class SSHVirtKeySettingPage extends StatefulWidget {
|
class SSHVirtKeySettingPage extends StatefulWidget {
|
||||||
const SSHVirtKeySettingPage({super.key});
|
const SSHVirtKeySettingPage({super.key});
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import 'package:toolbox/view/widget/input_field.dart';
|
|||||||
|
|
||||||
import '../../../data/model/server/snippet.dart';
|
import '../../../data/model/server/snippet.dart';
|
||||||
import '../../../data/res/ui.dart';
|
import '../../../data/res/ui.dart';
|
||||||
import '../../widget/custom_appbar.dart';
|
import '../../widget/appbar.dart';
|
||||||
import '../../widget/tag.dart';
|
import '../../widget/tag.dart';
|
||||||
|
|
||||||
class SnippetEditPage extends StatefulWidget {
|
class SnippetEditPage extends StatefulWidget {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import 'package:toolbox/core/extension/context/locale.dart';
|
|||||||
import 'package:toolbox/data/model/server/snippet.dart';
|
import 'package:toolbox/data/model/server/snippet.dart';
|
||||||
import 'package:toolbox/data/res/ui.dart';
|
import 'package:toolbox/data/res/ui.dart';
|
||||||
import 'package:toolbox/view/widget/cardx.dart';
|
import 'package:toolbox/view/widget/cardx.dart';
|
||||||
import 'package:toolbox/view/widget/custom_appbar.dart';
|
import 'package:toolbox/view/widget/appbar.dart';
|
||||||
import 'package:toolbox/view/widget/expand_tile.dart';
|
import 'package:toolbox/view/widget/expand_tile.dart';
|
||||||
|
|
||||||
class SnippetResultPage extends StatelessWidget {
|
class SnippetResultPage extends StatelessWidget {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import '../../../core/utils/misc.dart';
|
|||||||
import '../../../data/model/app/path_with_prefix.dart';
|
import '../../../data/model/app/path_with_prefix.dart';
|
||||||
import '../../../data/res/path.dart';
|
import '../../../data/res/path.dart';
|
||||||
import '../../../data/res/ui.dart';
|
import '../../../data/res/ui.dart';
|
||||||
import '../../widget/custom_appbar.dart';
|
import '../../widget/appbar.dart';
|
||||||
import '../../widget/fade_in.dart';
|
import '../../widget/fade_in.dart';
|
||||||
|
|
||||||
class LocalStoragePage extends StatefulWidget {
|
class LocalStoragePage extends StatefulWidget {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import '../../../data/model/sftp/browser_status.dart';
|
|||||||
import '../../../data/model/sftp/req.dart';
|
import '../../../data/model/sftp/req.dart';
|
||||||
import '../../../data/res/path.dart';
|
import '../../../data/res/path.dart';
|
||||||
import '../../../data/res/ui.dart';
|
import '../../../data/res/ui.dart';
|
||||||
import '../../widget/custom_appbar.dart';
|
import '../../widget/appbar.dart';
|
||||||
import '../../widget/fade_in.dart';
|
import '../../widget/fade_in.dart';
|
||||||
import '../../widget/input_field.dart';
|
import '../../widget/input_field.dart';
|
||||||
import '../../widget/two_line_text.dart';
|
import '../../widget/two_line_text.dart';
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import '../../../core/extension/numx.dart';
|
|||||||
import '../../../data/model/sftp/req.dart';
|
import '../../../data/model/sftp/req.dart';
|
||||||
import '../../../data/provider/sftp.dart';
|
import '../../../data/provider/sftp.dart';
|
||||||
import '../../../data/res/ui.dart';
|
import '../../../data/res/ui.dart';
|
||||||
import '../../widget/custom_appbar.dart';
|
import '../../widget/appbar.dart';
|
||||||
import '../../widget/cardx.dart';
|
import '../../widget/cardx.dart';
|
||||||
|
|
||||||
class SftpMissionPage extends StatefulWidget {
|
class SftpMissionPage extends StatefulWidget {
|
||||||
|
|||||||
Reference in New Issue
Block a user