feat: ui improvement

This commit is contained in:
Simon Ding
2024-08-08 10:56:03 +08:00
parent 64e98647a8
commit b34e39889c
6 changed files with 190 additions and 99 deletions

View File

@@ -66,8 +66,7 @@ class _DetailCardState extends ConsumerState<DetailCard> {
const SizedBox(
width: 30,
),
Text(
"${widget.details.storage!.name}:"),
Text("${widget.details.storage!.name}:"),
Text(
"${widget.details.mediaType == "tv" ? widget.details.storage!.tvPath : widget.details.storage!.moviePath}"
"${widget.details.targetDir}"),
@@ -90,13 +89,15 @@ class _DetailCardState extends ConsumerState<DetailCard> {
const Text(""),
Expanded(
child: Text(
overflow: TextOverflow.ellipsis,
overflow: TextOverflow.visible,
maxLines: 9,
widget.details.overview ?? "",
)),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
editIcon(widget.details),
downloadButton(),
editIcon(),
deleteIcon(),
],
)
@@ -113,11 +114,10 @@ class _DetailCardState extends ConsumerState<DetailCard> {
}
Widget deleteIcon() {
return Tooltip(
message: widget.details.mediaType == "tv" ? "删除剧集" : "删除电影",
child: IconButton(
onPressed: () => showConfirmDialog(), icon: const Icon(Icons.delete)),
);
return IconButton(
tooltip: widget.details.mediaType == "tv" ? "删除剧集" : "删除电影",
onPressed: () => showConfirmDialog(),
icon: const Icon(Icons.delete));
}
Future<void> showConfirmDialog() {
@@ -150,19 +150,21 @@ class _DetailCardState extends ConsumerState<DetailCard> {
);
}
Widget editIcon(SeriesDetails details) {
Widget editIcon() {
return IconButton(
onPressed: () => showEditDialog(details), icon: const Icon(Icons.edit));
tooltip: "编辑",
onPressed: () => showEditDialog(),
icon: const Icon(Icons.edit));
}
showEditDialog(SeriesDetails details) {
showEditDialog() {
final _formKey = GlobalKey<FormBuilderState>();
return showDialog<void>(
context: context,
barrierDismissible: true,
builder: (BuildContext context) {
return AlertDialog(
title: Text("编辑 ${details.name}"),
title: Text("编辑 ${widget.details.name}"),
content: SelectionArea(
child: SizedBox(
width: MediaQuery.of(context).size.width * 0.3,
@@ -171,11 +173,16 @@ class _DetailCardState extends ConsumerState<DetailCard> {
child: FormBuilder(
key: _formKey,
initialValue: {
"resolution": details.resolution,
"target_dir": details.targetDir,
"limiter": details.limiter != null
? RangeValues(details.limiter!.sizeMin.toDouble()/1000/1000,
details.limiter!.sizeMax.toDouble()/1000/1000)
"resolution": widget.details.resolution,
"target_dir": widget.details.targetDir,
"limiter": widget.details.limiter != null
? RangeValues(
widget.details.limiter!.sizeMin.toDouble() /
1000 /
1000,
widget.details.limiter!.sizeMax.toDouble() /
1000 /
1000)
: const RangeValues(0, 0)
},
child: Column(
@@ -204,23 +211,29 @@ class _DetailCardState extends ConsumerState<DetailCard> {
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text("取消")),
TextButton(
onPressed: () {
LoadingTextButton(
onPressed: () async {
if (_formKey.currentState!.saveAndValidate()) {
final values = _formKey.currentState!.value;
var f = ref
await ref
.read(mediaDetailsProvider(widget.details.id.toString())
.notifier)
.edit(values["resolution"], values["target_dir"],
values["limiter"])
.then((v) => Navigator.of(context).pop());
showLoadingWithFuture(f);
}
},
child: const Text("确认"))
label: const Text("确认"))
],
);
},
);
}
Widget downloadButton() {
return IconButton(
tooltip: widget.details.mediaType == "tv" ? "查找并下载所有监控剧集" : "查找并下载此电影",
onPressed: () {},
icon: const Icon(Icons.download_rounded));
}
}

View File

@@ -59,10 +59,10 @@ class ResourceList extends ConsumerWidget {
: "-")));
}
rows.add(DataCell(IconButton(
icon: const Icon(Icons.download),
rows.add(DataCell(LoadingIconButton(
icon: Icons.download,
onPressed: () async {
var f = ref
await ref
.read(mediaTorrentsDataProvider((
mediaId: mediaId,
seasonNumber: seasonNum,
@@ -70,7 +70,6 @@ class ResourceList extends ConsumerWidget {
)).notifier)
.download(torrent)
.then((v) => showSnakeBar("开始下载:${torrent.name}"));
showLoadingWithFuture(f);
},
)));
return DataRow(cells: rows);

View File

@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:ui/providers/APIs.dart';
import 'package:ui/widgets/utils.dart';
class Commons {
static InputDecoration requiredTextFieldStyle({
@@ -139,3 +140,93 @@ class _MySliderState extends State<MyRangeSlider> {
return "$v MB";
}
}
class LoadingIconButton extends StatefulWidget {
LoadingIconButton({required this.onPressed, required this.icon, this.tooltip});
final Future<void> Function() onPressed;
final IconData icon;
final String? tooltip;
@override
State<StatefulWidget> createState() {
return _LoadingIconButtonState();
}
}
class _LoadingIconButtonState extends State<LoadingIconButton> {
bool loading = false;
@override
Widget build(BuildContext context) {
return IconButton(
tooltip: widget.tooltip,
onPressed: loading
? null
: () async {
setState(() => loading = true);
try {
await widget.onPressed();
} catch (e) {
showSnakeBar("操作失败:$e");
} finally {
setState(() => loading = false);
}
},
icon: loading
? Container(
width: 24,
height: 24,
padding: const EdgeInsets.all(2.0),
child: const CircularProgressIndicator(
color: Colors.grey,
strokeWidth: 3,
),
)
: Icon(widget.icon));
}
}
class LoadingTextButton extends StatefulWidget {
LoadingTextButton({required this.onPressed, required this.label});
final Future<void> Function() onPressed;
final Widget label;
@override
State<StatefulWidget> createState() {
return _LoadingTextButtonState();
}
}
class _LoadingTextButtonState extends State<LoadingTextButton> {
bool loading = false;
@override
Widget build(BuildContext context) {
return TextButton.icon(
onPressed: loading
? null
: () async {
setState(() => loading = true);
try {
await widget.onPressed();
} catch (e) {
showSnakeBar("操作失败:$e");
} finally {
setState(() => loading = false);
}
},
icon: loading
? Container(
width: 24,
height: 24,
padding: const EdgeInsets.all(2.0),
child: const CircularProgressIndicator(
color: Colors.grey,
strokeWidth: 3,
),
)
: Text(""),
label: widget.label,
);
}
}