Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-08-13 14:16:19 +08:00
parent b2100f3872
commit 685852c0a4
18 changed files with 618 additions and 675 deletions

View File

@@ -97,12 +97,11 @@ class _AboutPageState extends State<AboutPage> {
);
}
},
child: ConstrainedBox(
constraints: const BoxConstraints(maxHeight: 150),
child: ExcludeSemantics(
child: Image.asset(
'assets/images/logo/logo.png',
),
child: ExcludeSemantics(
child: Image.asset(
width: 150,
height: 150,
'assets/images/logo/logo.png',
),
),
),

View File

@@ -106,20 +106,21 @@ abstract class ReplyController<R> extends CommonListController<R, ReplyInfo> {
}
(bool inputDisable, String? hint) get replyHint {
bool inputDisable = false;
String? hint;
try {
if (subjectControl != null && subjectControl!.hasRootText()) {
if (subjectControl!.inputDisable) {
SmartDialog.showToast(subjectControl!.rootText);
return (true, null);
final rootText = subjectControl!.rootText;
inputDisable = subjectControl!.inputDisable;
if (inputDisable) {
SmartDialog.showToast(rootText);
}
if ((subjectControl!.hasSwitcherType() &&
subjectControl!.switcherType != 1) ||
subjectControl!.rootText.contains('可发评论')) {
return (false, subjectControl!.rootText);
if (rootText.contains('可发') || rootText.contains('可见')) {
hint = rootText;
}
}
} catch (_) {}
return (false, null);
return (inputDisable, hint);
}
void onReply(

View File

@@ -144,18 +144,11 @@ class LiveRoomController extends GetxController {
acceptQnList = item.acceptQn!.map((e) {
return (
code: e,
desc:
LiveQuality.values
.firstWhereOrNull((element) => element.code == e)
?.description ??
e.toString(),
desc: LiveQuality.fromCode(e)?.desc ?? e.toString(),
);
}).toList();
currentQnDesc.value =
LiveQuality.values
.firstWhereOrNull((element) => element.code == currentQn)
?.description ??
currentQn.toString();
LiveQuality.fromCode(currentQn)?.desc ?? currentQn.toString();
videoUrl = VideoUtils.getCdnUrl(item);
await playerInit();
isLoaded.value = true;
@@ -286,10 +279,7 @@ class LiveRoomController extends GetxController {
}
currentQn = qn;
currentQnDesc.value =
LiveQuality.values
.firstWhereOrNull((element) => element.code == currentQn)
?.description ??
currentQn.toString();
LiveQuality.fromCode(currentQn)?.desc ?? currentQn.toString();
return queryLiveUrl();
}

View File

@@ -13,6 +13,7 @@ import 'package:PiliPlus/plugin/pl_player/controller.dart';
import 'package:PiliPlus/plugin/pl_player/models/play_status.dart';
import 'package:PiliPlus/plugin/pl_player/utils/fullscreen.dart';
import 'package:PiliPlus/plugin/pl_player/view.dart';
import 'package:PiliPlus/plugin/pl_player/widgets/common_btn.dart';
import 'package:PiliPlus/services/service_locator.dart';
import 'package:PiliPlus/utils/duration_util.dart';
import 'package:PiliPlus/utils/extension.dart';
@@ -46,8 +47,6 @@ class _LiveRoomPageState extends State<LiveRoomPage>
final GlobalKey chatKey = GlobalKey();
final GlobalKey playerKey = GlobalKey();
final Color _color = const Color(0xFFEEEEEE);
@override
void initState() {
super.initState();
@@ -630,13 +629,14 @@ class _LiveRoomPageState extends State<LiveRoomPage>
child: Padding(
padding: const EdgeInsets.only(top: 5, bottom: 10),
child: Row(
spacing: 6,
children: [
Obx(
() {
final enableShowDanmaku =
plPlayerController.enableShowDanmaku.value;
return IconButton(
onPressed: () {
return ComBtn(
onTap: () {
final newVal = !enableShowDanmaku;
plPlayerController.enableShowDanmaku.value = newVal;
if (!plPlayerController.tempPlayerConf) {
@@ -646,19 +646,24 @@ class _LiveRoomPageState extends State<LiveRoomPage>
);
}
},
icon: Icon(
enableShowDanmaku
? Icons.subtitles_outlined
: Icons.subtitles_off_outlined,
color: _color,
),
icon: enableShowDanmaku
? const Icon(
size: 22,
Icons.subtitles_outlined,
color: Color(0xFFEEEEEE),
)
: const Icon(
size: 22,
Icons.subtitles_off_outlined,
color: Color(0xFFEEEEEE),
),
);
},
),
Expanded(
const Expanded(
child: Text(
'发送弹幕',
style: TextStyle(color: _color),
style: TextStyle(color: Color(0xFFEEEEEE)),
),
),
Builder(
@@ -675,9 +680,13 @@ class _LiveRoomPageState extends State<LiveRoomPage>
onTapDown: _liveRoomController.onLikeTapDown,
onTapUp: _liveRoomController.onLikeTapUp,
onTapCancel: _liveRoomController.onLikeTapUp,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(Icons.thumb_up_off_alt, color: _color),
child: const SizedBox.square(
dimension: 34,
child: Icon(
size: 22,
color: Color(0xFFEEEEEE),
Icons.thumb_up_off_alt,
),
),
),
Positioned(
@@ -715,9 +724,13 @@ class _LiveRoomPageState extends State<LiveRoomPage>
);
},
),
IconButton(
onPressed: () => onSendDanmaku(true),
icon: Icon(Icons.emoji_emotions_outlined, color: _color),
ComBtn(
onTap: () => onSendDanmaku(true),
icon: const Icon(
size: 22,
color: Color(0xFFEEEEEE),
Icons.emoji_emotions_outlined,
),
),
],
),

View File

@@ -37,6 +37,7 @@ class BottomControl extends StatelessWidget {
children: [
PlayOrPauseButton(plPlayerController: plPlayerController),
ComBtn(
height: 30,
icon: const Icon(
Icons.refresh,
size: 18,
@@ -45,92 +46,81 @@ class BottomControl extends StatelessWidget {
onTap: onRefresh,
),
const Spacer(),
SizedBox(
width: 35,
height: 35,
child: IconButton(
tooltip: '弹幕屏蔽',
style: ButtonStyle(
padding: WidgetStateProperty.all(EdgeInsets.zero),
),
onPressed: () {
if (liveRoomCtr.isLogin) {
Get.toNamed(
'/liveDmBlockPage',
parameters: {
'roomId': liveRoomCtr.roomId.toString(),
},
);
} else {
SmartDialog.showToast('账号未登录');
}
},
icon: const Icon(
size: 18,
Icons.block,
color: Colors.white,
),
ComBtn(
height: 30,
icon: const Icon(
size: 18,
Icons.block,
color: Colors.white,
),
onTap: () {
if (liveRoomCtr.isLogin) {
Get.toNamed(
'/liveDmBlockPage',
parameters: {
'roomId': liveRoomCtr.roomId.toString(),
},
);
} else {
SmartDialog.showToast('账号未登录');
}
},
),
const SizedBox(width: 10),
const SizedBox(width: 3),
Obx(
() {
final enableShowDanmaku =
plPlayerController.enableShowDanmaku.value;
return SizedBox(
width: 35,
height: 35,
child: IconButton(
tooltip: '弹幕开关',
style: ButtonStyle(
padding: WidgetStateProperty.all(EdgeInsets.zero),
),
onPressed: () {
final newVal = !enableShowDanmaku;
plPlayerController.enableShowDanmaku.value = newVal;
if (!plPlayerController.tempPlayerConf) {
GStorage.setting.put(
SettingBoxKey.enableShowDanmaku,
newVal,
);
}
},
icon: Icon(
size: 18,
enableShowDanmaku
? Icons.subtitles_outlined
: Icons.subtitles_off_outlined,
color: Colors.white,
),
),
return ComBtn(
icon: enableShowDanmaku
? const Icon(
size: 18,
Icons.subtitles_outlined,
color: Colors.white,
)
: const Icon(
size: 18,
Icons.subtitles_off_outlined,
color: Colors.white,
),
onTap: () {
final newVal = !enableShowDanmaku;
plPlayerController.enableShowDanmaku.value = newVal;
if (!plPlayerController.tempPlayerConf) {
GStorage.setting.put(
SettingBoxKey.enableShowDanmaku,
newVal,
);
}
},
);
},
),
Obx(
() => Container(
height: 30,
margin: const EdgeInsets.symmetric(horizontal: 10),
alignment: Alignment.center,
child: PopupMenuButton<BoxFit>(
initialValue: plPlayerController.videoFit.value,
color: Colors.black.withValues(alpha: 0.8),
itemBuilder: (BuildContext context) {
return BoxFit.values.map((BoxFit boxFit) {
return PopupMenuItem<BoxFit>(
height: 35,
padding: const EdgeInsets.only(left: 30),
value: boxFit,
onTap: () => plPlayerController.toggleVideoFit(boxFit),
child: Text(
boxFit.desc,
style: const TextStyle(
color: Colors.white,
fontSize: 13,
() => PopupMenuButton<BoxFit>(
initialValue: plPlayerController.videoFit.value,
color: Colors.black.withValues(alpha: 0.8),
itemBuilder: (context) {
return BoxFit.values
.map(
(BoxFit boxFit) => PopupMenuItem<BoxFit>(
height: 35,
padding: const EdgeInsets.only(left: 30),
value: boxFit,
onTap: () => plPlayerController.toggleVideoFit(boxFit),
child: Text(
boxFit.desc,
style: const TextStyle(
color: Colors.white,
fontSize: 13,
),
),
),
);
}).toList();
},
)
.toList();
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Text(
plPlayerController.videoFit.value.desc,
style: const TextStyle(color: Colors.white, fontSize: 13),
@@ -138,46 +128,54 @@ class BottomControl extends StatelessWidget {
),
),
),
const SizedBox(width: 10),
Obx(
() => SizedBox(
width: 30,
child: PopupMenuButton<int>(
padding: EdgeInsets.zero,
initialValue: liveRoomCtr.currentQn,
color: Colors.black.withValues(alpha: 0.8),
() => PopupMenuButton<int>(
padding: EdgeInsets.zero,
initialValue: liveRoomCtr.currentQn,
color: Colors.black.withValues(alpha: 0.8),
itemBuilder: (context) {
return liveRoomCtr.acceptQnList
.map(
(e) => PopupMenuItem<int>(
height: 35,
padding: const EdgeInsets.only(left: 30),
value: e.code,
onTap: () => liveRoomCtr.changeQn(e.code),
child: Text(
e.desc,
style: const TextStyle(
color: Colors.white,
fontSize: 13,
),
),
),
)
.toList();
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Text(
liveRoomCtr.currentQnDesc.value,
style: const TextStyle(color: Colors.white, fontSize: 13),
),
itemBuilder: (BuildContext context) {
return liveRoomCtr.acceptQnList.map((e) {
return PopupMenuItem<int>(
height: 35,
padding: const EdgeInsets.only(left: 30),
value: e.code,
onTap: () => liveRoomCtr.changeQn(e.code),
child: Text(
e.desc,
style: const TextStyle(
color: Colors.white,
fontSize: 13,
),
),
);
}).toList();
},
),
),
),
const SizedBox(width: 10),
ComBtn(
icon: const Icon(
Icons.fullscreen,
semanticLabel: '全屏切换',
size: 20,
color: Colors.white,
),
height: 30,
icon: plPlayerController.isFullScreen.value
? const Icon(
Icons.fullscreen_exit,
semanticLabel: '退出全屏',
size: 24,
color: Colors.white,
)
: const Icon(
Icons.fullscreen,
semanticLabel: '全屏',
size: 24,
color: Colors.white,
),
onTap: () => plPlayerController.triggerFullScreen(
status: !plPlayerController.isFullScreen.value,
),

View File

@@ -1,6 +1,7 @@
import 'dart:io';
import 'package:PiliPlus/plugin/pl_player/controller.dart';
import 'package:PiliPlus/plugin/pl_player/widgets/common_btn.dart';
import 'package:PiliPlus/utils/page_utils.dart';
import 'package:floating/floating.dart';
import 'package:flutter/material.dart';
@@ -27,6 +28,39 @@ class LiveHeaderControl extends StatelessWidget {
@override
Widget build(BuildContext context) {
final isFullScreen = plPlayerController.isFullScreen.value;
Widget child;
if (title != null) {
child = Text(
title!,
maxLines: 1,
style: const TextStyle(
fontSize: 15,
height: 1,
color: Colors.white,
),
);
if (isFullScreen && upName != null) {
child = Column(
spacing: 5,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
child,
Text(
upName!,
maxLines: 1,
style: const TextStyle(
fontSize: 12,
height: 1,
color: Colors.white,
),
),
],
);
}
child = Expanded(child: child);
} else {
child = const Spacer();
}
return AppBar(
backgroundColor: Colors.transparent,
foregroundColor: Colors.white,
@@ -37,147 +71,75 @@ class LiveHeaderControl extends StatelessWidget {
spacing: 10,
children: [
if (isFullScreen)
SizedBox(
width: 35,
height: 35,
child: IconButton(
tooltip: '返回',
icon: const Icon(
FontAwesomeIcons.arrowLeft,
size: 15,
),
style: ButtonStyle(
padding: WidgetStateProperty.all(EdgeInsets.zero),
),
onPressed: () =>
plPlayerController.triggerFullScreen(status: false),
),
ComBtn(
icon: const Icon(FontAwesomeIcons.arrowLeft, size: 15),
onTap: () => plPlayerController.triggerFullScreen(status: false),
),
if (title != null)
Expanded(
child: Column(
spacing: 5,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title!,
maxLines: 1,
style: const TextStyle(
fontSize: 15,
height: 1,
color: Colors.white,
),
),
if (isFullScreen && upName != null)
Text(
upName!,
maxLines: 1,
style: const TextStyle(
fontSize: 12,
height: 1,
color: Colors.white,
),
),
],
),
)
else
const Spacer(),
SizedBox(
width: 35,
height: 35,
child: IconButton(
tooltip: '发弹幕',
style: ButtonStyle(
padding: WidgetStateProperty.all(EdgeInsets.zero),
),
onPressed: onSendDanmaku,
icon: const Icon(
Icons.comment_outlined,
size: 18,
color: Colors.white,
),
child,
ComBtn(
icon: const Icon(
size: 18,
Icons.comment_outlined,
color: Colors.white,
),
onTap: onSendDanmaku,
),
Obx(
() {
final onlyPlayAudio = plPlayerController.onlyPlayAudio.value;
return SizedBox(
width: 35,
height: 35,
child: IconButton(
onPressed: () {
plPlayerController.onlyPlayAudio.value = !onlyPlayAudio;
onPlayAudio();
},
style: ButtonStyle(
padding: WidgetStateProperty.all(EdgeInsets.zero),
),
icon: onlyPlayAudio
? const Icon(
size: 18,
MdiIcons.musicCircle,
color: Colors.white,
)
: const Icon(
size: 18,
MdiIcons.musicCircleOutline,
color: Colors.white,
),
),
return ComBtn(
onTap: () {
plPlayerController.onlyPlayAudio.value = !onlyPlayAudio;
onPlayAudio();
},
icon: onlyPlayAudio
? const Icon(
size: 18,
MdiIcons.musicCircle,
color: Colors.white,
)
: const Icon(
size: 18,
MdiIcons.musicCircleOutline,
color: Colors.white,
),
);
},
),
if (Platform.isAndroid)
SizedBox(
width: 35,
height: 35,
child: IconButton(
tooltip: '画中画',
style: ButtonStyle(
padding: WidgetStateProperty.all(EdgeInsets.zero),
),
onPressed: () async {
try {
var floating = Floating();
if ((await floating.isPipAvailable) == true) {
plPlayerController.hiddenControls(false);
floating.enable(
plPlayerController.isVertical
? const EnableManual(
aspectRatio: Rational.vertical(),
)
: const EnableManual(),
);
}
} catch (_) {}
},
icon: const Icon(
Icons.picture_in_picture_outlined,
size: 18,
color: Colors.white,
),
),
),
SizedBox(
width: 35,
height: 35,
child: IconButton(
tooltip: '定时关闭',
style: ButtonStyle(
padding: WidgetStateProperty.all(EdgeInsets.zero),
),
onPressed: () => PageUtils.scheduleExit(
context,
plPlayerController.isFullScreen.value,
true,
),
ComBtn(
onTap: () async {
try {
var floating = Floating();
if ((await floating.isPipAvailable) == true) {
plPlayerController.hiddenControls(false);
floating.enable(
plPlayerController.isVertical
? const EnableManual(
aspectRatio: Rational.vertical(),
)
: const EnableManual(),
);
}
} catch (_) {}
},
icon: const Icon(
size: 18,
Icons.schedule,
Icons.picture_in_picture_outlined,
color: Colors.white,
),
),
ComBtn(
onTap: () => PageUtils.scheduleExit(
context,
plPlayerController.isFullScreen.value,
true,
),
icon: const Icon(
size: 18,
Icons.schedule,
color: Colors.white,
),
),
],
),

View File

@@ -25,7 +25,6 @@ class MemberController extends CommonDataController<SpaceData, SpaceData?>
MemberController({required this.mid});
int mid;
String? username;
RxBool showUname = false.obs;
AccountService accountService = Get.find<AccountService>();
@@ -131,7 +130,6 @@ class MemberController extends CommonDataController<SpaceData, SpaceData?>
vsync: this,
length: tabs.length,
);
showUname.value = true;
username = errMsg;
loadingState.value = const Success(null);
return true;

View File

@@ -110,7 +110,7 @@ class UserInfoCard extends StatelessWidget {
List<Widget> _buildLeft(BuildContext context, ThemeData theme) => [
Padding(
padding: const EdgeInsets.only(left: 20, right: 20, top: 5),
padding: const EdgeInsets.only(left: 20, right: 20),
child: Wrap(
spacing: 8,
runSpacing: 8,
@@ -461,6 +461,7 @@ class UserInfoCard extends StatelessWidget {
),
],
),
const SizedBox(height: 5),
..._buildLeft(context, theme),
if (card.prInfo?.content?.isNotEmpty == true) buildPrInfo(theme),
const SizedBox(height: 5),

View File

@@ -61,27 +61,28 @@ class _MemberVideoState extends State<MemberVideo>
Widget build(BuildContext context) {
super.build(context);
final theme = Theme.of(context);
return Stack(
clipBehavior: Clip.none,
children: [
refreshIndicator(
onRefresh: _controller.onRefresh,
child: CustomScrollView(
physics: ReloadScrollPhysics(controller: _controller),
slivers: [
SliverPadding(
padding: EdgeInsets.only(
bottom: MediaQuery.paddingOf(context).bottom + 80,
),
sliver: Obx(
() => _buildBody(theme, _controller.loadingState.value),
),
),
],
Widget child = refreshIndicator(
onRefresh: _controller.onRefresh,
child: CustomScrollView(
physics: ReloadScrollPhysics(controller: _controller),
slivers: [
SliverPadding(
padding: EdgeInsets.only(
bottom: MediaQuery.paddingOf(context).bottom + 80,
),
sliver: Obx(
() => _buildBody(theme, _controller.loadingState.value),
),
),
),
if (widget.type == ContributeType.video &&
_controller.fromViewAid?.isNotEmpty == true)
],
),
);
if (widget.type == ContributeType.video &&
_controller.fromViewAid?.isNotEmpty == true) {
return Stack(
clipBehavior: Clip.none,
children: [
child,
Obx(
() => _controller.isLocating.value != true
? Positioned(
@@ -103,6 +104,7 @@ class _MemberVideoState extends State<MemberVideo>
?.indexWhere((i) => i.param == fromViewAid);
if (locatedIndex == null || locatedIndex == -1) {
_controller
..reload = true
..page = 0
..loadingState.value = LoadingState.loading()
..queryData();
@@ -120,8 +122,10 @@ class _MemberVideoState extends State<MemberVideo>
)
: const SizedBox.shrink(),
),
],
);
],
);
}
return child;
}
Widget _buildBody(

View File

@@ -527,14 +527,14 @@ List<SettingsModel> get extraSettings => [
title: '超分辨率',
leading: const Icon(Icons.stay_current_landscape_outlined),
getSubtitle: () =>
'当前:「${SuperResolutionType.values[Pref.superResolutionType].title}\n默认设置对番剧生效, 其他视频默认关闭\n超分辨率需要启用硬件解码, 若启用硬件解码后仍然不生效, 尝试切换硬件解码器为 auto-copy',
'当前:「${Pref.superResolutionType.title}\n默认设置对番剧生效, 其他视频默认关闭\n超分辨率需要启用硬件解码, 若启用硬件解码后仍然不生效, 尝试切换硬件解码器为 auto-copy',
onTap: (setState) async {
SuperResolutionType? result = await showDialog(
context: Get.context!,
builder: (context) {
return SelectDialog<SuperResolutionType>(
title: '超分辨率',
value: SuperResolutionType.values[Pref.superResolutionType],
value: Pref.superResolutionType,
values: SuperResolutionType.values
.map((e) => (e, e.title))
.toList(),

View File

@@ -204,8 +204,7 @@ List<SettingsModel> get videoSettings => [
settingsType: SettingsType.normal,
title: '直播默认画质',
leading: const Icon(Icons.video_settings_outlined),
getSubtitle: () =>
'当前画质:${LiveQualityExt.fromCode(Pref.liveQuality)!.description}',
getSubtitle: () => '当前画质:${LiveQuality.fromCode(Pref.liveQuality)?.desc}',
onTap: (setState) async {
int? result = await showDialog(
context: Get.context!,
@@ -213,9 +212,7 @@ List<SettingsModel> get videoSettings => [
return SelectDialog<int>(
title: '直播默认画质',
value: Pref.liveQuality,
values: LiveQuality.values
.map((e) => (e.code, e.description))
.toList(),
values: LiveQuality.values.map((e) => (e.code, e.desc)).toList(),
);
},
);
@@ -230,17 +227,15 @@ List<SettingsModel> get videoSettings => [
title: '蜂窝网络直播默认画质',
leading: const Icon(Icons.video_settings_outlined),
getSubtitle: () =>
'当前画质:${LiveQualityExt.fromCode(Pref.liveQualityCellular)!.description}',
'当前画质:${LiveQuality.fromCode(Pref.liveQualityCellular)?.desc}',
onTap: (setState) async {
int? result = await showDialog(
context: Get.context!,
builder: (context) {
return SelectDialog<int>(
title: '直播默认画质',
title: '蜂窝网络直播默认画质',
value: Pref.liveQualityCellular,
values: LiveQuality.values
.map((e) => (e.code, e.description))
.toList(),
values: LiveQuality.values.map((e) => (e.code, e.desc)).toList(),
);
},
);

View File

@@ -201,18 +201,18 @@ class HeaderControlState extends TripleState<HeaderControl> {
const SizedBox(width: 10),
Builder(
builder: (context) => PopupMenuButton(
initialValue: SuperResolutionType
.values[widget.controller.superResolutionType],
initialValue:
widget.controller.superResolutionType.value,
child: Padding(
padding: const EdgeInsets.all(4),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
SuperResolutionType
.values[widget
.controller
.superResolutionType]
widget
.controller
.superResolutionType
.value
.title,
strutStyle: const StrutStyle(
leading: 0,
@@ -235,7 +235,7 @@ class HeaderControlState extends TripleState<HeaderControl> {
),
),
onSelected: (value) {
widget.controller.setShader(value.index);
widget.controller.setShader(value);
if (context.mounted) {
(context as Element).markNeedsBuild();
}

View File

@@ -121,15 +121,15 @@ class _WebDavSettingPageState extends State<WebDavSettingPage> {
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.save),
onPressed: () async {
await GStorage.setting.putAll({
SettingBoxKey.webdavUri: _uriCtr.text,
SettingBoxKey.webdavUsername: _usernameCtr.text,
SettingBoxKey.webdavPassword: _passwordCtr.text,
SettingBoxKey.webdavDirectory: _directoryCtr.text,
});
if (_uriCtr.text.isEmpty) {
SmartDialog.showToast('地址不能为空');
return;
}
final setting = GStorage.setting;
await setting.put(SettingBoxKey.webdavUri, _uriCtr.text);
await setting.put(SettingBoxKey.webdavUsername, _usernameCtr.text);
await setting.put(SettingBoxKey.webdavPassword, _passwordCtr.text);
await setting.put(SettingBoxKey.webdavDirectory, _directoryCtr.text);
try {
final res = await WebDav().init();
if (res.first) {