add torrent api(magnet links)

This commit is contained in:
2025-07-19 18:13:13 +03:00
parent 05311129f3
commit 4ea75db105
18 changed files with 2329 additions and 15 deletions

View File

@@ -1,9 +1,11 @@
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:hive/hive.dart';
import 'package:json_annotation/json_annotation.dart';
part 'movie.g.dart';
@HiveType(typeId: 0)
@JsonSerializable()
class Movie extends HiveObject {
@HiveField(0)
final String id;
@@ -87,6 +89,8 @@ class Movie extends HiveObject {
);
}
Map<String, dynamic> toJson() => _$MovieToJson(this);
String get fullPosterUrl {
final baseUrl = dotenv.env['API_URL']!;
if (posterPath == null || posterPath!.isEmpty) {

View File

@@ -24,13 +24,18 @@ class MovieAdapter extends TypeAdapter<Movie> {
releaseDate: fields[4] as DateTime?,
genres: (fields[5] as List?)?.cast<String>(),
voteAverage: fields[6] as double?,
popularity: fields[9] as double,
runtime: fields[7] as int?,
seasonsCount: fields[10] as int?,
episodesCount: fields[11] as int?,
tagline: fields[8] as String?,
);
}
@override
void write(BinaryWriter writer, Movie obj) {
writer
..writeByte(7)
..writeByte(12)
..writeByte(0)
..write(obj.id)
..writeByte(1)
@@ -44,7 +49,17 @@ class MovieAdapter extends TypeAdapter<Movie> {
..writeByte(5)
..write(obj.genres)
..writeByte(6)
..write(obj.voteAverage);
..write(obj.voteAverage)
..writeByte(9)
..write(obj.popularity)
..writeByte(7)
..write(obj.runtime)
..writeByte(10)
..write(obj.seasonsCount)
..writeByte(11)
..write(obj.episodesCount)
..writeByte(8)
..write(obj.tagline);
}
@override
@@ -57,3 +72,42 @@ class MovieAdapter extends TypeAdapter<Movie> {
runtimeType == other.runtimeType &&
typeId == other.typeId;
}
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
Movie _$MovieFromJson(Map<String, dynamic> json) => Movie(
id: json['id'] as String,
title: json['title'] as String,
posterPath: json['posterPath'] as String?,
overview: json['overview'] as String?,
releaseDate: json['releaseDate'] == null
? null
: DateTime.parse(json['releaseDate'] as String),
genres:
(json['genres'] as List<dynamic>?)?.map((e) => e as String).toList(),
voteAverage: (json['voteAverage'] as num?)?.toDouble(),
popularity: (json['popularity'] as num?)?.toDouble() ?? 0.0,
runtime: (json['runtime'] as num?)?.toInt(),
seasonsCount: (json['seasonsCount'] as num?)?.toInt(),
episodesCount: (json['episodesCount'] as num?)?.toInt(),
tagline: json['tagline'] as String?,
mediaType: json['mediaType'] as String? ?? 'movie',
);
Map<String, dynamic> _$MovieToJson(Movie instance) => <String, dynamic>{
'id': instance.id,
'title': instance.title,
'posterPath': instance.posterPath,
'overview': instance.overview,
'releaseDate': instance.releaseDate?.toIso8601String(),
'genres': instance.genres,
'voteAverage': instance.voteAverage,
'popularity': instance.popularity,
'runtime': instance.runtime,
'seasonsCount': instance.seasonsCount,
'episodesCount': instance.episodesCount,
'tagline': instance.tagline,
'mediaType': instance.mediaType,
};

View File

@@ -1,8 +1,10 @@
import 'package:hive/hive.dart';
import 'package:json_annotation/json_annotation.dart';
part 'movie_preview.g.dart';
@HiveType(typeId: 1) // Use a new typeId to avoid conflicts with Movie
@JsonSerializable()
class MoviePreview extends HiveObject {
@HiveField(0)
final String id;
@@ -18,4 +20,7 @@ class MoviePreview extends HiveObject {
required this.title,
this.posterPath,
});
factory MoviePreview.fromJson(Map<String, dynamic> json) => _$MoviePreviewFromJson(json);
Map<String, dynamic> toJson() => _$MoviePreviewToJson(this);
}

View File

@@ -45,3 +45,20 @@ class MoviePreviewAdapter extends TypeAdapter<MoviePreview> {
runtimeType == other.runtimeType &&
typeId == other.typeId;
}
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
MoviePreview _$MoviePreviewFromJson(Map<String, dynamic> json) => MoviePreview(
id: json['id'] as String,
title: json['title'] as String,
posterPath: json['posterPath'] as String?,
);
Map<String, dynamic> _$MoviePreviewToJson(MoviePreview instance) =>
<String, dynamic>{
'id': instance.id,
'title': instance.title,
'posterPath': instance.posterPath,
};

View File

@@ -0,0 +1,18 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'torrent.freezed.dart';
part 'torrent.g.dart';
@freezed
class Torrent with _$Torrent {
const factory Torrent({
required String magnet,
String? title,
String? name,
String? quality,
int? seeders,
@JsonKey(name: 'size_gb') double? sizeGb,
}) = _Torrent;
factory Torrent.fromJson(Map<String, dynamic> json) => _$TorrentFromJson(json);
}

View File

@@ -0,0 +1,268 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'torrent.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
Torrent _$TorrentFromJson(Map<String, dynamic> json) {
return _Torrent.fromJson(json);
}
/// @nodoc
mixin _$Torrent {
String get magnet => throw _privateConstructorUsedError;
String? get title => throw _privateConstructorUsedError;
String? get name => throw _privateConstructorUsedError;
String? get quality => throw _privateConstructorUsedError;
int? get seeders => throw _privateConstructorUsedError;
@JsonKey(name: 'size_gb')
double? get sizeGb => throw _privateConstructorUsedError;
/// Serializes this Torrent to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
/// Create a copy of Torrent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$TorrentCopyWith<Torrent> get copyWith => throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $TorrentCopyWith<$Res> {
factory $TorrentCopyWith(Torrent value, $Res Function(Torrent) then) =
_$TorrentCopyWithImpl<$Res, Torrent>;
@useResult
$Res call(
{String magnet,
String? title,
String? name,
String? quality,
int? seeders,
@JsonKey(name: 'size_gb') double? sizeGb});
}
/// @nodoc
class _$TorrentCopyWithImpl<$Res, $Val extends Torrent>
implements $TorrentCopyWith<$Res> {
_$TorrentCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of Torrent
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? magnet = null,
Object? title = freezed,
Object? name = freezed,
Object? quality = freezed,
Object? seeders = freezed,
Object? sizeGb = freezed,
}) {
return _then(_value.copyWith(
magnet: null == magnet
? _value.magnet
: magnet // ignore: cast_nullable_to_non_nullable
as String,
title: freezed == title
? _value.title
: title // ignore: cast_nullable_to_non_nullable
as String?,
name: freezed == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String?,
quality: freezed == quality
? _value.quality
: quality // ignore: cast_nullable_to_non_nullable
as String?,
seeders: freezed == seeders
? _value.seeders
: seeders // ignore: cast_nullable_to_non_nullable
as int?,
sizeGb: freezed == sizeGb
? _value.sizeGb
: sizeGb // ignore: cast_nullable_to_non_nullable
as double?,
) as $Val);
}
}
/// @nodoc
abstract class _$$TorrentImplCopyWith<$Res> implements $TorrentCopyWith<$Res> {
factory _$$TorrentImplCopyWith(
_$TorrentImpl value, $Res Function(_$TorrentImpl) then) =
__$$TorrentImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{String magnet,
String? title,
String? name,
String? quality,
int? seeders,
@JsonKey(name: 'size_gb') double? sizeGb});
}
/// @nodoc
class __$$TorrentImplCopyWithImpl<$Res>
extends _$TorrentCopyWithImpl<$Res, _$TorrentImpl>
implements _$$TorrentImplCopyWith<$Res> {
__$$TorrentImplCopyWithImpl(
_$TorrentImpl _value, $Res Function(_$TorrentImpl) _then)
: super(_value, _then);
/// Create a copy of Torrent
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? magnet = null,
Object? title = freezed,
Object? name = freezed,
Object? quality = freezed,
Object? seeders = freezed,
Object? sizeGb = freezed,
}) {
return _then(_$TorrentImpl(
magnet: null == magnet
? _value.magnet
: magnet // ignore: cast_nullable_to_non_nullable
as String,
title: freezed == title
? _value.title
: title // ignore: cast_nullable_to_non_nullable
as String?,
name: freezed == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String?,
quality: freezed == quality
? _value.quality
: quality // ignore: cast_nullable_to_non_nullable
as String?,
seeders: freezed == seeders
? _value.seeders
: seeders // ignore: cast_nullable_to_non_nullable
as int?,
sizeGb: freezed == sizeGb
? _value.sizeGb
: sizeGb // ignore: cast_nullable_to_non_nullable
as double?,
));
}
}
/// @nodoc
@JsonSerializable()
class _$TorrentImpl implements _Torrent {
const _$TorrentImpl(
{required this.magnet,
this.title,
this.name,
this.quality,
this.seeders,
@JsonKey(name: 'size_gb') this.sizeGb});
factory _$TorrentImpl.fromJson(Map<String, dynamic> json) =>
_$$TorrentImplFromJson(json);
@override
final String magnet;
@override
final String? title;
@override
final String? name;
@override
final String? quality;
@override
final int? seeders;
@override
@JsonKey(name: 'size_gb')
final double? sizeGb;
@override
String toString() {
return 'Torrent(magnet: $magnet, title: $title, name: $name, quality: $quality, seeders: $seeders, sizeGb: $sizeGb)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$TorrentImpl &&
(identical(other.magnet, magnet) || other.magnet == magnet) &&
(identical(other.title, title) || other.title == title) &&
(identical(other.name, name) || other.name == name) &&
(identical(other.quality, quality) || other.quality == quality) &&
(identical(other.seeders, seeders) || other.seeders == seeders) &&
(identical(other.sizeGb, sizeGb) || other.sizeGb == sizeGb));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode =>
Object.hash(runtimeType, magnet, title, name, quality, seeders, sizeGb);
/// Create a copy of Torrent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$TorrentImplCopyWith<_$TorrentImpl> get copyWith =>
__$$TorrentImplCopyWithImpl<_$TorrentImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$TorrentImplToJson(
this,
);
}
}
abstract class _Torrent implements Torrent {
const factory _Torrent(
{required final String magnet,
final String? title,
final String? name,
final String? quality,
final int? seeders,
@JsonKey(name: 'size_gb') final double? sizeGb}) = _$TorrentImpl;
factory _Torrent.fromJson(Map<String, dynamic> json) = _$TorrentImpl.fromJson;
@override
String get magnet;
@override
String? get title;
@override
String? get name;
@override
String? get quality;
@override
int? get seeders;
@override
@JsonKey(name: 'size_gb')
double? get sizeGb;
/// Create a copy of Torrent
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$TorrentImplCopyWith<_$TorrentImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -0,0 +1,27 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'torrent.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$TorrentImpl _$$TorrentImplFromJson(Map<String, dynamic> json) =>
_$TorrentImpl(
magnet: json['magnet'] as String,
title: json['title'] as String?,
name: json['name'] as String?,
quality: json['quality'] as String?,
seeders: (json['seeders'] as num?)?.toInt(),
sizeGb: (json['size_gb'] as num?)?.toDouble(),
);
Map<String, dynamic> _$$TorrentImplToJson(_$TorrentImpl instance) =>
<String, dynamic>{
'magnet': instance.magnet,
'title': instance.title,
'name': instance.name,
'quality': instance.quality,
'seeders': instance.seeders,
'size_gb': instance.sizeGb,
};