mirror of
https://github.com/simon-ding/polaris.git
synced 2026-03-15 22:20:52 +08:00
feat: display loading animation
This commit is contained in:
@@ -69,7 +69,7 @@ func (s *Server) SuggestedSeriesFolderName(c *gin.Context) (interface{}, error)
|
||||
year := strings.Split(d.FirstAirDate, "-")[0]
|
||||
|
||||
|
||||
if utils.ContainsChineseChar(originalName) {
|
||||
if utils.ContainsChineseChar(originalName) || name == originalName {
|
||||
name = originalName
|
||||
} else {
|
||||
name = fmt.Sprintf("%s %s", name, originalName)
|
||||
@@ -95,9 +95,7 @@ func (s *Server) SuggestedMovieFolderName(c *gin.Context) (interface{}, error) {
|
||||
originalName := d1.OriginalTitle
|
||||
year := strings.Split(d1.ReleaseDate, "-")[0]
|
||||
|
||||
name = fmt.Sprintf("%s %s", name, originalName)
|
||||
|
||||
if utils.ContainsChineseChar(originalName) {
|
||||
if utils.ContainsChineseChar(originalName) || name == originalName {
|
||||
name = originalName
|
||||
} else {
|
||||
name = fmt.Sprintf("%s %s", name, originalName)
|
||||
|
||||
@@ -2,8 +2,8 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:percent_indicator/circular_percent_indicator.dart';
|
||||
import 'package:ui/providers/activity.dart';
|
||||
import 'package:ui/widgets/utils.dart';
|
||||
import 'package:ui/widgets/progress_indicator.dart';
|
||||
import 'package:ui/widgets/widgets.dart';
|
||||
|
||||
class ActivityPage extends ConsumerStatefulWidget {
|
||||
const ActivityPage({super.key});
|
||||
@@ -68,7 +68,7 @@ class _ActivityPageState extends ConsumerState<ActivityPage>
|
||||
DataColumn(label: Text("名称")),
|
||||
DataColumn(label: Text("开始时间")),
|
||||
DataColumn(label: Text("状态")),
|
||||
DataColumn(label: Text("操作"))
|
||||
DataColumn(label: Text("操作"))
|
||||
],
|
||||
source: ActivityDataSource(
|
||||
activities: activities,
|
||||
@@ -85,11 +85,10 @@ class _ActivityPageState extends ConsumerState<ActivityPage>
|
||||
|
||||
Function(int) onDelete() {
|
||||
return (id) {
|
||||
ref
|
||||
final f = ref
|
||||
.read(activitiesDataProvider("active").notifier)
|
||||
.deleteActivity(id)
|
||||
.then((v) => Utils.showSnakeBar("删除成功"))
|
||||
.onError((error, trace) => Utils.showSnakeBar("删除失败:$error"));
|
||||
.deleteActivity(id);
|
||||
showLoadingWithFuture(f);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,10 @@ import 'package:ui/providers/APIs.dart';
|
||||
import 'package:ui/providers/activity.dart';
|
||||
import 'package:ui/providers/series_details.dart';
|
||||
import 'package:ui/providers/settings.dart';
|
||||
import 'package:ui/widgets/utils.dart';
|
||||
import 'package:ui/welcome_page.dart';
|
||||
import 'package:ui/widgets/utils.dart';
|
||||
import 'package:ui/widgets/progress_indicator.dart';
|
||||
import 'package:ui/widgets/widgets.dart';
|
||||
|
||||
class MovieDetailsPage extends ConsumerStatefulWidget {
|
||||
static const route = "/movie/:id";
|
||||
@@ -44,7 +45,9 @@ class _MovieDetailsPageState extends ConsumerState<MovieDetailsPage> {
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
opacity: 0.3,
|
||||
colorFilter: ColorFilter.mode(Colors.black.withOpacity(0.3), BlendMode.dstATop),
|
||||
colorFilter: ColorFilter.mode(
|
||||
Colors.black.withOpacity(0.3),
|
||||
BlendMode.dstATop),
|
||||
image: NetworkImage(
|
||||
"${APIs.imagesUrl}/${details.id}/backdrop.jpg",
|
||||
))),
|
||||
@@ -101,7 +104,7 @@ class _MovieDetailsPageState extends ConsumerState<MovieDetailsPage> {
|
||||
),
|
||||
const Text(""),
|
||||
Text(
|
||||
details.overview!,
|
||||
details.overview??"",
|
||||
),
|
||||
],
|
||||
)),
|
||||
@@ -109,16 +112,12 @@ class _MovieDetailsPageState extends ConsumerState<MovieDetailsPage> {
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
ref
|
||||
var f = ref
|
||||
.read(mediaDetailsProvider(
|
||||
widget.id)
|
||||
.notifier)
|
||||
.delete()
|
||||
.then((v) => context
|
||||
.go(WelcomePage.routeMoivie))
|
||||
.onError((error, trace) =>
|
||||
Utils.showSnakeBar(
|
||||
"删除失败:$error"));
|
||||
.delete().then((v) => context.go(WelcomePage.routeMoivie));
|
||||
showLoadingWithFuture(f);
|
||||
},
|
||||
icon: const Icon(Icons.delete))
|
||||
],
|
||||
@@ -252,17 +251,18 @@ class _NestedTabBarState extends ConsumerState<NestedTabBar>
|
||||
DataCell(IconButton(
|
||||
icon: const Icon(Icons.download),
|
||||
onPressed: () {
|
||||
ref
|
||||
final f = ref
|
||||
.read(mediaTorrentsDataProvider((
|
||||
mediaId: widget.id,
|
||||
seasonNumber: 0,
|
||||
episodeNumber: 0
|
||||
)).notifier)
|
||||
.download(torrent)
|
||||
.then((v) => Utils.showSnakeBar(
|
||||
"开始下载:${torrent.name}"))
|
||||
.onError((error, trace) =>
|
||||
Utils.showSnakeBar("操作失败: $error"));
|
||||
.then((v) => showSnakeBar(
|
||||
"开始下载:${torrent.name}"));
|
||||
// .onError((error, trace) =>
|
||||
// Utils.showSnakeBar("操作失败: $error"));
|
||||
showLoadingWithFuture(f);
|
||||
},
|
||||
))
|
||||
]);
|
||||
|
||||
@@ -4,8 +4,9 @@ import 'package:go_router/go_router.dart';
|
||||
import 'package:ui/providers/APIs.dart';
|
||||
import 'package:ui/providers/settings.dart';
|
||||
import 'package:ui/providers/welcome_data.dart';
|
||||
import 'package:ui/widgets/utils.dart';
|
||||
import 'package:ui/widgets/progress_indicator.dart';
|
||||
import 'package:ui/widgets/utils.dart';
|
||||
import 'package:ui/widgets/widgets.dart';
|
||||
|
||||
class SearchPage extends ConsumerStatefulWidget {
|
||||
const SearchPage({super.key, this.query});
|
||||
@@ -155,9 +156,9 @@ class _SearchPageState extends ConsumerState<SearchPage> {
|
||||
String resSelected = "1080p";
|
||||
int storageSelected = 0;
|
||||
var storage = ref.watch(storageSettingProvider);
|
||||
var name = ref.watch(suggestNameDataProvider((id: item.id!, mediaType: item.mediaType!)));
|
||||
var name = ref.watch(suggestNameDataProvider(
|
||||
(id: item.id!, mediaType: item.mediaType!)));
|
||||
bool downloadHistoryEpisodes = false;
|
||||
bool buttonTapped = false;
|
||||
|
||||
var pathController = TextEditingController();
|
||||
return AlertDialog(
|
||||
@@ -275,14 +276,7 @@ class _SearchPageState extends ConsumerState<SearchPage> {
|
||||
),
|
||||
child: const Text('确定'),
|
||||
onPressed: () async {
|
||||
if (buttonTapped) {
|
||||
return;
|
||||
}
|
||||
setState(() {
|
||||
buttonTapped = true;
|
||||
});
|
||||
|
||||
await ref
|
||||
var f = ref
|
||||
.read(searchPageDataProvider(widget.query ?? "")
|
||||
.notifier)
|
||||
.submit2Watchlist(
|
||||
@@ -293,14 +287,10 @@ class _SearchPageState extends ConsumerState<SearchPage> {
|
||||
pathController.text,
|
||||
downloadHistoryEpisodes)
|
||||
.then((v) {
|
||||
Utils.showSnakeBar("添加成功");
|
||||
Navigator.of(context).pop();
|
||||
}).onError((error, trace) {
|
||||
Utils.showSnakeBar("添加失败:$error");
|
||||
});
|
||||
setState(() {
|
||||
buttonTapped = false;
|
||||
showSnakeBar("添加成功:${item.name}");
|
||||
});
|
||||
showLoadingWithFuture(f);
|
||||
},
|
||||
),
|
||||
],
|
||||
|
||||
@@ -18,7 +18,7 @@ class AuthSettings extends ConsumerStatefulWidget {
|
||||
}
|
||||
|
||||
class _AuthState extends ConsumerState<AuthSettings> {
|
||||
final _formKey2 = GlobalKey<FormBuilderState>();
|
||||
final _formKey2 = GlobalKey<FormBuilderState>();
|
||||
bool? _enableAuth;
|
||||
|
||||
@override
|
||||
@@ -84,12 +84,11 @@ class _AuthState extends ConsumerState<AuthSettings> {
|
||||
var f = ref
|
||||
.read(authSettingProvider.notifier)
|
||||
.updateAuthSetting(_enableAuth!,
|
||||
values["user"], values["password"]);
|
||||
f.then((v) {
|
||||
Utils.showSnakeBar("更新成功");
|
||||
}).onError((e, s) {
|
||||
Utils.showSnakeBar("更新失败:$e");
|
||||
values["user"], values["password"])
|
||||
.then((v) {
|
||||
showSnakeBar("更新成功");
|
||||
});
|
||||
showLoadingWithFuture(f);
|
||||
}
|
||||
}))
|
||||
],
|
||||
@@ -98,5 +97,4 @@ class _AuthState extends ConsumerState<AuthSettings> {
|
||||
error: (err, trace) => Text("$err"),
|
||||
loading: () => const MyProgressIndicator());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:ui/widgets/utils.dart';
|
||||
import 'package:ui/widgets/widgets.dart';
|
||||
|
||||
Future<void> showSettingDialog(BuildContext context,String title, bool showDelete, Widget body,
|
||||
Future Function() onSubmit, Future Function() onDelete) {
|
||||
Future<void> showSettingDialog(
|
||||
BuildContext context,
|
||||
String title,
|
||||
bool showDelete,
|
||||
Widget body,
|
||||
Future Function() onSubmit,
|
||||
Future Function() onDelete) {
|
||||
return showDialog<void>(
|
||||
context: context,
|
||||
barrierDismissible: true,
|
||||
@@ -19,13 +24,8 @@ Future<void> showSettingDialog(BuildContext context,String title, bool showDelet
|
||||
showDelete
|
||||
? TextButton(
|
||||
onPressed: () {
|
||||
final f = onDelete();
|
||||
f.then((v) {
|
||||
Utils.showSnakeBar("删除成功");
|
||||
Navigator.of(context).pop();
|
||||
}).onError((e, s) {
|
||||
Utils.showSnakeBar("删除失败:$e");
|
||||
});
|
||||
final f = onDelete().then((v) => Navigator.of(context).pop());
|
||||
showLoadingWithFuture(f);
|
||||
},
|
||||
child: const Text(
|
||||
'删除',
|
||||
@@ -38,15 +38,8 @@ Future<void> showSettingDialog(BuildContext context,String title, bool showDelet
|
||||
TextButton(
|
||||
child: const Text('确定'),
|
||||
onPressed: () {
|
||||
final f = onSubmit();
|
||||
f.then((v) {
|
||||
Utils.showSnakeBar("操作成功");
|
||||
Navigator.of(context).pop();
|
||||
}).onError((e, s) {
|
||||
if (e.toString() != "validation_error") {
|
||||
Utils.showSnakeBar("操作失败:$e");
|
||||
}
|
||||
});
|
||||
final f = onSubmit().then((v) => Navigator.of(context).pop());
|
||||
showLoadingWithFuture(f);
|
||||
},
|
||||
),
|
||||
],
|
||||
|
||||
@@ -3,8 +3,8 @@ import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:form_builder_validators/form_builder_validators.dart';
|
||||
import 'package:ui/providers/settings.dart';
|
||||
import 'package:ui/widgets/utils.dart';
|
||||
import 'package:ui/widgets/progress_indicator.dart';
|
||||
import 'package:ui/widgets/utils.dart';
|
||||
import 'package:ui/widgets/widgets.dart';
|
||||
|
||||
class GeneralSettings extends ConsumerStatefulWidget {
|
||||
@@ -17,9 +17,8 @@ class GeneralSettings extends ConsumerStatefulWidget {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class _GeneralState extends ConsumerState<GeneralSettings> {
|
||||
final _formKey = GlobalKey<FormBuilderState>();
|
||||
final _formKey = GlobalKey<FormBuilderState>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -96,12 +95,8 @@ class _GeneralState extends ConsumerState<GeneralSettings> {
|
||||
tmdbApiKey: values["tmdb_api"],
|
||||
downloadDIr: values["download_dir"],
|
||||
logLevel: values["log_level"],
|
||||
proxy: values["proxy"]));
|
||||
f.then((v) {
|
||||
Utils.showSnakeBar("更新成功");
|
||||
}).onError((e, s) {
|
||||
Utils.showSnakeBar("更新失败:$e");
|
||||
});
|
||||
proxy: values["proxy"])).then((v) => showSnakeBar("更新成功"));
|
||||
showLoadingWithFuture(f);
|
||||
}
|
||||
}),
|
||||
),
|
||||
@@ -113,5 +108,4 @@ class _GeneralState extends ConsumerState<GeneralSettings> {
|
||||
error: (err, trace) => Text("$err"),
|
||||
loading: () => const MyProgressIndicator());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,10 @@ import 'package:go_router/go_router.dart';
|
||||
import 'package:ui/providers/APIs.dart';
|
||||
import 'package:ui/providers/series_details.dart';
|
||||
import 'package:ui/providers/settings.dart';
|
||||
import 'package:ui/widgets/utils.dart';
|
||||
import 'package:ui/welcome_page.dart';
|
||||
import 'package:ui/widgets/utils.dart';
|
||||
import 'package:ui/widgets/progress_indicator.dart';
|
||||
import 'package:ui/widgets/widgets.dart';
|
||||
|
||||
class TvDetailsPage extends ConsumerStatefulWidget {
|
||||
static const route = "/series/:id";
|
||||
@@ -70,14 +71,12 @@ class _TvDetailsPageState extends ConsumerState<TvDetailsPage> {
|
||||
message: "搜索下载对应剧集",
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
ref
|
||||
var f = ref
|
||||
.read(mediaDetailsProvider(widget.seriesId)
|
||||
.notifier)
|
||||
.searchAndDownload(widget.seriesId,
|
||||
ep.seasonNumber!, ep.episodeNumber!)
|
||||
.then((v) => Utils.showSnakeBar("开始下载: $v"))
|
||||
.onError((error, trace) =>
|
||||
Utils.showSnakeBar("操作失败: $error"));
|
||||
ep.seasonNumber!, ep.episodeNumber!);
|
||||
showLoadingWithFuture(f);
|
||||
},
|
||||
icon: const Icon(Icons.download)),
|
||||
),
|
||||
@@ -120,13 +119,11 @@ class _TvDetailsPageState extends ConsumerState<TvDetailsPage> {
|
||||
message: "搜索下载全部剧集",
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
ref
|
||||
final f = ref
|
||||
.read(mediaDetailsProvider(widget.seriesId)
|
||||
.notifier)
|
||||
.searchAndDownload(widget.seriesId, k, 0)
|
||||
.then((v) => Utils.showSnakeBar("开始下载: $v"))
|
||||
.onError((error, trace) =>
|
||||
Utils.showSnakeBar("操作失败: $error"));
|
||||
.searchAndDownload(widget.seriesId, k, 0).then((v) => showSnakeBar("开始下载: $v"));
|
||||
showLoadingWithFuture(f);
|
||||
},
|
||||
icon: const Icon(Icons.download)),
|
||||
),
|
||||
@@ -154,7 +151,8 @@ class _TvDetailsPageState extends ConsumerState<TvDetailsPage> {
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
opacity: 0.3,
|
||||
colorFilter: ColorFilter.mode(Colors.black.withOpacity(0.3), BlendMode.dstATop),
|
||||
colorFilter: ColorFilter.mode(
|
||||
Colors.black.withOpacity(0.3), BlendMode.dstATop),
|
||||
image: NetworkImage(
|
||||
"${APIs.imagesUrl}/${details.id}/backdrop.jpg"))),
|
||||
child: Padding(
|
||||
@@ -166,9 +164,8 @@ class _TvDetailsPageState extends ConsumerState<TvDetailsPage> {
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Image.network(
|
||||
"${APIs.imagesUrl}/${details.id}/poster.jpg",
|
||||
fit: BoxFit.contain
|
||||
),
|
||||
"${APIs.imagesUrl}/${details.id}/poster.jpg",
|
||||
fit: BoxFit.contain),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
@@ -217,16 +214,12 @@ class _TvDetailsPageState extends ConsumerState<TvDetailsPage> {
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
ref
|
||||
var f = ref
|
||||
.read(mediaDetailsProvider(
|
||||
widget.seriesId)
|
||||
.notifier)
|
||||
.delete()
|
||||
.then((v) =>
|
||||
context.go(WelcomePage.routeTv))
|
||||
.onError((error, trace) =>
|
||||
Utils.showSnakeBar(
|
||||
"删除失败: $error"));
|
||||
.delete().then((v) => context.go(WelcomePage.routeTv));
|
||||
showLoadingWithFuture(f);
|
||||
},
|
||||
icon: const Icon(Icons.delete))
|
||||
],
|
||||
@@ -270,7 +263,8 @@ class _TvDetailsPageState extends ConsumerState<TvDetailsPage> {
|
||||
data: (v) {
|
||||
return SingleChildScrollView(
|
||||
child: DataTable(
|
||||
dataTextStyle: const TextStyle(fontSize: 12, height: 0),
|
||||
dataTextStyle:
|
||||
const TextStyle(fontSize: 12, height: 0),
|
||||
columns: const [
|
||||
DataColumn(label: Text("名称")),
|
||||
DataColumn(label: Text("大小")),
|
||||
@@ -289,19 +283,14 @@ class _TvDetailsPageState extends ConsumerState<TvDetailsPage> {
|
||||
DataCell(IconButton(
|
||||
icon: const Icon(Icons.download),
|
||||
onPressed: () async {
|
||||
await ref
|
||||
var f = ref
|
||||
.read(mediaTorrentsDataProvider((
|
||||
mediaId: id,
|
||||
seasonNumber: season,
|
||||
episodeNumber: episode
|
||||
)).notifier)
|
||||
.download(torrent)
|
||||
.then((v) {
|
||||
Navigator.of(context).pop();
|
||||
Utils.showSnakeBar(
|
||||
"开始下载:${torrent.name}");
|
||||
}).onError((error, trace) =>
|
||||
Utils.showSnakeBar("下载失败:$error"));
|
||||
.download(torrent).then((v) => showSnakeBar("开始下载:${torrent.name}"));
|
||||
showLoadingWithFuture(f);
|
||||
},
|
||||
))
|
||||
]);
|
||||
|
||||
@@ -74,7 +74,7 @@ class WelcomePage extends ConsumerWidget {
|
||||
),
|
||||
Text(
|
||||
item.name!,
|
||||
style: const TextStyle(
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
height: 2.5),
|
||||
|
||||
@@ -32,7 +32,9 @@ class Utils {
|
||||
);
|
||||
}
|
||||
|
||||
static showSnakeBar(String msg) {
|
||||
}
|
||||
|
||||
showSnakeBar(String msg) {
|
||||
final context = APIs.navigatorKey.currentContext;
|
||||
if (context != null) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||
@@ -42,17 +44,6 @@ class Utils {
|
||||
}
|
||||
}
|
||||
|
||||
static bool showError(BuildContext context, AsyncSnapshot snapshot) {
|
||||
final isErrored = snapshot.hasError &&
|
||||
snapshot.connectionState != ConnectionState.waiting;
|
||||
if (isErrored) {
|
||||
Utils.showSnakeBar("当前操作出错: ${snapshot.error}");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
extension FileFormatter on num {
|
||||
String readableFileSize({bool base1024 = true}) {
|
||||
final base = base1024 ? 1024 : 1000;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:ui/providers/APIs.dart';
|
||||
|
||||
class Commons {
|
||||
static InputDecoration requiredTextFieldStyle({
|
||||
@@ -41,3 +42,47 @@ class SettingsCard extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
showLoadingWithFuture(Future f) {
|
||||
final context = APIs.navigatorKey.currentContext;
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false, //点击遮罩不关闭对话框
|
||||
builder: (context) {
|
||||
return FutureBuilder(
|
||||
future: f,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.done) {
|
||||
if (snapshot.hasError) {
|
||||
return AlertDialog(
|
||||
content: Text("处理失败:${snapshot.error}"),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text("好"))
|
||||
],
|
||||
);
|
||||
}
|
||||
Navigator.of(context).pop();
|
||||
return Container();
|
||||
} else {
|
||||
return const AlertDialog(
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
CircularProgressIndicator(),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 26.0),
|
||||
child: Text("正在处理,请稍后..."),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user