import 'dart:async'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:quiver/strings.dart'; import 'package:ui/providers/APIs.dart'; import 'package:ui/providers/server_response.dart'; final tvWatchlistDataProvider = FutureProvider.autoDispose((ref) async { final dio = await APIs.getDio(); var resp = await dio.get(APIs.watchlistTvUrl); var sp = ServerResponse.fromJson(resp.data); List favList = List.empty(growable: true); for (var item in sp.data as List) { var tv = MediaDetail.fromJson(item); favList.add(tv); } return favList; }); final suggestNameDataProvider = FutureProvider.autoDispose.family( (ref, int arg) async { final dio = await APIs.getDio(); var resp = await dio.get(APIs.suggestedTvName + arg.toString()); var sp = ServerResponse.fromJson(resp.data); if (sp.code != 0) { throw sp.message; } return sp.data["name"] as String; }, ); final movieWatchlistDataProvider = FutureProvider.autoDispose((ref) async { final dio = await APIs.getDio(); var resp = await dio.get(APIs.watchlistMovieUrl); var sp = ServerResponse.fromJson(resp.data); List favList = List.empty(growable: true); for (var item in sp.data as List) { var tv = MediaDetail.fromJson(item); favList.add(tv); } return favList; }); var searchPageDataProvider = AsyncNotifierProvider.autoDispose .family, String>(SearchPageData.new); var movieTorrentsDataProvider = AsyncNotifierProvider.autoDispose .family, String>( MovieTorrentResource.new); class SearchPageData extends AutoDisposeFamilyAsyncNotifier, String> { List list = List.empty(growable: true); String? q; int page = 1; @override FutureOr> build(String arg) async { q = arg; if (isBlank(arg)) { return List.empty(); } return query(arg, 1); } FutureOr> query(String q, int page) async { final dio = await APIs.getDio(); var resp = await dio .get(APIs.searchUrl, queryParameters: {"query": q, "page": page}); var rsp = ServerResponse.fromJson(resp.data as Map); if (rsp.code != 0) { throw rsp.message; } var sp = SearchResponse.fromJson(rsp.data); return sp.results ?? List.empty(); } FutureOr queryNextPage() async { //state = const AsyncLoading(); final newState = await AsyncValue.guard( () async { page++; final awaiteddata = await query(q!, page); return [...?state.value, ...awaiteddata]; }, ); state = newState; } Future submit2Watchlist(int tmdbId, int storageId, String resolution, String mediaType, String folder) async { final dio = await APIs.getDio(); if (mediaType == "tv") { var resp = await dio.post(APIs.watchlistTvUrl, data: { "tmdb_id": tmdbId, "storage_id": storageId, "resolution": resolution, "folder": folder }); var sp = ServerResponse.fromJson(resp.data); if (sp.code != 0) { throw sp.message; } ref.invalidate(tvWatchlistDataProvider); } else { var resp = await dio.post(APIs.watchlistMovieUrl, data: { "tmdb_id": tmdbId, "storage_id": storageId, "resolution": resolution, "folder": folder }); var sp = ServerResponse.fromJson(resp.data); if (sp.code != 0) { throw sp.message; } } } } class SearchResponse { int? page; int? totalResults; int? totalPage; List? results; SearchResponse({this.page, this.totalResults, this.totalPage, this.results}); factory SearchResponse.fromJson(Map json) { return SearchResponse( page: json["page"], totalPage: json["total_page"], totalResults: json["total_results"], results: json["results"] == null ? [] : (json["results"] as List) .map((v) => SearchResult.fromJson(v)) .toList()); } } class MediaDetail { int? id; int? tmdbId; String? mediaType; String? name; String? originalName; String? overview; String? posterPath; String? createdAt; String? resolution; int? storageId; String? airDate; MediaDetail({ this.id, this.tmdbId, this.mediaType, this.name, this.originalName, this.overview, this.posterPath, this.createdAt, this.resolution, this.storageId, this.airDate, }); MediaDetail.fromJson(Map json) { id = json['id']; tmdbId = json['tmdb_id']; mediaType = json["media_type"]; name = json['name_cn']; originalName = json['original_name']; overview = json['overview']; posterPath = json['poster_path']; createdAt = json['created_at']; resolution = json["resolution"]; storageId = json["storage_id"]; airDate = json["air_date"]; } } class SearchResult { SearchResult({ required this.backdropPath, required this.id, required this.name, required this.originalName, required this.overview, required this.posterPath, required this.mediaType, required this.adult, required this.originalLanguage, required this.genreIds, required this.popularity, required this.firstAirDate, required this.voteAverage, required this.voteCount, required this.originCountry, }); final String? backdropPath; final int? id; final String? name; final String? originalName; final String? overview; final String? posterPath; final String? mediaType; final bool? adult; final String? originalLanguage; final List genreIds; final double? popularity; final DateTime? firstAirDate; final double? voteAverage; final int? voteCount; final List originCountry; factory SearchResult.fromJson(Map json) { return SearchResult( backdropPath: json["backdrop_path"], id: json["id"], name: json["name"], originalName: json["original_name"], overview: json["overview"], posterPath: json["poster_path"], mediaType: json["media_type"], adult: json["adult"], originalLanguage: json["original_language"], genreIds: json["genre_ids"] == null ? [] : List.from(json["genre_ids"]!.map((x) => x)), popularity: json["popularity"], firstAirDate: DateTime.tryParse(json["first_air_date"] ?? ""), voteAverage: json["vote_average"], voteCount: json["vote_count"], originCountry: json["origin_country"] == null ? [] : List.from(json["origin_country"]!.map((x) => x)), ); } } class MovieTorrentResource extends AutoDisposeFamilyAsyncNotifier, String> { String? mediaId; @override FutureOr> build(String id) async { mediaId = id; final dio = await APIs.getDio(); var resp = await dio.get(APIs.availableMoviesUrl + id); var rsp = ServerResponse.fromJson(resp.data); if (rsp.code != 0) { throw rsp.message; } return (rsp.data as List).map((v) => TorrentResource.fromJson(v)).toList(); } Future download(String link) async { final dio = await APIs.getDio(); var resp = await dio.post(APIs.availableMoviesUrl, data: {"media_id": int.parse(mediaId!), "link": link}); var rsp = ServerResponse.fromJson(resp.data); if (rsp.code != 0) { throw rsp.message; } } } class TorrentResource { TorrentResource({this.name, this.size, this.seeders, this.peers, this.link}); String? name; int? size; int? seeders; int? peers; String? link; factory TorrentResource.fromJson(Map json) { return TorrentResource( name: json["name"], size: json["size"], seeders: json["seeders"], peers: json["peers"], link: json["link"]); } }