From 52d4f60ccc59dcbe7b1229dd4a7c8a2226c3b6b0 Mon Sep 17 00:00:00 2001 From: Kingkor Roy Tirtho Date: Fri, 14 Jun 2024 21:24:42 +0600 Subject: [PATCH] refactor: use drift for skip segments and source matches --- lib/main.dart | 19 - lib/models/database/database.dart | 5 +- lib/models/database/database.g.dart | 878 +++++++++++++++++- lib/models/database/tables/skip_segment.dart | 9 + lib/models/database/tables/source_match.dart | 25 + lib/models/skip_segment.dart | 25 - lib/models/skip_segment.g.dart | 44 - lib/models/source_match.dart | 54 -- lib/models/source_match.g.dart | 119 --- .../proxy_playlist/skip_segments.dart | 50 +- .../sourced_track/sources/jiosaavn.dart | 42 +- lib/services/sourced_track/sources/piped.dart | 47 +- .../sourced_track/sources/youtube.dart | 42 +- lib/utils/service_utils.dart | 11 +- 14 files changed, 1019 insertions(+), 351 deletions(-) create mode 100644 lib/models/database/tables/skip_segment.dart create mode 100644 lib/models/database/tables/source_match.dart delete mode 100644 lib/models/skip_segment.dart delete mode 100644 lib/models/skip_segment.g.dart delete mode 100644 lib/models/source_match.dart delete mode 100644 lib/models/source_match.g.dart diff --git a/lib/main.dart b/lib/main.dart index 1f5e5909..bdccadd4 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -22,8 +22,6 @@ import 'package:spotube/provider/server/bonsoir.dart'; import 'package:spotube/provider/server/server.dart'; import 'package:spotube/provider/tray_manager/tray_manager.dart'; import 'package:spotube/l10n/l10n.dart'; -import 'package:spotube/models/skip_segment.dart'; -import 'package:spotube/models/source_match.dart'; import 'package:spotube/provider/connect/clients.dart'; import 'package:spotube/provider/palette_provider.dart'; import 'package:spotube/provider/user_preferences/user_preferences_provider.dart'; @@ -84,23 +82,6 @@ Future main(List rawArgs) async { Hive.init(hiveCacheDir); - Hive.registerAdapter(SkipSegmentAdapter()); - - Hive.registerAdapter(SourceMatchAdapter()); - Hive.registerAdapter(SourceTypeAdapter()); - - // Cache versioning entities with Adapter - SourceMatch.version = 'v1'; - SkipSegment.version = 'v1'; - - await Hive.openLazyBox( - SourceMatch.boxName, - path: hiveCacheDir, - ); - await Hive.openLazyBox( - SkipSegment.boxName, - path: hiveCacheDir, - ); await PersistedStateNotifier.initializeBoxes( path: hiveCacheDir, ); diff --git a/lib/models/database/database.dart b/lib/models/database/database.dart index 7d8fe088..e7ac2558 100644 --- a/lib/models/database/database.dart +++ b/lib/models/database/database.dart @@ -17,11 +17,14 @@ import 'package:sqlite3_flutter_libs/sqlite3_flutter_libs.dart'; part 'database.g.dart'; part 'tables/preferences.dart'; +part 'tables/source_match.dart'; +part 'tables/skip_segment.dart'; + part 'typeconverters/color.dart'; part 'typeconverters/locale.dart'; part 'typeconverters/string_list.dart'; -@DriftDatabase(tables: [PreferencesTable]) +@DriftDatabase(tables: [PreferencesTable, SourceMatchTable, SkipSegmentTable]) class AppDatabase extends _$AppDatabase { AppDatabase() : super(_openConnection()); diff --git a/lib/models/database/database.g.dart b/lib/models/database/database.g.dart index 1516b266..9cc8a1c1 100644 --- a/lib/models/database/database.g.dart +++ b/lib/models/database/database.g.dart @@ -1204,16 +1204,608 @@ class PreferencesTableCompanion extends UpdateCompanion { } } +class $SourceMatchTableTable extends SourceMatchTable + with TableInfo<$SourceMatchTableTable, SourceMatchTableData> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $SourceMatchTableTable(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 _trackIdMeta = + const VerificationMeta('trackId'); + @override + late final GeneratedColumn trackId = GeneratedColumn( + 'track_id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _sourceIdMeta = + const VerificationMeta('sourceId'); + @override + late final GeneratedColumn sourceId = GeneratedColumn( + 'source_id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _sourceTypeMeta = + const VerificationMeta('sourceType'); + @override + late final GeneratedColumnWithTypeConverter sourceType = + GeneratedColumn('source_type', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: Constant(SourceType.youtube.name)) + .withConverter( + $SourceMatchTableTable.$convertersourceType); + static const VerificationMeta _createdAtMeta = + const VerificationMeta('createdAt'); + @override + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: currentDateAndTime); + @override + List get $columns => + [id, trackId, sourceId, sourceType, createdAt]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'source_match_table'; + @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('track_id')) { + context.handle(_trackIdMeta, + trackId.isAcceptableOrUnknown(data['track_id']!, _trackIdMeta)); + } else if (isInserting) { + context.missing(_trackIdMeta); + } + if (data.containsKey('source_id')) { + context.handle(_sourceIdMeta, + sourceId.isAcceptableOrUnknown(data['source_id']!, _sourceIdMeta)); + } else if (isInserting) { + context.missing(_sourceIdMeta); + } + context.handle(_sourceTypeMeta, const VerificationResult.success()); + if (data.containsKey('created_at')) { + context.handle(_createdAtMeta, + createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta)); + } + return context; + } + + @override + Set get $primaryKey => {id}; + @override + SourceMatchTableData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return SourceMatchTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + trackId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}track_id'])!, + sourceId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}source_id'])!, + sourceType: $SourceMatchTableTable.$convertersourceType.fromSql( + attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}source_type'])!), + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + ); + } + + @override + $SourceMatchTableTable createAlias(String alias) { + return $SourceMatchTableTable(attachedDatabase, alias); + } + + static JsonTypeConverter2 $convertersourceType = + const EnumNameConverter(SourceType.values); +} + +class SourceMatchTableData extends DataClass + implements Insertable { + final int id; + final String trackId; + final String sourceId; + final SourceType sourceType; + final DateTime createdAt; + const SourceMatchTableData( + {required this.id, + required this.trackId, + required this.sourceId, + required this.sourceType, + required this.createdAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['track_id'] = Variable(trackId); + map['source_id'] = Variable(sourceId); + { + map['source_type'] = Variable( + $SourceMatchTableTable.$convertersourceType.toSql(sourceType)); + } + map['created_at'] = Variable(createdAt); + return map; + } + + SourceMatchTableCompanion toCompanion(bool nullToAbsent) { + return SourceMatchTableCompanion( + id: Value(id), + trackId: Value(trackId), + sourceId: Value(sourceId), + sourceType: Value(sourceType), + createdAt: Value(createdAt), + ); + } + + factory SourceMatchTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return SourceMatchTableData( + id: serializer.fromJson(json['id']), + trackId: serializer.fromJson(json['trackId']), + sourceId: serializer.fromJson(json['sourceId']), + sourceType: $SourceMatchTableTable.$convertersourceType + .fromJson(serializer.fromJson(json['sourceType'])), + createdAt: serializer.fromJson(json['createdAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'trackId': serializer.toJson(trackId), + 'sourceId': serializer.toJson(sourceId), + 'sourceType': serializer.toJson( + $SourceMatchTableTable.$convertersourceType.toJson(sourceType)), + 'createdAt': serializer.toJson(createdAt), + }; + } + + SourceMatchTableData copyWith( + {int? id, + String? trackId, + String? sourceId, + SourceType? sourceType, + DateTime? createdAt}) => + SourceMatchTableData( + id: id ?? this.id, + trackId: trackId ?? this.trackId, + sourceId: sourceId ?? this.sourceId, + sourceType: sourceType ?? this.sourceType, + createdAt: createdAt ?? this.createdAt, + ); + @override + String toString() { + return (StringBuffer('SourceMatchTableData(') + ..write('id: $id, ') + ..write('trackId: $trackId, ') + ..write('sourceId: $sourceId, ') + ..write('sourceType: $sourceType, ') + ..write('createdAt: $createdAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, trackId, sourceId, sourceType, createdAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is SourceMatchTableData && + other.id == this.id && + other.trackId == this.trackId && + other.sourceId == this.sourceId && + other.sourceType == this.sourceType && + other.createdAt == this.createdAt); +} + +class SourceMatchTableCompanion extends UpdateCompanion { + final Value id; + final Value trackId; + final Value sourceId; + final Value sourceType; + final Value createdAt; + const SourceMatchTableCompanion({ + this.id = const Value.absent(), + this.trackId = const Value.absent(), + this.sourceId = const Value.absent(), + this.sourceType = const Value.absent(), + this.createdAt = const Value.absent(), + }); + SourceMatchTableCompanion.insert({ + this.id = const Value.absent(), + required String trackId, + required String sourceId, + this.sourceType = const Value.absent(), + this.createdAt = const Value.absent(), + }) : trackId = Value(trackId), + sourceId = Value(sourceId); + static Insertable custom({ + Expression? id, + Expression? trackId, + Expression? sourceId, + Expression? sourceType, + Expression? createdAt, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (trackId != null) 'track_id': trackId, + if (sourceId != null) 'source_id': sourceId, + if (sourceType != null) 'source_type': sourceType, + if (createdAt != null) 'created_at': createdAt, + }); + } + + SourceMatchTableCompanion copyWith( + {Value? id, + Value? trackId, + Value? sourceId, + Value? sourceType, + Value? createdAt}) { + return SourceMatchTableCompanion( + id: id ?? this.id, + trackId: trackId ?? this.trackId, + sourceId: sourceId ?? this.sourceId, + sourceType: sourceType ?? this.sourceType, + createdAt: createdAt ?? this.createdAt, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (trackId.present) { + map['track_id'] = Variable(trackId.value); + } + if (sourceId.present) { + map['source_id'] = Variable(sourceId.value); + } + if (sourceType.present) { + map['source_type'] = Variable( + $SourceMatchTableTable.$convertersourceType.toSql(sourceType.value)); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('SourceMatchTableCompanion(') + ..write('id: $id, ') + ..write('trackId: $trackId, ') + ..write('sourceId: $sourceId, ') + ..write('sourceType: $sourceType, ') + ..write('createdAt: $createdAt') + ..write(')')) + .toString(); + } +} + +class $SkipSegmentTableTable extends SkipSegmentTable + with TableInfo<$SkipSegmentTableTable, SkipSegmentTableData> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $SkipSegmentTableTable(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 _startMeta = const VerificationMeta('start'); + @override + late final GeneratedColumn start = GeneratedColumn( + 'start', aliasedName, false, + type: DriftSqlType.int, requiredDuringInsert: true); + static const VerificationMeta _endMeta = const VerificationMeta('end'); + @override + late final GeneratedColumn end = GeneratedColumn( + 'end', aliasedName, false, + type: DriftSqlType.int, requiredDuringInsert: true); + static const VerificationMeta _trackIdMeta = + const VerificationMeta('trackId'); + @override + late final GeneratedColumn trackId = GeneratedColumn( + 'track_id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _createdAtMeta = + const VerificationMeta('createdAt'); + @override + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: currentDateAndTime); + @override + List get $columns => [id, start, end, trackId, createdAt]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'skip_segment_table'; + @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('start')) { + context.handle( + _startMeta, start.isAcceptableOrUnknown(data['start']!, _startMeta)); + } else if (isInserting) { + context.missing(_startMeta); + } + if (data.containsKey('end')) { + context.handle( + _endMeta, end.isAcceptableOrUnknown(data['end']!, _endMeta)); + } else if (isInserting) { + context.missing(_endMeta); + } + if (data.containsKey('track_id')) { + context.handle(_trackIdMeta, + trackId.isAcceptableOrUnknown(data['track_id']!, _trackIdMeta)); + } else if (isInserting) { + context.missing(_trackIdMeta); + } + if (data.containsKey('created_at')) { + context.handle(_createdAtMeta, + createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta)); + } + return context; + } + + @override + Set get $primaryKey => {id}; + @override + SkipSegmentTableData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return SkipSegmentTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + start: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}start'])!, + end: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}end'])!, + trackId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}track_id'])!, + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + ); + } + + @override + $SkipSegmentTableTable createAlias(String alias) { + return $SkipSegmentTableTable(attachedDatabase, alias); + } +} + +class SkipSegmentTableData extends DataClass + implements Insertable { + final int id; + final int start; + final int end; + final String trackId; + final DateTime createdAt; + const SkipSegmentTableData( + {required this.id, + required this.start, + required this.end, + required this.trackId, + required this.createdAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['start'] = Variable(start); + map['end'] = Variable(end); + map['track_id'] = Variable(trackId); + map['created_at'] = Variable(createdAt); + return map; + } + + SkipSegmentTableCompanion toCompanion(bool nullToAbsent) { + return SkipSegmentTableCompanion( + id: Value(id), + start: Value(start), + end: Value(end), + trackId: Value(trackId), + createdAt: Value(createdAt), + ); + } + + factory SkipSegmentTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return SkipSegmentTableData( + id: serializer.fromJson(json['id']), + start: serializer.fromJson(json['start']), + end: serializer.fromJson(json['end']), + trackId: serializer.fromJson(json['trackId']), + createdAt: serializer.fromJson(json['createdAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'start': serializer.toJson(start), + 'end': serializer.toJson(end), + 'trackId': serializer.toJson(trackId), + 'createdAt': serializer.toJson(createdAt), + }; + } + + SkipSegmentTableData copyWith( + {int? id, + int? start, + int? end, + String? trackId, + DateTime? createdAt}) => + SkipSegmentTableData( + id: id ?? this.id, + start: start ?? this.start, + end: end ?? this.end, + trackId: trackId ?? this.trackId, + createdAt: createdAt ?? this.createdAt, + ); + @override + String toString() { + return (StringBuffer('SkipSegmentTableData(') + ..write('id: $id, ') + ..write('start: $start, ') + ..write('end: $end, ') + ..write('trackId: $trackId, ') + ..write('createdAt: $createdAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, start, end, trackId, createdAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is SkipSegmentTableData && + other.id == this.id && + other.start == this.start && + other.end == this.end && + other.trackId == this.trackId && + other.createdAt == this.createdAt); +} + +class SkipSegmentTableCompanion extends UpdateCompanion { + final Value id; + final Value start; + final Value end; + final Value trackId; + final Value createdAt; + const SkipSegmentTableCompanion({ + this.id = const Value.absent(), + this.start = const Value.absent(), + this.end = const Value.absent(), + this.trackId = const Value.absent(), + this.createdAt = const Value.absent(), + }); + SkipSegmentTableCompanion.insert({ + this.id = const Value.absent(), + required int start, + required int end, + required String trackId, + this.createdAt = const Value.absent(), + }) : start = Value(start), + end = Value(end), + trackId = Value(trackId); + static Insertable custom({ + Expression? id, + Expression? start, + Expression? end, + Expression? trackId, + Expression? createdAt, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (start != null) 'start': start, + if (end != null) 'end': end, + if (trackId != null) 'track_id': trackId, + if (createdAt != null) 'created_at': createdAt, + }); + } + + SkipSegmentTableCompanion copyWith( + {Value? id, + Value? start, + Value? end, + Value? trackId, + Value? createdAt}) { + return SkipSegmentTableCompanion( + id: id ?? this.id, + start: start ?? this.start, + end: end ?? this.end, + trackId: trackId ?? this.trackId, + createdAt: createdAt ?? this.createdAt, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (start.present) { + map['start'] = Variable(start.value); + } + if (end.present) { + map['end'] = Variable(end.value); + } + if (trackId.present) { + map['track_id'] = Variable(trackId.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('SkipSegmentTableCompanion(') + ..write('id: $id, ') + ..write('start: $start, ') + ..write('end: $end, ') + ..write('trackId: $trackId, ') + ..write('createdAt: $createdAt') + ..write(')')) + .toString(); + } +} + abstract class _$AppDatabase extends GeneratedDatabase { _$AppDatabase(QueryExecutor e) : super(e); _$AppDatabaseManager get managers => _$AppDatabaseManager(this); late final $PreferencesTableTable preferencesTable = $PreferencesTableTable(this); + late final $SourceMatchTableTable sourceMatchTable = + $SourceMatchTableTable(this); + late final $SkipSegmentTableTable skipSegmentTable = + $SkipSegmentTableTable(this); + late final Index uniqTrackMatch = Index('uniq_track_match', + 'CREATE UNIQUE INDEX uniq_track_match ON source_match_table (track_id, source_id, source_type)'); @override Iterable> get allTables => allSchemaEntities.whereType>(); @override - List get allSchemaEntities => [preferencesTable]; + List get allSchemaEntities => + [preferencesTable, sourceMatchTable, skipSegmentTable, uniqTrackMatch]; } typedef $$PreferencesTableTableInsertCompanionBuilder @@ -1699,9 +2291,293 @@ class $$PreferencesTableTableOrderingComposer ColumnOrderings(column, joinBuilders: joinBuilders)); } +typedef $$SourceMatchTableTableInsertCompanionBuilder + = SourceMatchTableCompanion Function({ + Value id, + required String trackId, + required String sourceId, + Value sourceType, + Value createdAt, +}); +typedef $$SourceMatchTableTableUpdateCompanionBuilder + = SourceMatchTableCompanion Function({ + Value id, + Value trackId, + Value sourceId, + Value sourceType, + Value createdAt, +}); + +class $$SourceMatchTableTableTableManager extends RootTableManager< + _$AppDatabase, + $SourceMatchTableTable, + SourceMatchTableData, + $$SourceMatchTableTableFilterComposer, + $$SourceMatchTableTableOrderingComposer, + $$SourceMatchTableTableProcessedTableManager, + $$SourceMatchTableTableInsertCompanionBuilder, + $$SourceMatchTableTableUpdateCompanionBuilder> { + $$SourceMatchTableTableTableManager( + _$AppDatabase db, $SourceMatchTableTable table) + : super(TableManagerState( + db: db, + table: table, + filteringComposer: + $$SourceMatchTableTableFilterComposer(ComposerState(db, table)), + orderingComposer: + $$SourceMatchTableTableOrderingComposer(ComposerState(db, table)), + getChildManagerBuilder: (p) => + $$SourceMatchTableTableProcessedTableManager(p), + getUpdateCompanionBuilder: ({ + Value id = const Value.absent(), + Value trackId = const Value.absent(), + Value sourceId = const Value.absent(), + Value sourceType = const Value.absent(), + Value createdAt = const Value.absent(), + }) => + SourceMatchTableCompanion( + id: id, + trackId: trackId, + sourceId: sourceId, + sourceType: sourceType, + createdAt: createdAt, + ), + getInsertCompanionBuilder: ({ + Value id = const Value.absent(), + required String trackId, + required String sourceId, + Value sourceType = const Value.absent(), + Value createdAt = const Value.absent(), + }) => + SourceMatchTableCompanion.insert( + id: id, + trackId: trackId, + sourceId: sourceId, + sourceType: sourceType, + createdAt: createdAt, + ), + )); +} + +class $$SourceMatchTableTableProcessedTableManager + extends ProcessedTableManager< + _$AppDatabase, + $SourceMatchTableTable, + SourceMatchTableData, + $$SourceMatchTableTableFilterComposer, + $$SourceMatchTableTableOrderingComposer, + $$SourceMatchTableTableProcessedTableManager, + $$SourceMatchTableTableInsertCompanionBuilder, + $$SourceMatchTableTableUpdateCompanionBuilder> { + $$SourceMatchTableTableProcessedTableManager(super.$state); +} + +class $$SourceMatchTableTableFilterComposer + extends FilterComposer<_$AppDatabase, $SourceMatchTableTable> { + $$SourceMatchTableTableFilterComposer(super.$state); + ColumnFilters get id => $state.composableBuilder( + column: $state.table.id, + builder: (column, joinBuilders) => + ColumnFilters(column, joinBuilders: joinBuilders)); + + ColumnFilters get trackId => $state.composableBuilder( + column: $state.table.trackId, + builder: (column, joinBuilders) => + ColumnFilters(column, joinBuilders: joinBuilders)); + + ColumnFilters get sourceId => $state.composableBuilder( + column: $state.table.sourceId, + builder: (column, joinBuilders) => + ColumnFilters(column, joinBuilders: joinBuilders)); + + ColumnWithTypeConverterFilters + get sourceType => $state.composableBuilder( + column: $state.table.sourceType, + builder: (column, joinBuilders) => ColumnWithTypeConverterFilters( + column, + joinBuilders: joinBuilders)); + + ColumnFilters get createdAt => $state.composableBuilder( + column: $state.table.createdAt, + builder: (column, joinBuilders) => + ColumnFilters(column, joinBuilders: joinBuilders)); +} + +class $$SourceMatchTableTableOrderingComposer + extends OrderingComposer<_$AppDatabase, $SourceMatchTableTable> { + $$SourceMatchTableTableOrderingComposer(super.$state); + ColumnOrderings get id => $state.composableBuilder( + column: $state.table.id, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); + + ColumnOrderings get trackId => $state.composableBuilder( + column: $state.table.trackId, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); + + ColumnOrderings get sourceId => $state.composableBuilder( + column: $state.table.sourceId, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); + + ColumnOrderings get sourceType => $state.composableBuilder( + column: $state.table.sourceType, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); + + ColumnOrderings get createdAt => $state.composableBuilder( + column: $state.table.createdAt, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); +} + +typedef $$SkipSegmentTableTableInsertCompanionBuilder + = SkipSegmentTableCompanion Function({ + Value id, + required int start, + required int end, + required String trackId, + Value createdAt, +}); +typedef $$SkipSegmentTableTableUpdateCompanionBuilder + = SkipSegmentTableCompanion Function({ + Value id, + Value start, + Value end, + Value trackId, + Value createdAt, +}); + +class $$SkipSegmentTableTableTableManager extends RootTableManager< + _$AppDatabase, + $SkipSegmentTableTable, + SkipSegmentTableData, + $$SkipSegmentTableTableFilterComposer, + $$SkipSegmentTableTableOrderingComposer, + $$SkipSegmentTableTableProcessedTableManager, + $$SkipSegmentTableTableInsertCompanionBuilder, + $$SkipSegmentTableTableUpdateCompanionBuilder> { + $$SkipSegmentTableTableTableManager( + _$AppDatabase db, $SkipSegmentTableTable table) + : super(TableManagerState( + db: db, + table: table, + filteringComposer: + $$SkipSegmentTableTableFilterComposer(ComposerState(db, table)), + orderingComposer: + $$SkipSegmentTableTableOrderingComposer(ComposerState(db, table)), + getChildManagerBuilder: (p) => + $$SkipSegmentTableTableProcessedTableManager(p), + getUpdateCompanionBuilder: ({ + Value id = const Value.absent(), + Value start = const Value.absent(), + Value end = const Value.absent(), + Value trackId = const Value.absent(), + Value createdAt = const Value.absent(), + }) => + SkipSegmentTableCompanion( + id: id, + start: start, + end: end, + trackId: trackId, + createdAt: createdAt, + ), + getInsertCompanionBuilder: ({ + Value id = const Value.absent(), + required int start, + required int end, + required String trackId, + Value createdAt = const Value.absent(), + }) => + SkipSegmentTableCompanion.insert( + id: id, + start: start, + end: end, + trackId: trackId, + createdAt: createdAt, + ), + )); +} + +class $$SkipSegmentTableTableProcessedTableManager + extends ProcessedTableManager< + _$AppDatabase, + $SkipSegmentTableTable, + SkipSegmentTableData, + $$SkipSegmentTableTableFilterComposer, + $$SkipSegmentTableTableOrderingComposer, + $$SkipSegmentTableTableProcessedTableManager, + $$SkipSegmentTableTableInsertCompanionBuilder, + $$SkipSegmentTableTableUpdateCompanionBuilder> { + $$SkipSegmentTableTableProcessedTableManager(super.$state); +} + +class $$SkipSegmentTableTableFilterComposer + extends FilterComposer<_$AppDatabase, $SkipSegmentTableTable> { + $$SkipSegmentTableTableFilterComposer(super.$state); + ColumnFilters get id => $state.composableBuilder( + column: $state.table.id, + builder: (column, joinBuilders) => + ColumnFilters(column, joinBuilders: joinBuilders)); + + ColumnFilters get start => $state.composableBuilder( + column: $state.table.start, + builder: (column, joinBuilders) => + ColumnFilters(column, joinBuilders: joinBuilders)); + + ColumnFilters get end => $state.composableBuilder( + column: $state.table.end, + builder: (column, joinBuilders) => + ColumnFilters(column, joinBuilders: joinBuilders)); + + ColumnFilters get trackId => $state.composableBuilder( + column: $state.table.trackId, + builder: (column, joinBuilders) => + ColumnFilters(column, joinBuilders: joinBuilders)); + + ColumnFilters get createdAt => $state.composableBuilder( + column: $state.table.createdAt, + builder: (column, joinBuilders) => + ColumnFilters(column, joinBuilders: joinBuilders)); +} + +class $$SkipSegmentTableTableOrderingComposer + extends OrderingComposer<_$AppDatabase, $SkipSegmentTableTable> { + $$SkipSegmentTableTableOrderingComposer(super.$state); + ColumnOrderings get id => $state.composableBuilder( + column: $state.table.id, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); + + ColumnOrderings get start => $state.composableBuilder( + column: $state.table.start, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); + + ColumnOrderings get end => $state.composableBuilder( + column: $state.table.end, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); + + ColumnOrderings get trackId => $state.composableBuilder( + column: $state.table.trackId, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); + + ColumnOrderings get createdAt => $state.composableBuilder( + column: $state.table.createdAt, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); +} + class _$AppDatabaseManager { final _$AppDatabase _db; _$AppDatabaseManager(this._db); $$PreferencesTableTableTableManager get preferencesTable => $$PreferencesTableTableTableManager(_db, _db.preferencesTable); + $$SourceMatchTableTableTableManager get sourceMatchTable => + $$SourceMatchTableTableTableManager(_db, _db.sourceMatchTable); + $$SkipSegmentTableTableTableManager get skipSegmentTable => + $$SkipSegmentTableTableTableManager(_db, _db.skipSegmentTable); } diff --git a/lib/models/database/tables/skip_segment.dart b/lib/models/database/tables/skip_segment.dart new file mode 100644 index 00000000..719f2617 --- /dev/null +++ b/lib/models/database/tables/skip_segment.dart @@ -0,0 +1,9 @@ +part of '../database.dart'; + +class SkipSegmentTable extends Table { + IntColumn get id => integer().autoIncrement()(); + IntColumn get start => integer()(); + IntColumn get end => integer()(); + TextColumn get trackId => text()(); + DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)(); +} diff --git a/lib/models/database/tables/source_match.dart b/lib/models/database/tables/source_match.dart new file mode 100644 index 00000000..78d0eb05 --- /dev/null +++ b/lib/models/database/tables/source_match.dart @@ -0,0 +1,25 @@ +part of '../database.dart'; + +enum SourceType { + youtube._("YouTube"), + youtubeMusic._("YouTube Music"), + jiosaavn._("JioSaavn"); + + final String label; + + const SourceType._(this.label); +} + +@TableIndex( + name: "uniq_track_match", + columns: {#trackId, #sourceId, #sourceType}, + unique: true, +) +class SourceMatchTable extends Table { + IntColumn get id => integer().autoIncrement()(); + TextColumn get trackId => text()(); + TextColumn get sourceId => text()(); + TextColumn get sourceType => + textEnum().withDefault(Constant(SourceType.youtube.name))(); + DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)(); +} diff --git a/lib/models/skip_segment.dart b/lib/models/skip_segment.dart deleted file mode 100644 index 90f20f5a..00000000 --- a/lib/models/skip_segment.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'package:hive/hive.dart'; - -part 'skip_segment.g.dart'; - -@HiveType(typeId: 2) -class SkipSegment { - @HiveField(0) - final int start; - @HiveField(1) - final int end; - SkipSegment(this.start, this.end); - - static String version = 'v1'; - static final boxName = "oss.krtirtho.spotube.skip_segments.$version"; - static LazyBox get box => Hive.lazyBox(boxName); - - SkipSegment.fromJson(Map json) - : start = json['start'], - end = json['end']; - - Map toJson() => { - 'start': start, - 'end': end, - }; -} diff --git a/lib/models/skip_segment.g.dart b/lib/models/skip_segment.g.dart deleted file mode 100644 index f2ad4459..00000000 --- a/lib/models/skip_segment.g.dart +++ /dev/null @@ -1,44 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'skip_segment.dart'; - -// ************************************************************************** -// TypeAdapterGenerator -// ************************************************************************** - -class SkipSegmentAdapter extends TypeAdapter { - @override - final int typeId = 2; - - @override - SkipSegment read(BinaryReader reader) { - final numOfFields = reader.readByte(); - final fields = { - for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), - }; - return SkipSegment( - fields[0] as int, - fields[1] as int, - ); - } - - @override - void write(BinaryWriter writer, SkipSegment obj) { - writer - ..writeByte(2) - ..writeByte(0) - ..write(obj.start) - ..writeByte(1) - ..write(obj.end); - } - - @override - int get hashCode => typeId.hashCode; - - @override - bool operator ==(Object other) => - identical(this, other) || - other is SkipSegmentAdapter && - runtimeType == other.runtimeType && - typeId == other.typeId; -} diff --git a/lib/models/source_match.dart b/lib/models/source_match.dart deleted file mode 100644 index 57a9f963..00000000 --- a/lib/models/source_match.dart +++ /dev/null @@ -1,54 +0,0 @@ -import 'package:hive/hive.dart'; -import 'package:json_annotation/json_annotation.dart'; - -part 'source_match.g.dart'; - -@JsonEnum() -@HiveType(typeId: 5) -enum SourceType { - @HiveField(0) - youtube._("YouTube"), - - @HiveField(1) - youtubeMusic._("YouTube Music"), - - @HiveField(2) - jiosaavn._("JioSaavn"); - - final String label; - - const SourceType._(this.label); -} - -@JsonSerializable() -@HiveType(typeId: 6) -class SourceMatch { - @HiveField(0) - String id; - - @HiveField(1) - String sourceId; - - @HiveField(2) - SourceType sourceType; - - @HiveField(3) - DateTime createdAt; - - SourceMatch({ - required this.id, - required this.sourceId, - required this.sourceType, - required this.createdAt, - }); - - factory SourceMatch.fromJson(Map json) => - _$SourceMatchFromJson(json); - - Map toJson() => _$SourceMatchToJson(this); - - static String version = 'v1'; - static final boxName = "oss.krtirtho.spotube.source_matches.$version"; - - static LazyBox get box => Hive.lazyBox(boxName); -} diff --git a/lib/models/source_match.g.dart b/lib/models/source_match.g.dart deleted file mode 100644 index 3b469694..00000000 --- a/lib/models/source_match.g.dart +++ /dev/null @@ -1,119 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'source_match.dart'; - -// ************************************************************************** -// TypeAdapterGenerator -// ************************************************************************** - -class SourceMatchAdapter extends TypeAdapter { - @override - final int typeId = 6; - - @override - SourceMatch read(BinaryReader reader) { - final numOfFields = reader.readByte(); - final fields = { - for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), - }; - return SourceMatch( - id: fields[0] as String, - sourceId: fields[1] as String, - sourceType: fields[2] as SourceType, - createdAt: fields[3] as DateTime, - ); - } - - @override - void write(BinaryWriter writer, SourceMatch obj) { - writer - ..writeByte(4) - ..writeByte(0) - ..write(obj.id) - ..writeByte(1) - ..write(obj.sourceId) - ..writeByte(2) - ..write(obj.sourceType) - ..writeByte(3) - ..write(obj.createdAt); - } - - @override - int get hashCode => typeId.hashCode; - - @override - bool operator ==(Object other) => - identical(this, other) || - other is SourceMatchAdapter && - runtimeType == other.runtimeType && - typeId == other.typeId; -} - -class SourceTypeAdapter extends TypeAdapter { - @override - final int typeId = 5; - - @override - SourceType read(BinaryReader reader) { - switch (reader.readByte()) { - case 0: - return SourceType.youtube; - case 1: - return SourceType.youtubeMusic; - case 2: - return SourceType.jiosaavn; - default: - return SourceType.youtube; - } - } - - @override - void write(BinaryWriter writer, SourceType obj) { - switch (obj) { - case SourceType.youtube: - writer.writeByte(0); - break; - case SourceType.youtubeMusic: - writer.writeByte(1); - break; - case SourceType.jiosaavn: - writer.writeByte(2); - break; - } - } - - @override - int get hashCode => typeId.hashCode; - - @override - bool operator ==(Object other) => - identical(this, other) || - other is SourceTypeAdapter && - runtimeType == other.runtimeType && - typeId == other.typeId; -} - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -SourceMatch _$SourceMatchFromJson(Map json) => SourceMatch( - id: json['id'] as String, - sourceId: json['sourceId'] as String, - sourceType: $enumDecode(_$SourceTypeEnumMap, json['sourceType']), - createdAt: DateTime.parse(json['createdAt'] as String), - ); - -Map _$SourceMatchToJson(SourceMatch instance) => - { - 'id': instance.id, - 'sourceId': instance.sourceId, - 'sourceType': _$SourceTypeEnumMap[instance.sourceType]!, - 'createdAt': instance.createdAt.toIso8601String(), - }; - -const _$SourceTypeEnumMap = { - SourceType.youtube: 'youtube', - SourceType.youtubeMusic: 'youtubeMusic', - SourceType.jiosaavn: 'jiosaavn', -}; diff --git a/lib/provider/proxy_playlist/skip_segments.dart b/lib/provider/proxy_playlist/skip_segments.dart index 461ac24e..005797f4 100644 --- a/lib/provider/proxy_playlist/skip_segments.dart +++ b/lib/provider/proxy_playlist/skip_segments.dart @@ -1,8 +1,8 @@ import 'package:spotube/models/database/database.dart'; +import 'package:spotube/provider/database/database.dart'; import 'package:spotube/services/logger/logger.dart'; import 'package:dio/dio.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:spotube/models/skip_segment.dart'; import 'package:spotube/provider/server/active_sourced_track.dart'; import 'package:spotube/provider/user_preferences/user_preferences_provider.dart'; @@ -10,24 +10,21 @@ import 'package:spotube/services/dio/dio.dart'; class SourcedSegments { final String source; - final List segments; + final List segments; SourcedSegments({required this.source, required this.segments}); } -Future> getAndCacheSkipSegments(String id) async { +Future> getAndCacheSkipSegments( + String id, Ref ref) async { + final database = ref.read(databaseProvider); try { - final cached = await SkipSegment.box.get(id) as List?; - if (cached != null && cached.isNotEmpty) { - return List.castFrom( - cached - .map( - (json) => SkipSegment.fromJson( - Map.castFrom(json), - ), - ) - .toList(), - ); + final cached = await (database.select(database.skipSegmentTable) + ..where((s) => s.trackId.equals(id))) + .get(); + + if (cached.isNotEmpty) { + return cached; } final res = await globalDio.getUri( @@ -55,25 +52,30 @@ Future> getAndCacheSkipSegments(String id) async { ); if (res.data == "Not Found") { - return List.castFrom([]); + return List.castFrom([]); } final data = res.data as List; final segments = data.map((obj) { final start = obj["segment"].first.toInt(); final end = obj["segment"].last.toInt(); - return SkipSegment(start, end); + return SkipSegmentTableCompanion.insert( + trackId: id, + start: start, + end: end, + ); }).toList(); - await SkipSegment.box.put( - id, - segments.map((e) => e.toJson()).toList(), - ); - return List.castFrom(segments); + await database.batch((b) { + b.insertAll(database.skipSegmentTable, segments); + }); + + return await (database.select(database.skipSegmentTable) + ..where((s) => s.trackId.equals(id))) + .get(); } catch (e, stack) { - await SkipSegment.box.put(id, []); AppLogger.reportError(e, stack); - return List.castFrom([]); + return List.castFrom([]); } } @@ -100,7 +102,7 @@ final segmentProvider = FutureProvider( ); } - final segments = await getAndCacheSkipSegments(track.sourceInfo.id); + final segments = await getAndCacheSkipSegments(track.sourceInfo.id, ref); return SourcedSegments( source: track.sourceInfo.id, diff --git a/lib/services/sourced_track/sources/jiosaavn.dart b/lib/services/sourced_track/sources/jiosaavn.dart index f731de6c..865e3d63 100644 --- a/lib/services/sourced_track/sources/jiosaavn.dart +++ b/lib/services/sourced_track/sources/jiosaavn.dart @@ -1,7 +1,9 @@ import 'package:collection/collection.dart'; +import 'package:drift/drift.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:spotify/spotify.dart'; -import 'package:spotube/models/source_match.dart'; +import 'package:spotube/models/database/database.dart'; +import 'package:spotube/provider/database/database.dart'; import 'package:spotube/services/sourced_track/enums.dart'; import 'package:spotube/services/sourced_track/exceptions.dart'; import 'package:spotube/services/sourced_track/models/source_info.dart'; @@ -39,7 +41,10 @@ class JioSaavnSourcedTrack extends SourcedTrack { required Ref ref, bool weakMatch = false, }) async { - final cachedSource = await SourceMatch.box.get(track.id); + final database = ref.read(databaseProvider); + final cachedSource = await (database.select(database.sourceMatchTable) + ..where((s) => s.trackId.equals(track.id!))) + .getSingleOrNull(); if (cachedSource == null || cachedSource.sourceType != SourceType.jiosaavn) { @@ -50,15 +55,13 @@ class JioSaavnSourcedTrack extends SourcedTrack { throw TrackNotFoundError(track); } - await SourceMatch.box.put( - track.id!, - SourceMatch( - id: track.id!, - sourceType: SourceType.jiosaavn, - createdAt: DateTime.now(), - sourceId: siblings.first.info.id, - ), - ); + await database.into(database.sourceMatchTable).insert( + SourceMatchTableCompanion.insert( + trackId: track.id!, + sourceId: siblings.first.info.id, + sourceType: const Value(SourceType.jiosaavn), + ), + ); return JioSaavnSourcedTrack( ref: ref, @@ -206,15 +209,14 @@ class JioSaavnSourcedTrack extends SourcedTrack { final (:info, :source) = toSiblingType(item); - await SourceMatch.box.put( - id!, - SourceMatch( - id: id!, - sourceType: SourceType.jiosaavn, - createdAt: DateTime.now(), - sourceId: info.id, - ), - ); + final database = ref.read(databaseProvider); + await database.into(database.sourceMatchTable).insert( + SourceMatchTableCompanion.insert( + trackId: id!, + sourceId: info.id, + sourceType: const Value(SourceType.jiosaavn), + ), + ); return JioSaavnSourcedTrack( ref: ref, diff --git a/lib/services/sourced_track/sources/piped.dart b/lib/services/sourced_track/sources/piped.dart index b6689f6a..d156b26e 100644 --- a/lib/services/sourced_track/sources/piped.dart +++ b/lib/services/sourced_track/sources/piped.dart @@ -1,9 +1,10 @@ import 'package:collection/collection.dart'; +import 'package:drift/drift.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:piped_client/piped_client.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/models/database/database.dart'; -import 'package:spotube/models/source_match.dart'; +import 'package:spotube/provider/database/database.dart'; import 'package:spotube/provider/user_preferences/user_preferences_provider.dart'; import 'package:spotube/services/sourced_track/enums.dart'; @@ -49,7 +50,10 @@ class PipedSourcedTrack extends SourcedTrack { required Track track, required Ref ref, }) async { - final cachedSource = await SourceMatch.box.get(track.id); + final database = ref.read(databaseProvider); + final cachedSource = await (database.select(database.sourceMatchTable) + ..where((s) => s.trackId.equals(track.id!))) + .getSingleOrNull(); final preferences = ref.read(userPreferencesProvider); final pipedClient = ref.read(pipedProvider); @@ -59,17 +63,17 @@ class PipedSourcedTrack extends SourcedTrack { throw TrackNotFoundError(track); } - await SourceMatch.box.put( - track.id!, - SourceMatch( - id: track.id!, - sourceType: preferences.searchMode == SearchMode.youtube - ? SourceType.youtube - : SourceType.youtubeMusic, - createdAt: DateTime.now(), - sourceId: siblings.first.info.id, - ), - ); + await database.into(database.sourceMatchTable).insert( + SourceMatchTableCompanion.insert( + trackId: track.id!, + sourceId: siblings.first.info.id, + sourceType: Value( + preferences.searchMode == SearchMode.youtube + ? SourceType.youtube + : SourceType.youtubeMusic, + ), + ), + ); return PipedSourcedTrack( ref: ref, @@ -268,15 +272,14 @@ class PipedSourcedTrack extends SourcedTrack { final manifest = await pipedClient.streams(newSourceInfo.id); - await SourceMatch.box.put( - id!, - SourceMatch( - id: id!, - sourceType: SourceType.jiosaavn, - createdAt: DateTime.now(), - sourceId: newSourceInfo.id, - ), - ); + final database = ref.read(databaseProvider); + await database.into(database.sourceMatchTable).insert( + SourceMatchTableCompanion.insert( + trackId: id!, + sourceId: newSourceInfo.id, + sourceType: const Value(SourceType.youtube), + ), + ); return PipedSourcedTrack( ref: ref, diff --git a/lib/services/sourced_track/sources/youtube.dart b/lib/services/sourced_track/sources/youtube.dart index b144d701..0501a499 100644 --- a/lib/services/sourced_track/sources/youtube.dart +++ b/lib/services/sourced_track/sources/youtube.dart @@ -1,8 +1,10 @@ import 'package:collection/collection.dart'; +import 'package:drift/drift.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:http/http.dart'; import 'package:spotify/spotify.dart'; -import 'package:spotube/models/source_match.dart'; +import 'package:spotube/models/database/database.dart'; +import 'package:spotube/provider/database/database.dart'; import 'package:spotube/services/logger/logger.dart'; import 'package:spotube/services/song_link/song_link.dart'; import 'package:spotube/services/sourced_track/enums.dart'; @@ -46,7 +48,10 @@ class YoutubeSourcedTrack extends SourcedTrack { required Track track, required Ref ref, }) async { - final cachedSource = await SourceMatch.box.get(track.id); + final database = ref.read(databaseProvider); + final cachedSource = await (database.select(database.sourceMatchTable) + ..where((s) => s.trackId.equals(track.id!))) + .getSingleOrNull(); if (cachedSource == null || cachedSource.sourceType != SourceType.youtube) { final siblings = await fetchSiblings(ref: ref, track: track); @@ -54,15 +59,13 @@ class YoutubeSourcedTrack extends SourcedTrack { throw TrackNotFoundError(track); } - await SourceMatch.box.put( - track.id!, - SourceMatch( - id: track.id!, - sourceType: SourceType.youtube, - createdAt: DateTime.now(), - sourceId: siblings.first.info.id, - ), - ); + await database.into(database.sourceMatchTable).insert( + SourceMatchTableCompanion.insert( + trackId: track.id!, + sourceId: siblings.first.info.id, + sourceType: const Value(SourceType.youtube), + ), + ); return YoutubeSourcedTrack( ref: ref, @@ -283,15 +286,14 @@ class YoutubeSourcedTrack extends SourcedTrack { onTimeout: () => throw ClientException("Timeout"), ); - await SourceMatch.box.put( - id!, - SourceMatch( - id: id!, - sourceType: SourceType.jiosaavn, - createdAt: DateTime.now(), - sourceId: newSourceInfo.id, - ), - ); + final database = ref.read(databaseProvider); + await database.into(database.sourceMatchTable).insert( + SourceMatchTableCompanion.insert( + trackId: id!, + sourceId: newSourceInfo.id, + sourceType: const Value(SourceType.youtube), + ), + ); return YoutubeSourcedTrack( ref: ref, diff --git a/lib/utils/service_utils.dart b/lib/utils/service_utils.dart index 885f9a2c..5950bc8c 100644 --- a/lib/utils/service_utils.dart +++ b/lib/utils/service_utils.dart @@ -6,6 +6,7 @@ import 'package:spotube/modules/library/user_local_tracks.dart'; import 'package:spotube/modules/root/update_dialog.dart'; import 'package:spotube/models/logger.dart'; import 'package:spotube/models/lyrics.dart'; +import 'package:spotube/provider/database/database.dart'; import 'package:spotube/services/dio/dio.dart'; import 'package:spotube/services/sourced_track/sourced_track.dart'; @@ -20,7 +21,6 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:spotube/collections/env.dart'; -import 'package:spotube/provider/user_preferences/user_preferences_provider.dart'; import 'package:version/version.dart'; abstract class ServiceUtils { @@ -392,7 +392,14 @@ abstract class ServiceUtils { WidgetRef ref, ) async { if (!Env.enableUpdateChecker) return; - if (!ref.read(userPreferencesProvider.select((s) => s.checkUpdate))) return; + final database = ref.read(databaseProvider); + final checkUpdate = await (database.selectOnly(database.preferencesTable) + ..addColumns([database.preferencesTable.checkUpdate]) + ..where(database.preferencesTable.id.equals(0))) + .map((row) => row.read(database.preferencesTable.checkUpdate)) + .getSingleOrNull(); + + if (checkUpdate == false) return; final packageInfo = await PackageInfo.fromPlatform(); if (Env.releaseChannel == ReleaseChannel.nightly) {