mirror of
https://github.com/simon-ding/polaris.git
synced 2026-02-06 15:10:49 +08:00
use riverpod
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:ui/navdrawer.dart';
|
import 'package:ui/navdrawer.dart';
|
||||||
import 'package:ui/search.dart';
|
import 'package:ui/search.dart';
|
||||||
@@ -46,7 +47,7 @@ class MyApp extends StatelessWidget {
|
|||||||
// Center is a layout widget. It takes a single child and positions it
|
// Center is a layout widget. It takes a single child and positions it
|
||||||
// in the middle of the parent.
|
// in the middle of the parent.
|
||||||
child: Row(children: <Widget>[
|
child: Row(children: <Widget>[
|
||||||
NavDrawer(),
|
const NavDrawer(),
|
||||||
const VerticalDivider(thickness: 1, width: 1),
|
const VerticalDivider(thickness: 1, width: 1),
|
||||||
Expanded(child: child)
|
Expanded(child: child)
|
||||||
]))),
|
]))),
|
||||||
@@ -81,7 +82,8 @@ class MyApp extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
return MaterialApp.router(
|
return ProviderScope(
|
||||||
|
child: MaterialApp.router(
|
||||||
title: 'Flutter Demo',
|
title: 'Flutter Demo',
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
// This is the theme of your application.
|
// This is the theme of your application.
|
||||||
@@ -104,6 +106,7 @@ class MyApp extends StatelessWidget {
|
|||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
),
|
),
|
||||||
routerConfig: _router,
|
routerConfig: _router,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
82
ui/lib/providers/series_details.dart
Normal file
82
ui/lib/providers/series_details.dart
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:ui/APIs.dart';
|
||||||
|
import 'package:ui/server_response.dart';
|
||||||
|
|
||||||
|
var seriesDetailsProvider = FutureProvider.family((ref, seriesId) async {
|
||||||
|
var resp = await Dio().get("${APIs.seriesDetailUrl}$seriesId");
|
||||||
|
var rsp = ServerResponse.fromJson(resp.data);
|
||||||
|
if (rsp.code != 0) {
|
||||||
|
throw rsp.message;
|
||||||
|
}
|
||||||
|
return SeriesDetails.fromJson(rsp.data);
|
||||||
|
});
|
||||||
|
|
||||||
|
class SeriesDetails {
|
||||||
|
int? id;
|
||||||
|
int? tmdbId;
|
||||||
|
String? name;
|
||||||
|
String? originalName;
|
||||||
|
String? overview;
|
||||||
|
String? path;
|
||||||
|
String? posterPath;
|
||||||
|
String? createdAt;
|
||||||
|
List<Episodes>? episodes;
|
||||||
|
|
||||||
|
SeriesDetails(
|
||||||
|
{this.id,
|
||||||
|
this.tmdbId,
|
||||||
|
this.name,
|
||||||
|
this.originalName,
|
||||||
|
this.overview,
|
||||||
|
this.path,
|
||||||
|
this.posterPath,
|
||||||
|
this.createdAt,
|
||||||
|
this.episodes});
|
||||||
|
|
||||||
|
SeriesDetails.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = json['id'];
|
||||||
|
tmdbId = json['tmdb_id'];
|
||||||
|
name = json['name'];
|
||||||
|
originalName = json['original_name'];
|
||||||
|
overview = json['overview'];
|
||||||
|
path = json['path'];
|
||||||
|
posterPath = json['poster_path'];
|
||||||
|
createdAt = json['created_at'];
|
||||||
|
if (json['episodes'] != null) {
|
||||||
|
episodes = <Episodes>[];
|
||||||
|
json['episodes'].forEach((v) {
|
||||||
|
episodes!.add(Episodes.fromJson(v));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Episodes {
|
||||||
|
int? id;
|
||||||
|
int? seriesId;
|
||||||
|
int? episodeNumber;
|
||||||
|
String? title;
|
||||||
|
String? airDate;
|
||||||
|
int? seasonNumber;
|
||||||
|
String? overview;
|
||||||
|
|
||||||
|
Episodes(
|
||||||
|
{this.id,
|
||||||
|
this.seriesId,
|
||||||
|
this.episodeNumber,
|
||||||
|
this.title,
|
||||||
|
this.airDate,
|
||||||
|
this.seasonNumber,
|
||||||
|
this.overview});
|
||||||
|
|
||||||
|
Episodes.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = json['id'];
|
||||||
|
seriesId = json['series_id'];
|
||||||
|
episodeNumber = json['episode_number'];
|
||||||
|
title = json['title'];
|
||||||
|
airDate = json['air_date'];
|
||||||
|
seasonNumber = json['season_number'];
|
||||||
|
overview = json['overview'];
|
||||||
|
}
|
||||||
|
}
|
||||||
58
ui/lib/providers/welcome_data.dart
Normal file
58
ui/lib/providers/welcome_data.dart
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:ui/APIs.dart';
|
||||||
|
import 'package:ui/server_response.dart';
|
||||||
|
|
||||||
|
final welcomePageDataProvider = FutureProvider((ref) async {
|
||||||
|
var resp = await Dio().get(APIs.watchlistUrl);
|
||||||
|
var sp = ServerResponse.fromJson(resp.data);
|
||||||
|
List<TvSeries> favList = List.empty(growable: true);
|
||||||
|
for (var item in sp.data as List) {
|
||||||
|
var tv = TvSeries.fromJson(item);
|
||||||
|
favList.add(tv);
|
||||||
|
}
|
||||||
|
return favList;
|
||||||
|
});
|
||||||
|
|
||||||
|
class TvSeries {
|
||||||
|
int? id;
|
||||||
|
int? tmdbId;
|
||||||
|
String? name;
|
||||||
|
String? originalName;
|
||||||
|
String? overview;
|
||||||
|
String? path;
|
||||||
|
String? posterPath;
|
||||||
|
|
||||||
|
TvSeries(
|
||||||
|
{this.id,
|
||||||
|
this.tmdbId,
|
||||||
|
this.name,
|
||||||
|
this.originalName,
|
||||||
|
this.overview,
|
||||||
|
this.path,
|
||||||
|
this.posterPath});
|
||||||
|
|
||||||
|
TvSeries.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = json['id'];
|
||||||
|
tmdbId = json['tmdb_id'];
|
||||||
|
name = json['name'];
|
||||||
|
originalName = json['original_name'];
|
||||||
|
overview = json['overview'];
|
||||||
|
path = json['path'];
|
||||||
|
posterPath = json["poster_path"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var tmdbApiSettingProvider = FutureProvider(
|
||||||
|
(ref) async {
|
||||||
|
final dio = Dio();
|
||||||
|
var resp = await dio
|
||||||
|
.get(APIs.settingsUrl, queryParameters: {"key": APIs.tmdbApiKey});
|
||||||
|
var rrr = resp.data as Map<String, dynamic>;
|
||||||
|
var data = rrr["data"] as Map<String, dynamic>;
|
||||||
|
var key = data[APIs.tmdbApiKey] as String;
|
||||||
|
|
||||||
|
return key;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
@@ -1,35 +1,38 @@
|
|||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:ui/APIs.dart';
|
import 'package:ui/APIs.dart';
|
||||||
|
import 'package:ui/providers/welcome_data.dart';
|
||||||
import 'package:ui/server_response.dart';
|
import 'package:ui/server_response.dart';
|
||||||
import 'package:ui/utils.dart';
|
import 'package:ui/utils.dart';
|
||||||
|
|
||||||
class SystemSettingsPage extends StatefulWidget {
|
class SystemSettingsPage extends ConsumerStatefulWidget {
|
||||||
static const route = "/systemsettings";
|
static const route = "/systemsettings";
|
||||||
|
|
||||||
const SystemSettingsPage({super.key});
|
const SystemSettingsPage({super.key});
|
||||||
@override
|
@override
|
||||||
State<StatefulWidget> createState() {
|
ConsumerState<ConsumerStatefulWidget> createState() {
|
||||||
return _SystemSettingsPageState();
|
return _SystemSettingsPageState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SystemSettingsPageState extends State<SystemSettingsPage> {
|
class _SystemSettingsPageState extends ConsumerState<SystemSettingsPage> {
|
||||||
final GlobalKey _formKey = GlobalKey<FormState>();
|
final GlobalKey _formKey = GlobalKey<FormState>();
|
||||||
final TextEditingController _tmdbApiKeyController = TextEditingController();
|
|
||||||
|
List<dynamic> indexers = List.empty();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_handleRefresh();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
var key = ref.watch(tmdbApiSettingProvider);
|
||||||
|
|
||||||
|
return key.when(
|
||||||
|
data: (data ) => Container(
|
||||||
padding: const EdgeInsets.fromLTRB(40, 10, 40, 0),
|
padding: const EdgeInsets.fromLTRB(40, 10, 40, 0),
|
||||||
child: RefreshIndicator(
|
|
||||||
onRefresh: _handleRefresh,
|
|
||||||
child: Form(
|
child: Form(
|
||||||
key: _formKey, //设置globalKey,用于后面获取FormState
|
key: _formKey, //设置globalKey,用于后面获取FormState
|
||||||
autovalidateMode: AutovalidateMode.onUserInteraction,
|
autovalidateMode: AutovalidateMode.onUserInteraction,
|
||||||
@@ -37,7 +40,7 @@ class _SystemSettingsPageState extends State<SystemSettingsPage> {
|
|||||||
children: [
|
children: [
|
||||||
TextFormField(
|
TextFormField(
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
controller: _tmdbApiKeyController,
|
initialValue: data,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: "TMDB Api Key",
|
labelText: "TMDB Api Key",
|
||||||
icon: Icon(Icons.key),
|
icon: Icon(Icons.key),
|
||||||
@@ -46,6 +49,9 @@ class _SystemSettingsPageState extends State<SystemSettingsPage> {
|
|||||||
validator: (v) {
|
validator: (v) {
|
||||||
return v!.trim().isNotEmpty ? null : "ApiKey 不能为空";
|
return v!.trim().isNotEmpty ? null : "ApiKey 不能为空";
|
||||||
},
|
},
|
||||||
|
onSaved: (newValue) {
|
||||||
|
_submitSettings(context, newValue!);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
Center(
|
Center(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
@@ -60,7 +66,7 @@ class _SystemSettingsPageState extends State<SystemSettingsPage> {
|
|||||||
// 调用validate()方法校验用户名密码是否合法,校验
|
// 调用validate()方法校验用户名密码是否合法,校验
|
||||||
// 通过后再提交数据。
|
// 通过后再提交数据。
|
||||||
if ((_formKey.currentState as FormState).validate()) {
|
if ((_formKey.currentState as FormState).validate()) {
|
||||||
_submitSettings(context, _tmdbApiKeyController.text);
|
(_formKey.currentState as FormState).save();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -68,20 +74,10 @@ class _SystemSettingsPageState extends State<SystemSettingsPage> {
|
|||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)),
|
),
|
||||||
);
|
),
|
||||||
}
|
error: (err, trace) => Text("$err"),
|
||||||
|
loading: () => const CircularProgressIndicator());
|
||||||
Future<void> _handleRefresh() async {
|
|
||||||
final dio = Dio();
|
|
||||||
var resp = await dio
|
|
||||||
.get(APIs.settingsUrl, queryParameters: {"key": APIs.tmdbApiKey});
|
|
||||||
var rrr = resp.data as Map<String, dynamic>;
|
|
||||||
var data = rrr["data"] as Map<String, dynamic>;
|
|
||||||
var key = data[APIs.tmdbApiKey] as String;
|
|
||||||
_tmdbApiKeyController.text = key;
|
|
||||||
|
|
||||||
// Fetch new data and update the UI
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _submitSettings(BuildContext context, String v) async {
|
void _submitSettings(BuildContext context, String v) async {
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:ui/APIs.dart';
|
import 'package:ui/APIs.dart';
|
||||||
|
import 'package:ui/providers/series_details.dart';
|
||||||
import 'package:ui/server_response.dart';
|
import 'package:ui/server_response.dart';
|
||||||
import 'package:ui/utils.dart';
|
import 'package:ui/utils.dart';
|
||||||
|
|
||||||
class TvDetailsPage extends StatefulWidget {
|
class TvDetailsPage extends ConsumerStatefulWidget {
|
||||||
static const route = "/series/:id";
|
static const route = "/series/:id";
|
||||||
|
|
||||||
static String toRoute(int id) {
|
static String toRoute(int id) {
|
||||||
@@ -16,34 +18,28 @@ class TvDetailsPage extends StatefulWidget {
|
|||||||
const TvDetailsPage({super.key, required this.seriesId});
|
const TvDetailsPage({super.key, required this.seriesId});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<StatefulWidget> createState() {
|
ConsumerState<ConsumerStatefulWidget> createState() {
|
||||||
return _TvDetailsPageState(seriesId: seriesId);
|
return _TvDetailsPageState(seriesId: seriesId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _TvDetailsPageState extends State<TvDetailsPage> {
|
class _TvDetailsPageState extends ConsumerState<TvDetailsPage> {
|
||||||
final String seriesId;
|
final String seriesId;
|
||||||
|
|
||||||
_TvDetailsPageState({required this.seriesId});
|
_TvDetailsPageState({required this.seriesId});
|
||||||
|
|
||||||
SeriesDetails? details;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_querySeriesDetails();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (details == null) {
|
var seriesDetails = ref.watch(seriesDetailsProvider(seriesId));
|
||||||
return const Center(
|
return seriesDetails.when(
|
||||||
child: Text("nothing here"),
|
data: (details) {
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<int, List<Widget>> m = Map();
|
Map<int, List<Widget>> m = Map();
|
||||||
for (final ep in details!.episodes!) {
|
for (final ep in details.episodes!) {
|
||||||
var w = Container(
|
var w = Container(
|
||||||
alignment: Alignment.topLeft,
|
alignment: Alignment.topLeft,
|
||||||
child: Row(
|
child: Row(
|
||||||
@@ -63,8 +59,8 @@ class _TvDetailsPageState extends State<TvDetailsPage> {
|
|||||||
const Expanded(child: Text("")),
|
const Expanded(child: Text("")),
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_searchAndDownload(
|
_searchAndDownload(context, seriesId, ep.seasonNumber!,
|
||||||
context, seriesId, ep.seasonNumber!, ep.episodeNumber!);
|
ep.episodeNumber!);
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.search))
|
icon: const Icon(Icons.search))
|
||||||
],
|
],
|
||||||
@@ -97,7 +93,6 @@ class _TvDetailsPageState extends State<TvDetailsPage> {
|
|||||||
);
|
);
|
||||||
list.add(seasonList);
|
list.add(seasonList);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ListView(
|
return ListView(
|
||||||
children: [
|
children: [
|
||||||
Card(
|
Card(
|
||||||
@@ -135,21 +130,13 @@ class _TvDetailsPageState extends State<TvDetailsPage> {
|
|||||||
Column(
|
Column(
|
||||||
children: list,
|
children: list,
|
||||||
),
|
),
|
||||||
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
|
error: (err, trace) {
|
||||||
void _querySeriesDetails() async {
|
return Text("$err");
|
||||||
if (details != null) {
|
},
|
||||||
return;
|
loading: () => const CircularProgressIndicator());
|
||||||
}
|
|
||||||
var resp = await Dio().get("${APIs.seriesDetailUrl}$seriesId");
|
|
||||||
var rsp = ServerResponse.fromJson(resp.data);
|
|
||||||
|
|
||||||
setState(() {
|
|
||||||
details = SeriesDetails.fromJson(rsp.data);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _searchAndDownload(BuildContext context, String seriesId, int seasonNum,
|
void _searchAndDownload(BuildContext context, String seriesId, int seasonNum,
|
||||||
@@ -170,72 +157,3 @@ class _TvDetailsPageState extends State<TvDetailsPage> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SeriesDetails {
|
|
||||||
int? id;
|
|
||||||
int? tmdbId;
|
|
||||||
String? name;
|
|
||||||
String? originalName;
|
|
||||||
String? overview;
|
|
||||||
String? path;
|
|
||||||
String? posterPath;
|
|
||||||
String? createdAt;
|
|
||||||
List<Episodes>? episodes;
|
|
||||||
|
|
||||||
SeriesDetails(
|
|
||||||
{this.id,
|
|
||||||
this.tmdbId,
|
|
||||||
this.name,
|
|
||||||
this.originalName,
|
|
||||||
this.overview,
|
|
||||||
this.path,
|
|
||||||
this.posterPath,
|
|
||||||
this.createdAt,
|
|
||||||
this.episodes});
|
|
||||||
|
|
||||||
SeriesDetails.fromJson(Map<String, dynamic> json) {
|
|
||||||
id = json['id'];
|
|
||||||
tmdbId = json['tmdb_id'];
|
|
||||||
name = json['name'];
|
|
||||||
originalName = json['original_name'];
|
|
||||||
overview = json['overview'];
|
|
||||||
path = json['path'];
|
|
||||||
posterPath = json['poster_path'];
|
|
||||||
createdAt = json['created_at'];
|
|
||||||
if (json['episodes'] != null) {
|
|
||||||
episodes = <Episodes>[];
|
|
||||||
json['episodes'].forEach((v) {
|
|
||||||
episodes!.add(Episodes.fromJson(v));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Episodes {
|
|
||||||
int? id;
|
|
||||||
int? seriesId;
|
|
||||||
int? episodeNumber;
|
|
||||||
String? title;
|
|
||||||
String? airDate;
|
|
||||||
int? seasonNumber;
|
|
||||||
String? overview;
|
|
||||||
|
|
||||||
Episodes(
|
|
||||||
{this.id,
|
|
||||||
this.seriesId,
|
|
||||||
this.episodeNumber,
|
|
||||||
this.title,
|
|
||||||
this.airDate,
|
|
||||||
this.seasonNumber,
|
|
||||||
this.overview});
|
|
||||||
|
|
||||||
Episodes.fromJson(Map<String, dynamic> json) {
|
|
||||||
id = json['id'];
|
|
||||||
seriesId = json['series_id'];
|
|
||||||
episodeNumber = json['episode_number'];
|
|
||||||
title = json['title'];
|
|
||||||
airDate = json['air_date'];
|
|
||||||
seasonNumber = json['season_number'];
|
|
||||||
overview = json['overview'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,37 +1,26 @@
|
|||||||
import 'package:dio/dio.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:ui/APIs.dart';
|
import 'package:ui/APIs.dart';
|
||||||
import 'package:ui/server_response.dart';
|
import 'package:ui/providers/welcome_data.dart';
|
||||||
import 'package:ui/tv_details.dart';
|
import 'package:ui/tv_details.dart';
|
||||||
|
|
||||||
class WelcomePage extends StatefulWidget {
|
class WelcomePage extends ConsumerWidget {
|
||||||
const WelcomePage({super.key});
|
|
||||||
static const route = "/welcome";
|
static const route = "/welcome";
|
||||||
|
|
||||||
@override
|
const WelcomePage({super.key});
|
||||||
State<StatefulWidget> createState() {
|
|
||||||
return _WeclomePageState();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _WeclomePageState extends State<WelcomePage> {
|
|
||||||
var favList = List.empty(growable: true);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
super.initState();
|
final data = ref.watch(welcomePageDataProvider);
|
||||||
_onRefresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
return switch (data) {
|
||||||
Widget build(BuildContext context) {
|
AsyncData(:final value) => GridView.builder(
|
||||||
return GridView.builder(
|
itemCount: value.length,
|
||||||
itemCount: favList.length,
|
|
||||||
gridDelegate:
|
gridDelegate:
|
||||||
const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 6),
|
const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 6),
|
||||||
itemBuilder: (context, i) {
|
itemBuilder: (context, i) {
|
||||||
var item = TvSeries.fromJson(favList[i]);
|
var item = value[i];
|
||||||
return Card(
|
return Card(
|
||||||
margin: const EdgeInsets.all(4),
|
margin: const EdgeInsets.all(4),
|
||||||
clipBehavior: Clip.hardEdge,
|
clipBehavior: Clip.hardEdge,
|
||||||
@@ -63,46 +52,9 @@ class _WeclomePageState extends State<WelcomePage> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
});
|
}),
|
||||||
}
|
_ => const CircularProgressIndicator(),
|
||||||
|
|
||||||
Future<void> _onRefresh() async {
|
};
|
||||||
if (favList.isNotEmpty) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var resp = await Dio().get(APIs.watchlistUrl);
|
|
||||||
var sp = ServerResponse.fromJson(resp.data);
|
|
||||||
setState(() {
|
|
||||||
favList = sp.data as List;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TvSeries {
|
|
||||||
int? id;
|
|
||||||
int? tmdbId;
|
|
||||||
String? name;
|
|
||||||
String? originalName;
|
|
||||||
String? overview;
|
|
||||||
String? path;
|
|
||||||
String? posterPath;
|
|
||||||
|
|
||||||
TvSeries(
|
|
||||||
{this.id,
|
|
||||||
this.tmdbId,
|
|
||||||
this.name,
|
|
||||||
this.originalName,
|
|
||||||
this.overview,
|
|
||||||
this.path,
|
|
||||||
this.posterPath});
|
|
||||||
|
|
||||||
TvSeries.fromJson(Map<String, dynamic> json) {
|
|
||||||
id = json['id'];
|
|
||||||
tmdbId = json['tmdb_id'];
|
|
||||||
name = json['name'];
|
|
||||||
originalName = json['original_name'];
|
|
||||||
overview = json['overview'];
|
|
||||||
path = json['path'];
|
|
||||||
posterPath = json["poster_path"];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,6 +78,14 @@ packages:
|
|||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.0"
|
version: "4.0.0"
|
||||||
|
flutter_riverpod:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_riverpod
|
||||||
|
sha256: "0f1974eff5bbe774bf1d870e406fc6f29e3d6f1c46bd9c58e7172ff68a785d7d"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "2.5.1"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
@@ -176,6 +184,14 @@ packages:
|
|||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.9.0"
|
version: "1.9.0"
|
||||||
|
riverpod:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: riverpod
|
||||||
|
sha256: f21b32ffd26a36555e501b04f4a5dca43ed59e16343f1a30c13632b2351dfa4d
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "2.5.1"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
@@ -197,6 +213,14 @@ packages:
|
|||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.11.1"
|
version: "1.11.1"
|
||||||
|
state_notifier:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: state_notifier
|
||||||
|
sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.0"
|
||||||
stream_channel:
|
stream_channel:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ dependencies:
|
|||||||
# Use with the CupertinoIcons class for iOS style icons.
|
# Use with the CupertinoIcons class for iOS style icons.
|
||||||
cupertino_icons: ^1.0.6
|
cupertino_icons: ^1.0.6
|
||||||
go_router: ^14.2.0
|
go_router: ^14.2.0
|
||||||
|
flutter_riverpod: ^2.5.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
Reference in New Issue
Block a user