From dc443540360f0bdd179a2141458d0ed628c5974c Mon Sep 17 00:00:00 2001
From: edde746 <86283021+edde746@users.noreply.github.com>
Date: Thu, 11 Dec 2025 19:15:06 +0100
Subject: [PATCH] feat: downloads
---
ios/Podfile.lock | 102 +
ios/Runner.xcodeproj/project.pbxproj | 3 +
ios/Runner/Info.plist | 4 +
lib/database/app_database.dart | 208 +
lib/database/app_database.g.dart | 3635 +++
lib/database/tables/api_cache.dart | 20 +
lib/database/tables/download_queue.dart | 13 +
lib/database/tables/downloaded_media.dart | 21 +
.../tables/offline_watch_progress.dart | 46 +
lib/i18n/strings.g.dart | 20593 +++++++++++-----
lib/i18n/strings.i18n.json | 75 +-
lib/i18n/strings_de.i18n.json | 77 +-
lib/i18n/strings_it.i18n.json | 75 +-
lib/i18n/strings_nl.i18n.json | 75 +-
lib/i18n/strings_sv.i18n.json | 75 +-
lib/i18n/strings_zh.i18n.json | 75 +-
lib/main.dart | 138 +-
lib/models/deletion_progress.dart | 45 +
lib/models/download_progress.dart | 81 +
lib/models/download_status.dart | 9 +
lib/models/plex_media_info.dart | 8 +
lib/models/plex_metadata.dart | 37 +-
lib/models/plex_metadata.g.dart | 2 +
lib/providers/download_provider.dart | 1277 +
lib/providers/offline_mode_provider.dart | 83 +
lib/providers/offline_watch_provider.dart | 214 +
lib/screens/downloads/downloads_screen.dart | 365 +
lib/screens/main_screen.dart | 250 +-
lib/screens/media_detail_screen.dart | 1032 +-
lib/screens/season_detail_screen.dart | 302 +-
lib/screens/settings/settings_screen.dart | 186 +
lib/screens/video_player_screen.dart | 111 +-
lib/services/download_manager_service.dart | 1717 ++
lib/services/download_storage_service.dart | 710 +
lib/services/offline_watch_sync_service.dart | 507 +
.../playback_initialization_service.dart | 129 +-
lib/services/playback_progress_tracker.dart | 115 +-
lib/services/plex_api_cache.dart | 142 +
lib/services/plex_client.dart | 349 +-
lib/services/saf_storage_service.dart | 233 +
lib/services/settings_service.dart | 41 +
lib/utils/plex_image_helper.dart | 9 +-
lib/utils/smart_deletion_handler.dart | 79 +
lib/utils/video_player_navigation.dart | 3 +
lib/widgets/deletion_progress_dialog.dart | 80 +
lib/widgets/download_tree_item.dart | 363 +
lib/widgets/download_tree_view.dart | 639 +
lib/widgets/focusable_media_card.dart | 5 +
lib/widgets/hub_section.dart | 10 +-
lib/widgets/media_card.dart | 69 +-
lib/widgets/media_context_menu.dart | 199 +-
lib/widgets/plex_optimized_image.dart | 48 +-
lib/widgets/side_navigation_rail.dart | 100 +-
.../video_controls/sheets/chapter_sheet.dart | 24 +-
.../video_controls/video_controls.dart | 116 +-
linux/flutter/generated_plugin_registrant.cc | 4 +
linux/flutter/generated_plugins.cmake | 1 +
macos/Flutter/GeneratedPluginRegistrant.swift | 6 +
macos/Podfile.lock | 43 +
macos/Runner/Configs/AppInfo.xcconfig | 4 +-
pubspec.lock | 130 +-
pubspec.yaml | 8 +
.../flutter/generated_plugin_registrant.cc | 3 +
windows/flutter/generated_plugins.cmake | 1 +
windows/runner/Runner.rc | 4 +-
65 files changed, 28245 insertions(+), 6883 deletions(-)
create mode 100644 lib/database/app_database.dart
create mode 100644 lib/database/app_database.g.dart
create mode 100644 lib/database/tables/api_cache.dart
create mode 100644 lib/database/tables/download_queue.dart
create mode 100644 lib/database/tables/downloaded_media.dart
create mode 100644 lib/database/tables/offline_watch_progress.dart
create mode 100644 lib/models/deletion_progress.dart
create mode 100644 lib/models/download_progress.dart
create mode 100644 lib/models/download_status.dart
create mode 100644 lib/providers/download_provider.dart
create mode 100644 lib/providers/offline_mode_provider.dart
create mode 100644 lib/providers/offline_watch_provider.dart
create mode 100644 lib/screens/downloads/downloads_screen.dart
create mode 100644 lib/services/download_manager_service.dart
create mode 100644 lib/services/download_storage_service.dart
create mode 100644 lib/services/offline_watch_sync_service.dart
create mode 100644 lib/services/plex_api_cache.dart
create mode 100644 lib/services/saf_storage_service.dart
create mode 100644 lib/utils/smart_deletion_handler.dart
create mode 100644 lib/widgets/deletion_progress_dialog.dart
create mode 100644 lib/widgets/download_tree_item.dart
create mode 100644 lib/widgets/download_tree_view.dart
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index e1eee8e7..1ee582a1 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -3,7 +3,43 @@ PODS:
- Flutter
- device_info_plus (0.0.1):
- Flutter
+ - DKImagePickerController/Core (4.3.9):
+ - DKImagePickerController/ImageDataManager
+ - DKImagePickerController/Resource
+ - DKImagePickerController/ImageDataManager (4.3.9)
+ - DKImagePickerController/PhotoGallery (4.3.9):
+ - DKImagePickerController/Core
+ - DKPhotoGallery
+ - DKImagePickerController/Resource (4.3.9)
+ - DKPhotoGallery (0.0.19):
+ - DKPhotoGallery/Core (= 0.0.19)
+ - DKPhotoGallery/Model (= 0.0.19)
+ - DKPhotoGallery/Preview (= 0.0.19)
+ - DKPhotoGallery/Resource (= 0.0.19)
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Core (0.0.19):
+ - DKPhotoGallery/Model
+ - DKPhotoGallery/Preview
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Model (0.0.19):
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Preview (0.0.19):
+ - DKPhotoGallery/Model
+ - DKPhotoGallery/Resource
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Resource (0.0.19):
+ - SDWebImage
+ - SwiftyGif
+ - file_picker (0.0.1):
+ - DKImagePickerController/PhotoGallery
+ - Flutter
- Flutter (1.0.0)
+ - gamepads_ios (0.1.1):
+ - Flutter
- os_media_controls (0.0.1):
- Flutter
- package_info_plus (0.4.5):
@@ -11,33 +47,83 @@ PODS:
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
+ - SDWebImage (5.21.3):
+ - SDWebImage/Core (= 5.21.3)
+ - SDWebImage/Core (5.21.3)
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
- sqflite_darwin (0.0.4):
- Flutter
- FlutterMacOS
+ - sqlite3 (3.51.1):
+ - sqlite3/common (= 3.51.1)
+ - sqlite3/common (3.51.1)
+ - sqlite3/dbstatvtab (3.51.1):
+ - sqlite3/common
+ - sqlite3/fts5 (3.51.1):
+ - sqlite3/common
+ - sqlite3/math (3.51.1):
+ - sqlite3/common
+ - sqlite3/perf-threadsafe (3.51.1):
+ - sqlite3/common
+ - sqlite3/rtree (3.51.1):
+ - sqlite3/common
+ - sqlite3/session (3.51.1):
+ - sqlite3/common
+ - sqlite3_flutter_libs (0.0.1):
+ - Flutter
+ - FlutterMacOS
+ - sqlite3 (~> 3.51.1)
+ - sqlite3/dbstatvtab
+ - sqlite3/fts5
+ - sqlite3/math
+ - sqlite3/perf-threadsafe
+ - sqlite3/rtree
+ - sqlite3/session
+ - SwiftyGif (5.4.5)
- url_launcher_ios (0.0.1):
- Flutter
+ - wakelock_plus (0.0.1):
+ - Flutter
+ - workmanager_apple (0.0.1):
+ - Flutter
DEPENDENCIES:
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
+ - file_picker (from `.symlinks/plugins/file_picker/ios`)
- Flutter (from `Flutter`)
+ - gamepads_ios (from `.symlinks/plugins/gamepads_ios/ios`)
- os_media_controls (from `.symlinks/plugins/os_media_controls/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
+ - sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/darwin`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
+ - wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
+ - workmanager_apple (from `.symlinks/plugins/workmanager_apple/ios`)
+
+SPEC REPOS:
+ trunk:
+ - DKImagePickerController
+ - DKPhotoGallery
+ - SDWebImage
+ - sqlite3
+ - SwiftyGif
EXTERNAL SOURCES:
connectivity_plus:
:path: ".symlinks/plugins/connectivity_plus/ios"
device_info_plus:
:path: ".symlinks/plugins/device_info_plus/ios"
+ file_picker:
+ :path: ".symlinks/plugins/file_picker/ios"
Flutter:
:path: Flutter
+ gamepads_ios:
+ :path: ".symlinks/plugins/gamepads_ios/ios"
os_media_controls:
:path: ".symlinks/plugins/os_media_controls/ios"
package_info_plus:
@@ -48,19 +134,35 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
sqflite_darwin:
:path: ".symlinks/plugins/sqflite_darwin/darwin"
+ sqlite3_flutter_libs:
+ :path: ".symlinks/plugins/sqlite3_flutter_libs/darwin"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
+ wakelock_plus:
+ :path: ".symlinks/plugins/wakelock_plus/ios"
+ workmanager_apple:
+ :path: ".symlinks/plugins/workmanager_apple/ios"
SPEC CHECKSUMS:
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
+ DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
+ DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
+ file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
+ gamepads_ios: c75c6d31377d275b0effb9174c619e2705678c09
os_media_controls: 86dceab6245a5325af90fc0fdebe243c42d789b4
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880
+ SDWebImage: 16309af6d214ba3f77a7c6f6fdda888cb313a50a
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
+ sqlite3: 8d708bc63e9f4ce48f0ad9d6269e478c5ced1d9b
+ sqlite3_flutter_libs: d13b8b3003f18f596e542bcb9482d105577eff41
+ SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
+ wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556
+ workmanager_apple: 904529ae31e97fc5be632cf628507652294a0778
PODFILE CHECKSUM: 3c63482e143d1b91d2d2560aee9fb04ecc74ac7e
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index 9dab84dd..65cff4e7 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -496,6 +496,7 @@
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Plezy;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.entertainment";
+ IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -682,6 +683,7 @@
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Plezy;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.entertainment";
+ IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -708,6 +710,7 @@
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Plezy;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.entertainment";
+ IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 0fc3e407..1d395ccc 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -26,6 +26,8 @@
$(FLUTTER_BUILD_NUMBER)
LSRequiresIPhoneOS
+ LSSupportsOpeningDocumentsInPlace
+
NSAppTransportSecurity
NSAllowsArbitraryLoads
@@ -39,6 +41,8 @@
This app needs to connect to your Plex Media Server on your local network.
UIApplicationSupportsIndirectInputEvents
+ UIFileSharingEnabled
+
UILaunchStoryboardName
LaunchScreen
UIMainStoryboardFile
diff --git a/lib/database/app_database.dart b/lib/database/app_database.dart
new file mode 100644
index 00000000..1f247c53
--- /dev/null
+++ b/lib/database/app_database.dart
@@ -0,0 +1,208 @@
+import 'dart:io';
+import 'package:drift/drift.dart';
+import 'package:drift/native.dart';
+import 'package:path_provider/path_provider.dart';
+import 'package:path/path.dart' as p;
+
+import 'tables/downloaded_media.dart';
+import 'tables/download_queue.dart';
+import 'tables/api_cache.dart';
+import 'tables/offline_watch_progress.dart';
+import '../models/download_status.dart';
+import '../utils/app_logger.dart';
+
+part 'app_database.g.dart';
+
+// Simplified database with API cache for offline support
+@DriftDatabase(
+ tables: [DownloadedMedia, DownloadQueue, ApiCache, OfflineWatchProgress],
+)
+class AppDatabase extends _$AppDatabase {
+ AppDatabase() : super(_openConnection());
+
+ @override
+ int get schemaVersion => 7; // Added OfflineWatchProgress table
+
+ @override
+ MigrationStrategy get migration {
+ return MigrationStrategy(
+ onCreate: (Migrator m) async {
+ await m.createAll();
+ },
+ onUpgrade: (Migrator m, int from, int to) async {
+ // Additive migration for schema version 7
+ if (from < 7) {
+ appLogger.i('Adding OfflineWatchProgress table (v7 migration)');
+ await m.createTable(offlineWatchProgress);
+ }
+ },
+ );
+ }
+
+ // ============================================================
+ // Offline Watch Progress Operations
+ // ============================================================
+
+ /// Get all pending offline watch actions for sync
+ Future> getPendingWatchActions() {
+ return (select(
+ offlineWatchProgress,
+ )..orderBy([(t) => OrderingTerm.asc(t.createdAt)])).get();
+ }
+
+ /// Get pending watch actions for a specific server
+ Future> getPendingWatchActionsForServer(
+ String serverId,
+ ) {
+ return (select(offlineWatchProgress)
+ ..where((t) => t.serverId.equals(serverId))
+ ..orderBy([(t) => OrderingTerm.asc(t.createdAt)]))
+ .get();
+ }
+
+ /// Get the latest action for a specific item
+ Future getLatestWatchAction(String globalKey) {
+ return (select(offlineWatchProgress)
+ ..where((t) => t.globalKey.equals(globalKey))
+ ..orderBy([(t) => OrderingTerm.desc(t.updatedAt)])
+ ..limit(1))
+ .getSingleOrNull();
+ }
+
+ /// Insert or update a progress action (merges with existing)
+ Future upsertProgressAction({
+ required String serverId,
+ required String ratingKey,
+ required int viewOffset,
+ required int duration,
+ required bool shouldMarkWatched,
+ }) async {
+ final globalKey = '$serverId:$ratingKey';
+ final now = DateTime.now().millisecondsSinceEpoch;
+
+ // Check for existing progress entry
+ final existing =
+ await (select(offlineWatchProgress)
+ ..where(
+ (t) =>
+ t.globalKey.equals(globalKey) &
+ t.actionType.equals('progress'),
+ )
+ ..limit(1))
+ .getSingleOrNull();
+
+ if (existing != null) {
+ // Update existing progress entry
+ await (update(
+ offlineWatchProgress,
+ )..where((t) => t.id.equals(existing.id))).write(
+ OfflineWatchProgressCompanion(
+ viewOffset: Value(viewOffset),
+ duration: Value(duration),
+ shouldMarkWatched: Value(shouldMarkWatched),
+ updatedAt: Value(now),
+ ),
+ );
+ } else {
+ // Insert new progress entry
+ await into(offlineWatchProgress).insert(
+ OfflineWatchProgressCompanion.insert(
+ serverId: serverId,
+ ratingKey: ratingKey,
+ globalKey: globalKey,
+ actionType: 'progress',
+ viewOffset: Value(viewOffset),
+ duration: Value(duration),
+ shouldMarkWatched: Value(shouldMarkWatched),
+ createdAt: now,
+ updatedAt: now,
+ ),
+ );
+ }
+ }
+
+ /// Insert a manual watch action (watched or unwatched)
+ /// Removes conflicting actions for the same item
+ Future insertWatchAction({
+ required String serverId,
+ required String ratingKey,
+ required String actionType, // 'watched' or 'unwatched'
+ }) async {
+ final globalKey = '$serverId:$ratingKey';
+ final now = DateTime.now().millisecondsSinceEpoch;
+
+ // Remove conflicting actions (opposite action type and progress)
+ await (delete(
+ offlineWatchProgress,
+ )..where((t) => t.globalKey.equals(globalKey))).go();
+
+ // Insert the new action
+ await into(offlineWatchProgress).insert(
+ OfflineWatchProgressCompanion.insert(
+ serverId: serverId,
+ ratingKey: ratingKey,
+ globalKey: globalKey,
+ actionType: actionType,
+ createdAt: now,
+ updatedAt: now,
+ ),
+ );
+ }
+
+ /// Delete a specific watch action after successful sync
+ Future deleteWatchAction(int id) {
+ return (delete(offlineWatchProgress)..where((t) => t.id.equals(id))).go();
+ }
+
+ /// Update sync attempt count and error message
+ Future updateSyncAttempt(int id, String? errorMessage) async {
+ final existing = await (select(
+ offlineWatchProgress,
+ )..where((t) => t.id.equals(id))).getSingleOrNull();
+
+ if (existing != null) {
+ await (update(offlineWatchProgress)..where((t) => t.id.equals(id))).write(
+ OfflineWatchProgressCompanion(
+ syncAttempts: Value(existing.syncAttempts + 1),
+ lastError: Value(errorMessage),
+ ),
+ );
+ }
+ }
+
+ /// Get count of pending sync items
+ Future getPendingSyncCount() async {
+ final count =
+ await (selectOnly(offlineWatchProgress)
+ ..addColumns([offlineWatchProgress.id.count()]))
+ .map((row) => row.read(offlineWatchProgress.id.count()))
+ .getSingle();
+ return count ?? 0;
+ }
+
+ /// Clear all pending watch actions (e.g., after logout)
+ Future clearAllWatchActions() {
+ return delete(offlineWatchProgress).go();
+ }
+
+ // ============================================================
+ // Downloaded Media Queries for Watch State Sync
+ // ============================================================
+
+ /// Get all downloaded media items (for syncing watch states)
+ Future> getAllDownloadedMetadata() {
+ return (select(downloadedMedia)
+ ..where(
+ (t) => t.status.equals(DownloadStatus.completed.index),
+ ))
+ .get();
+ }
+}
+
+LazyDatabase _openConnection() {
+ return LazyDatabase(() async {
+ final dbFolder = await getApplicationDocumentsDirectory();
+ final file = File(p.join(dbFolder.path, 'plezy_downloads.db'));
+ return NativeDatabase(file);
+ });
+}
diff --git a/lib/database/app_database.g.dart b/lib/database/app_database.g.dart
new file mode 100644
index 00000000..db269630
--- /dev/null
+++ b/lib/database/app_database.g.dart
@@ -0,0 +1,3635 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'app_database.dart';
+
+// ignore_for_file: type=lint
+class $DownloadedMediaTable extends DownloadedMedia
+ with TableInfo<$DownloadedMediaTable, DownloadedMediaItem> {
+ @override
+ final GeneratedDatabase attachedDatabase;
+ final String? _alias;
+ $DownloadedMediaTable(this.attachedDatabase, [this._alias]);
+ static const VerificationMeta _idMeta = const VerificationMeta('id');
+ @override
+ late final GeneratedColumn id = GeneratedColumn(
+ 'id',
+ aliasedName,
+ false,
+ hasAutoIncrement: true,
+ type: DriftSqlType.int,
+ requiredDuringInsert: false,
+ defaultConstraints: GeneratedColumn.constraintIsAlways(
+ 'PRIMARY KEY AUTOINCREMENT',
+ ),
+ );
+ static const VerificationMeta _serverIdMeta = const VerificationMeta(
+ 'serverId',
+ );
+ @override
+ late final GeneratedColumn serverId = GeneratedColumn(
+ 'server_id',
+ aliasedName,
+ false,
+ type: DriftSqlType.string,
+ requiredDuringInsert: true,
+ );
+ static const VerificationMeta _ratingKeyMeta = const VerificationMeta(
+ 'ratingKey',
+ );
+ @override
+ late final GeneratedColumn ratingKey = GeneratedColumn(
+ 'rating_key',
+ aliasedName,
+ false,
+ type: DriftSqlType.string,
+ requiredDuringInsert: true,
+ );
+ static const VerificationMeta _globalKeyMeta = const VerificationMeta(
+ 'globalKey',
+ );
+ @override
+ late final GeneratedColumn globalKey = GeneratedColumn(
+ 'global_key',
+ aliasedName,
+ false,
+ type: DriftSqlType.string,
+ requiredDuringInsert: true,
+ defaultConstraints: GeneratedColumn.constraintIsAlways('UNIQUE'),
+ );
+ static const VerificationMeta _typeMeta = const VerificationMeta('type');
+ @override
+ late final GeneratedColumn type = GeneratedColumn(
+ 'type',
+ aliasedName,
+ false,
+ type: DriftSqlType.string,
+ requiredDuringInsert: true,
+ );
+ static const VerificationMeta _parentRatingKeyMeta = const VerificationMeta(
+ 'parentRatingKey',
+ );
+ @override
+ late final GeneratedColumn parentRatingKey = GeneratedColumn(
+ 'parent_rating_key',
+ aliasedName,
+ true,
+ type: DriftSqlType.string,
+ requiredDuringInsert: false,
+ );
+ static const VerificationMeta _grandparentRatingKeyMeta =
+ const VerificationMeta('grandparentRatingKey');
+ @override
+ late final GeneratedColumn grandparentRatingKey =
+ GeneratedColumn(
+ 'grandparent_rating_key',
+ aliasedName,
+ true,
+ type: DriftSqlType.string,
+ requiredDuringInsert: false,
+ );
+ static const VerificationMeta _statusMeta = const VerificationMeta('status');
+ @override
+ late final GeneratedColumn status = GeneratedColumn(
+ 'status',
+ aliasedName,
+ false,
+ type: DriftSqlType.int,
+ requiredDuringInsert: true,
+ );
+ static const VerificationMeta _progressMeta = const VerificationMeta(
+ 'progress',
+ );
+ @override
+ late final GeneratedColumn progress = GeneratedColumn(
+ 'progress',
+ aliasedName,
+ false,
+ type: DriftSqlType.int,
+ requiredDuringInsert: false,
+ defaultValue: const Constant(0),
+ );
+ static const VerificationMeta _totalBytesMeta = const VerificationMeta(
+ 'totalBytes',
+ );
+ @override
+ late final GeneratedColumn totalBytes = GeneratedColumn(
+ 'total_bytes',
+ aliasedName,
+ true,
+ type: DriftSqlType.int,
+ requiredDuringInsert: false,
+ );
+ static const VerificationMeta _downloadedBytesMeta = const VerificationMeta(
+ 'downloadedBytes',
+ );
+ @override
+ late final GeneratedColumn downloadedBytes = GeneratedColumn(
+ 'downloaded_bytes',
+ aliasedName,
+ false,
+ type: DriftSqlType.int,
+ requiredDuringInsert: false,
+ defaultValue: const Constant(0),
+ );
+ static const VerificationMeta _videoFilePathMeta = const VerificationMeta(
+ 'videoFilePath',
+ );
+ @override
+ late final GeneratedColumn videoFilePath = GeneratedColumn(
+ 'video_file_path',
+ aliasedName,
+ true,
+ type: DriftSqlType.string,
+ requiredDuringInsert: false,
+ );
+ static const VerificationMeta _thumbPathMeta = const VerificationMeta(
+ 'thumbPath',
+ );
+ @override
+ late final GeneratedColumn thumbPath = GeneratedColumn(
+ 'thumb_path',
+ aliasedName,
+ true,
+ type: DriftSqlType.string,
+ requiredDuringInsert: false,
+ );
+ static const VerificationMeta _downloadedAtMeta = const VerificationMeta(
+ 'downloadedAt',
+ );
+ @override
+ late final GeneratedColumn downloadedAt = GeneratedColumn(
+ 'downloaded_at',
+ aliasedName,
+ true,
+ type: DriftSqlType.int,
+ requiredDuringInsert: false,
+ );
+ static const VerificationMeta _errorMessageMeta = const VerificationMeta(
+ 'errorMessage',
+ );
+ @override
+ late final GeneratedColumn errorMessage = GeneratedColumn(
+ 'error_message',
+ aliasedName,
+ true,
+ type: DriftSqlType.string,
+ requiredDuringInsert: false,
+ );
+ static const VerificationMeta _retryCountMeta = const VerificationMeta(
+ 'retryCount',
+ );
+ @override
+ late final GeneratedColumn retryCount = GeneratedColumn(
+ 'retry_count',
+ aliasedName,
+ false,
+ type: DriftSqlType.int,
+ requiredDuringInsert: false,
+ defaultValue: const Constant(0),
+ );
+ @override
+ List get $columns => [
+ id,
+ serverId,
+ ratingKey,
+ globalKey,
+ type,
+ parentRatingKey,
+ grandparentRatingKey,
+ status,
+ progress,
+ totalBytes,
+ downloadedBytes,
+ videoFilePath,
+ thumbPath,
+ downloadedAt,
+ errorMessage,
+ retryCount,
+ ];
+ @override
+ String get aliasedName => _alias ?? actualTableName;
+ @override
+ String get actualTableName => $name;
+ static const String $name = 'downloaded_media';
+ @override
+ VerificationContext validateIntegrity(
+ Insertable instance, {
+ bool isInserting = false,
+ }) {
+ final context = VerificationContext();
+ final data = instance.toColumns(true);
+ if (data.containsKey('id')) {
+ context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
+ }
+ if (data.containsKey('server_id')) {
+ context.handle(
+ _serverIdMeta,
+ serverId.isAcceptableOrUnknown(data['server_id']!, _serverIdMeta),
+ );
+ } else if (isInserting) {
+ context.missing(_serverIdMeta);
+ }
+ if (data.containsKey('rating_key')) {
+ context.handle(
+ _ratingKeyMeta,
+ ratingKey.isAcceptableOrUnknown(data['rating_key']!, _ratingKeyMeta),
+ );
+ } else if (isInserting) {
+ context.missing(_ratingKeyMeta);
+ }
+ if (data.containsKey('global_key')) {
+ context.handle(
+ _globalKeyMeta,
+ globalKey.isAcceptableOrUnknown(data['global_key']!, _globalKeyMeta),
+ );
+ } else if (isInserting) {
+ context.missing(_globalKeyMeta);
+ }
+ if (data.containsKey('type')) {
+ context.handle(
+ _typeMeta,
+ type.isAcceptableOrUnknown(data['type']!, _typeMeta),
+ );
+ } else if (isInserting) {
+ context.missing(_typeMeta);
+ }
+ if (data.containsKey('parent_rating_key')) {
+ context.handle(
+ _parentRatingKeyMeta,
+ parentRatingKey.isAcceptableOrUnknown(
+ data['parent_rating_key']!,
+ _parentRatingKeyMeta,
+ ),
+ );
+ }
+ if (data.containsKey('grandparent_rating_key')) {
+ context.handle(
+ _grandparentRatingKeyMeta,
+ grandparentRatingKey.isAcceptableOrUnknown(
+ data['grandparent_rating_key']!,
+ _grandparentRatingKeyMeta,
+ ),
+ );
+ }
+ if (data.containsKey('status')) {
+ context.handle(
+ _statusMeta,
+ status.isAcceptableOrUnknown(data['status']!, _statusMeta),
+ );
+ } else if (isInserting) {
+ context.missing(_statusMeta);
+ }
+ if (data.containsKey('progress')) {
+ context.handle(
+ _progressMeta,
+ progress.isAcceptableOrUnknown(data['progress']!, _progressMeta),
+ );
+ }
+ if (data.containsKey('total_bytes')) {
+ context.handle(
+ _totalBytesMeta,
+ totalBytes.isAcceptableOrUnknown(data['total_bytes']!, _totalBytesMeta),
+ );
+ }
+ if (data.containsKey('downloaded_bytes')) {
+ context.handle(
+ _downloadedBytesMeta,
+ downloadedBytes.isAcceptableOrUnknown(
+ data['downloaded_bytes']!,
+ _downloadedBytesMeta,
+ ),
+ );
+ }
+ if (data.containsKey('video_file_path')) {
+ context.handle(
+ _videoFilePathMeta,
+ videoFilePath.isAcceptableOrUnknown(
+ data['video_file_path']!,
+ _videoFilePathMeta,
+ ),
+ );
+ }
+ if (data.containsKey('thumb_path')) {
+ context.handle(
+ _thumbPathMeta,
+ thumbPath.isAcceptableOrUnknown(data['thumb_path']!, _thumbPathMeta),
+ );
+ }
+ if (data.containsKey('downloaded_at')) {
+ context.handle(
+ _downloadedAtMeta,
+ downloadedAt.isAcceptableOrUnknown(
+ data['downloaded_at']!,
+ _downloadedAtMeta,
+ ),
+ );
+ }
+ if (data.containsKey('error_message')) {
+ context.handle(
+ _errorMessageMeta,
+ errorMessage.isAcceptableOrUnknown(
+ data['error_message']!,
+ _errorMessageMeta,
+ ),
+ );
+ }
+ if (data.containsKey('retry_count')) {
+ context.handle(
+ _retryCountMeta,
+ retryCount.isAcceptableOrUnknown(data['retry_count']!, _retryCountMeta),
+ );
+ }
+ return context;
+ }
+
+ @override
+ Set get $primaryKey => {id};
+ @override
+ DownloadedMediaItem map(Map data, {String? tablePrefix}) {
+ final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
+ return DownloadedMediaItem(
+ id: attachedDatabase.typeMapping.read(
+ DriftSqlType.int,
+ data['${effectivePrefix}id'],
+ )!,
+ serverId: attachedDatabase.typeMapping.read(
+ DriftSqlType.string,
+ data['${effectivePrefix}server_id'],
+ )!,
+ ratingKey: attachedDatabase.typeMapping.read(
+ DriftSqlType.string,
+ data['${effectivePrefix}rating_key'],
+ )!,
+ globalKey: attachedDatabase.typeMapping.read(
+ DriftSqlType.string,
+ data['${effectivePrefix}global_key'],
+ )!,
+ type: attachedDatabase.typeMapping.read(
+ DriftSqlType.string,
+ data['${effectivePrefix}type'],
+ )!,
+ parentRatingKey: attachedDatabase.typeMapping.read(
+ DriftSqlType.string,
+ data['${effectivePrefix}parent_rating_key'],
+ ),
+ grandparentRatingKey: attachedDatabase.typeMapping.read(
+ DriftSqlType.string,
+ data['${effectivePrefix}grandparent_rating_key'],
+ ),
+ status: attachedDatabase.typeMapping.read(
+ DriftSqlType.int,
+ data['${effectivePrefix}status'],
+ )!,
+ progress: attachedDatabase.typeMapping.read(
+ DriftSqlType.int,
+ data['${effectivePrefix}progress'],
+ )!,
+ totalBytes: attachedDatabase.typeMapping.read(
+ DriftSqlType.int,
+ data['${effectivePrefix}total_bytes'],
+ ),
+ downloadedBytes: attachedDatabase.typeMapping.read(
+ DriftSqlType.int,
+ data['${effectivePrefix}downloaded_bytes'],
+ )!,
+ videoFilePath: attachedDatabase.typeMapping.read(
+ DriftSqlType.string,
+ data['${effectivePrefix}video_file_path'],
+ ),
+ thumbPath: attachedDatabase.typeMapping.read(
+ DriftSqlType.string,
+ data['${effectivePrefix}thumb_path'],
+ ),
+ downloadedAt: attachedDatabase.typeMapping.read(
+ DriftSqlType.int,
+ data['${effectivePrefix}downloaded_at'],
+ ),
+ errorMessage: attachedDatabase.typeMapping.read(
+ DriftSqlType.string,
+ data['${effectivePrefix}error_message'],
+ ),
+ retryCount: attachedDatabase.typeMapping.read(
+ DriftSqlType.int,
+ data['${effectivePrefix}retry_count'],
+ )!,
+ );
+ }
+
+ @override
+ $DownloadedMediaTable createAlias(String alias) {
+ return $DownloadedMediaTable(attachedDatabase, alias);
+ }
+}
+
+class DownloadedMediaItem extends DataClass
+ implements Insertable {
+ final int id;
+ final String serverId;
+ final String ratingKey;
+ final String globalKey;
+ final String type;
+ final String? parentRatingKey;
+ final String? grandparentRatingKey;
+ final int status;
+ final int progress;
+ final int? totalBytes;
+ final int downloadedBytes;
+ final String? videoFilePath;
+ final String? thumbPath;
+ final int? downloadedAt;
+ final String? errorMessage;
+ final int retryCount;
+ const DownloadedMediaItem({
+ required this.id,
+ required this.serverId,
+ required this.ratingKey,
+ required this.globalKey,
+ required this.type,
+ this.parentRatingKey,
+ this.grandparentRatingKey,
+ required this.status,
+ required this.progress,
+ this.totalBytes,
+ required this.downloadedBytes,
+ this.videoFilePath,
+ this.thumbPath,
+ this.downloadedAt,
+ this.errorMessage,
+ required this.retryCount,
+ });
+ @override
+ Map toColumns(bool nullToAbsent) {
+ final map = {};
+ map['id'] = Variable(id);
+ map['server_id'] = Variable(serverId);
+ map['rating_key'] = Variable(ratingKey);
+ map['global_key'] = Variable(globalKey);
+ map['type'] = Variable(type);
+ if (!nullToAbsent || parentRatingKey != null) {
+ map['parent_rating_key'] = Variable(parentRatingKey);
+ }
+ if (!nullToAbsent || grandparentRatingKey != null) {
+ map['grandparent_rating_key'] = Variable(grandparentRatingKey);
+ }
+ map['status'] = Variable(status);
+ map['progress'] = Variable(progress);
+ if (!nullToAbsent || totalBytes != null) {
+ map['total_bytes'] = Variable(totalBytes);
+ }
+ map['downloaded_bytes'] = Variable(downloadedBytes);
+ if (!nullToAbsent || videoFilePath != null) {
+ map['video_file_path'] = Variable(videoFilePath);
+ }
+ if (!nullToAbsent || thumbPath != null) {
+ map['thumb_path'] = Variable(thumbPath);
+ }
+ if (!nullToAbsent || downloadedAt != null) {
+ map['downloaded_at'] = Variable(downloadedAt);
+ }
+ if (!nullToAbsent || errorMessage != null) {
+ map['error_message'] = Variable(errorMessage);
+ }
+ map['retry_count'] = Variable(retryCount);
+ return map;
+ }
+
+ DownloadedMediaCompanion toCompanion(bool nullToAbsent) {
+ return DownloadedMediaCompanion(
+ id: Value(id),
+ serverId: Value(serverId),
+ ratingKey: Value(ratingKey),
+ globalKey: Value(globalKey),
+ type: Value(type),
+ parentRatingKey: parentRatingKey == null && nullToAbsent
+ ? const Value.absent()
+ : Value(parentRatingKey),
+ grandparentRatingKey: grandparentRatingKey == null && nullToAbsent
+ ? const Value.absent()
+ : Value(grandparentRatingKey),
+ status: Value(status),
+ progress: Value(progress),
+ totalBytes: totalBytes == null && nullToAbsent
+ ? const Value.absent()
+ : Value(totalBytes),
+ downloadedBytes: Value(downloadedBytes),
+ videoFilePath: videoFilePath == null && nullToAbsent
+ ? const Value.absent()
+ : Value(videoFilePath),
+ thumbPath: thumbPath == null && nullToAbsent
+ ? const Value.absent()
+ : Value(thumbPath),
+ downloadedAt: downloadedAt == null && nullToAbsent
+ ? const Value.absent()
+ : Value(downloadedAt),
+ errorMessage: errorMessage == null && nullToAbsent
+ ? const Value.absent()
+ : Value(errorMessage),
+ retryCount: Value(retryCount),
+ );
+ }
+
+ factory DownloadedMediaItem.fromJson(
+ Map json, {
+ ValueSerializer? serializer,
+ }) {
+ serializer ??= driftRuntimeOptions.defaultSerializer;
+ return DownloadedMediaItem(
+ id: serializer.fromJson(json['id']),
+ serverId: serializer.fromJson(json['serverId']),
+ ratingKey: serializer.fromJson(json['ratingKey']),
+ globalKey: serializer.fromJson(json['globalKey']),
+ type: serializer.fromJson(json['type']),
+ parentRatingKey: serializer.fromJson(json['parentRatingKey']),
+ grandparentRatingKey: serializer.fromJson(
+ json['grandparentRatingKey'],
+ ),
+ status: serializer.fromJson(json['status']),
+ progress: serializer.fromJson(json['progress']),
+ totalBytes: serializer.fromJson(json['totalBytes']),
+ downloadedBytes: serializer.fromJson(json['downloadedBytes']),
+ videoFilePath: serializer.fromJson(json['videoFilePath']),
+ thumbPath: serializer.fromJson(json['thumbPath']),
+ downloadedAt: serializer.fromJson(json['downloadedAt']),
+ errorMessage: serializer.fromJson(json['errorMessage']),
+ retryCount: serializer.fromJson(json['retryCount']),
+ );
+ }
+ @override
+ Map toJson({ValueSerializer? serializer}) {
+ serializer ??= driftRuntimeOptions.defaultSerializer;
+ return {
+ 'id': serializer.toJson(id),
+ 'serverId': serializer.toJson(serverId),
+ 'ratingKey': serializer.toJson(ratingKey),
+ 'globalKey': serializer.toJson(globalKey),
+ 'type': serializer.toJson(type),
+ 'parentRatingKey': serializer.toJson(parentRatingKey),
+ 'grandparentRatingKey': serializer.toJson(grandparentRatingKey),
+ 'status': serializer.toJson(status),
+ 'progress': serializer.toJson(progress),
+ 'totalBytes': serializer.toJson(totalBytes),
+ 'downloadedBytes': serializer.toJson(downloadedBytes),
+ 'videoFilePath': serializer.toJson(videoFilePath),
+ 'thumbPath': serializer.toJson(thumbPath),
+ 'downloadedAt': serializer.toJson(downloadedAt),
+ 'errorMessage': serializer.toJson(errorMessage),
+ 'retryCount': serializer.toJson(retryCount),
+ };
+ }
+
+ DownloadedMediaItem copyWith({
+ int? id,
+ String? serverId,
+ String? ratingKey,
+ String? globalKey,
+ String? type,
+ Value parentRatingKey = const Value.absent(),
+ Value grandparentRatingKey = const Value.absent(),
+ int? status,
+ int? progress,
+ Value totalBytes = const Value.absent(),
+ int? downloadedBytes,
+ Value videoFilePath = const Value.absent(),
+ Value thumbPath = const Value.absent(),
+ Value downloadedAt = const Value.absent(),
+ Value errorMessage = const Value.absent(),
+ int? retryCount,
+ }) => DownloadedMediaItem(
+ id: id ?? this.id,
+ serverId: serverId ?? this.serverId,
+ ratingKey: ratingKey ?? this.ratingKey,
+ globalKey: globalKey ?? this.globalKey,
+ type: type ?? this.type,
+ parentRatingKey: parentRatingKey.present
+ ? parentRatingKey.value
+ : this.parentRatingKey,
+ grandparentRatingKey: grandparentRatingKey.present
+ ? grandparentRatingKey.value
+ : this.grandparentRatingKey,
+ status: status ?? this.status,
+ progress: progress ?? this.progress,
+ totalBytes: totalBytes.present ? totalBytes.value : this.totalBytes,
+ downloadedBytes: downloadedBytes ?? this.downloadedBytes,
+ videoFilePath: videoFilePath.present
+ ? videoFilePath.value
+ : this.videoFilePath,
+ thumbPath: thumbPath.present ? thumbPath.value : this.thumbPath,
+ downloadedAt: downloadedAt.present ? downloadedAt.value : this.downloadedAt,
+ errorMessage: errorMessage.present ? errorMessage.value : this.errorMessage,
+ retryCount: retryCount ?? this.retryCount,
+ );
+ DownloadedMediaItem copyWithCompanion(DownloadedMediaCompanion data) {
+ return DownloadedMediaItem(
+ id: data.id.present ? data.id.value : this.id,
+ serverId: data.serverId.present ? data.serverId.value : this.serverId,
+ ratingKey: data.ratingKey.present ? data.ratingKey.value : this.ratingKey,
+ globalKey: data.globalKey.present ? data.globalKey.value : this.globalKey,
+ type: data.type.present ? data.type.value : this.type,
+ parentRatingKey: data.parentRatingKey.present
+ ? data.parentRatingKey.value
+ : this.parentRatingKey,
+ grandparentRatingKey: data.grandparentRatingKey.present
+ ? data.grandparentRatingKey.value
+ : this.grandparentRatingKey,
+ status: data.status.present ? data.status.value : this.status,
+ progress: data.progress.present ? data.progress.value : this.progress,
+ totalBytes: data.totalBytes.present
+ ? data.totalBytes.value
+ : this.totalBytes,
+ downloadedBytes: data.downloadedBytes.present
+ ? data.downloadedBytes.value
+ : this.downloadedBytes,
+ videoFilePath: data.videoFilePath.present
+ ? data.videoFilePath.value
+ : this.videoFilePath,
+ thumbPath: data.thumbPath.present ? data.thumbPath.value : this.thumbPath,
+ downloadedAt: data.downloadedAt.present
+ ? data.downloadedAt.value
+ : this.downloadedAt,
+ errorMessage: data.errorMessage.present
+ ? data.errorMessage.value
+ : this.errorMessage,
+ retryCount: data.retryCount.present
+ ? data.retryCount.value
+ : this.retryCount,
+ );
+ }
+
+ @override
+ String toString() {
+ return (StringBuffer('DownloadedMediaItem(')
+ ..write('id: $id, ')
+ ..write('serverId: $serverId, ')
+ ..write('ratingKey: $ratingKey, ')
+ ..write('globalKey: $globalKey, ')
+ ..write('type: $type, ')
+ ..write('parentRatingKey: $parentRatingKey, ')
+ ..write('grandparentRatingKey: $grandparentRatingKey, ')
+ ..write('status: $status, ')
+ ..write('progress: $progress, ')
+ ..write('totalBytes: $totalBytes, ')
+ ..write('downloadedBytes: $downloadedBytes, ')
+ ..write('videoFilePath: $videoFilePath, ')
+ ..write('thumbPath: $thumbPath, ')
+ ..write('downloadedAt: $downloadedAt, ')
+ ..write('errorMessage: $errorMessage, ')
+ ..write('retryCount: $retryCount')
+ ..write(')'))
+ .toString();
+ }
+
+ @override
+ int get hashCode => Object.hash(
+ id,
+ serverId,
+ ratingKey,
+ globalKey,
+ type,
+ parentRatingKey,
+ grandparentRatingKey,
+ status,
+ progress,
+ totalBytes,
+ downloadedBytes,
+ videoFilePath,
+ thumbPath,
+ downloadedAt,
+ errorMessage,
+ retryCount,
+ );
+ @override
+ bool operator ==(Object other) =>
+ identical(this, other) ||
+ (other is DownloadedMediaItem &&
+ other.id == this.id &&
+ other.serverId == this.serverId &&
+ other.ratingKey == this.ratingKey &&
+ other.globalKey == this.globalKey &&
+ other.type == this.type &&
+ other.parentRatingKey == this.parentRatingKey &&
+ other.grandparentRatingKey == this.grandparentRatingKey &&
+ other.status == this.status &&
+ other.progress == this.progress &&
+ other.totalBytes == this.totalBytes &&
+ other.downloadedBytes == this.downloadedBytes &&
+ other.videoFilePath == this.videoFilePath &&
+ other.thumbPath == this.thumbPath &&
+ other.downloadedAt == this.downloadedAt &&
+ other.errorMessage == this.errorMessage &&
+ other.retryCount == this.retryCount);
+}
+
+class DownloadedMediaCompanion extends UpdateCompanion {
+ final Value id;
+ final Value serverId;
+ final Value ratingKey;
+ final Value globalKey;
+ final Value type;
+ final Value parentRatingKey;
+ final Value grandparentRatingKey;
+ final Value status;
+ final Value progress;
+ final Value totalBytes;
+ final Value downloadedBytes;
+ final Value videoFilePath;
+ final Value thumbPath;
+ final Value downloadedAt;
+ final Value errorMessage;
+ final Value retryCount;
+ const DownloadedMediaCompanion({
+ this.id = const Value.absent(),
+ this.serverId = const Value.absent(),
+ this.ratingKey = const Value.absent(),
+ this.globalKey = const Value.absent(),
+ this.type = const Value.absent(),
+ this.parentRatingKey = const Value.absent(),
+ this.grandparentRatingKey = const Value.absent(),
+ this.status = const Value.absent(),
+ this.progress = const Value.absent(),
+ this.totalBytes = const Value.absent(),
+ this.downloadedBytes = const Value.absent(),
+ this.videoFilePath = const Value.absent(),
+ this.thumbPath = const Value.absent(),
+ this.downloadedAt = const Value.absent(),
+ this.errorMessage = const Value.absent(),
+ this.retryCount = const Value.absent(),
+ });
+ DownloadedMediaCompanion.insert({
+ this.id = const Value.absent(),
+ required String serverId,
+ required String ratingKey,
+ required String globalKey,
+ required String type,
+ this.parentRatingKey = const Value.absent(),
+ this.grandparentRatingKey = const Value.absent(),
+ required int status,
+ this.progress = const Value.absent(),
+ this.totalBytes = const Value.absent(),
+ this.downloadedBytes = const Value.absent(),
+ this.videoFilePath = const Value.absent(),
+ this.thumbPath = const Value.absent(),
+ this.downloadedAt = const Value.absent(),
+ this.errorMessage = const Value.absent(),
+ this.retryCount = const Value.absent(),
+ }) : serverId = Value(serverId),
+ ratingKey = Value(ratingKey),
+ globalKey = Value(globalKey),
+ type = Value(type),
+ status = Value(status);
+ static Insertable custom({
+ Expression? id,
+ Expression? serverId,
+ Expression? ratingKey,
+ Expression? globalKey,
+ Expression? type,
+ Expression? parentRatingKey,
+ Expression? grandparentRatingKey,
+ Expression? status,
+ Expression? progress,
+ Expression? totalBytes,
+ Expression? downloadedBytes,
+ Expression? videoFilePath,
+ Expression? thumbPath,
+ Expression? downloadedAt,
+ Expression? errorMessage,
+ Expression? retryCount,
+ }) {
+ return RawValuesInsertable({
+ if (id != null) 'id': id,
+ if (serverId != null) 'server_id': serverId,
+ if (ratingKey != null) 'rating_key': ratingKey,
+ if (globalKey != null) 'global_key': globalKey,
+ if (type != null) 'type': type,
+ if (parentRatingKey != null) 'parent_rating_key': parentRatingKey,
+ if (grandparentRatingKey != null)
+ 'grandparent_rating_key': grandparentRatingKey,
+ if (status != null) 'status': status,
+ if (progress != null) 'progress': progress,
+ if (totalBytes != null) 'total_bytes': totalBytes,
+ if (downloadedBytes != null) 'downloaded_bytes': downloadedBytes,
+ if (videoFilePath != null) 'video_file_path': videoFilePath,
+ if (thumbPath != null) 'thumb_path': thumbPath,
+ if (downloadedAt != null) 'downloaded_at': downloadedAt,
+ if (errorMessage != null) 'error_message': errorMessage,
+ if (retryCount != null) 'retry_count': retryCount,
+ });
+ }
+
+ DownloadedMediaCompanion copyWith({
+ Value? id,
+ Value? serverId,
+ Value? ratingKey,
+ Value? globalKey,
+ Value? type,
+ Value? parentRatingKey,
+ Value? grandparentRatingKey,
+ Value? status,
+ Value? progress,
+ Value? totalBytes,
+ Value? downloadedBytes,
+ Value? videoFilePath,
+ Value? thumbPath,
+ Value? downloadedAt,
+ Value? errorMessage,
+ Value? retryCount,
+ }) {
+ return DownloadedMediaCompanion(
+ id: id ?? this.id,
+ serverId: serverId ?? this.serverId,
+ ratingKey: ratingKey ?? this.ratingKey,
+ globalKey: globalKey ?? this.globalKey,
+ type: type ?? this.type,
+ parentRatingKey: parentRatingKey ?? this.parentRatingKey,
+ grandparentRatingKey: grandparentRatingKey ?? this.grandparentRatingKey,
+ status: status ?? this.status,
+ progress: progress ?? this.progress,
+ totalBytes: totalBytes ?? this.totalBytes,
+ downloadedBytes: downloadedBytes ?? this.downloadedBytes,
+ videoFilePath: videoFilePath ?? this.videoFilePath,
+ thumbPath: thumbPath ?? this.thumbPath,
+ downloadedAt: downloadedAt ?? this.downloadedAt,
+ errorMessage: errorMessage ?? this.errorMessage,
+ retryCount: retryCount ?? this.retryCount,
+ );
+ }
+
+ @override
+ Map toColumns(bool nullToAbsent) {
+ final map = {};
+ if (id.present) {
+ map['id'] = Variable(id.value);
+ }
+ if (serverId.present) {
+ map['server_id'] = Variable(serverId.value);
+ }
+ if (ratingKey.present) {
+ map['rating_key'] = Variable(ratingKey.value);
+ }
+ if (globalKey.present) {
+ map['global_key'] = Variable(globalKey.value);
+ }
+ if (type.present) {
+ map['type'] = Variable(type.value);
+ }
+ if (parentRatingKey.present) {
+ map['parent_rating_key'] = Variable(parentRatingKey.value);
+ }
+ if (grandparentRatingKey.present) {
+ map['grandparent_rating_key'] = Variable(
+ grandparentRatingKey.value,
+ );
+ }
+ if (status.present) {
+ map['status'] = Variable(status.value);
+ }
+ if (progress.present) {
+ map['progress'] = Variable(progress.value);
+ }
+ if (totalBytes.present) {
+ map['total_bytes'] = Variable(totalBytes.value);
+ }
+ if (downloadedBytes.present) {
+ map['downloaded_bytes'] = Variable(downloadedBytes.value);
+ }
+ if (videoFilePath.present) {
+ map['video_file_path'] = Variable(videoFilePath.value);
+ }
+ if (thumbPath.present) {
+ map['thumb_path'] = Variable(thumbPath.value);
+ }
+ if (downloadedAt.present) {
+ map['downloaded_at'] = Variable(downloadedAt.value);
+ }
+ if (errorMessage.present) {
+ map['error_message'] = Variable(errorMessage.value);
+ }
+ if (retryCount.present) {
+ map['retry_count'] = Variable(retryCount.value);
+ }
+ return map;
+ }
+
+ @override
+ String toString() {
+ return (StringBuffer('DownloadedMediaCompanion(')
+ ..write('id: $id, ')
+ ..write('serverId: $serverId, ')
+ ..write('ratingKey: $ratingKey, ')
+ ..write('globalKey: $globalKey, ')
+ ..write('type: $type, ')
+ ..write('parentRatingKey: $parentRatingKey, ')
+ ..write('grandparentRatingKey: $grandparentRatingKey, ')
+ ..write('status: $status, ')
+ ..write('progress: $progress, ')
+ ..write('totalBytes: $totalBytes, ')
+ ..write('downloadedBytes: $downloadedBytes, ')
+ ..write('videoFilePath: $videoFilePath, ')
+ ..write('thumbPath: $thumbPath, ')
+ ..write('downloadedAt: $downloadedAt, ')
+ ..write('errorMessage: $errorMessage, ')
+ ..write('retryCount: $retryCount')
+ ..write(')'))
+ .toString();
+ }
+}
+
+class $DownloadQueueTable extends DownloadQueue
+ with TableInfo<$DownloadQueueTable, DownloadQueueItem> {
+ @override
+ final GeneratedDatabase attachedDatabase;
+ final String? _alias;
+ $DownloadQueueTable(this.attachedDatabase, [this._alias]);
+ static const VerificationMeta _idMeta = const VerificationMeta('id');
+ @override
+ late final GeneratedColumn id = GeneratedColumn(
+ 'id',
+ aliasedName,
+ false,
+ hasAutoIncrement: true,
+ type: DriftSqlType.int,
+ requiredDuringInsert: false,
+ defaultConstraints: GeneratedColumn.constraintIsAlways(
+ 'PRIMARY KEY AUTOINCREMENT',
+ ),
+ );
+ static const VerificationMeta _mediaGlobalKeyMeta = const VerificationMeta(
+ 'mediaGlobalKey',
+ );
+ @override
+ late final GeneratedColumn mediaGlobalKey = GeneratedColumn(
+ 'media_global_key',
+ aliasedName,
+ false,
+ type: DriftSqlType.string,
+ requiredDuringInsert: true,
+ defaultConstraints: GeneratedColumn.constraintIsAlways('UNIQUE'),
+ );
+ static const VerificationMeta _priorityMeta = const VerificationMeta(
+ 'priority',
+ );
+ @override
+ late final GeneratedColumn priority = GeneratedColumn(
+ 'priority',
+ aliasedName,
+ false,
+ type: DriftSqlType.int,
+ requiredDuringInsert: false,
+ defaultValue: const Constant(0),
+ );
+ static const VerificationMeta _addedAtMeta = const VerificationMeta(
+ 'addedAt',
+ );
+ @override
+ late final GeneratedColumn addedAt = GeneratedColumn(
+ 'added_at',
+ aliasedName,
+ false,
+ type: DriftSqlType.int,
+ requiredDuringInsert: true,
+ );
+ static const VerificationMeta _downloadSubtitlesMeta = const VerificationMeta(
+ 'downloadSubtitles',
+ );
+ @override
+ late final GeneratedColumn downloadSubtitles = GeneratedColumn(
+ 'download_subtitles',
+ aliasedName,
+ false,
+ type: DriftSqlType.bool,
+ requiredDuringInsert: false,
+ defaultConstraints: GeneratedColumn.constraintIsAlways(
+ 'CHECK ("download_subtitles" IN (0, 1))',
+ ),
+ defaultValue: const Constant(true),
+ );
+ static const VerificationMeta _downloadArtworkMeta = const VerificationMeta(
+ 'downloadArtwork',
+ );
+ @override
+ late final GeneratedColumn downloadArtwork = GeneratedColumn(
+ 'download_artwork',
+ aliasedName,
+ false,
+ type: DriftSqlType.bool,
+ requiredDuringInsert: false,
+ defaultConstraints: GeneratedColumn.constraintIsAlways(
+ 'CHECK ("download_artwork" IN (0, 1))',
+ ),
+ defaultValue: const Constant(true),
+ );
+ @override
+ List get $columns => [
+ id,
+ mediaGlobalKey,
+ priority,
+ addedAt,
+ downloadSubtitles,
+ downloadArtwork,
+ ];
+ @override
+ String get aliasedName => _alias ?? actualTableName;
+ @override
+ String get actualTableName => $name;
+ static const String $name = 'download_queue';
+ @override
+ VerificationContext validateIntegrity(
+ Insertable instance, {
+ bool isInserting = false,
+ }) {
+ final context = VerificationContext();
+ final data = instance.toColumns(true);
+ if (data.containsKey('id')) {
+ context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
+ }
+ if (data.containsKey('media_global_key')) {
+ context.handle(
+ _mediaGlobalKeyMeta,
+ mediaGlobalKey.isAcceptableOrUnknown(
+ data['media_global_key']!,
+ _mediaGlobalKeyMeta,
+ ),
+ );
+ } else if (isInserting) {
+ context.missing(_mediaGlobalKeyMeta);
+ }
+ if (data.containsKey('priority')) {
+ context.handle(
+ _priorityMeta,
+ priority.isAcceptableOrUnknown(data['priority']!, _priorityMeta),
+ );
+ }
+ if (data.containsKey('added_at')) {
+ context.handle(
+ _addedAtMeta,
+ addedAt.isAcceptableOrUnknown(data['added_at']!, _addedAtMeta),
+ );
+ } else if (isInserting) {
+ context.missing(_addedAtMeta);
+ }
+ if (data.containsKey('download_subtitles')) {
+ context.handle(
+ _downloadSubtitlesMeta,
+ downloadSubtitles.isAcceptableOrUnknown(
+ data['download_subtitles']!,
+ _downloadSubtitlesMeta,
+ ),
+ );
+ }
+ if (data.containsKey('download_artwork')) {
+ context.handle(
+ _downloadArtworkMeta,
+ downloadArtwork.isAcceptableOrUnknown(
+ data['download_artwork']!,
+ _downloadArtworkMeta,
+ ),
+ );
+ }
+ return context;
+ }
+
+ @override
+ Set get $primaryKey => {id};
+ @override
+ DownloadQueueItem map(Map data, {String? tablePrefix}) {
+ final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
+ return DownloadQueueItem(
+ id: attachedDatabase.typeMapping.read(
+ DriftSqlType.int,
+ data['${effectivePrefix}id'],
+ )!,
+ mediaGlobalKey: attachedDatabase.typeMapping.read(
+ DriftSqlType.string,
+ data['${effectivePrefix}media_global_key'],
+ )!,
+ priority: attachedDatabase.typeMapping.read(
+ DriftSqlType.int,
+ data['${effectivePrefix}priority'],
+ )!,
+ addedAt: attachedDatabase.typeMapping.read(
+ DriftSqlType.int,
+ data['${effectivePrefix}added_at'],
+ )!,
+ downloadSubtitles: attachedDatabase.typeMapping.read(
+ DriftSqlType.bool,
+ data['${effectivePrefix}download_subtitles'],
+ )!,
+ downloadArtwork: attachedDatabase.typeMapping.read(
+ DriftSqlType.bool,
+ data['${effectivePrefix}download_artwork'],
+ )!,
+ );
+ }
+
+ @override
+ $DownloadQueueTable createAlias(String alias) {
+ return $DownloadQueueTable(attachedDatabase, alias);
+ }
+}
+
+class DownloadQueueItem extends DataClass
+ implements Insertable {
+ final int id;
+ final String mediaGlobalKey;
+ final int priority;
+ final int addedAt;
+ final bool downloadSubtitles;
+ final bool downloadArtwork;
+ const DownloadQueueItem({
+ required this.id,
+ required this.mediaGlobalKey,
+ required this.priority,
+ required this.addedAt,
+ required this.downloadSubtitles,
+ required this.downloadArtwork,
+ });
+ @override
+ Map toColumns(bool nullToAbsent) {
+ final map = {};
+ map['id'] = Variable(id);
+ map['media_global_key'] = Variable(mediaGlobalKey);
+ map['priority'] = Variable(priority);
+ map['added_at'] = Variable(addedAt);
+ map['download_subtitles'] = Variable(downloadSubtitles);
+ map['download_artwork'] = Variable(downloadArtwork);
+ return map;
+ }
+
+ DownloadQueueCompanion toCompanion(bool nullToAbsent) {
+ return DownloadQueueCompanion(
+ id: Value(id),
+ mediaGlobalKey: Value(mediaGlobalKey),
+ priority: Value(priority),
+ addedAt: Value(addedAt),
+ downloadSubtitles: Value(downloadSubtitles),
+ downloadArtwork: Value(downloadArtwork),
+ );
+ }
+
+ factory DownloadQueueItem.fromJson(
+ Map json, {
+ ValueSerializer? serializer,
+ }) {
+ serializer ??= driftRuntimeOptions.defaultSerializer;
+ return DownloadQueueItem(
+ id: serializer.fromJson(json['id']),
+ mediaGlobalKey: serializer.fromJson(json['mediaGlobalKey']),
+ priority: serializer.fromJson(json['priority']),
+ addedAt: serializer.fromJson(json['addedAt']),
+ downloadSubtitles: serializer.fromJson(json['downloadSubtitles']),
+ downloadArtwork: serializer.fromJson(json['downloadArtwork']),
+ );
+ }
+ @override
+ Map toJson({ValueSerializer? serializer}) {
+ serializer ??= driftRuntimeOptions.defaultSerializer;
+ return {
+ 'id': serializer.toJson(id),
+ 'mediaGlobalKey': serializer.toJson(mediaGlobalKey),
+ 'priority': serializer.toJson(priority),
+ 'addedAt': serializer.toJson(addedAt),
+ 'downloadSubtitles': serializer.toJson(downloadSubtitles),
+ 'downloadArtwork': serializer.toJson(downloadArtwork),
+ };
+ }
+
+ DownloadQueueItem copyWith({
+ int? id,
+ String? mediaGlobalKey,
+ int? priority,
+ int? addedAt,
+ bool? downloadSubtitles,
+ bool? downloadArtwork,
+ }) => DownloadQueueItem(
+ id: id ?? this.id,
+ mediaGlobalKey: mediaGlobalKey ?? this.mediaGlobalKey,
+ priority: priority ?? this.priority,
+ addedAt: addedAt ?? this.addedAt,
+ downloadSubtitles: downloadSubtitles ?? this.downloadSubtitles,
+ downloadArtwork: downloadArtwork ?? this.downloadArtwork,
+ );
+ DownloadQueueItem copyWithCompanion(DownloadQueueCompanion data) {
+ return DownloadQueueItem(
+ id: data.id.present ? data.id.value : this.id,
+ mediaGlobalKey: data.mediaGlobalKey.present
+ ? data.mediaGlobalKey.value
+ : this.mediaGlobalKey,
+ priority: data.priority.present ? data.priority.value : this.priority,
+ addedAt: data.addedAt.present ? data.addedAt.value : this.addedAt,
+ downloadSubtitles: data.downloadSubtitles.present
+ ? data.downloadSubtitles.value
+ : this.downloadSubtitles,
+ downloadArtwork: data.downloadArtwork.present
+ ? data.downloadArtwork.value
+ : this.downloadArtwork,
+ );
+ }
+
+ @override
+ String toString() {
+ return (StringBuffer('DownloadQueueItem(')
+ ..write('id: $id, ')
+ ..write('mediaGlobalKey: $mediaGlobalKey, ')
+ ..write('priority: $priority, ')
+ ..write('addedAt: $addedAt, ')
+ ..write('downloadSubtitles: $downloadSubtitles, ')
+ ..write('downloadArtwork: $downloadArtwork')
+ ..write(')'))
+ .toString();
+ }
+
+ @override
+ int get hashCode => Object.hash(
+ id,
+ mediaGlobalKey,
+ priority,
+ addedAt,
+ downloadSubtitles,
+ downloadArtwork,
+ );
+ @override
+ bool operator ==(Object other) =>
+ identical(this, other) ||
+ (other is DownloadQueueItem &&
+ other.id == this.id &&
+ other.mediaGlobalKey == this.mediaGlobalKey &&
+ other.priority == this.priority &&
+ other.addedAt == this.addedAt &&
+ other.downloadSubtitles == this.downloadSubtitles &&
+ other.downloadArtwork == this.downloadArtwork);
+}
+
+class DownloadQueueCompanion extends UpdateCompanion {
+ final Value id;
+ final Value mediaGlobalKey;
+ final Value priority;
+ final Value addedAt;
+ final Value downloadSubtitles;
+ final Value downloadArtwork;
+ const DownloadQueueCompanion({
+ this.id = const Value.absent(),
+ this.mediaGlobalKey = const Value.absent(),
+ this.priority = const Value.absent(),
+ this.addedAt = const Value.absent(),
+ this.downloadSubtitles = const Value.absent(),
+ this.downloadArtwork = const Value.absent(),
+ });
+ DownloadQueueCompanion.insert({
+ this.id = const Value.absent(),
+ required String mediaGlobalKey,
+ this.priority = const Value.absent(),
+ required int addedAt,
+ this.downloadSubtitles = const Value.absent(),
+ this.downloadArtwork = const Value.absent(),
+ }) : mediaGlobalKey = Value(mediaGlobalKey),
+ addedAt = Value(addedAt);
+ static Insertable custom({
+ Expression? id,
+ Expression? mediaGlobalKey,
+ Expression? priority,
+ Expression? addedAt,
+ Expression? downloadSubtitles,
+ Expression? downloadArtwork,
+ }) {
+ return RawValuesInsertable({
+ if (id != null) 'id': id,
+ if (mediaGlobalKey != null) 'media_global_key': mediaGlobalKey,
+ if (priority != null) 'priority': priority,
+ if (addedAt != null) 'added_at': addedAt,
+ if (downloadSubtitles != null) 'download_subtitles': downloadSubtitles,
+ if (downloadArtwork != null) 'download_artwork': downloadArtwork,
+ });
+ }
+
+ DownloadQueueCompanion copyWith({
+ Value? id,
+ Value? mediaGlobalKey,
+ Value? priority,
+ Value? addedAt,
+ Value? downloadSubtitles,
+ Value? downloadArtwork,
+ }) {
+ return DownloadQueueCompanion(
+ id: id ?? this.id,
+ mediaGlobalKey: mediaGlobalKey ?? this.mediaGlobalKey,
+ priority: priority ?? this.priority,
+ addedAt: addedAt ?? this.addedAt,
+ downloadSubtitles: downloadSubtitles ?? this.downloadSubtitles,
+ downloadArtwork: downloadArtwork ?? this.downloadArtwork,
+ );
+ }
+
+ @override
+ Map toColumns(bool nullToAbsent) {
+ final map = {};
+ if (id.present) {
+ map['id'] = Variable(id.value);
+ }
+ if (mediaGlobalKey.present) {
+ map['media_global_key'] = Variable(mediaGlobalKey.value);
+ }
+ if (priority.present) {
+ map['priority'] = Variable(priority.value);
+ }
+ if (addedAt.present) {
+ map['added_at'] = Variable(addedAt.value);
+ }
+ if (downloadSubtitles.present) {
+ map['download_subtitles'] = Variable(downloadSubtitles.value);
+ }
+ if (downloadArtwork.present) {
+ map['download_artwork'] = Variable(downloadArtwork.value);
+ }
+ return map;
+ }
+
+ @override
+ String toString() {
+ return (StringBuffer('DownloadQueueCompanion(')
+ ..write('id: $id, ')
+ ..write('mediaGlobalKey: $mediaGlobalKey, ')
+ ..write('priority: $priority, ')
+ ..write('addedAt: $addedAt, ')
+ ..write('downloadSubtitles: $downloadSubtitles, ')
+ ..write('downloadArtwork: $downloadArtwork')
+ ..write(')'))
+ .toString();
+ }
+}
+
+class $ApiCacheTable extends ApiCache
+ with TableInfo<$ApiCacheTable, ApiCacheData> {
+ @override
+ final GeneratedDatabase attachedDatabase;
+ final String? _alias;
+ $ApiCacheTable(this.attachedDatabase, [this._alias]);
+ static const VerificationMeta _cacheKeyMeta = const VerificationMeta(
+ 'cacheKey',
+ );
+ @override
+ late final GeneratedColumn cacheKey = GeneratedColumn(
+ 'cache_key',
+ aliasedName,
+ false,
+ type: DriftSqlType.string,
+ requiredDuringInsert: true,
+ );
+ static const VerificationMeta _dataMeta = const VerificationMeta('data');
+ @override
+ late final GeneratedColumn data = GeneratedColumn(
+ 'data',
+ aliasedName,
+ false,
+ type: DriftSqlType.string,
+ requiredDuringInsert: true,
+ );
+ static const VerificationMeta _pinnedMeta = const VerificationMeta('pinned');
+ @override
+ late final GeneratedColumn pinned = GeneratedColumn(
+ 'pinned',
+ aliasedName,
+ false,
+ type: DriftSqlType.bool,
+ requiredDuringInsert: false,
+ defaultConstraints: GeneratedColumn.constraintIsAlways(
+ 'CHECK ("pinned" IN (0, 1))',
+ ),
+ defaultValue: const Constant(false),
+ );
+ static const VerificationMeta _cachedAtMeta = const VerificationMeta(
+ 'cachedAt',
+ );
+ @override
+ late final GeneratedColumn cachedAt = GeneratedColumn(
+ 'cached_at',
+ aliasedName,
+ false,
+ type: DriftSqlType.dateTime,
+ requiredDuringInsert: false,
+ defaultValue: currentDateAndTime,
+ );
+ @override
+ List get $columns => [cacheKey, data, pinned, cachedAt];
+ @override
+ String get aliasedName => _alias ?? actualTableName;
+ @override
+ String get actualTableName => $name;
+ static const String $name = 'api_cache';
+ @override
+ VerificationContext validateIntegrity(
+ Insertable instance, {
+ bool isInserting = false,
+ }) {
+ final context = VerificationContext();
+ final data = instance.toColumns(true);
+ if (data.containsKey('cache_key')) {
+ context.handle(
+ _cacheKeyMeta,
+ cacheKey.isAcceptableOrUnknown(data['cache_key']!, _cacheKeyMeta),
+ );
+ } else if (isInserting) {
+ context.missing(_cacheKeyMeta);
+ }
+ if (data.containsKey('data')) {
+ context.handle(
+ _dataMeta,
+ this.data.isAcceptableOrUnknown(data['data']!, _dataMeta),
+ );
+ } else if (isInserting) {
+ context.missing(_dataMeta);
+ }
+ if (data.containsKey('pinned')) {
+ context.handle(
+ _pinnedMeta,
+ pinned.isAcceptableOrUnknown(data['pinned']!, _pinnedMeta),
+ );
+ }
+ if (data.containsKey('cached_at')) {
+ context.handle(
+ _cachedAtMeta,
+ cachedAt.isAcceptableOrUnknown(data['cached_at']!, _cachedAtMeta),
+ );
+ }
+ return context;
+ }
+
+ @override
+ Set