diff --git a/lib/collections/routes.dart b/lib/collections/routes.dart index b9e06c61..b3cba581 100644 --- a/lib/collections/routes.dart +++ b/lib/collections/routes.dart @@ -32,7 +32,7 @@ import 'package:spotube/pages/stats/playlists/playlists.dart'; import 'package:spotube/pages/stats/stats.dart'; import 'package:spotube/pages/stats/streams/streams.dart'; import 'package:spotube/pages/track/track.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/services/kv_store/kv_store.dart'; import 'package:spotube/utils/platform.dart'; import 'package:spotube/components/spotube_page_route.dart'; @@ -59,11 +59,9 @@ final routerProvider = Provider((ref) { path: "/", name: HomePage.name, redirect: (context, state) async { - final authNotifier = ref.read(authenticationProvider.notifier); - final json = await authNotifier.box.get(authNotifier.cacheKey); + final auth = await ref.read(authenticationProvider.future); - if (json?["cookie"] == null && - !KVStoreService.doneGettingStarted) { + if (auth == null && !KVStoreService.doneGettingStarted) { return "/getting-started"; } diff --git a/lib/components/fallbacks/anonymous_fallback.dart b/lib/components/fallbacks/anonymous_fallback.dart index 5ced6bb6..799297e3 100644 --- a/lib/components/fallbacks/anonymous_fallback.dart +++ b/lib/components/fallbacks/anonymous_fallback.dart @@ -3,7 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:spotube/extensions/context.dart'; import 'package:spotube/pages/settings/settings.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/utils/service_utils.dart'; class AnonymousFallback extends ConsumerWidget { diff --git a/lib/components/heart_button/heart_button.dart b/lib/components/heart_button/heart_button.dart index 8222b8e6..fa4318cc 100644 --- a/lib/components/heart_button/heart_button.dart +++ b/lib/components/heart_button/heart_button.dart @@ -4,7 +4,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/components/heart_button/use_track_toggle_like.dart'; import 'package:spotube/extensions/context.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/provider/spotify/spotify.dart'; class HeartButton extends HookConsumerWidget { @@ -26,7 +26,7 @@ class HeartButton extends HookConsumerWidget { Widget build(BuildContext context, ref) { final auth = ref.watch(authenticationProvider); - if (auth == null) return const SizedBox.shrink(); + if (auth.asData?.value == null) return const SizedBox.shrink(); return IconButton( tooltip: tooltip, diff --git a/lib/components/track_tile/track_options.dart b/lib/components/track_tile/track_options.dart index fd3018ba..d54a0c15 100644 --- a/lib/components/track_tile/track_options.dart +++ b/lib/components/track_tile/track_options.dart @@ -20,7 +20,7 @@ import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/image.dart'; import 'package:spotube/models/database/database.dart'; import 'package:spotube/models/local_track.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/provider/blacklist_provider.dart'; import 'package:spotube/provider/download_manager_provider.dart'; import 'package:spotube/provider/local_tracks/local_tracks_provider.dart'; diff --git a/lib/components/tracks_view/sections/header/header_actions.dart b/lib/components/tracks_view/sections/header/header_actions.dart index 3e0c4cc1..f20cd553 100644 --- a/lib/components/tracks_view/sections/header/header_actions.dart +++ b/lib/components/tracks_view/sections/header/header_actions.dart @@ -9,7 +9,7 @@ import 'package:spotube/components/heart_button/heart_button.dart'; import 'package:spotube/components/tracks_view/sections/body/use_is_user_playlist.dart'; import 'package:spotube/components/tracks_view/track_view_props.dart'; import 'package:spotube/extensions/context.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/provider/history/history.dart'; import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart'; diff --git a/lib/hooks/configurators/use_endless_playback.dart b/lib/hooks/configurators/use_endless_playback.dart index 97eb3f48..9b90b23d 100644 --- a/lib/hooks/configurators/use_endless_playback.dart +++ b/lib/hooks/configurators/use_endless_playback.dart @@ -2,7 +2,7 @@ import 'package:spotube/services/logger/logger.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:spotify/spotify.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart'; import 'package:spotube/provider/spotify_provider.dart'; import 'package:spotube/provider/user_preferences/user_preferences_provider.dart'; @@ -18,7 +18,7 @@ void useEndlessPlayback(WidgetRef ref) { useEffect( () { - if (!endlessPlayback || auth == null) return null; + if (!endlessPlayback || auth.asData?.value == null) return null; void listener(int index) async { try { diff --git a/lib/models/database/database.dart b/lib/models/database/database.dart index ac0223fd..56f72ee7 100644 --- a/lib/models/database/database.dart +++ b/lib/models/database/database.dart @@ -19,10 +19,11 @@ 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 'tables/authentication.dart'; part 'tables/blacklist.dart'; +part 'tables/preferences.dart'; +part 'tables/skip_segment.dart'; +part 'tables/source_match.dart'; part 'typeconverters/color.dart'; part 'typeconverters/locale.dart'; @@ -31,10 +32,11 @@ part 'typeconverters/encrypted_text.dart'; @DriftDatabase( tables: [ - PreferencesTable, - SourceMatchTable, - SkipSegmentTable, + AuthenticationTable, BlacklistTable, + PreferencesTable, + SkipSegmentTable, + SourceMatchTable, ], ) class AppDatabase extends _$AppDatabase { diff --git a/lib/models/database/database.g.dart b/lib/models/database/database.g.dart index 8c996d21..0ac7005e 100644 --- a/lib/models/database/database.g.dart +++ b/lib/models/database/database.g.dart @@ -3,6 +3,533 @@ part of 'database.dart'; // ignore_for_file: type=lint +class $AuthenticationTableTable extends AuthenticationTable + with TableInfo<$AuthenticationTableTable, AuthenticationTableData> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $AuthenticationTableTable(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 _cookieMeta = const VerificationMeta('cookie'); + @override + late final GeneratedColumnWithTypeConverter cookie = + GeneratedColumn('cookie', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true) + .withConverter( + $AuthenticationTableTable.$convertercookie); + static const VerificationMeta _accessTokenMeta = + const VerificationMeta('accessToken'); + @override + late final GeneratedColumnWithTypeConverter + accessToken = GeneratedColumn('access_token', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true) + .withConverter( + $AuthenticationTableTable.$converteraccessToken); + static const VerificationMeta _expirationMeta = + const VerificationMeta('expiration'); + @override + late final GeneratedColumn expiration = GeneratedColumn( + 'expiration', aliasedName, false, + type: DriftSqlType.dateTime, requiredDuringInsert: true); + @override + List get $columns => [id, cookie, accessToken, expiration]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'authentication_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)); + } + context.handle(_cookieMeta, const VerificationResult.success()); + context.handle(_accessTokenMeta, const VerificationResult.success()); + if (data.containsKey('expiration')) { + context.handle( + _expirationMeta, + expiration.isAcceptableOrUnknown( + data['expiration']!, _expirationMeta)); + } else if (isInserting) { + context.missing(_expirationMeta); + } + return context; + } + + @override + Set get $primaryKey => {id}; + @override + AuthenticationTableData map(Map data, + {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return AuthenticationTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + cookie: $AuthenticationTableTable.$convertercookie.fromSql( + attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}cookie'])!), + accessToken: $AuthenticationTableTable.$converteraccessToken.fromSql( + attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}access_token'])!), + expiration: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}expiration'])!, + ); + } + + @override + $AuthenticationTableTable createAlias(String alias) { + return $AuthenticationTableTable(attachedDatabase, alias); + } + + static TypeConverter $convertercookie = + EncryptedTextConverter(); + static TypeConverter $converteraccessToken = + EncryptedTextConverter(); +} + +class AuthenticationTableData extends DataClass + implements Insertable { + final int id; + final DecryptedText cookie; + final DecryptedText accessToken; + final DateTime expiration; + const AuthenticationTableData( + {required this.id, + required this.cookie, + required this.accessToken, + required this.expiration}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + { + map['cookie'] = Variable( + $AuthenticationTableTable.$convertercookie.toSql(cookie)); + } + { + map['access_token'] = Variable( + $AuthenticationTableTable.$converteraccessToken.toSql(accessToken)); + } + map['expiration'] = Variable(expiration); + return map; + } + + AuthenticationTableCompanion toCompanion(bool nullToAbsent) { + return AuthenticationTableCompanion( + id: Value(id), + cookie: Value(cookie), + accessToken: Value(accessToken), + expiration: Value(expiration), + ); + } + + factory AuthenticationTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return AuthenticationTableData( + id: serializer.fromJson(json['id']), + cookie: serializer.fromJson(json['cookie']), + accessToken: serializer.fromJson(json['accessToken']), + expiration: serializer.fromJson(json['expiration']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'cookie': serializer.toJson(cookie), + 'accessToken': serializer.toJson(accessToken), + 'expiration': serializer.toJson(expiration), + }; + } + + AuthenticationTableData copyWith( + {int? id, + DecryptedText? cookie, + DecryptedText? accessToken, + DateTime? expiration}) => + AuthenticationTableData( + id: id ?? this.id, + cookie: cookie ?? this.cookie, + accessToken: accessToken ?? this.accessToken, + expiration: expiration ?? this.expiration, + ); + @override + String toString() { + return (StringBuffer('AuthenticationTableData(') + ..write('id: $id, ') + ..write('cookie: $cookie, ') + ..write('accessToken: $accessToken, ') + ..write('expiration: $expiration') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, cookie, accessToken, expiration); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is AuthenticationTableData && + other.id == this.id && + other.cookie == this.cookie && + other.accessToken == this.accessToken && + other.expiration == this.expiration); +} + +class AuthenticationTableCompanion + extends UpdateCompanion { + final Value id; + final Value cookie; + final Value accessToken; + final Value expiration; + const AuthenticationTableCompanion({ + this.id = const Value.absent(), + this.cookie = const Value.absent(), + this.accessToken = const Value.absent(), + this.expiration = const Value.absent(), + }); + AuthenticationTableCompanion.insert({ + this.id = const Value.absent(), + required DecryptedText cookie, + required DecryptedText accessToken, + required DateTime expiration, + }) : cookie = Value(cookie), + accessToken = Value(accessToken), + expiration = Value(expiration); + static Insertable custom({ + Expression? id, + Expression? cookie, + Expression? accessToken, + Expression? expiration, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (cookie != null) 'cookie': cookie, + if (accessToken != null) 'access_token': accessToken, + if (expiration != null) 'expiration': expiration, + }); + } + + AuthenticationTableCompanion copyWith( + {Value? id, + Value? cookie, + Value? accessToken, + Value? expiration}) { + return AuthenticationTableCompanion( + id: id ?? this.id, + cookie: cookie ?? this.cookie, + accessToken: accessToken ?? this.accessToken, + expiration: expiration ?? this.expiration, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (cookie.present) { + map['cookie'] = Variable( + $AuthenticationTableTable.$convertercookie.toSql(cookie.value)); + } + if (accessToken.present) { + map['access_token'] = Variable($AuthenticationTableTable + .$converteraccessToken + .toSql(accessToken.value)); + } + if (expiration.present) { + map['expiration'] = Variable(expiration.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('AuthenticationTableCompanion(') + ..write('id: $id, ') + ..write('cookie: $cookie, ') + ..write('accessToken: $accessToken, ') + ..write('expiration: $expiration') + ..write(')')) + .toString(); + } +} + +class $BlacklistTableTable extends BlacklistTable + with TableInfo<$BlacklistTableTable, BlacklistTableData> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $BlacklistTableTable(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 _nameMeta = const VerificationMeta('name'); + @override + late final GeneratedColumn name = GeneratedColumn( + 'name', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _elementTypeMeta = + const VerificationMeta('elementType'); + @override + late final GeneratedColumnWithTypeConverter + elementType = GeneratedColumn('element_type', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true) + .withConverter( + $BlacklistTableTable.$converterelementType); + static const VerificationMeta _elementIdMeta = + const VerificationMeta('elementId'); + @override + late final GeneratedColumn elementId = GeneratedColumn( + 'element_id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + @override + List get $columns => [id, name, elementType, elementId]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'blacklist_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('name')) { + context.handle( + _nameMeta, name.isAcceptableOrUnknown(data['name']!, _nameMeta)); + } else if (isInserting) { + context.missing(_nameMeta); + } + context.handle(_elementTypeMeta, const VerificationResult.success()); + if (data.containsKey('element_id')) { + context.handle(_elementIdMeta, + elementId.isAcceptableOrUnknown(data['element_id']!, _elementIdMeta)); + } else if (isInserting) { + context.missing(_elementIdMeta); + } + return context; + } + + @override + Set get $primaryKey => {id}; + @override + BlacklistTableData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return BlacklistTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + name: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}name'])!, + elementType: $BlacklistTableTable.$converterelementType.fromSql( + attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}element_type'])!), + elementId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}element_id'])!, + ); + } + + @override + $BlacklistTableTable createAlias(String alias) { + return $BlacklistTableTable(attachedDatabase, alias); + } + + static JsonTypeConverter2 + $converterelementType = + const EnumNameConverter(BlacklistedType.values); +} + +class BlacklistTableData extends DataClass + implements Insertable { + final int id; + final String name; + final BlacklistedType elementType; + final String elementId; + const BlacklistTableData( + {required this.id, + required this.name, + required this.elementType, + required this.elementId}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['name'] = Variable(name); + { + map['element_type'] = Variable( + $BlacklistTableTable.$converterelementType.toSql(elementType)); + } + map['element_id'] = Variable(elementId); + return map; + } + + BlacklistTableCompanion toCompanion(bool nullToAbsent) { + return BlacklistTableCompanion( + id: Value(id), + name: Value(name), + elementType: Value(elementType), + elementId: Value(elementId), + ); + } + + factory BlacklistTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return BlacklistTableData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + elementType: $BlacklistTableTable.$converterelementType + .fromJson(serializer.fromJson(json['elementType'])), + elementId: serializer.fromJson(json['elementId']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'elementType': serializer.toJson( + $BlacklistTableTable.$converterelementType.toJson(elementType)), + 'elementId': serializer.toJson(elementId), + }; + } + + BlacklistTableData copyWith( + {int? id, + String? name, + BlacklistedType? elementType, + String? elementId}) => + BlacklistTableData( + id: id ?? this.id, + name: name ?? this.name, + elementType: elementType ?? this.elementType, + elementId: elementId ?? this.elementId, + ); + @override + String toString() { + return (StringBuffer('BlacklistTableData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('elementType: $elementType, ') + ..write('elementId: $elementId') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, name, elementType, elementId); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is BlacklistTableData && + other.id == this.id && + other.name == this.name && + other.elementType == this.elementType && + other.elementId == this.elementId); +} + +class BlacklistTableCompanion extends UpdateCompanion { + final Value id; + final Value name; + final Value elementType; + final Value elementId; + const BlacklistTableCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.elementType = const Value.absent(), + this.elementId = const Value.absent(), + }); + BlacklistTableCompanion.insert({ + this.id = const Value.absent(), + required String name, + required BlacklistedType elementType, + required String elementId, + }) : name = Value(name), + elementType = Value(elementType), + elementId = Value(elementId); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? elementType, + Expression? elementId, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (elementType != null) 'element_type': elementType, + if (elementId != null) 'element_id': elementId, + }); + } + + BlacklistTableCompanion copyWith( + {Value? id, + Value? name, + Value? elementType, + Value? elementId}) { + return BlacklistTableCompanion( + id: id ?? this.id, + name: name ?? this.name, + elementType: elementType ?? this.elementType, + elementId: elementId ?? this.elementId, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (elementType.present) { + map['element_type'] = Variable( + $BlacklistTableTable.$converterelementType.toSql(elementType.value)); + } + if (elementId.present) { + map['element_id'] = Variable(elementId.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('BlacklistTableCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('elementType: $elementType, ') + ..write('elementId: $elementId') + ..write(')')) + .toString(); + } +} + class $PreferencesTableTable extends PreferencesTable with TableInfo<$PreferencesTableTable, PreferencesTableData> { @override @@ -1204,6 +1731,293 @@ class PreferencesTableCompanion extends UpdateCompanion { } } +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(); + } +} + class $SourceMatchTableTable extends SourceMatchTable with TableInfo<$SourceMatchTableTable, SourceMatchTableData> { @override @@ -1502,581 +2316,288 @@ class SourceMatchTableCompanion extends UpdateCompanion { } } -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(); - } -} - -class $BlacklistTableTable extends BlacklistTable - with TableInfo<$BlacklistTableTable, BlacklistTableData> { - @override - final GeneratedDatabase attachedDatabase; - final String? _alias; - $BlacklistTableTable(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 _nameMeta = const VerificationMeta('name'); - @override - late final GeneratedColumn name = GeneratedColumn( - 'name', aliasedName, false, - type: DriftSqlType.string, requiredDuringInsert: true); - static const VerificationMeta _elementTypeMeta = - const VerificationMeta('elementType'); - @override - late final GeneratedColumnWithTypeConverter - elementType = GeneratedColumn('element_type', aliasedName, false, - type: DriftSqlType.string, requiredDuringInsert: true) - .withConverter( - $BlacklistTableTable.$converterelementType); - static const VerificationMeta _elementIdMeta = - const VerificationMeta('elementId'); - @override - late final GeneratedColumn elementId = GeneratedColumn( - 'element_id', aliasedName, false, - type: DriftSqlType.string, requiredDuringInsert: true); - @override - List get $columns => [id, name, elementType, elementId]; - @override - String get aliasedName => _alias ?? actualTableName; - @override - String get actualTableName => $name; - static const String $name = 'blacklist_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('name')) { - context.handle( - _nameMeta, name.isAcceptableOrUnknown(data['name']!, _nameMeta)); - } else if (isInserting) { - context.missing(_nameMeta); - } - context.handle(_elementTypeMeta, const VerificationResult.success()); - if (data.containsKey('element_id')) { - context.handle(_elementIdMeta, - elementId.isAcceptableOrUnknown(data['element_id']!, _elementIdMeta)); - } else if (isInserting) { - context.missing(_elementIdMeta); - } - return context; - } - - @override - Set get $primaryKey => {id}; - @override - BlacklistTableData map(Map data, {String? tablePrefix}) { - final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; - return BlacklistTableData( - id: attachedDatabase.typeMapping - .read(DriftSqlType.int, data['${effectivePrefix}id'])!, - name: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}name'])!, - elementType: $BlacklistTableTable.$converterelementType.fromSql( - attachedDatabase.typeMapping.read( - DriftSqlType.string, data['${effectivePrefix}element_type'])!), - elementId: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}element_id'])!, - ); - } - - @override - $BlacklistTableTable createAlias(String alias) { - return $BlacklistTableTable(attachedDatabase, alias); - } - - static JsonTypeConverter2 - $converterelementType = - const EnumNameConverter(BlacklistedType.values); -} - -class BlacklistTableData extends DataClass - implements Insertable { - final int id; - final String name; - final BlacklistedType elementType; - final String elementId; - const BlacklistTableData( - {required this.id, - required this.name, - required this.elementType, - required this.elementId}); - @override - Map toColumns(bool nullToAbsent) { - final map = {}; - map['id'] = Variable(id); - map['name'] = Variable(name); - { - map['element_type'] = Variable( - $BlacklistTableTable.$converterelementType.toSql(elementType)); - } - map['element_id'] = Variable(elementId); - return map; - } - - BlacklistTableCompanion toCompanion(bool nullToAbsent) { - return BlacklistTableCompanion( - id: Value(id), - name: Value(name), - elementType: Value(elementType), - elementId: Value(elementId), - ); - } - - factory BlacklistTableData.fromJson(Map json, - {ValueSerializer? serializer}) { - serializer ??= driftRuntimeOptions.defaultSerializer; - return BlacklistTableData( - id: serializer.fromJson(json['id']), - name: serializer.fromJson(json['name']), - elementType: $BlacklistTableTable.$converterelementType - .fromJson(serializer.fromJson(json['elementType'])), - elementId: serializer.fromJson(json['elementId']), - ); - } - @override - Map toJson({ValueSerializer? serializer}) { - serializer ??= driftRuntimeOptions.defaultSerializer; - return { - 'id': serializer.toJson(id), - 'name': serializer.toJson(name), - 'elementType': serializer.toJson( - $BlacklistTableTable.$converterelementType.toJson(elementType)), - 'elementId': serializer.toJson(elementId), - }; - } - - BlacklistTableData copyWith( - {int? id, - String? name, - BlacklistedType? elementType, - String? elementId}) => - BlacklistTableData( - id: id ?? this.id, - name: name ?? this.name, - elementType: elementType ?? this.elementType, - elementId: elementId ?? this.elementId, - ); - @override - String toString() { - return (StringBuffer('BlacklistTableData(') - ..write('id: $id, ') - ..write('name: $name, ') - ..write('elementType: $elementType, ') - ..write('elementId: $elementId') - ..write(')')) - .toString(); - } - - @override - int get hashCode => Object.hash(id, name, elementType, elementId); - @override - bool operator ==(Object other) => - identical(this, other) || - (other is BlacklistTableData && - other.id == this.id && - other.name == this.name && - other.elementType == this.elementType && - other.elementId == this.elementId); -} - -class BlacklistTableCompanion extends UpdateCompanion { - final Value id; - final Value name; - final Value elementType; - final Value elementId; - const BlacklistTableCompanion({ - this.id = const Value.absent(), - this.name = const Value.absent(), - this.elementType = const Value.absent(), - this.elementId = const Value.absent(), - }); - BlacklistTableCompanion.insert({ - this.id = const Value.absent(), - required String name, - required BlacklistedType elementType, - required String elementId, - }) : name = Value(name), - elementType = Value(elementType), - elementId = Value(elementId); - static Insertable custom({ - Expression? id, - Expression? name, - Expression? elementType, - Expression? elementId, - }) { - return RawValuesInsertable({ - if (id != null) 'id': id, - if (name != null) 'name': name, - if (elementType != null) 'element_type': elementType, - if (elementId != null) 'element_id': elementId, - }); - } - - BlacklistTableCompanion copyWith( - {Value? id, - Value? name, - Value? elementType, - Value? elementId}) { - return BlacklistTableCompanion( - id: id ?? this.id, - name: name ?? this.name, - elementType: elementType ?? this.elementType, - elementId: elementId ?? this.elementId, - ); - } - - @override - Map toColumns(bool nullToAbsent) { - final map = {}; - if (id.present) { - map['id'] = Variable(id.value); - } - if (name.present) { - map['name'] = Variable(name.value); - } - if (elementType.present) { - map['element_type'] = Variable( - $BlacklistTableTable.$converterelementType.toSql(elementType.value)); - } - if (elementId.present) { - map['element_id'] = Variable(elementId.value); - } - return map; - } - - @override - String toString() { - return (StringBuffer('BlacklistTableCompanion(') - ..write('id: $id, ') - ..write('name: $name, ') - ..write('elementType: $elementType, ') - ..write('elementId: $elementId') - ..write(')')) - .toString(); - } -} - abstract class _$AppDatabase extends GeneratedDatabase { _$AppDatabase(QueryExecutor e) : super(e); _$AppDatabaseManager get managers => _$AppDatabaseManager(this); + late final $AuthenticationTableTable authenticationTable = + $AuthenticationTableTable(this); + late final $BlacklistTableTable blacklistTable = $BlacklistTableTable(this); late final $PreferencesTableTable preferencesTable = $PreferencesTableTable(this); - late final $SourceMatchTableTable sourceMatchTable = - $SourceMatchTableTable(this); late final $SkipSegmentTableTable skipSegmentTable = $SkipSegmentTableTable(this); - late final $BlacklistTableTable blacklistTable = $BlacklistTableTable(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)'); + late final $SourceMatchTableTable sourceMatchTable = + $SourceMatchTableTable(this); late final Index uniqueBlacklist = Index('unique_blacklist', 'CREATE UNIQUE INDEX unique_blacklist ON blacklist_table (element_type, element_id)'); + 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, - sourceMatchTable, - skipSegmentTable, + authenticationTable, blacklistTable, - uniqTrackMatch, - uniqueBlacklist + preferencesTable, + skipSegmentTable, + sourceMatchTable, + uniqueBlacklist, + uniqTrackMatch ]; } +typedef $$AuthenticationTableTableInsertCompanionBuilder + = AuthenticationTableCompanion Function({ + Value id, + required DecryptedText cookie, + required DecryptedText accessToken, + required DateTime expiration, +}); +typedef $$AuthenticationTableTableUpdateCompanionBuilder + = AuthenticationTableCompanion Function({ + Value id, + Value cookie, + Value accessToken, + Value expiration, +}); + +class $$AuthenticationTableTableTableManager extends RootTableManager< + _$AppDatabase, + $AuthenticationTableTable, + AuthenticationTableData, + $$AuthenticationTableTableFilterComposer, + $$AuthenticationTableTableOrderingComposer, + $$AuthenticationTableTableProcessedTableManager, + $$AuthenticationTableTableInsertCompanionBuilder, + $$AuthenticationTableTableUpdateCompanionBuilder> { + $$AuthenticationTableTableTableManager( + _$AppDatabase db, $AuthenticationTableTable table) + : super(TableManagerState( + db: db, + table: table, + filteringComposer: $$AuthenticationTableTableFilterComposer( + ComposerState(db, table)), + orderingComposer: $$AuthenticationTableTableOrderingComposer( + ComposerState(db, table)), + getChildManagerBuilder: (p) => + $$AuthenticationTableTableProcessedTableManager(p), + getUpdateCompanionBuilder: ({ + Value id = const Value.absent(), + Value cookie = const Value.absent(), + Value accessToken = const Value.absent(), + Value expiration = const Value.absent(), + }) => + AuthenticationTableCompanion( + id: id, + cookie: cookie, + accessToken: accessToken, + expiration: expiration, + ), + getInsertCompanionBuilder: ({ + Value id = const Value.absent(), + required DecryptedText cookie, + required DecryptedText accessToken, + required DateTime expiration, + }) => + AuthenticationTableCompanion.insert( + id: id, + cookie: cookie, + accessToken: accessToken, + expiration: expiration, + ), + )); +} + +class $$AuthenticationTableTableProcessedTableManager + extends ProcessedTableManager< + _$AppDatabase, + $AuthenticationTableTable, + AuthenticationTableData, + $$AuthenticationTableTableFilterComposer, + $$AuthenticationTableTableOrderingComposer, + $$AuthenticationTableTableProcessedTableManager, + $$AuthenticationTableTableInsertCompanionBuilder, + $$AuthenticationTableTableUpdateCompanionBuilder> { + $$AuthenticationTableTableProcessedTableManager(super.$state); +} + +class $$AuthenticationTableTableFilterComposer + extends FilterComposer<_$AppDatabase, $AuthenticationTableTable> { + $$AuthenticationTableTableFilterComposer(super.$state); + ColumnFilters get id => $state.composableBuilder( + column: $state.table.id, + builder: (column, joinBuilders) => + ColumnFilters(column, joinBuilders: joinBuilders)); + + ColumnWithTypeConverterFilters + get cookie => $state.composableBuilder( + column: $state.table.cookie, + builder: (column, joinBuilders) => ColumnWithTypeConverterFilters( + column, + joinBuilders: joinBuilders)); + + ColumnWithTypeConverterFilters + get accessToken => $state.composableBuilder( + column: $state.table.accessToken, + builder: (column, joinBuilders) => ColumnWithTypeConverterFilters( + column, + joinBuilders: joinBuilders)); + + ColumnFilters get expiration => $state.composableBuilder( + column: $state.table.expiration, + builder: (column, joinBuilders) => + ColumnFilters(column, joinBuilders: joinBuilders)); +} + +class $$AuthenticationTableTableOrderingComposer + extends OrderingComposer<_$AppDatabase, $AuthenticationTableTable> { + $$AuthenticationTableTableOrderingComposer(super.$state); + ColumnOrderings get id => $state.composableBuilder( + column: $state.table.id, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); + + ColumnOrderings get cookie => $state.composableBuilder( + column: $state.table.cookie, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); + + ColumnOrderings get accessToken => $state.composableBuilder( + column: $state.table.accessToken, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); + + ColumnOrderings get expiration => $state.composableBuilder( + column: $state.table.expiration, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); +} + +typedef $$BlacklistTableTableInsertCompanionBuilder = BlacklistTableCompanion + Function({ + Value id, + required String name, + required BlacklistedType elementType, + required String elementId, +}); +typedef $$BlacklistTableTableUpdateCompanionBuilder = BlacklistTableCompanion + Function({ + Value id, + Value name, + Value elementType, + Value elementId, +}); + +class $$BlacklistTableTableTableManager extends RootTableManager< + _$AppDatabase, + $BlacklistTableTable, + BlacklistTableData, + $$BlacklistTableTableFilterComposer, + $$BlacklistTableTableOrderingComposer, + $$BlacklistTableTableProcessedTableManager, + $$BlacklistTableTableInsertCompanionBuilder, + $$BlacklistTableTableUpdateCompanionBuilder> { + $$BlacklistTableTableTableManager( + _$AppDatabase db, $BlacklistTableTable table) + : super(TableManagerState( + db: db, + table: table, + filteringComposer: + $$BlacklistTableTableFilterComposer(ComposerState(db, table)), + orderingComposer: + $$BlacklistTableTableOrderingComposer(ComposerState(db, table)), + getChildManagerBuilder: (p) => + $$BlacklistTableTableProcessedTableManager(p), + getUpdateCompanionBuilder: ({ + Value id = const Value.absent(), + Value name = const Value.absent(), + Value elementType = const Value.absent(), + Value elementId = const Value.absent(), + }) => + BlacklistTableCompanion( + id: id, + name: name, + elementType: elementType, + elementId: elementId, + ), + getInsertCompanionBuilder: ({ + Value id = const Value.absent(), + required String name, + required BlacklistedType elementType, + required String elementId, + }) => + BlacklistTableCompanion.insert( + id: id, + name: name, + elementType: elementType, + elementId: elementId, + ), + )); +} + +class $$BlacklistTableTableProcessedTableManager extends ProcessedTableManager< + _$AppDatabase, + $BlacklistTableTable, + BlacklistTableData, + $$BlacklistTableTableFilterComposer, + $$BlacklistTableTableOrderingComposer, + $$BlacklistTableTableProcessedTableManager, + $$BlacklistTableTableInsertCompanionBuilder, + $$BlacklistTableTableUpdateCompanionBuilder> { + $$BlacklistTableTableProcessedTableManager(super.$state); +} + +class $$BlacklistTableTableFilterComposer + extends FilterComposer<_$AppDatabase, $BlacklistTableTable> { + $$BlacklistTableTableFilterComposer(super.$state); + ColumnFilters get id => $state.composableBuilder( + column: $state.table.id, + builder: (column, joinBuilders) => + ColumnFilters(column, joinBuilders: joinBuilders)); + + ColumnFilters get name => $state.composableBuilder( + column: $state.table.name, + builder: (column, joinBuilders) => + ColumnFilters(column, joinBuilders: joinBuilders)); + + ColumnWithTypeConverterFilters + get elementType => $state.composableBuilder( + column: $state.table.elementType, + builder: (column, joinBuilders) => ColumnWithTypeConverterFilters( + column, + joinBuilders: joinBuilders)); + + ColumnFilters get elementId => $state.composableBuilder( + column: $state.table.elementId, + builder: (column, joinBuilders) => + ColumnFilters(column, joinBuilders: joinBuilders)); +} + +class $$BlacklistTableTableOrderingComposer + extends OrderingComposer<_$AppDatabase, $BlacklistTableTable> { + $$BlacklistTableTableOrderingComposer(super.$state); + ColumnOrderings get id => $state.composableBuilder( + column: $state.table.id, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); + + ColumnOrderings get name => $state.composableBuilder( + column: $state.table.name, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); + + ColumnOrderings get elementType => $state.composableBuilder( + column: $state.table.elementType, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); + + ColumnOrderings get elementId => $state.composableBuilder( + column: $state.table.elementId, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); +} + typedef $$PreferencesTableTableInsertCompanionBuilder = PreferencesTableCompanion Function({ Value id, @@ -2560,6 +3081,145 @@ class $$PreferencesTableTableOrderingComposer 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)); +} + typedef $$SourceMatchTableTableInsertCompanionBuilder = SourceMatchTableCompanion Function({ Value id, @@ -2701,278 +3361,17 @@ class $$SourceMatchTableTableOrderingComposer 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)); -} - -typedef $$BlacklistTableTableInsertCompanionBuilder = BlacklistTableCompanion - Function({ - Value id, - required String name, - required BlacklistedType elementType, - required String elementId, -}); -typedef $$BlacklistTableTableUpdateCompanionBuilder = BlacklistTableCompanion - Function({ - Value id, - Value name, - Value elementType, - Value elementId, -}); - -class $$BlacklistTableTableTableManager extends RootTableManager< - _$AppDatabase, - $BlacklistTableTable, - BlacklistTableData, - $$BlacklistTableTableFilterComposer, - $$BlacklistTableTableOrderingComposer, - $$BlacklistTableTableProcessedTableManager, - $$BlacklistTableTableInsertCompanionBuilder, - $$BlacklistTableTableUpdateCompanionBuilder> { - $$BlacklistTableTableTableManager( - _$AppDatabase db, $BlacklistTableTable table) - : super(TableManagerState( - db: db, - table: table, - filteringComposer: - $$BlacklistTableTableFilterComposer(ComposerState(db, table)), - orderingComposer: - $$BlacklistTableTableOrderingComposer(ComposerState(db, table)), - getChildManagerBuilder: (p) => - $$BlacklistTableTableProcessedTableManager(p), - getUpdateCompanionBuilder: ({ - Value id = const Value.absent(), - Value name = const Value.absent(), - Value elementType = const Value.absent(), - Value elementId = const Value.absent(), - }) => - BlacklistTableCompanion( - id: id, - name: name, - elementType: elementType, - elementId: elementId, - ), - getInsertCompanionBuilder: ({ - Value id = const Value.absent(), - required String name, - required BlacklistedType elementType, - required String elementId, - }) => - BlacklistTableCompanion.insert( - id: id, - name: name, - elementType: elementType, - elementId: elementId, - ), - )); -} - -class $$BlacklistTableTableProcessedTableManager extends ProcessedTableManager< - _$AppDatabase, - $BlacklistTableTable, - BlacklistTableData, - $$BlacklistTableTableFilterComposer, - $$BlacklistTableTableOrderingComposer, - $$BlacklistTableTableProcessedTableManager, - $$BlacklistTableTableInsertCompanionBuilder, - $$BlacklistTableTableUpdateCompanionBuilder> { - $$BlacklistTableTableProcessedTableManager(super.$state); -} - -class $$BlacklistTableTableFilterComposer - extends FilterComposer<_$AppDatabase, $BlacklistTableTable> { - $$BlacklistTableTableFilterComposer(super.$state); - ColumnFilters get id => $state.composableBuilder( - column: $state.table.id, - builder: (column, joinBuilders) => - ColumnFilters(column, joinBuilders: joinBuilders)); - - ColumnFilters get name => $state.composableBuilder( - column: $state.table.name, - builder: (column, joinBuilders) => - ColumnFilters(column, joinBuilders: joinBuilders)); - - ColumnWithTypeConverterFilters - get elementType => $state.composableBuilder( - column: $state.table.elementType, - builder: (column, joinBuilders) => ColumnWithTypeConverterFilters( - column, - joinBuilders: joinBuilders)); - - ColumnFilters get elementId => $state.composableBuilder( - column: $state.table.elementId, - builder: (column, joinBuilders) => - ColumnFilters(column, joinBuilders: joinBuilders)); -} - -class $$BlacklistTableTableOrderingComposer - extends OrderingComposer<_$AppDatabase, $BlacklistTableTable> { - $$BlacklistTableTableOrderingComposer(super.$state); - ColumnOrderings get id => $state.composableBuilder( - column: $state.table.id, - builder: (column, joinBuilders) => - ColumnOrderings(column, joinBuilders: joinBuilders)); - - ColumnOrderings get name => $state.composableBuilder( - column: $state.table.name, - builder: (column, joinBuilders) => - ColumnOrderings(column, joinBuilders: joinBuilders)); - - ColumnOrderings get elementType => $state.composableBuilder( - column: $state.table.elementType, - builder: (column, joinBuilders) => - ColumnOrderings(column, joinBuilders: joinBuilders)); - - ColumnOrderings get elementId => $state.composableBuilder( - column: $state.table.elementId, - 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); + $$AuthenticationTableTableTableManager get authenticationTable => + $$AuthenticationTableTableTableManager(_db, _db.authenticationTable); $$BlacklistTableTableTableManager get blacklistTable => $$BlacklistTableTableTableManager(_db, _db.blacklistTable); + $$PreferencesTableTableTableManager get preferencesTable => + $$PreferencesTableTableTableManager(_db, _db.preferencesTable); + $$SkipSegmentTableTableTableManager get skipSegmentTable => + $$SkipSegmentTableTableTableManager(_db, _db.skipSegmentTable); + $$SourceMatchTableTableTableManager get sourceMatchTable => + $$SourceMatchTableTableTableManager(_db, _db.sourceMatchTable); } diff --git a/lib/models/database/tables/authentication.dart b/lib/models/database/tables/authentication.dart new file mode 100644 index 00000000..96041952 --- /dev/null +++ b/lib/models/database/tables/authentication.dart @@ -0,0 +1,8 @@ +part of '../database.dart'; + +class AuthenticationTable extends Table { + IntColumn get id => integer().autoIncrement()(); + TextColumn get cookie => text().map(EncryptedTextConverter())(); + TextColumn get accessToken => text().map(EncryptedTextConverter())(); + DateTimeColumn get expiration => dateTime()(); +} diff --git a/lib/models/database/typeconverters/encrypted_text.dart b/lib/models/database/typeconverters/encrypted_text.dart index 27921788..6afa8210 100644 --- a/lib/models/database/typeconverters/encrypted_text.dart +++ b/lib/models/database/typeconverters/encrypted_text.dart @@ -22,6 +22,11 @@ class DecryptedText { } String encrypt() { + _encrypter ??= Encrypter( + Salsa20( + Key.fromUtf8(EncryptedKvStoreService.encryptionKeySync), + ), + ); return _encrypter!.encrypt(value, iv: KVStoreService.ivKey).base64; } } diff --git a/lib/models/database/typeconverters/string_list.dart b/lib/models/database/typeconverters/string_list.dart index 5c30a997..466ae4c4 100644 --- a/lib/models/database/typeconverters/string_list.dart +++ b/lib/models/database/typeconverters/string_list.dart @@ -5,7 +5,7 @@ class StringListConverter extends TypeConverter, String> { @override List fromSql(String fromDb) { - return fromDb.split(","); + return fromDb.split(",").where((e) => e.isNotEmpty).toList(); } @override diff --git a/lib/modules/desktop_login/login_form.dart b/lib/modules/desktop_login/login_form.dart index 6091829c..e5d31215 100644 --- a/lib/modules/desktop_login/login_form.dart +++ b/lib/modules/desktop_login/login_form.dart @@ -3,7 +3,7 @@ import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:spotube/extensions/context.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; class TokenLoginForm extends HookConsumerWidget { final void Function()? onDone; @@ -52,10 +52,7 @@ class TokenLoginForm extends HookConsumerWidget { final cookieHeader = "sp_dc=${directCodeController.text.trim()}"; - authenticationNotifier.setCredentials( - await AuthenticationCredentials.fromCookie( - cookieHeader), - ); + await authenticationNotifier.login(cookieHeader); if (context.mounted) { onDone?.call(); } diff --git a/lib/modules/home/sections/friends.dart b/lib/modules/home/sections/friends.dart index 85325f5a..d6bed6a8 100644 --- a/lib/modules/home/sections/friends.dart +++ b/lib/modules/home/sections/friends.dart @@ -8,7 +8,7 @@ import 'package:spotube/collections/fake.dart'; import 'package:spotube/modules/home/sections/friends/friend_item.dart'; import 'package:spotube/hooks/utils/use_breakpoint_value.dart'; import 'package:spotube/models/spotify_friends.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/provider/spotify/spotify.dart'; class HomePageFriendsSection extends HookConsumerWidget { @@ -59,7 +59,7 @@ class HomePageFriendsSection extends HookConsumerWidget { if (friendsQuery.isLoading || friendsQuery.asData?.value.friends.isEmpty == true || - auth == null) { + auth.asData?.value == null) { return const SliverToBoxAdapter( child: SizedBox.shrink(), ); diff --git a/lib/modules/home/sections/new_releases.dart b/lib/modules/home/sections/new_releases.dart index 08b28138..e2b32741 100644 --- a/lib/modules/home/sections/new_releases.dart +++ b/lib/modules/home/sections/new_releases.dart @@ -3,7 +3,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/components/horizontal_playbutton_card_view/horizontal_playbutton_card_view.dart'; import 'package:spotube/extensions/context.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/provider/spotify/spotify.dart'; class HomeNewReleasesSection extends HookConsumerWidget { @@ -18,7 +18,7 @@ class HomeNewReleasesSection extends HookConsumerWidget { final albums = ref.watch(userArtistAlbumReleasesProvider); - if (auth == null || + if (auth.asData?.value == null || newReleases.isLoading || newReleases.asData?.value.items.isEmpty == true) { return const SizedBox.shrink(); diff --git a/lib/modules/library/local_folder/local_folder_item.dart b/lib/modules/library/local_folder/local_folder_item.dart index 9408d008..a5831fc2 100644 --- a/lib/modules/library/local_folder/local_folder_item.dart +++ b/lib/modules/library/local_folder/local_folder_item.dart @@ -46,7 +46,7 @@ class LocalFolderItem extends HookConsumerWidget { ...pathSegments.skip(pathSegments.length - 3).toList() ..removeLast(), ] - : pathSegments.take(pathSegments.length - 1).toList(); + : pathSegments.take(max(pathSegments.length - 1, 0)).toList(); final trackSnapshot = ref.watch( localTracksProvider.select( diff --git a/lib/modules/library/user_albums.dart b/lib/modules/library/user_albums.dart index 71e5b65a..c2c91293 100644 --- a/lib/modules/library/user_albums.dart +++ b/lib/modules/library/user_albums.dart @@ -14,7 +14,7 @@ import 'package:spotube/components/fallbacks/anonymous_fallback.dart'; import 'package:spotube/components/waypoint.dart'; import 'package:spotube/extensions/constrains.dart'; import 'package:spotube/extensions/context.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/provider/spotify/spotify.dart'; class UserAlbums extends HookConsumerWidget { @@ -46,7 +46,7 @@ class UserAlbums extends HookConsumerWidget { []; }, [albumsQuery.asData?.value, searchText.value]); - if (auth == null) { + if (auth.asData?.value == null) { return const AnonymousFallback(); } diff --git a/lib/modules/library/user_artists.dart b/lib/modules/library/user_artists.dart index dbdd8682..dd097080 100644 --- a/lib/modules/library/user_artists.dart +++ b/lib/modules/library/user_artists.dart @@ -14,7 +14,7 @@ import 'package:spotube/components/inter_scrollbar/inter_scrollbar.dart'; import 'package:spotube/components/waypoint.dart'; import 'package:spotube/extensions/constrains.dart'; import 'package:spotube/extensions/context.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/provider/spotify/spotify.dart'; class UserArtists extends HookConsumerWidget { @@ -48,7 +48,7 @@ class UserArtists extends HookConsumerWidget { final controller = useScrollController(); - if (auth == null) { + if (auth.asData?.value == null) { return const AnonymousFallback(); } diff --git a/lib/modules/library/user_playlists.dart b/lib/modules/library/user_playlists.dart index e0c501bb..577f9655 100644 --- a/lib/modules/library/user_playlists.dart +++ b/lib/modules/library/user_playlists.dart @@ -17,7 +17,7 @@ import 'package:spotube/components/waypoint.dart'; import 'package:spotube/extensions/constrains.dart'; import 'package:spotube/extensions/context.dart'; import 'package:spotube/pages/library/playlist_generate/playlist_generate.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/provider/spotify/spotify.dart'; import 'package:spotube/utils/platform.dart'; import 'package:spotube/utils/service_utils.dart'; @@ -75,7 +75,7 @@ class UserPlaylists extends HookConsumerWidget { final controller = useScrollController(); - if (auth == null) { + if (auth.asData?.value == null) { return const AnonymousFallback(); } diff --git a/lib/modules/player/player.dart b/lib/modules/player/player.dart index 6a8a3e52..66344792 100644 --- a/lib/modules/player/player.dart +++ b/lib/modules/player/player.dart @@ -24,7 +24,7 @@ import 'package:spotube/hooks/utils/use_custom_status_bar_color.dart'; import 'package:spotube/hooks/utils/use_palette_color.dart'; import 'package:spotube/models/local_track.dart'; import 'package:spotube/pages/lyrics/lyrics.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart'; import 'package:spotube/provider/server/active_sourced_track.dart'; import 'package:spotube/provider/volume_provider.dart'; diff --git a/lib/modules/player/player_actions.dart b/lib/modules/player/player_actions.dart index 41de7388..8fd434ad 100644 --- a/lib/modules/player/player_actions.dart +++ b/lib/modules/player/player_actions.dart @@ -13,7 +13,7 @@ import 'package:spotube/extensions/duration.dart'; import 'package:spotube/models/local_track.dart'; import 'package:spotube/models/logger.dart'; import 'package:spotube/provider/download_manager_provider.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart'; import 'package:spotube/provider/sleep_timer_provider.dart'; diff --git a/lib/modules/root/bottom_player.dart b/lib/modules/root/bottom_player.dart index 14784176..a77ab6fe 100644 --- a/lib/modules/root/bottom_player.dart +++ b/lib/modules/root/bottom_player.dart @@ -18,7 +18,7 @@ import 'package:spotube/extensions/image.dart'; import 'package:spotube/hooks/utils/use_brightness_value.dart'; import 'package:spotube/models/logger.dart'; import 'package:flutter/material.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart'; import 'package:spotube/provider/user_preferences/user_preferences_provider.dart'; diff --git a/lib/modules/root/sidebar.dart b/lib/modules/root/sidebar.dart index 592a3d90..ef735798 100644 --- a/lib/modules/root/sidebar.dart +++ b/lib/modules/root/sidebar.dart @@ -20,7 +20,7 @@ import 'package:spotube/hooks/controllers/use_sidebarx_controller.dart'; import 'package:spotube/pages/profile/profile.dart'; import 'package:spotube/pages/settings/settings.dart'; import 'package:spotube/provider/download_manager_provider.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/provider/spotify/spotify.dart'; import 'package:spotube/provider/user_preferences/user_preferences_provider.dart'; @@ -269,7 +269,7 @@ class SidebarFooter extends HookConsumerWidget { mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - if (auth != null && data == null) + if (auth.asData?.value != null && data == null) const CircularProgressIndicator() else if (data != null) Flexible( diff --git a/lib/pages/artist/section/header.dart b/lib/pages/artist/section/header.dart index a30535dd..7d7fa8ef 100644 --- a/lib/pages/artist/section/header.dart +++ b/lib/pages/artist/section/header.dart @@ -11,7 +11,7 @@ import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/image.dart'; import 'package:spotube/hooks/utils/use_breakpoint_value.dart'; import 'package:spotube/models/database/database.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/provider/blacklist_provider.dart'; import 'package:spotube/provider/spotify/spotify.dart'; import 'package:spotube/utils/primitive_utils.dart'; diff --git a/lib/pages/desktop_login/login_tutorial.dart b/lib/pages/desktop_login/login_tutorial.dart index d78143e4..ec62543c 100644 --- a/lib/pages/desktop_login/login_tutorial.dart +++ b/lib/pages/desktop_login/login_tutorial.dart @@ -9,7 +9,7 @@ import 'package:spotube/components/links/hyper_link.dart'; import 'package:spotube/components/titlebar/titlebar.dart'; import 'package:spotube/extensions/context.dart'; import 'package:spotube/pages/home/home.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/utils/service_utils.dart'; class LoginTutorial extends ConsumerWidget { @@ -18,8 +18,7 @@ class LoginTutorial extends ConsumerWidget { @override Widget build(BuildContext context, ref) { - ref.watch(authenticationProvider); - final authenticationNotifier = ref.watch(authenticationProvider.notifier); + final auth = ref.watch(authenticationProvider); final key = GlobalKey>(); final theme = Theme.of(context); @@ -53,7 +52,7 @@ class LoginTutorial extends ConsumerWidget { ), showBackButton: true, overrideDone: FilledButton( - onPressed: authenticationNotifier.isLoggedIn + onPressed: auth.asData?.value != null ? () { ServiceUtils.pushNamed(context, HomePage.name); } @@ -91,7 +90,7 @@ class LoginTutorial extends ConsumerWidget { bodyWidget: Text(context.l10n.step_3_steps, textAlign: TextAlign.left), ), - if (authenticationNotifier.isLoggedIn) + if (auth.asData?.value != null) PageViewModel( decoration: pageDecoration.copyWith( bodyAlignment: Alignment.center, diff --git a/lib/pages/lyrics/lyrics.dart b/lib/pages/lyrics/lyrics.dart index f75c715c..c484046b 100644 --- a/lib/pages/lyrics/lyrics.dart +++ b/lib/pages/lyrics/lyrics.dart @@ -17,7 +17,7 @@ import 'package:spotube/hooks/utils/use_custom_status_bar_color.dart'; import 'package:spotube/hooks/utils/use_palette_color.dart'; import 'package:spotube/pages/lyrics/plain_lyrics.dart'; import 'package:spotube/pages/lyrics/synced_lyrics.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart'; import 'package:spotube/utils/platform.dart'; import 'package:spotube/provider/spotify/spotify.dart'; @@ -84,7 +84,7 @@ class LyricsPage extends HookConsumerWidget { final auth = ref.watch(authenticationProvider); - if (auth == null) { + if (auth.asData?.value == null) { return Scaffold( appBar: !kIsMacOS && !isModal ? const PageWindowTitleBar() : null, body: const AnonymousFallback(), diff --git a/lib/pages/lyrics/mini_lyrics.dart b/lib/pages/lyrics/mini_lyrics.dart index 603f90d3..f9659538 100644 --- a/lib/pages/lyrics/mini_lyrics.dart +++ b/lib/pages/lyrics/mini_lyrics.dart @@ -14,7 +14,7 @@ import 'package:spotube/extensions/context.dart'; import 'package:spotube/hooks/utils/use_force_update.dart'; import 'package:spotube/pages/lyrics/plain_lyrics.dart'; import 'package:spotube/pages/lyrics/synced_lyrics.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart'; import 'package:spotube/utils/platform.dart'; import 'package:window_manager/window_manager.dart'; @@ -48,7 +48,7 @@ class MiniLyricsPage extends HookConsumerWidget { final auth = ref.watch(authenticationProvider); - if (auth == null) { + if (auth.asData?.value == null) { return const Scaffold( appBar: PageWindowTitleBar(), body: AnonymousFallback(), diff --git a/lib/pages/mobile_login/mobile_login.dart b/lib/pages/mobile_login/mobile_login.dart index 1f2df95a..290c2b2f 100644 --- a/lib/pages/mobile_login/mobile_login.dart +++ b/lib/pages/mobile_login/mobile_login.dart @@ -3,7 +3,7 @@ import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/utils/platform.dart'; class WebViewLogin extends HookConsumerWidget { @@ -53,9 +53,7 @@ class WebViewLogin extends HookConsumerWidget { final cookieHeader = "sp_dc=${cookies.firstWhere((element) => element.name == "sp_dc").value}"; - authenticationNotifier.setCredentials( - await AuthenticationCredentials.fromCookie(cookieHeader), - ); + await authenticationNotifier.login(cookieHeader); if (context.mounted) { // ignore: use_build_context_synchronously GoRouter.of(context).go("/"); diff --git a/lib/pages/search/search.dart b/lib/pages/search/search.dart index 4f53f8e6..e28a5eff 100644 --- a/lib/pages/search/search.dart +++ b/lib/pages/search/search.dart @@ -20,7 +20,7 @@ import 'package:spotube/pages/search/sections/albums.dart'; import 'package:spotube/pages/search/sections/artists.dart'; import 'package:spotube/pages/search/sections/playlists.dart'; import 'package:spotube/pages/search/sections/tracks.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/provider/spotify/spotify.dart'; import 'package:spotube/services/kv_store/kv_store.dart'; @@ -37,8 +37,7 @@ class SearchPage extends HookConsumerWidget { final searchTerm = ref.watch(searchTermStateProvider); final controller = useSearchController(); - ref.watch(authenticationProvider); - final authenticationNotifier = ref.watch(authenticationProvider.notifier); + final auth = ref.watch(authenticationProvider); final mediaQuery = MediaQuery.of(context); final searchTrack = ref.watch(searchProvider(SearchType.track)); @@ -91,7 +90,7 @@ class SearchPage extends HookConsumerWidget { appBar: kIsDesktop && !kIsMacOS ? const PageWindowTitleBar(automaticallyImplyLeading: true) : null, - body: !authenticationNotifier.isLoggedIn + body: auth.asData?.value == null ? const AnonymousFallback() : Column( children: [ diff --git a/lib/pages/settings/sections/accounts.dart b/lib/pages/settings/sections/accounts.dart index a007fbeb..1604f14b 100644 --- a/lib/pages/settings/sections/accounts.dart +++ b/lib/pages/settings/sections/accounts.dart @@ -9,7 +9,7 @@ import 'package:spotube/extensions/constrains.dart'; import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/image.dart'; import 'package:spotube/pages/profile/profile.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/provider/scrobbler_provider.dart'; import 'package:spotube/provider/spotify/spotify.dart'; import 'package:spotube/utils/service_utils.dart'; @@ -35,7 +35,7 @@ class SettingsAccountSection extends HookConsumerWidget { return SectionCardWithHeading( heading: context.l10n.account, children: [ - if (auth != null) + if (auth.asData?.value != null) ListTile( leading: const Icon(SpotubeIcons.user), title: const Text("User Profile"), @@ -53,7 +53,7 @@ class SettingsAccountSection extends HookConsumerWidget { ServiceUtils.pushNamed(context, ProfilePage.name); }, ), - if (auth == null) + if (auth.asData?.value == null) LayoutBuilder(builder: (context, constrains) { return ListTile( leading: Icon( diff --git a/lib/provider/authentication_provider.dart b/lib/provider/authentication/authentication.dart similarity index 51% rename from lib/provider/authentication_provider.dart rename to lib/provider/authentication/authentication.dart index 52c7f281..3ea8693b 100644 --- a/lib/provider/authentication_provider.dart +++ b/lib/provider/authentication/authentication.dart @@ -4,22 +4,30 @@ import 'dart:io'; import 'package:collection/collection.dart'; import 'package:dio/dio.dart'; import 'package:dio/io.dart'; +import 'package:drift/drift.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart' hide X509Certificate; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:spotube/collections/routes.dart'; import 'package:spotube/components/dialogs/prompt_dialog.dart'; import 'package:spotube/extensions/context.dart'; -import 'package:spotube/utils/persisted_state_notifier.dart'; +import 'package:spotube/models/database/database.dart'; +import 'package:spotube/provider/database/database.dart'; import 'package:spotube/utils/platform.dart'; -class AuthenticationCredentials { - String cookie; - String accessToken; - DateTime expiration; - +extension ExpirationAuthenticationTableData on AuthenticationTableData { bool get isExpired => DateTime.now().isAfter(expiration); + String? getCookie(String key) => cookie.value + .split("; ") + .firstWhereOrNull((c) => c.trim().startsWith("$key=")) + ?.trim() + .split("=") + .last + .replaceAll(";", ""); +} + +class AuthenticationNotifier extends AsyncNotifier { static final Dio dio = () { final dio = Dio(); @@ -32,13 +40,68 @@ class AuthenticationCredentials { return dio; }(); - AuthenticationCredentials({ - required this.cookie, - required this.accessToken, - required this.expiration, - }); + @override + build() async { + final database = ref.watch(databaseProvider); - static Future fromCookie(String cookie) async { + final data = await (database.select(database.authenticationTable) + ..where((s) => s.id.equals(0))) + .getSingleOrNull(); + + Timer? refreshTimer; + + ref.listenSelf((prevData, newData) async { + if (newData.asData?.value == null) return; + + if (newData.asData!.value!.isExpired) { + await refreshCredentials(); + } + + // set the refresh timer + refreshTimer?.cancel(); + refreshTimer = Timer( + newData.asData!.value!.expiration.difference(DateTime.now()), + () => refreshCredentials(), + ); + }); + + final subscription = + database.select(database.authenticationTable).watch().listen( + (event) { + state = AsyncData(event.isEmpty ? null : event.first); + }, + ); + + ref.onDispose(() { + subscription.cancel(); + refreshTimer?.cancel(); + }); + + return data; + } + + Future refreshCredentials() async { + final database = ref.read(databaseProvider); + final refreshedCredentials = + await credentialsFromCookie(state.asData!.value!.cookie.value); + + await database + .update(database.authenticationTable) + .replace(refreshedCredentials); + } + + Future login(String cookie) async { + final database = ref.read(databaseProvider); + final refreshedCredentials = await credentialsFromCookie(cookie); + + await database + .into(database.authenticationTable) + .insert(refreshedCredentials); + } + + Future credentialsFromCookie( + String cookie, + ) async { try { final spDc = cookie .split("; ") @@ -65,9 +128,10 @@ class AuthenticationCredentials { ); } - return AuthenticationCredentials( - cookie: "${res.headers["set-cookie"]?.join(";")}; $spDc", - accessToken: body['accessToken'], + return AuthenticationTableCompanion.insert( + id: const Value(0), + cookie: DecryptedText("${res.headers["set-cookie"]?.join(";")}; $spDc"), + accessToken: DecryptedText(body['accessToken']), expiration: DateTime.fromMillisecondsSinceEpoch( body['accessTokenExpirationTimestampMs'], ), @@ -86,102 +150,20 @@ class AuthenticationCredentials { } } - /// Returns the cookie value - String? getCookie(String key) => cookie - .split("; ") - .firstWhereOrNull((c) => c.trim().startsWith("$key=")) - ?.trim() - .split("=") - .last - .replaceAll(";", ""); - - factory AuthenticationCredentials.fromJson(Map json) { - return AuthenticationCredentials( - cookie: json['cookie'] as String, - accessToken: json['accessToken'] as String, - expiration: DateTime.parse(json['expiration'] as String), - ); - } - - Map toJson() { - return { - 'cookie': cookie, - 'accessToken': accessToken, - 'expiration': expiration.toIso8601String(), - }; - } - - AuthenticationCredentials copyWith({ - String? cookie, - String? accessToken, - DateTime? expiration, - }) { - return AuthenticationCredentials( - cookie: cookie ?? this.cookie, - accessToken: accessToken ?? this.accessToken, - expiration: expiration ?? this.expiration, - ); - } -} - -class AuthenticationNotifier - extends PersistedStateNotifier { - bool get isLoggedIn => state != null; - - AuthenticationNotifier() : super(null, "authentication", encrypted: true); - - Timer? _refreshTimer; - - @override - FutureOr onInit() async { - super.onInit(); - if (isLoggedIn && state!.isExpired) { - await refreshCredentials(); - } - - addListener((state) { - _refreshTimer?.cancel(); - if (isLoggedIn && !state!.isExpired) { - _refreshTimer = Timer( - state.expiration.difference(DateTime.now()), - () => refreshCredentials(), - ); - } - }); - } - - void setCredentials(AuthenticationCredentials credentials) { - state = credentials; - } - Future logout() async { - state = null; + state = const AsyncData(null); + final database = ref.read(databaseProvider); + await (database.delete(database.authenticationTable) + ..where((s) => s.id.equals(0))) + .go(); if (kIsMobile) { WebStorageManager.instance().deleteAllData(); CookieManager.instance().deleteAllCookies(); } } - - Future refreshCredentials() async { - if (!isLoggedIn) { - return; - } - - state = await AuthenticationCredentials.fromCookie(state!.cookie); - } - - @override - FutureOr fromJson(Map json) { - return AuthenticationCredentials.fromJson(json); - } - - @override - Map toJson() { - return state?.toJson() ?? {}; - } } final authenticationProvider = - StateNotifierProvider( - (ref) => AuthenticationNotifier(), + AsyncNotifierProvider( + () => AuthenticationNotifier(), ); diff --git a/lib/provider/custom_spotify_endpoint_provider.dart b/lib/provider/custom_spotify_endpoint_provider.dart index 4634549a..ad0c389a 100644 --- a/lib/provider/custom_spotify_endpoint_provider.dart +++ b/lib/provider/custom_spotify_endpoint_provider.dart @@ -1,10 +1,10 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/provider/spotify_provider.dart'; import 'package:spotube/services/custom_spotify_endpoints/spotify_endpoints.dart'; final customSpotifyEndpointProvider = Provider((ref) { ref.watch(spotifyProvider); final auth = ref.watch(authenticationProvider); - return CustomSpotifyEndpoints(auth?.accessToken ?? ""); + return CustomSpotifyEndpoints(auth.asData?.value?.accessToken.value ?? ""); }); diff --git a/lib/provider/spotify/views/home.dart b/lib/provider/spotify/views/home.dart index 51586953..ad6a076a 100644 --- a/lib/provider/spotify/views/home.dart +++ b/lib/provider/spotify/views/home.dart @@ -1,5 +1,5 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/provider/custom_spotify_endpoint_provider.dart'; import 'package:spotube/provider/user_preferences/user_preferences_provider.dart'; @@ -8,7 +8,7 @@ final homeViewProvider = FutureProvider((ref) async { userPreferencesProvider.select((s) => s.market), ); final spTCookie = ref.watch( - authenticationProvider.select((s) => s?.getCookie("sp_t")), + authenticationProvider.select((s) => s.asData?.value?.getCookie("sp_t")), ); if (spTCookie == null) return null; diff --git a/lib/provider/spotify/views/home_section.dart b/lib/provider/spotify/views/home_section.dart index 04c4cbd6..5eb9183d 100644 --- a/lib/provider/spotify/views/home_section.dart +++ b/lib/provider/spotify/views/home_section.dart @@ -1,6 +1,6 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:spotube/models/spotify/home_feed.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/provider/custom_spotify_endpoint_provider.dart'; import 'package:spotube/provider/user_preferences/user_preferences_provider.dart'; @@ -11,7 +11,7 @@ final homeSectionViewProvider = userPreferencesProvider.select((s) => s.market), ); final spTCookie = ref.watch( - authenticationProvider.select((s) => s?.getCookie("sp_t")), + authenticationProvider.select((s) => s.asData?.value?.getCookie("sp_t")), ); if (spTCookie == null) return null; diff --git a/lib/provider/spotify_provider.dart b/lib/provider/spotify_provider.dart index f8b6e044..5824cce0 100644 --- a/lib/provider/spotify_provider.dart +++ b/lib/provider/spotify_provider.dart @@ -2,14 +2,14 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/collections/env.dart'; -import 'package:spotube/provider/authentication_provider.dart'; +import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/utils/primitive_utils.dart'; final spotifyProvider = Provider((ref) { final authState = ref.watch(authenticationProvider); final anonCred = PrimitiveUtils.getRandomElement(Env.spotifySecrets); - if (authState == null) { + if (authState.asData?.value == null) { return SpotifyApi( SpotifyApiCredentials( anonCred["clientId"], @@ -18,5 +18,5 @@ final spotifyProvider = Provider((ref) { ); } - return SpotifyApi.withAccessToken(authState.accessToken); + return SpotifyApi.withAccessToken(authState.asData!.value!.accessToken.value); }); diff --git a/lib/provider/user_preferences/user_preferences_provider.dart b/lib/provider/user_preferences/user_preferences_provider.dart index 8b96305f..a730c313 100644 --- a/lib/provider/user_preferences/user_preferences_provider.dart +++ b/lib/provider/user_preferences/user_preferences_provider.dart @@ -134,8 +134,11 @@ class UserPreferencesNotifier extends Notifier { void setLocalLibraryLocation(List localLibraryDirs) { //if (localLibraryDir.isEmpty) return; - setData(PreferencesTableCompanion( - localLibraryLocation: Value(localLibraryDirs))); + setData( + PreferencesTableCompanion( + localLibraryLocation: Value(localLibraryDirs), + ), + ); } void setLayoutMode(LayoutMode mode) { diff --git a/lib/services/kv_store/encrypted_kv_store.dart b/lib/services/kv_store/encrypted_kv_store.dart index d8f69690..ab4a750e 100644 --- a/lib/services/kv_store/encrypted_kv_store.dart +++ b/lib/services/kv_store/encrypted_kv_store.dart @@ -1,6 +1,7 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:spotube/services/kv_store/kv_store.dart'; import 'package:uuid/uuid.dart'; +import 'package:spotube/utils/platform.dart'; abstract class EncryptedKvStoreService { static const _storage = FlutterSecureStorage( @@ -9,15 +10,21 @@ abstract class EncryptedKvStoreService { ), ); - static late final String _encryptionKeySync; + static String? _encryptionKeySync; static Future initialize() async { _encryptionKeySync = await encryptionKey; } - static String get encryptionKeySync => _encryptionKeySync; + static String get encryptionKeySync => _encryptionKeySync!; + + static bool get isUnsupportedPlatform => + kIsMacOS || kIsIOS || (kIsLinux && !kIsFlatpak); static Future get encryptionKey async { + if (isUnsupportedPlatform) { + return KVStoreService.encryptionKey; + } try { final value = await _storage.read(key: 'encryption'); final key = const Uuid().v4(); @@ -34,10 +41,17 @@ abstract class EncryptedKvStoreService { } static Future setEncryptionKey(String key) async { + if (isUnsupportedPlatform) { + await KVStoreService.setEncryptionKey(key); + return; + } + try { await _storage.write(key: 'encryption', value: key); } catch (e) { await KVStoreService.setEncryptionKey(key); + } finally { + _encryptionKeySync = key; } } }