mirror of
https://gitlab.com/foxixus/neomovies_mobile.git
synced 2025-10-27 19:58:50 +05:00
- Fix torrent platform service integration with Android engine - Add downloads page with torrent list and progress tracking - Implement torrent detail screen with file selection and priorities - Create native video player with fullscreen controls - Add WebView players for Vibix and Alloha - Integrate corrected torrent engine with file selector - Update dependencies for auto_route and video players Features: ✅ Downloads screen with real-time torrent status ✅ File-level priority management and selection ✅ Three player options: native, Vibix WebView, Alloha WebView ✅ Torrent pause/resume/remove functionality ✅ Progress tracking and seeder/peer counts ✅ Video file detection and playback integration ✅ Fixed Android torrent engine method calls This resolves torrent integration issues and provides complete downloads management UI with video playback capabilities.
180 lines
5.2 KiB
Dart
180 lines
5.2 KiB
Dart
/// File priority enum matching Android implementation
|
|
enum FilePriority {
|
|
DONT_DOWNLOAD(0),
|
|
NORMAL(4),
|
|
HIGH(7);
|
|
|
|
const FilePriority(this.value);
|
|
final int value;
|
|
|
|
static FilePriority fromValue(int value) {
|
|
return FilePriority.values.firstWhere(
|
|
(priority) => priority.value == value,
|
|
orElse: () => FilePriority.NORMAL,
|
|
);
|
|
}
|
|
|
|
bool operator >(FilePriority other) => value > other.value;
|
|
bool operator <(FilePriority other) => value < other.value;
|
|
bool operator >=(FilePriority other) => value >= other.value;
|
|
bool operator <=(FilePriority other) => value <= other.value;
|
|
}
|
|
|
|
/// Torrent file information matching Android TorrentFileInfo
|
|
class TorrentFileInfo {
|
|
final String path;
|
|
final int size;
|
|
final FilePriority priority;
|
|
final double progress;
|
|
|
|
TorrentFileInfo({
|
|
required this.path,
|
|
required this.size,
|
|
required this.priority,
|
|
this.progress = 0.0,
|
|
});
|
|
|
|
factory TorrentFileInfo.fromAndroidJson(Map<String, dynamic> json) {
|
|
return TorrentFileInfo(
|
|
path: json['path'] as String,
|
|
size: json['size'] as int,
|
|
priority: FilePriority.fromValue(json['priority'] as int),
|
|
progress: (json['progress'] as num?)?.toDouble() ?? 0.0,
|
|
);
|
|
}
|
|
|
|
Map<String, dynamic> toJson() {
|
|
return {
|
|
'path': path,
|
|
'size': size,
|
|
'priority': priority.value,
|
|
'progress': progress,
|
|
};
|
|
}
|
|
}
|
|
|
|
/// Main torrent information class matching Android TorrentInfo
|
|
class TorrentInfo {
|
|
final String infoHash;
|
|
final String name;
|
|
final int totalSize;
|
|
final double progress;
|
|
final int downloadSpeed;
|
|
final int uploadSpeed;
|
|
final int numSeeds;
|
|
final int numPeers;
|
|
final String state;
|
|
final String savePath;
|
|
final List<TorrentFileInfo> files;
|
|
final int pieceLength;
|
|
final int numPieces;
|
|
final DateTime? addedTime;
|
|
|
|
TorrentInfo({
|
|
required this.infoHash,
|
|
required this.name,
|
|
required this.totalSize,
|
|
required this.progress,
|
|
required this.downloadSpeed,
|
|
required this.uploadSpeed,
|
|
required this.numSeeds,
|
|
required this.numPeers,
|
|
required this.state,
|
|
required this.savePath,
|
|
required this.files,
|
|
this.pieceLength = 0,
|
|
this.numPieces = 0,
|
|
this.addedTime,
|
|
});
|
|
|
|
factory TorrentInfo.fromAndroidJson(Map<String, dynamic> json) {
|
|
final filesJson = json['files'] as List<dynamic>? ?? [];
|
|
final files = filesJson
|
|
.map((fileJson) => TorrentFileInfo.fromAndroidJson(fileJson as Map<String, dynamic>))
|
|
.toList();
|
|
|
|
return TorrentInfo(
|
|
infoHash: json['infoHash'] as String,
|
|
name: json['name'] as String,
|
|
totalSize: json['totalSize'] as int,
|
|
progress: (json['progress'] as num).toDouble(),
|
|
downloadSpeed: json['downloadSpeed'] as int,
|
|
uploadSpeed: json['uploadSpeed'] as int,
|
|
numSeeds: json['numSeeds'] as int,
|
|
numPeers: json['numPeers'] as int,
|
|
state: json['state'] as String,
|
|
savePath: json['savePath'] as String,
|
|
files: files,
|
|
pieceLength: json['pieceLength'] as int? ?? 0,
|
|
numPieces: json['numPieces'] as int? ?? 0,
|
|
addedTime: json['addedTime'] != null
|
|
? DateTime.fromMillisecondsSinceEpoch(json['addedTime'] as int)
|
|
: null,
|
|
);
|
|
}
|
|
|
|
Map<String, dynamic> toJson() {
|
|
return {
|
|
'infoHash': infoHash,
|
|
'name': name,
|
|
'totalSize': totalSize,
|
|
'progress': progress,
|
|
'downloadSpeed': downloadSpeed,
|
|
'uploadSpeed': uploadSpeed,
|
|
'numSeeds': numSeeds,
|
|
'numPeers': numPeers,
|
|
'state': state,
|
|
'savePath': savePath,
|
|
'files': files.map((file) => file.toJson()).toList(),
|
|
'pieceLength': pieceLength,
|
|
'numPieces': numPieces,
|
|
'addedTime': addedTime?.millisecondsSinceEpoch,
|
|
};
|
|
}
|
|
|
|
/// Get video files only
|
|
List<TorrentFileInfo> get videoFiles {
|
|
final videoExtensions = {'.mp4', '.mkv', '.avi', '.mov', '.wmv', '.flv', '.webm', '.m4v'};
|
|
return files.where((file) {
|
|
final extension = file.path.toLowerCase().split('.').last;
|
|
return videoExtensions.contains('.$extension');
|
|
}).toList();
|
|
}
|
|
|
|
/// Get the largest video file (usually the main movie file)
|
|
TorrentFileInfo? get mainVideoFile {
|
|
final videos = videoFiles;
|
|
if (videos.isEmpty) return null;
|
|
|
|
videos.sort((a, b) => b.size.compareTo(a.size));
|
|
return videos.first;
|
|
}
|
|
|
|
/// Check if torrent is completed
|
|
bool get isCompleted => progress >= 1.0;
|
|
|
|
/// Check if torrent is downloading
|
|
bool get isDownloading => state == 'DOWNLOADING';
|
|
|
|
/// Check if torrent is seeding
|
|
bool get isSeeding => state == 'SEEDING';
|
|
|
|
/// Check if torrent is paused
|
|
bool get isPaused => state == 'PAUSED';
|
|
|
|
/// Get formatted download speed
|
|
String get formattedDownloadSpeed => _formatBytes(downloadSpeed);
|
|
|
|
/// Get formatted upload speed
|
|
String get formattedUploadSpeed => _formatBytes(uploadSpeed);
|
|
|
|
/// Get formatted total size
|
|
String get formattedTotalSize => _formatBytes(totalSize);
|
|
|
|
static String _formatBytes(int bytes) {
|
|
if (bytes < 1024) return '${bytes}B';
|
|
if (bytes < 1024 * 1024) return '${(bytes / 1024).toStringAsFixed(1)}KB';
|
|
if (bytes < 1024 * 1024 * 1024) return '${(bytes / (1024 * 1024)).toStringAsFixed(1)}MB';
|
|
return '${(bytes / (1024 * 1024 * 1024)).toStringAsFixed(1)}GB';
|
|
}
|
|
} |