mirror of
https://github.com/simon-ding/polaris.git
synced 2026-03-17 00:40:55 +08:00
refactor code
This commit is contained in:
@@ -1,11 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
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/welcome_page.dart';
|
||||
import 'package:ui/widgets/detail_card.dart';
|
||||
import 'package:ui/widgets/utils.dart';
|
||||
import 'package:ui/widgets/progress_indicator.dart';
|
||||
import 'package:ui/widgets/widgets.dart';
|
||||
@@ -31,104 +28,12 @@ class _MovieDetailsPageState extends ConsumerState<MovieDetailsPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var seriesDetails = ref.watch(mediaDetailsProvider(widget.id));
|
||||
var storage = ref.watch(storageSettingProvider);
|
||||
|
||||
return seriesDetails.when(
|
||||
data: (details) {
|
||||
return ListView(
|
||||
children: [
|
||||
Card(
|
||||
margin: const EdgeInsets.all(4),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
opacity: 0.3,
|
||||
colorFilter: ColorFilter.mode(
|
||||
Colors.black.withOpacity(0.3),
|
||||
BlendMode.dstATop),
|
||||
image: NetworkImage(
|
||||
"${APIs.imagesUrl}/${details.id}/backdrop.jpg",
|
||||
))),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Flexible(
|
||||
flex: 1,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Image.network(
|
||||
"${APIs.imagesUrl}/${details.id}/poster.jpg",
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 6,
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text("${details.resolution}"),
|
||||
const SizedBox(
|
||||
width: 30,
|
||||
),
|
||||
storage.when(
|
||||
data: (value) {
|
||||
for (final s in value) {
|
||||
if (s.id == details.storageId) {
|
||||
return Text(
|
||||
"${s.name}(${s.implementation})");
|
||||
}
|
||||
}
|
||||
return const Text("未知存储");
|
||||
},
|
||||
error: (error, stackTrace) =>
|
||||
Text("$error"),
|
||||
loading: () =>
|
||||
const MyProgressIndicator()),
|
||||
],
|
||||
),
|
||||
const Divider(thickness: 1, height: 1),
|
||||
Text(
|
||||
"${details.name} (${details.airDate!.split("-")[0]})",
|
||||
style: const TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
const Text(""),
|
||||
Text(
|
||||
details.overview??"",
|
||||
),
|
||||
],
|
||||
)),
|
||||
Column(
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
var f = ref
|
||||
.read(mediaDetailsProvider(
|
||||
widget.id)
|
||||
.notifier)
|
||||
.delete().then((v) => context.go(WelcomePage.routeMoivie));
|
||||
showLoadingWithFuture(f);
|
||||
},
|
||||
icon: const Icon(Icons.delete))
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)),
|
||||
),
|
||||
DetailCard(details: details),
|
||||
NestedTabBar(
|
||||
id: widget.id,
|
||||
)
|
||||
@@ -157,7 +62,7 @@ class _NestedTabBarState extends ConsumerState<NestedTabBar>
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_nestedTabController = new TabController(length: 2, vsync: this);
|
||||
_nestedTabController = TabController(length: 2, vsync: this);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'dart:async';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:ui/providers/APIs.dart';
|
||||
import 'package:ui/providers/server_response.dart';
|
||||
import 'package:ui/providers/settings.dart';
|
||||
|
||||
var mediaDetailsProvider = AsyncNotifierProvider.autoDispose
|
||||
.family<SeriesDetailData, SeriesDetails, String>(SeriesDetailData.new);
|
||||
@@ -61,6 +62,8 @@ class SeriesDetails {
|
||||
String? resolution;
|
||||
int? storageId;
|
||||
String? airDate;
|
||||
String? mediaType;
|
||||
Storage? storage;
|
||||
|
||||
SeriesDetails(
|
||||
{this.id,
|
||||
@@ -73,7 +76,9 @@ class SeriesDetails {
|
||||
this.resolution,
|
||||
this.storageId,
|
||||
this.airDate,
|
||||
this.episodes});
|
||||
this.episodes,
|
||||
this.mediaType,
|
||||
this.storage});
|
||||
|
||||
SeriesDetails.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
@@ -86,6 +91,8 @@ class SeriesDetails {
|
||||
resolution = json["resolution"];
|
||||
storageId = json["storage_id"];
|
||||
airDate = json["air_date"];
|
||||
mediaType = json["media_type"];
|
||||
storage = Storage.fromJson(json["storage"]);
|
||||
if (json['episodes'] != null) {
|
||||
episodes = <Episodes>[];
|
||||
json['episodes'].forEach((v) {
|
||||
@@ -146,14 +153,12 @@ var mediaTorrentsDataProvider = AsyncNotifierProvider.autoDispose
|
||||
// }
|
||||
// }
|
||||
|
||||
typedef TorrentQuery =({String mediaId, int seasonNumber, int episodeNumber});
|
||||
typedef TorrentQuery = ({String mediaId, int seasonNumber, int episodeNumber});
|
||||
|
||||
class MediaTorrentResource extends AutoDisposeFamilyAsyncNotifier<
|
||||
List<TorrentResource>, TorrentQuery> {
|
||||
|
||||
@override
|
||||
FutureOr<List<TorrentResource>> build(TorrentQuery arg) async {
|
||||
|
||||
final dio = await APIs.getDio();
|
||||
var resp = await dio.post(APIs.availableTorrentsUrl, data: {
|
||||
"id": int.parse(arg.mediaId),
|
||||
|
||||
@@ -283,6 +283,8 @@ class Storage {
|
||||
this.id,
|
||||
this.name,
|
||||
this.implementation,
|
||||
this.tvPath,
|
||||
this.moviePath,
|
||||
this.settings,
|
||||
this.isDefault,
|
||||
});
|
||||
@@ -290,6 +292,8 @@ class Storage {
|
||||
final int? id;
|
||||
final String? name;
|
||||
final String? implementation;
|
||||
final String? tvPath;
|
||||
final String? moviePath;
|
||||
final Map<String, dynamic>? settings;
|
||||
final bool? isDefault;
|
||||
|
||||
@@ -298,6 +302,8 @@ class Storage {
|
||||
id: json1["id"],
|
||||
name: json1["name"],
|
||||
implementation: json1["implementation"],
|
||||
tvPath: json1["tv_path"],
|
||||
moviePath: json1["movie_path"],
|
||||
settings: json.decode(json1["settings"]),
|
||||
isDefault: json1["default"]);
|
||||
}
|
||||
@@ -306,6 +312,8 @@ class Storage {
|
||||
"id": id,
|
||||
"name": name,
|
||||
"implementation": implementation,
|
||||
"tv_path": tvPath,
|
||||
"movie_path": moviePath,
|
||||
"settings": settings,
|
||||
"default": isDefault,
|
||||
};
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
@@ -59,7 +59,7 @@ class _GeneralState extends ConsumerState<GeneralSettings> {
|
||||
name: "proxy",
|
||||
decoration: const InputDecoration(
|
||||
labelText: "代理地址",
|
||||
icon: Icon(Icons.folder),
|
||||
icon: Icon(Icons.web),
|
||||
helperText: "后台联网代理地址,留空表示不启用代理"),
|
||||
),
|
||||
SizedBox(
|
||||
|
||||
@@ -39,7 +39,7 @@ class _StorageState extends ConsumerState<StorageSettings> {
|
||||
loading: () => const MyProgressIndicator());
|
||||
}
|
||||
|
||||
Future<void> showStorageDetails(Storage s) {
|
||||
Future<void> showStorageDetails(Storage s) {
|
||||
final _formKey = GlobalKey<FormBuilderState>();
|
||||
|
||||
String selectImpl = s.implementation == null ? "local" : s.implementation!;
|
||||
@@ -53,10 +53,9 @@ class _StorageState extends ConsumerState<StorageSettings> {
|
||||
"impl": s.implementation == null ? "local" : s.implementation!,
|
||||
"user": s.settings != null ? s.settings!["user"] ?? "" : "",
|
||||
"password": s.settings != null ? s.settings!["password"] ?? "" : "",
|
||||
"tv_path": s.settings != null ? s.settings!["tv_path"] ?? "" : "",
|
||||
"tv_path": s.tvPath,
|
||||
"url": s.settings != null ? s.settings!["url"] ?? "" : "",
|
||||
"movie_path":
|
||||
s.settings != null ? s.settings!["movie_path"] ?? "" : "",
|
||||
"movie_path": s.moviePath,
|
||||
"change_file_hash": s.settings != null
|
||||
? s.settings!["change_file_hash"] == "true"
|
||||
? true
|
||||
@@ -147,9 +146,9 @@ class _StorageState extends ConsumerState<StorageSettings> {
|
||||
return ref.read(storageSettingProvider.notifier).addStorage(Storage(
|
||||
name: values["name"],
|
||||
implementation: selectImpl,
|
||||
tvPath: values["tv_path"],
|
||||
moviePath: values["movie_path"],
|
||||
settings: {
|
||||
"tv_path": values["tv_path"],
|
||||
"movie_path": values["movie_path"],
|
||||
"url": values["url"],
|
||||
"user": values["user"],
|
||||
"password": values["password"],
|
||||
@@ -168,7 +167,7 @@ class _StorageState extends ConsumerState<StorageSettings> {
|
||||
return ref.read(storageSettingProvider.notifier).deleteStorage(s.id!);
|
||||
}
|
||||
|
||||
return showSettingDialog(context,'存储', s.id != null, widgets, onSubmit, onDelete);
|
||||
return showSettingDialog(
|
||||
context, '存储', s.id != null, widgets, onSubmit, onDelete);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
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/welcome_page.dart';
|
||||
import 'package:ui/widgets/detail_card.dart';
|
||||
import 'package:ui/widgets/utils.dart';
|
||||
import 'package:ui/widgets/progress_indicator.dart';
|
||||
import 'package:ui/widgets/widgets.dart';
|
||||
@@ -35,7 +32,6 @@ class _TvDetailsPageState extends ConsumerState<TvDetailsPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var seriesDetails = ref.watch(mediaDetailsProvider(widget.seriesId));
|
||||
var storage = ref.watch(storageSettingProvider);
|
||||
return seriesDetails.when(
|
||||
data: (details) {
|
||||
Map<int, List<DataRow>> m = {};
|
||||
@@ -143,95 +139,7 @@ class _TvDetailsPageState extends ConsumerState<TvDetailsPage> {
|
||||
}
|
||||
return ListView(
|
||||
children: [
|
||||
Card(
|
||||
margin: const EdgeInsets.all(4),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
opacity: 0.3,
|
||||
colorFilter: ColorFilter.mode(
|
||||
Colors.black.withOpacity(0.3), BlendMode.dstATop),
|
||||
image: NetworkImage(
|
||||
"${APIs.imagesUrl}/${details.id}/backdrop.jpg"))),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Flexible(
|
||||
flex: 1,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Image.network(
|
||||
"${APIs.imagesUrl}/${details.id}/poster.jpg",
|
||||
fit: BoxFit.contain),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
flex: 6,
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text("${details.resolution}"),
|
||||
const SizedBox(
|
||||
width: 30,
|
||||
),
|
||||
storage.when(
|
||||
data: (value) {
|
||||
for (final s in value) {
|
||||
if (s.id == details.storageId) {
|
||||
return Text(
|
||||
"${s.name}(${s.implementation})");
|
||||
}
|
||||
}
|
||||
return const Text("未知存储");
|
||||
},
|
||||
error: (error, stackTrace) =>
|
||||
Text("$error"),
|
||||
loading: () => const Text("")),
|
||||
],
|
||||
),
|
||||
const Divider(thickness: 1, height: 1),
|
||||
Text(
|
||||
"${details.name} ${details.name != details.originalName ? details.originalName : ''} (${details.airDate!.split("-")[0]})",
|
||||
style: const TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
const Text(""),
|
||||
Text(
|
||||
details.overview ?? "",
|
||||
),
|
||||
],
|
||||
)),
|
||||
Column(
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
var f = ref
|
||||
.read(mediaDetailsProvider(
|
||||
widget.seriesId)
|
||||
.notifier)
|
||||
.delete().then((v) => context.go(WelcomePage.routeTv));
|
||||
showLoadingWithFuture(f);
|
||||
},
|
||||
icon: const Icon(Icons.delete))
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
DetailCard(details: details),
|
||||
Column(
|
||||
children: list,
|
||||
),
|
||||
|
||||
111
ui/lib/widgets/detail_card.dart
Normal file
111
ui/lib/widgets/detail_card.dart
Normal file
@@ -0,0 +1,111 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:ui/providers/APIs.dart';
|
||||
import 'package:ui/providers/series_details.dart';
|
||||
import 'package:ui/welcome_page.dart';
|
||||
|
||||
import 'widgets.dart';
|
||||
|
||||
class DetailCard extends ConsumerStatefulWidget {
|
||||
final SeriesDetails details;
|
||||
|
||||
const DetailCard({super.key, required this.details});
|
||||
|
||||
@override
|
||||
ConsumerState<ConsumerStatefulWidget> createState() {
|
||||
return _DetailCardState();
|
||||
}
|
||||
}
|
||||
|
||||
class _DetailCardState extends ConsumerState<DetailCard> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Card(
|
||||
margin: const EdgeInsets.all(4),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: Container(
|
||||
constraints: BoxConstraints(maxHeight: MediaQuery.of(context).size.height*0.4),
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
opacity: 0.3,
|
||||
colorFilter: ColorFilter.mode(
|
||||
Colors.black.withOpacity(0.3), BlendMode.dstATop),
|
||||
image: NetworkImage(
|
||||
"${APIs.imagesUrl}/${widget.details.id}/backdrop.jpg"))),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Flexible(
|
||||
flex: 2,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Image.network(
|
||||
"${APIs.imagesUrl}/${widget.details.id}/poster.jpg",
|
||||
fit: BoxFit.contain),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
flex: 4,
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text(""),
|
||||
Row(
|
||||
children: [
|
||||
Text("${widget.details.resolution}"),
|
||||
const SizedBox(
|
||||
width: 30,
|
||||
),
|
||||
Text(
|
||||
"${widget.details.storage!.name} (${widget.details.storage!.implementation})")
|
||||
],
|
||||
),
|
||||
const Divider(thickness: 1, height: 1),
|
||||
Text(
|
||||
"${widget.details.name} ${widget.details.name != widget.details.originalName ? widget.details.originalName : ''} (${widget.details.airDate!.split("-")[0]})",
|
||||
style: const TextStyle(
|
||||
fontSize: 20, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const Text(""),
|
||||
Expanded(
|
||||
child: Text(
|
||||
widget.details.overview ?? "",
|
||||
)),
|
||||
Row(
|
||||
children: [
|
||||
deleteIcon(),
|
||||
],
|
||||
)
|
||||
],
|
||||
)),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget deleteIcon() {
|
||||
return IconButton(
|
||||
onPressed: () {
|
||||
var f = ref
|
||||
.read(mediaDetailsProvider(widget.details.id.toString()).notifier)
|
||||
.delete()
|
||||
.then((v) => context.go(widget.details.mediaType == "tv"
|
||||
? WelcomePage.routeTv
|
||||
: WelcomePage.routeMoivie));
|
||||
showLoadingWithFuture(f);
|
||||
},
|
||||
icon: const Icon(Icons.delete));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user