feat: Add repository and plugin API version fields to metadata plugins

- Updated database schema to include `repository` and `pluginApiVersion` columns in the `MetadataPluginsTable`.
- Modified `PluginConfiguration` model to include new fields for `repository` and `pluginApiVersion`.
- Enhanced JSON serialization and deserialization for the new fields in `PluginConfiguration`.
- Refactored `SettingsMetadataProviderPage` to display installed plugins with their repository information.
- Created new components `MetadataInstalledPluginItem` and `MetadataPluginRepositoryItem` for better UI representation of plugins.
- Updated plugin installation logic to handle new fields and display relevant information.
- Bumped `youtube_explode_dart` dependency version to `2.5.1`.
This commit is contained in:
Kingkor Roy Tirtho 2025-07-18 15:55:28 +06:00
parent 2f304fa943
commit cdc64e4bb0
22 changed files with 719 additions and 212 deletions

View File

@ -1,3 +1,3 @@
{
"flutterSdkVersion": "3.32.5"
"flutterSdkVersion": "3.32.7"
}

2
.fvmrc
View File

@ -1,4 +1,4 @@
{
"flutter": "3.32.5",
"flutter": "3.32.7",
"flavors": {}
}

View File

@ -4,7 +4,7 @@ on:
pull_request:
env:
FLUTTER_VERSION: 3.32.5
FLUTTER_VERSION: 3.32.7
jobs:
lint:

View File

@ -20,7 +20,7 @@ on:
description: Dry run without uploading to release
env:
FLUTTER_VERSION: 3.32.5
FLUTTER_VERSION: 3.32.7
FLUTTER_CHANNEL: master
permissions:

View File

@ -30,5 +30,5 @@
"README.md": "LICENSE,CODE_OF_CONDUCT.md,CONTRIBUTING.md,SECURITY.md,CONTRIBUTION.md,CHANGELOG.md,PRIVACY_POLICY.md",
"*.dart": "${capture}.g.dart,${capture}.freezed.dart"
},
"dart.flutterSdkPath": ".fvm/versions/3.32.5"
"dart.flutterSdkPath": ".fvm/versions/3.32.7"
}

File diff suppressed because one or more lines are too long

View File

@ -3878,6 +3878,18 @@ class $MetadataPluginsTableTable extends MetadataPluginsTable
defaultConstraints:
GeneratedColumn.constraintIsAlways('CHECK ("selected" IN (0, 1))'),
defaultValue: const Constant(false));
static const VerificationMeta _repositoryMeta =
const VerificationMeta('repository');
@override
late final GeneratedColumn<String> repository = GeneratedColumn<String>(
'repository', aliasedName, true,
type: DriftSqlType.string, requiredDuringInsert: false);
static const VerificationMeta _pluginApiVersionMeta =
const VerificationMeta('pluginApiVersion');
@override
late final GeneratedColumn<String> pluginApiVersion = GeneratedColumn<String>(
'plugin_api_version', aliasedName, false,
type: DriftSqlType.string, requiredDuringInsert: true);
@override
List<GeneratedColumn> get $columns => [
id,
@ -3888,7 +3900,9 @@ class $MetadataPluginsTableTable extends MetadataPluginsTable
entryPoint,
apis,
abilities,
selected
selected,
repository,
pluginApiVersion
];
@override
String get aliasedName => _alias ?? actualTableName;
@ -3944,6 +3958,20 @@ class $MetadataPluginsTableTable extends MetadataPluginsTable
context.handle(_selectedMeta,
selected.isAcceptableOrUnknown(data['selected']!, _selectedMeta));
}
if (data.containsKey('repository')) {
context.handle(
_repositoryMeta,
repository.isAcceptableOrUnknown(
data['repository']!, _repositoryMeta));
}
if (data.containsKey('plugin_api_version')) {
context.handle(
_pluginApiVersionMeta,
pluginApiVersion.isAcceptableOrUnknown(
data['plugin_api_version']!, _pluginApiVersionMeta));
} else if (isInserting) {
context.missing(_pluginApiVersionMeta);
}
return context;
}
@ -3974,6 +4002,10 @@ class $MetadataPluginsTableTable extends MetadataPluginsTable
.read(DriftSqlType.string, data['${effectivePrefix}abilities'])!),
selected: attachedDatabase.typeMapping
.read(DriftSqlType.bool, data['${effectivePrefix}selected'])!,
repository: attachedDatabase.typeMapping
.read(DriftSqlType.string, data['${effectivePrefix}repository']),
pluginApiVersion: attachedDatabase.typeMapping.read(
DriftSqlType.string, data['${effectivePrefix}plugin_api_version'])!,
);
}
@ -3999,6 +4031,8 @@ class MetadataPluginsTableData extends DataClass
final List<String> apis;
final List<String> abilities;
final bool selected;
final String? repository;
final String pluginApiVersion;
const MetadataPluginsTableData(
{required this.id,
required this.name,
@ -4008,7 +4042,9 @@ class MetadataPluginsTableData extends DataClass
required this.entryPoint,
required this.apis,
required this.abilities,
required this.selected});
required this.selected,
this.repository,
required this.pluginApiVersion});
@override
Map<String, Expression> toColumns(bool nullToAbsent) {
final map = <String, Expression>{};
@ -4027,6 +4063,10 @@ class MetadataPluginsTableData extends DataClass
$MetadataPluginsTableTable.$converterabilities.toSql(abilities));
}
map['selected'] = Variable<bool>(selected);
if (!nullToAbsent || repository != null) {
map['repository'] = Variable<String>(repository);
}
map['plugin_api_version'] = Variable<String>(pluginApiVersion);
return map;
}
@ -4041,6 +4081,10 @@ class MetadataPluginsTableData extends DataClass
apis: Value(apis),
abilities: Value(abilities),
selected: Value(selected),
repository: repository == null && nullToAbsent
? const Value.absent()
: Value(repository),
pluginApiVersion: Value(pluginApiVersion),
);
}
@ -4057,6 +4101,8 @@ class MetadataPluginsTableData extends DataClass
apis: serializer.fromJson<List<String>>(json['apis']),
abilities: serializer.fromJson<List<String>>(json['abilities']),
selected: serializer.fromJson<bool>(json['selected']),
repository: serializer.fromJson<String?>(json['repository']),
pluginApiVersion: serializer.fromJson<String>(json['pluginApiVersion']),
);
}
@override
@ -4072,6 +4118,8 @@ class MetadataPluginsTableData extends DataClass
'apis': serializer.toJson<List<String>>(apis),
'abilities': serializer.toJson<List<String>>(abilities),
'selected': serializer.toJson<bool>(selected),
'repository': serializer.toJson<String?>(repository),
'pluginApiVersion': serializer.toJson<String>(pluginApiVersion),
};
}
@ -4084,7 +4132,9 @@ class MetadataPluginsTableData extends DataClass
String? entryPoint,
List<String>? apis,
List<String>? abilities,
bool? selected}) =>
bool? selected,
Value<String?> repository = const Value.absent(),
String? pluginApiVersion}) =>
MetadataPluginsTableData(
id: id ?? this.id,
name: name ?? this.name,
@ -4095,6 +4145,8 @@ class MetadataPluginsTableData extends DataClass
apis: apis ?? this.apis,
abilities: abilities ?? this.abilities,
selected: selected ?? this.selected,
repository: repository.present ? repository.value : this.repository,
pluginApiVersion: pluginApiVersion ?? this.pluginApiVersion,
);
MetadataPluginsTableData copyWithCompanion(
MetadataPluginsTableCompanion data) {
@ -4110,6 +4162,11 @@ class MetadataPluginsTableData extends DataClass
apis: data.apis.present ? data.apis.value : this.apis,
abilities: data.abilities.present ? data.abilities.value : this.abilities,
selected: data.selected.present ? data.selected.value : this.selected,
repository:
data.repository.present ? data.repository.value : this.repository,
pluginApiVersion: data.pluginApiVersion.present
? data.pluginApiVersion.value
: this.pluginApiVersion,
);
}
@ -4124,14 +4181,16 @@ class MetadataPluginsTableData extends DataClass
..write('entryPoint: $entryPoint, ')
..write('apis: $apis, ')
..write('abilities: $abilities, ')
..write('selected: $selected')
..write('selected: $selected, ')
..write('repository: $repository, ')
..write('pluginApiVersion: $pluginApiVersion')
..write(')'))
.toString();
}
@override
int get hashCode => Object.hash(id, name, description, version, author,
entryPoint, apis, abilities, selected);
entryPoint, apis, abilities, selected, repository, pluginApiVersion);
@override
bool operator ==(Object other) =>
identical(this, other) ||
@ -4144,7 +4203,9 @@ class MetadataPluginsTableData extends DataClass
other.entryPoint == this.entryPoint &&
other.apis == this.apis &&
other.abilities == this.abilities &&
other.selected == this.selected);
other.selected == this.selected &&
other.repository == this.repository &&
other.pluginApiVersion == this.pluginApiVersion);
}
class MetadataPluginsTableCompanion
@ -4158,6 +4219,8 @@ class MetadataPluginsTableCompanion
final Value<List<String>> apis;
final Value<List<String>> abilities;
final Value<bool> selected;
final Value<String?> repository;
final Value<String> pluginApiVersion;
const MetadataPluginsTableCompanion({
this.id = const Value.absent(),
this.name = const Value.absent(),
@ -4168,6 +4231,8 @@ class MetadataPluginsTableCompanion
this.apis = const Value.absent(),
this.abilities = const Value.absent(),
this.selected = const Value.absent(),
this.repository = const Value.absent(),
this.pluginApiVersion = const Value.absent(),
});
MetadataPluginsTableCompanion.insert({
this.id = const Value.absent(),
@ -4179,13 +4244,16 @@ class MetadataPluginsTableCompanion
required List<String> apis,
required List<String> abilities,
this.selected = const Value.absent(),
this.repository = const Value.absent(),
required String pluginApiVersion,
}) : name = Value(name),
description = Value(description),
version = Value(version),
author = Value(author),
entryPoint = Value(entryPoint),
apis = Value(apis),
abilities = Value(abilities);
abilities = Value(abilities),
pluginApiVersion = Value(pluginApiVersion);
static Insertable<MetadataPluginsTableData> custom({
Expression<int>? id,
Expression<String>? name,
@ -4196,6 +4264,8 @@ class MetadataPluginsTableCompanion
Expression<String>? apis,
Expression<String>? abilities,
Expression<bool>? selected,
Expression<String>? repository,
Expression<String>? pluginApiVersion,
}) {
return RawValuesInsertable({
if (id != null) 'id': id,
@ -4207,6 +4277,8 @@ class MetadataPluginsTableCompanion
if (apis != null) 'apis': apis,
if (abilities != null) 'abilities': abilities,
if (selected != null) 'selected': selected,
if (repository != null) 'repository': repository,
if (pluginApiVersion != null) 'plugin_api_version': pluginApiVersion,
});
}
@ -4219,7 +4291,9 @@ class MetadataPluginsTableCompanion
Value<String>? entryPoint,
Value<List<String>>? apis,
Value<List<String>>? abilities,
Value<bool>? selected}) {
Value<bool>? selected,
Value<String?>? repository,
Value<String>? pluginApiVersion}) {
return MetadataPluginsTableCompanion(
id: id ?? this.id,
name: name ?? this.name,
@ -4230,6 +4304,8 @@ class MetadataPluginsTableCompanion
apis: apis ?? this.apis,
abilities: abilities ?? this.abilities,
selected: selected ?? this.selected,
repository: repository ?? this.repository,
pluginApiVersion: pluginApiVersion ?? this.pluginApiVersion,
);
}
@ -4266,6 +4342,12 @@ class MetadataPluginsTableCompanion
if (selected.present) {
map['selected'] = Variable<bool>(selected.value);
}
if (repository.present) {
map['repository'] = Variable<String>(repository.value);
}
if (pluginApiVersion.present) {
map['plugin_api_version'] = Variable<String>(pluginApiVersion.value);
}
return map;
}
@ -4280,7 +4362,9 @@ class MetadataPluginsTableCompanion
..write('entryPoint: $entryPoint, ')
..write('apis: $apis, ')
..write('abilities: $abilities, ')
..write('selected: $selected')
..write('selected: $selected, ')
..write('repository: $repository, ')
..write('pluginApiVersion: $pluginApiVersion')
..write(')'))
.toString();
}
@ -6280,6 +6364,8 @@ typedef $$MetadataPluginsTableTableCreateCompanionBuilder
required List<String> apis,
required List<String> abilities,
Value<bool> selected,
Value<String?> repository,
required String pluginApiVersion,
});
typedef $$MetadataPluginsTableTableUpdateCompanionBuilder
= MetadataPluginsTableCompanion Function({
@ -6292,6 +6378,8 @@ typedef $$MetadataPluginsTableTableUpdateCompanionBuilder
Value<List<String>> apis,
Value<List<String>> abilities,
Value<bool> selected,
Value<String?> repository,
Value<String> pluginApiVersion,
});
class $$MetadataPluginsTableTableFilterComposer
@ -6333,6 +6421,13 @@ class $$MetadataPluginsTableTableFilterComposer
ColumnFilters<bool> get selected => $composableBuilder(
column: $table.selected, builder: (column) => ColumnFilters(column));
ColumnFilters<String> get repository => $composableBuilder(
column: $table.repository, builder: (column) => ColumnFilters(column));
ColumnFilters<String> get pluginApiVersion => $composableBuilder(
column: $table.pluginApiVersion,
builder: (column) => ColumnFilters(column));
}
class $$MetadataPluginsTableTableOrderingComposer
@ -6370,6 +6465,13 @@ class $$MetadataPluginsTableTableOrderingComposer
ColumnOrderings<bool> get selected => $composableBuilder(
column: $table.selected, builder: (column) => ColumnOrderings(column));
ColumnOrderings<String> get repository => $composableBuilder(
column: $table.repository, builder: (column) => ColumnOrderings(column));
ColumnOrderings<String> get pluginApiVersion => $composableBuilder(
column: $table.pluginApiVersion,
builder: (column) => ColumnOrderings(column));
}
class $$MetadataPluginsTableTableAnnotationComposer
@ -6407,6 +6509,12 @@ class $$MetadataPluginsTableTableAnnotationComposer
GeneratedColumn<bool> get selected =>
$composableBuilder(column: $table.selected, builder: (column) => column);
GeneratedColumn<String> get repository => $composableBuilder(
column: $table.repository, builder: (column) => column);
GeneratedColumn<String> get pluginApiVersion => $composableBuilder(
column: $table.pluginApiVersion, builder: (column) => column);
}
class $$MetadataPluginsTableTableTableManager extends RootTableManager<
@ -6448,6 +6556,8 @@ class $$MetadataPluginsTableTableTableManager extends RootTableManager<
Value<List<String>> apis = const Value.absent(),
Value<List<String>> abilities = const Value.absent(),
Value<bool> selected = const Value.absent(),
Value<String?> repository = const Value.absent(),
Value<String> pluginApiVersion = const Value.absent(),
}) =>
MetadataPluginsTableCompanion(
id: id,
@ -6459,6 +6569,8 @@ class $$MetadataPluginsTableTableTableManager extends RootTableManager<
apis: apis,
abilities: abilities,
selected: selected,
repository: repository,
pluginApiVersion: pluginApiVersion,
),
createCompanionCallback: ({
Value<int> id = const Value.absent(),
@ -6470,6 +6582,8 @@ class $$MetadataPluginsTableTableTableManager extends RootTableManager<
required List<String> apis,
required List<String> abilities,
Value<bool> selected = const Value.absent(),
Value<String?> repository = const Value.absent(),
required String pluginApiVersion,
}) =>
MetadataPluginsTableCompanion.insert(
id: id,
@ -6481,6 +6595,8 @@ class $$MetadataPluginsTableTableTableManager extends RootTableManager<
apis: apis,
abilities: abilities,
selected: selected,
repository: repository,
pluginApiVersion: pluginApiVersion,
),
withReferenceMapper: (p0) => p0
.map((e) => (e.readTable(table), BaseReferences(db, table, e)))

View File

@ -1891,6 +1891,8 @@ final class Schema7 extends i0.VersionedSchema {
_column_64,
_column_65,
_column_66,
_column_67,
_column_68,
],
attachedDatabase: database,
),
@ -1946,6 +1948,10 @@ class Shape15 extends i0.VersionedTable {
columnsByName['abilities']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<bool> get selected =>
columnsByName['selected']! as i1.GeneratedColumn<bool>;
i1.GeneratedColumn<String> get repository =>
columnsByName['repository']! as i1.GeneratedColumn<String>;
i1.GeneratedColumn<String> get pluginApiVersion =>
columnsByName['plugin_api_version']! as i1.GeneratedColumn<String>;
}
i1.GeneratedColumn<String> _column_59(String aliasedName) =>
@ -1977,6 +1983,12 @@ i1.GeneratedColumn<bool> _column_66(String aliasedName) =>
defaultConstraints: i1.GeneratedColumn.constraintIsAlways(
'CHECK ("selected" IN (0, 1))'),
defaultValue: const Constant(false));
i1.GeneratedColumn<String> _column_67(String aliasedName) =>
i1.GeneratedColumn<String>('repository', aliasedName, true,
type: i1.DriftSqlType.string);
i1.GeneratedColumn<String> _column_68(String aliasedName) =>
i1.GeneratedColumn<String>('plugin_api_version', aliasedName, false,
type: i1.DriftSqlType.string);
i0.MigrationStepWithVersion migrationSteps({
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,

View File

@ -10,4 +10,6 @@ class MetadataPluginsTable extends Table {
TextColumn get apis => text().map(const StringListConverter())();
TextColumn get abilities => text().map(const StringListConverter())();
BoolColumn get selected => boolean().withDefault(const Constant(false))();
TextColumn get repository => text().nullable()();
TextColumn get pluginApiVersion => text()();
}

View File

@ -4505,8 +4505,10 @@ mixin _$PluginConfiguration {
String get version => throw _privateConstructorUsedError;
String get author => throw _privateConstructorUsedError;
String get entryPoint => throw _privateConstructorUsedError;
String get pluginApiVersion => throw _privateConstructorUsedError;
List<PluginApis> get apis => throw _privateConstructorUsedError;
List<PluginAbilities> get abilities => throw _privateConstructorUsedError;
String? get repository => throw _privateConstructorUsedError;
/// Serializes this PluginConfiguration to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@ -4531,8 +4533,10 @@ abstract class $PluginConfigurationCopyWith<$Res> {
String version,
String author,
String entryPoint,
String pluginApiVersion,
List<PluginApis> apis,
List<PluginAbilities> abilities});
List<PluginAbilities> abilities,
String? repository});
}
/// @nodoc
@ -4556,8 +4560,10 @@ class _$PluginConfigurationCopyWithImpl<$Res, $Val extends PluginConfiguration>
Object? version = null,
Object? author = null,
Object? entryPoint = null,
Object? pluginApiVersion = null,
Object? apis = null,
Object? abilities = null,
Object? repository = freezed,
}) {
return _then(_value.copyWith(
type: null == type
@ -4584,6 +4590,10 @@ class _$PluginConfigurationCopyWithImpl<$Res, $Val extends PluginConfiguration>
? _value.entryPoint
: entryPoint // ignore: cast_nullable_to_non_nullable
as String,
pluginApiVersion: null == pluginApiVersion
? _value.pluginApiVersion
: pluginApiVersion // ignore: cast_nullable_to_non_nullable
as String,
apis: null == apis
? _value.apis
: apis // ignore: cast_nullable_to_non_nullable
@ -4592,6 +4602,10 @@ class _$PluginConfigurationCopyWithImpl<$Res, $Val extends PluginConfiguration>
? _value.abilities
: abilities // ignore: cast_nullable_to_non_nullable
as List<PluginAbilities>,
repository: freezed == repository
? _value.repository
: repository // ignore: cast_nullable_to_non_nullable
as String?,
) as $Val);
}
}
@ -4611,8 +4625,10 @@ abstract class _$$PluginConfigurationImplCopyWith<$Res>
String version,
String author,
String entryPoint,
String pluginApiVersion,
List<PluginApis> apis,
List<PluginAbilities> abilities});
List<PluginAbilities> abilities,
String? repository});
}
/// @nodoc
@ -4634,8 +4650,10 @@ class __$$PluginConfigurationImplCopyWithImpl<$Res>
Object? version = null,
Object? author = null,
Object? entryPoint = null,
Object? pluginApiVersion = null,
Object? apis = null,
Object? abilities = null,
Object? repository = freezed,
}) {
return _then(_$PluginConfigurationImpl(
type: null == type
@ -4662,6 +4680,10 @@ class __$$PluginConfigurationImplCopyWithImpl<$Res>
? _value.entryPoint
: entryPoint // ignore: cast_nullable_to_non_nullable
as String,
pluginApiVersion: null == pluginApiVersion
? _value.pluginApiVersion
: pluginApiVersion // ignore: cast_nullable_to_non_nullable
as String,
apis: null == apis
? _value._apis
: apis // ignore: cast_nullable_to_non_nullable
@ -4670,6 +4692,10 @@ class __$$PluginConfigurationImplCopyWithImpl<$Res>
? _value._abilities
: abilities // ignore: cast_nullable_to_non_nullable
as List<PluginAbilities>,
repository: freezed == repository
? _value.repository
: repository // ignore: cast_nullable_to_non_nullable
as String?,
));
}
}
@ -4684,8 +4710,10 @@ class _$PluginConfigurationImpl extends _PluginConfiguration {
required this.version,
required this.author,
required this.entryPoint,
required this.pluginApiVersion,
final List<PluginApis> apis = const [],
final List<PluginAbilities> abilities = const []})
final List<PluginAbilities> abilities = const [],
this.repository})
: _apis = apis,
_abilities = abilities,
super._();
@ -4705,6 +4733,8 @@ class _$PluginConfigurationImpl extends _PluginConfiguration {
final String author;
@override
final String entryPoint;
@override
final String pluginApiVersion;
final List<PluginApis> _apis;
@override
@JsonKey()
@ -4723,9 +4753,12 @@ class _$PluginConfigurationImpl extends _PluginConfiguration {
return EqualUnmodifiableListView(_abilities);
}
@override
final String? repository;
@override
String toString() {
return 'PluginConfiguration(type: $type, name: $name, description: $description, version: $version, author: $author, entryPoint: $entryPoint, apis: $apis, abilities: $abilities)';
return 'PluginConfiguration(type: $type, name: $name, description: $description, version: $version, author: $author, entryPoint: $entryPoint, pluginApiVersion: $pluginApiVersion, apis: $apis, abilities: $abilities, repository: $repository)';
}
@override
@ -4741,9 +4774,13 @@ class _$PluginConfigurationImpl extends _PluginConfiguration {
(identical(other.author, author) || other.author == author) &&
(identical(other.entryPoint, entryPoint) ||
other.entryPoint == entryPoint) &&
(identical(other.pluginApiVersion, pluginApiVersion) ||
other.pluginApiVersion == pluginApiVersion) &&
const DeepCollectionEquality().equals(other._apis, _apis) &&
const DeepCollectionEquality()
.equals(other._abilities, _abilities));
.equals(other._abilities, _abilities) &&
(identical(other.repository, repository) ||
other.repository == repository));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@ -4756,8 +4793,10 @@ class _$PluginConfigurationImpl extends _PluginConfiguration {
version,
author,
entryPoint,
pluginApiVersion,
const DeepCollectionEquality().hash(_apis),
const DeepCollectionEquality().hash(_abilities));
const DeepCollectionEquality().hash(_abilities),
repository);
/// Create a copy of PluginConfiguration
/// with the given fields replaced by the non-null parameter values.
@ -4784,8 +4823,10 @@ abstract class _PluginConfiguration extends PluginConfiguration {
required final String version,
required final String author,
required final String entryPoint,
required final String pluginApiVersion,
final List<PluginApis> apis,
final List<PluginAbilities> abilities}) = _$PluginConfigurationImpl;
final List<PluginAbilities> abilities,
final String? repository}) = _$PluginConfigurationImpl;
_PluginConfiguration._() : super._();
factory _PluginConfiguration.fromJson(Map<String, dynamic> json) =
@ -4804,9 +4845,13 @@ abstract class _PluginConfiguration extends PluginConfiguration {
@override
String get entryPoint;
@override
String get pluginApiVersion;
@override
List<PluginApis> get apis;
@override
List<PluginAbilities> get abilities;
@override
String? get repository;
/// Create a copy of PluginConfiguration
/// with the given fields replaced by the non-null parameter values.

View File

@ -425,6 +425,7 @@ _$PluginConfigurationImpl _$$PluginConfigurationImplFromJson(Map json) =>
version: json['version'] as String,
author: json['author'] as String,
entryPoint: json['entryPoint'] as String,
pluginApiVersion: json['pluginApiVersion'] as String,
apis: (json['apis'] as List<dynamic>?)
?.map((e) => $enumDecode(_$PluginApisEnumMap, e))
.toList() ??
@ -433,6 +434,7 @@ _$PluginConfigurationImpl _$$PluginConfigurationImplFromJson(Map json) =>
?.map((e) => $enumDecode(_$PluginAbilitiesEnumMap, e))
.toList() ??
const [],
repository: json['repository'] as String?,
);
Map<String, dynamic> _$$PluginConfigurationImplToJson(
@ -444,9 +446,11 @@ Map<String, dynamic> _$$PluginConfigurationImplToJson(
'version': instance.version,
'author': instance.author,
'entryPoint': instance.entryPoint,
'pluginApiVersion': instance.pluginApiVersion,
'apis': instance.apis.map((e) => _$PluginApisEnumMap[e]!).toList(),
'abilities':
instance.abilities.map((e) => _$PluginAbilitiesEnumMap[e]!).toList(),
'repository': instance.repository,
};
const _$PluginTypeEnumMap = {

View File

@ -17,8 +17,10 @@ class PluginConfiguration with _$PluginConfiguration {
required String version,
required String author,
required String entryPoint,
required String pluginApiVersion,
@Default([]) List<PluginApis> apis,
@Default([]) List<PluginAbilities> abilities,
String? repository,
}) = _PluginConfiguration;
factory PluginConfiguration.fromJson(Map<String, dynamic> json) =>

View File

@ -93,7 +93,6 @@ class BasicSourcedTrack {
final AudioSource source;
final TrackSourceInfo info;
final List<TrackSource> sources;
@JsonKey(defaultValue: [])
final List<TrackSourceInfo> siblings;
BasicSourcedTrack({
required this.query,

View File

@ -19,7 +19,7 @@ BasicSourcedTrack _$BasicSourcedTrackFromJson(Map json) => BasicSourcedTrack(
?.map((e) =>
TrackSourceInfo.fromJson(Map<String, dynamic>.from(e as Map)))
.toList() ??
[],
const [],
);
Map<String, dynamic> _$BasicSourcedTrackToJson(BasicSourcedTrack instance) =>

View File

@ -0,0 +1,162 @@
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:shadcn_flutter/shadcn_flutter.dart';
import 'package:shadcn_flutter/shadcn_flutter_extension.dart';
import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/models/metadata/metadata.dart';
import 'package:spotube/provider/metadata_plugin/core/auth.dart';
import 'package:spotube/provider/metadata_plugin/metadata_plugin_provider.dart';
import 'package:url_launcher/url_launcher.dart';
class MetadataInstalledPluginItem extends HookConsumerWidget {
final PluginConfiguration plugin;
final bool isDefault;
const MetadataInstalledPluginItem({
super.key,
required this.plugin,
required this.isDefault,
});
@override
Widget build(BuildContext context, ref) {
final metadataPlugin = ref.watch(metadataPluginProvider);
final isAuthenticated = ref.watch(metadataPluginAuthenticatedProvider);
final pluginsNotifier = ref.watch(metadataPluginsProvider.notifier);
final requiresAuth =
isDefault && plugin.abilities.contains(PluginAbilities.authentication);
return Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
spacing: 12,
children: [
FutureBuilder(
future: pluginsNotifier.getLogoPath(plugin),
builder: (context, snapshot) {
final repoUrl = plugin.repository != null
? Uri.tryParse(plugin.repository!)
: null;
final repoOwner = repoUrl?.pathSegments.firstOrNull;
final isOfficial =
repoUrl?.host == "github.com" && repoOwner == "KRTirtho";
return Basic(
leading: snapshot.hasData
? Image.file(
snapshot.data!,
width: 36,
height: 36,
)
: Container(
height: 36,
width: 36,
alignment: Alignment.center,
decoration: BoxDecoration(
color: context.theme.colorScheme.secondary,
borderRadius: BorderRadius.circular(8),
),
child: const Icon(SpotubeIcons.plugin),
),
title: Text(plugin.name),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 8,
children: [
Text(plugin.description),
if (repoUrl != null)
Row(
spacing: 8,
children: [
if (isOfficial)
const PrimaryBadge(
leading: Icon(SpotubeIcons.done),
child: Text("Official"),
)
else ...[
Text("Author: ${plugin.author}"),
const DestructiveBadge(
leading: Icon(SpotubeIcons.warning),
child: Text("Third-party"),
)
],
SecondaryBadge(
leading: repoUrl.host == "github.com"
? const Icon(SpotubeIcons.github)
: null,
child: Text(repoUrl.host),
onPressed: () {
launchUrl(repoUrl);
},
),
],
)
],
),
trailing: IconButton.ghost(
onPressed: () async {
await pluginsNotifier.removePlugin(plugin);
},
icon: const Icon(
SpotubeIcons.trash,
color: Colors.red,
),
),
);
},
),
if (plugin.abilities.contains(PluginAbilities.authentication) &&
isDefault)
Container(
decoration: BoxDecoration(
color: context.theme.colorScheme.secondary,
borderRadius: BorderRadius.circular(8),
),
padding: const EdgeInsets.all(12),
child: const Row(
spacing: 8,
children: [
Icon(SpotubeIcons.warning, color: Colors.yellow),
Text("Plugin requires authentication"),
],
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Button.secondary(
enabled: !isDefault,
onPressed: () async {
await pluginsNotifier.setDefaultPlugin(plugin);
},
child: isDefault
? const Text("Default")
: const Text("Set default"),
),
if (isAuthenticated.asData?.value != true &&
requiresAuth &&
isDefault)
Button.primary(
onPressed: () async {
await metadataPlugin.asData?.value?.auth.authenticate();
},
leading: const Icon(SpotubeIcons.login),
child: const Text("Login"),
)
else if (isAuthenticated.asData?.value == true &&
requiresAuth &&
isDefault)
Button.destructive(
onPressed: () async {
await metadataPlugin.asData?.value?.auth.logout();
},
leading: const Icon(SpotubeIcons.logout),
child: const Text("Logout"),
)
],
)
],
),
);
}
}

View File

@ -0,0 +1,174 @@
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_markdown_plus/flutter_markdown_plus.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:shadcn_flutter/shadcn_flutter.dart';
import 'package:shadcn_flutter/shadcn_flutter_extension.dart';
import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/models/metadata/metadata.dart';
import 'package:spotube/provider/metadata_plugin/metadata_plugin_provider.dart';
import 'package:url_launcher/url_launcher_string.dart';
class MetadataPluginRepositoryItem extends HookConsumerWidget {
final MetadataPluginRepository pluginRepo;
const MetadataPluginRepositoryItem({
super.key,
required this.pluginRepo,
});
@override
Widget build(BuildContext context, ref) {
final pluginsNotifier = ref.watch(metadataPluginsProvider.notifier);
final host = useMemoized(
() => Uri.parse(pluginRepo.repoUrl).host,
[pluginRepo.repoUrl],
);
final isInstalling = useState(false);
return Card(
child: Basic(
title: Text(pluginRepo.name),
subtitle: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 8,
children: [
Text(pluginRepo.description),
Row(
spacing: 8,
children: [
if (pluginRepo.owner == "KRTirtho") ...[
const PrimaryBadge(
leading: Icon(SpotubeIcons.done),
child: Text("Official"),
),
SecondaryBadge(
leading: host == "github.com"
? const Icon(SpotubeIcons.github)
: null,
child: Text(host),
onPressed: () {
launchUrlString(pluginRepo.repoUrl);
},
),
] else ...[
Text("Author: ${pluginRepo.owner}"),
const DestructiveBadge(
leading: Icon(SpotubeIcons.warning),
child: Text("Third-party"),
)
]
],
),
],
),
trailing: Button.primary(
enabled: !isInstalling.value,
onPressed: () async {
try {
isInstalling.value = true;
final pluginConfig = await pluginsNotifier
.downloadAndCachePlugin(pluginRepo.repoUrl);
if (!context.mounted) return;
final isOfficialPlugin = pluginRepo.owner == "KRTirtho";
final isAllowed = isOfficialPlugin
? true
: await showDialog<bool>(
context: context,
builder: (context) {
final pluginAbilities = pluginConfig.apis
.map((e) => "- Can access **${e.name}** API")
.join("\n\n");
return AlertDialog(
title:
const Text("Do you want to install this plugin?"),
content: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"This plugin is from a third-party repository. "
"Please ensure you trust the source before installing.",
),
const Gap(8),
FutureBuilder(
future:
pluginsNotifier.getLogoPath(pluginConfig),
builder: (context, snapshot) {
return Basic(
leading: snapshot.hasData
? Image.file(
snapshot.data!,
width: 36,
height: 36,
)
: Container(
height: 36,
width: 36,
alignment: Alignment.center,
decoration: BoxDecoration(
color: context
.theme.colorScheme.secondary,
borderRadius:
BorderRadius.circular(8),
),
child:
const Icon(SpotubeIcons.plugin),
),
title: Text(pluginConfig.name),
subtitle: Text(pluginConfig.description),
);
},
),
const Gap(8),
MarkdownBody(
data: "**Author**: ${pluginConfig.author}\n\n"
"**Repository**: [${pluginConfig.repository ?? 'N/A'}](${pluginConfig.repository})\n\n\n\n"
"This plugin can do following:\n\n"
"$pluginAbilities",
onTapLink: (text, href, title) {
if (href != null) {
launchUrlString(href);
}
},
),
],
),
actions: [
Button.secondary(
onPressed: () {
Navigator.of(context).pop(false);
},
child: const Text("Deny"),
),
Button.primary(
onPressed: () {
Navigator.of(context).pop(true);
},
child: const Text("Allow"),
),
],
);
},
);
if (isAllowed != true) return;
await pluginsNotifier.addPlugin(pluginConfig);
} finally {
if (context.mounted) {
isInstalling.value = false;
}
}
},
leading: isInstalling.value
? const CircularProgressIndicator()
: const Icon(SpotubeIcons.add),
child: const Text("Install"),
),
),
);
}
}

View File

@ -1,23 +1,24 @@
import 'package:auto_route/auto_route.dart';
import 'package:collection/collection.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:shadcn_flutter/shadcn_flutter.dart';
import 'package:shadcn_flutter/shadcn_flutter_extension.dart';
import 'package:skeletonizer/skeletonizer.dart';
import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/components/form/text_form_field.dart';
import 'package:spotube/components/titlebar/titlebar.dart';
import 'package:spotube/models/metadata/metadata.dart';
import 'package:spotube/provider/metadata_plugin/core/auth.dart';
import 'package:spotube/modules/metadata_plugins/installed_plugin.dart';
import 'package:spotube/modules/metadata_plugins/plugin_repository.dart';
import 'package:spotube/provider/metadata_plugin/core/repositories.dart';
import 'package:spotube/provider/metadata_plugin/metadata_plugin_provider.dart';
import 'package:file_picker/file_picker.dart';
import 'package:spotube/provider/metadata_plugin/utils/common.dart';
import 'package:spotube/utils/platform.dart';
import 'package:url_launcher/url_launcher_string.dart';
import 'package:very_good_infinite_list/very_good_infinite_list.dart';
import 'package:sliver_tools/sliver_tools.dart';
@RoutePage()
class SettingsMetadataProviderPage extends HookConsumerWidget {
@ -29,13 +30,27 @@ class SettingsMetadataProviderPage extends HookConsumerWidget {
final plugins = ref.watch(metadataPluginsProvider);
final pluginsNotifier = ref.watch(metadataPluginsProvider.notifier);
final metadataPlugin = ref.watch(metadataPluginProvider);
final isAuthenticated = ref.watch(metadataPluginAuthenticatedProvider);
final pluginReposSnapshot = ref.watch(metadataPluginRepositoriesProvider);
final pluginReposNotifier =
ref.watch(metadataPluginRepositoriesProvider.notifier);
final pluginRepos = pluginReposSnapshot.asData?.value.items ?? [];
final pluginRepos = useMemoized(
() {
final installedPluginIds = plugins.asData?.value.plugins
.map((e) => e.repository)
.nonNulls
.toList() ??
[];
final pluginRepos = pluginReposSnapshot.asData?.value.items ?? [];
if (installedPluginIds.isEmpty) return pluginRepos;
return pluginRepos
.whereNot((repo) => installedPluginIds.contains(repo.repoUrl))
.toList();
},
[plugins.asData?.value.plugins, pluginReposSnapshot.asData?.value],
);
return Scaffold(
headers: const [
@ -115,17 +130,18 @@ class SettingsMetadataProviderPage extends HookConsumerWidget {
),
),
const SliverGap(12),
SliverToBoxAdapter(
child: Row(
children: [
const Gap(8),
const Text("Installed").h4,
const Gap(8),
const Expanded(child: Divider()),
const Gap(8),
],
if (plugins.asData?.value.plugins.isNotEmpty ?? false)
SliverToBoxAdapter(
child: Row(
children: [
const Gap(8),
const Text("Installed").h4,
const Gap(8),
const Expanded(child: Divider()),
const Gap(8),
],
),
),
),
const SliverGap(20),
SliverList.separated(
itemCount: plugins.asData?.value.plugins.length ?? 0,
@ -133,105 +149,9 @@ class SettingsMetadataProviderPage extends HookConsumerWidget {
itemBuilder: (context, index) {
final plugin = plugins.asData!.value.plugins[index];
final isDefault = plugins.asData!.value.defaultPlugin == index;
final requiresAuth = isDefault &&
plugin.abilities.contains(PluginAbilities.authentication);
return Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
spacing: 12,
children: [
FutureBuilder(
future: pluginsNotifier.getLogoPath(plugin),
builder: (context, snapshot) {
return Basic(
leading: snapshot.hasData
? Image.file(
snapshot.data!,
width: 36,
height: 36,
)
: Container(
height: 36,
width: 36,
alignment: Alignment.center,
decoration: BoxDecoration(
color:
context.theme.colorScheme.secondary,
borderRadius: BorderRadius.circular(8),
),
child: const Icon(SpotubeIcons.plugin),
),
title: Text(plugin.name),
subtitle: Text(plugin.description),
trailing: IconButton.ghost(
onPressed: () async {
await pluginsNotifier.removePlugin(plugin);
},
icon: const Icon(
SpotubeIcons.trash,
color: Colors.red,
),
),
);
},
),
if (plugin.abilities
.contains(PluginAbilities.authentication) &&
isDefault)
Container(
decoration: BoxDecoration(
color: context.theme.colorScheme.secondary,
borderRadius: BorderRadius.circular(8),
),
padding: const EdgeInsets.all(12),
child: const Row(
spacing: 8,
children: [
Icon(SpotubeIcons.warning, color: Colors.yellow),
Text("Plugin requires authentication"),
],
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Button.secondary(
enabled: !isDefault,
onPressed: () async {
await pluginsNotifier.setDefaultPlugin(plugin);
},
child: isDefault
? const Text("Default")
: const Text("Set default"),
),
if (isAuthenticated.asData?.value != true &&
requiresAuth &&
isDefault)
Button.primary(
onPressed: () async {
await metadataPlugin.asData?.value?.auth
.authenticate();
},
leading: const Icon(SpotubeIcons.login),
child: const Text("Login"),
)
else if (isAuthenticated.asData?.value == true &&
requiresAuth &&
isDefault)
Button.destructive(
onPressed: () async {
await metadataPlugin.asData?.value?.auth
.logout();
},
leading: const Icon(SpotubeIcons.logout),
child: const Text("Logout"),
)
],
)
],
),
return MetadataInstalledPluginItem(
plugin: plugin,
isDefault: isDefault,
);
},
),
@ -248,67 +168,70 @@ class SettingsMetadataProviderPage extends HookConsumerWidget {
),
),
const SliverGap(12),
Skeletonizer.sliver(
enabled: pluginReposSnapshot.isLoading,
child: SliverInfiniteList(
isLoading: pluginReposSnapshot.isLoading &&
!pluginReposSnapshot.isLoadingNextPage,
itemCount: pluginRepos.length,
onFetchData: pluginReposNotifier.fetchMore,
itemBuilder: (context, index) {
final pluginRepo = pluginRepos[index];
final host = Uri.parse(pluginRepo.repoUrl).host;
SliverInfiniteList(
isLoading: pluginReposSnapshot.isLoading &&
!pluginReposSnapshot.isLoadingNextPage,
itemCount: pluginRepos.length,
onFetchData: pluginReposNotifier.fetchMore,
loadingBuilder: (context) {
return Skeletonizer(
enabled: true,
child: MetadataPluginRepositoryItem(
pluginRepo: MetadataPluginRepository(
name: "Loading...",
description: "Loading...",
repoUrl: "",
owner: "",
),
),
);
},
itemBuilder: (context, index) {
final pluginRepo = pluginRepos[index];
return Card(
child: Basic(
title: Text(pluginRepo.name),
subtitle: Column(
return MetadataPluginRepositoryItem(
pluginRepo: pluginRepo,
);
},
),
SliverCrossAxisConstrained(
maxCrossAxisExtent: 720,
child: SliverFillRemaining(
hasScrollBody: false,
child: Container(
alignment: Alignment.bottomCenter,
margin: const EdgeInsets.only(bottom: 20),
child: SafeArea(
child: Card(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 8,
spacing: 12,
children: [
Text(pluginRepo.description),
Row(
spacing: 8,
children: [
if (pluginRepo.owner == "KRTirtho") ...[
const PrimaryBadge(
leading: Icon(SpotubeIcons.done),
child: Text("Official"),
),
SecondaryBadge(
leading: host == "github.com"
? const Icon(SpotubeIcons.github)
: null,
child: Text(host),
onPressed: () {
launchUrlString(pluginRepo.repoUrl);
},
),
] else ...[
Text("Author: ${pluginRepo.owner}"),
const DestructiveBadge(
leading: Icon(SpotubeIcons.warning),
child: Text("Third-party"),
)
]
const Icon(SpotubeIcons.warning, size: 16),
const Text(
"Disclaimer",
style: TextStyle(fontWeight: FontWeight.bold),
).bold,
],
),
const Text(
"The Spotube team does not hold any responsibility (including legal) for any \"Third-party\" plugins.\n"
"Please use them at your own risk. For any bugs/issues, please report them to the plugin repository."
"\n\n"
"If any \"Third-party\" plugin is breaking ToS/DMCA of any service/legal entity, "
"please ask the \"Third-party\" plugin author or the hosting platform .e.g GitHub/Codeberg to take action. "
"Above listed (\"Third-party\" labelled) are all public/community maintained plugins. We're not curating them, "
"so we cannot take any action on them.\n\n",
).muted.xSmall,
],
),
trailing: Button.primary(
onPressed: () async {
final pluginConfig = await pluginsNotifier
.downloadAndCachePlugin(pluginRepo.repoUrl);
await pluginsNotifier.addPlugin(pluginConfig);
},
leading: const Icon(SpotubeIcons.add),
child: const Text("Install"),
),
),
);
},
),
),
),
),
],

View File

@ -101,6 +101,8 @@ class MetadataPluginNotifier extends AsyncNotifier<MetadataPluginState> {
description: plugin.description,
version: plugin.version,
entryPoint: plugin.entryPoint,
pluginApiVersion: plugin.pluginApiVersion,
repository: plugin.repository,
apis: plugin.apis
.map(
(e) => PluginApis.values.firstWhereOrNull(
@ -298,6 +300,8 @@ class MetadataPluginNotifier extends AsyncNotifier<MetadataPluginState> {
entryPoint: plugin.entryPoint,
apis: plugin.apis.map((e) => e.name).toList(),
abilities: plugin.abilities.map((e) => e.name).toList(),
pluginApiVersion: plugin.pluginApiVersion,
repository: Value(plugin.repository),
),
);
}

View File

@ -2829,10 +2829,10 @@ packages:
dependency: "direct main"
description:
name: youtube_explode_dart
sha256: "8db47e0f947598f6aa29d2862efb98b92af0c78990d4b23c224f3475c556b47b"
sha256: "9cd131624135065a6866c1e8ad4f4703e5bcfd1da322d4fddc55c972d04b6b22"
url: "https://pub.dev"
source: hosted
version: "2.4.2"
version: "2.5.1"
yt_dlp_dart:
dependency: "direct main"
description:

View File

@ -129,7 +129,7 @@ dependencies:
wikipedia_api: ^0.1.0
win32_registry: ^1.1.5
window_manager: ^0.4.3
youtube_explode_dart: ^2.4.2
youtube_explode_dart: ^2.5.1
yt_dlp_dart:
git:
url: https://github.com/KRTirtho/yt_dlp_dart.git

View File

@ -3,32 +3,32 @@
// ignore_for_file: type=lint
import 'package:drift/drift.dart';
import 'package:drift/internal/migrations.dart';
import 'schema_v3.dart' as v3;
import 'schema_v5.dart' as v5;
import 'schema_v6.dart' as v6;
import 'schema_v1.dart' as v1;
import 'schema_v2.dart' as v2;
import 'schema_v7.dart' as v7;
import 'schema_v3.dart' as v3;
import 'schema_v4.dart' as v4;
import 'schema_v5.dart' as v5;
import 'schema_v6.dart' as v6;
import 'schema_v7.dart' as v7;
class GeneratedHelper implements SchemaInstantiationHelper {
@override
GeneratedDatabase databaseForVersion(QueryExecutor db, int version) {
switch (version) {
case 3:
return v3.DatabaseAtV3(db);
case 5:
return v5.DatabaseAtV5(db);
case 6:
return v6.DatabaseAtV6(db);
case 1:
return v1.DatabaseAtV1(db);
case 2:
return v2.DatabaseAtV2(db);
case 7:
return v7.DatabaseAtV7(db);
case 3:
return v3.DatabaseAtV3(db);
case 4:
return v4.DatabaseAtV4(db);
case 5:
return v5.DatabaseAtV5(db);
case 6:
return v6.DatabaseAtV6(db);
case 7:
return v7.DatabaseAtV7(db);
default:
throw MissingSchemaException(version, versions);
}

View File

@ -3070,6 +3070,12 @@ class MetadataPluginsTable extends Table
defaultConstraints:
GeneratedColumn.constraintIsAlways('CHECK ("selected" IN (0, 1))'),
defaultValue: const Constant(false));
late final GeneratedColumn<String> repository = GeneratedColumn<String>(
'repository', aliasedName, true,
type: DriftSqlType.string, requiredDuringInsert: false);
late final GeneratedColumn<String> pluginApiVersion = GeneratedColumn<String>(
'plugin_api_version', aliasedName, false,
type: DriftSqlType.string, requiredDuringInsert: true);
@override
List<GeneratedColumn> get $columns => [
id,
@ -3080,7 +3086,9 @@ class MetadataPluginsTable extends Table
entryPoint,
apis,
abilities,
selected
selected,
repository,
pluginApiVersion
];
@override
String get aliasedName => _alias ?? actualTableName;
@ -3112,6 +3120,10 @@ class MetadataPluginsTable extends Table
.read(DriftSqlType.string, data['${effectivePrefix}abilities'])!,
selected: attachedDatabase.typeMapping
.read(DriftSqlType.bool, data['${effectivePrefix}selected'])!,
repository: attachedDatabase.typeMapping
.read(DriftSqlType.string, data['${effectivePrefix}repository']),
pluginApiVersion: attachedDatabase.typeMapping.read(
DriftSqlType.string, data['${effectivePrefix}plugin_api_version'])!,
);
}
@ -3132,6 +3144,8 @@ class MetadataPluginsTableData extends DataClass
final String apis;
final String abilities;
final bool selected;
final String? repository;
final String pluginApiVersion;
const MetadataPluginsTableData(
{required this.id,
required this.name,
@ -3141,7 +3155,9 @@ class MetadataPluginsTableData extends DataClass
required this.entryPoint,
required this.apis,
required this.abilities,
required this.selected});
required this.selected,
this.repository,
required this.pluginApiVersion});
@override
Map<String, Expression> toColumns(bool nullToAbsent) {
final map = <String, Expression>{};
@ -3154,6 +3170,10 @@ class MetadataPluginsTableData extends DataClass
map['apis'] = Variable<String>(apis);
map['abilities'] = Variable<String>(abilities);
map['selected'] = Variable<bool>(selected);
if (!nullToAbsent || repository != null) {
map['repository'] = Variable<String>(repository);
}
map['plugin_api_version'] = Variable<String>(pluginApiVersion);
return map;
}
@ -3168,6 +3188,10 @@ class MetadataPluginsTableData extends DataClass
apis: Value(apis),
abilities: Value(abilities),
selected: Value(selected),
repository: repository == null && nullToAbsent
? const Value.absent()
: Value(repository),
pluginApiVersion: Value(pluginApiVersion),
);
}
@ -3184,6 +3208,8 @@ class MetadataPluginsTableData extends DataClass
apis: serializer.fromJson<String>(json['apis']),
abilities: serializer.fromJson<String>(json['abilities']),
selected: serializer.fromJson<bool>(json['selected']),
repository: serializer.fromJson<String?>(json['repository']),
pluginApiVersion: serializer.fromJson<String>(json['pluginApiVersion']),
);
}
@override
@ -3199,6 +3225,8 @@ class MetadataPluginsTableData extends DataClass
'apis': serializer.toJson<String>(apis),
'abilities': serializer.toJson<String>(abilities),
'selected': serializer.toJson<bool>(selected),
'repository': serializer.toJson<String?>(repository),
'pluginApiVersion': serializer.toJson<String>(pluginApiVersion),
};
}
@ -3211,7 +3239,9 @@ class MetadataPluginsTableData extends DataClass
String? entryPoint,
String? apis,
String? abilities,
bool? selected}) =>
bool? selected,
Value<String?> repository = const Value.absent(),
String? pluginApiVersion}) =>
MetadataPluginsTableData(
id: id ?? this.id,
name: name ?? this.name,
@ -3222,6 +3252,8 @@ class MetadataPluginsTableData extends DataClass
apis: apis ?? this.apis,
abilities: abilities ?? this.abilities,
selected: selected ?? this.selected,
repository: repository.present ? repository.value : this.repository,
pluginApiVersion: pluginApiVersion ?? this.pluginApiVersion,
);
MetadataPluginsTableData copyWithCompanion(
MetadataPluginsTableCompanion data) {
@ -3237,6 +3269,11 @@ class MetadataPluginsTableData extends DataClass
apis: data.apis.present ? data.apis.value : this.apis,
abilities: data.abilities.present ? data.abilities.value : this.abilities,
selected: data.selected.present ? data.selected.value : this.selected,
repository:
data.repository.present ? data.repository.value : this.repository,
pluginApiVersion: data.pluginApiVersion.present
? data.pluginApiVersion.value
: this.pluginApiVersion,
);
}
@ -3251,14 +3288,16 @@ class MetadataPluginsTableData extends DataClass
..write('entryPoint: $entryPoint, ')
..write('apis: $apis, ')
..write('abilities: $abilities, ')
..write('selected: $selected')
..write('selected: $selected, ')
..write('repository: $repository, ')
..write('pluginApiVersion: $pluginApiVersion')
..write(')'))
.toString();
}
@override
int get hashCode => Object.hash(id, name, description, version, author,
entryPoint, apis, abilities, selected);
entryPoint, apis, abilities, selected, repository, pluginApiVersion);
@override
bool operator ==(Object other) =>
identical(this, other) ||
@ -3271,7 +3310,9 @@ class MetadataPluginsTableData extends DataClass
other.entryPoint == this.entryPoint &&
other.apis == this.apis &&
other.abilities == this.abilities &&
other.selected == this.selected);
other.selected == this.selected &&
other.repository == this.repository &&
other.pluginApiVersion == this.pluginApiVersion);
}
class MetadataPluginsTableCompanion
@ -3285,6 +3326,8 @@ class MetadataPluginsTableCompanion
final Value<String> apis;
final Value<String> abilities;
final Value<bool> selected;
final Value<String?> repository;
final Value<String> pluginApiVersion;
const MetadataPluginsTableCompanion({
this.id = const Value.absent(),
this.name = const Value.absent(),
@ -3295,6 +3338,8 @@ class MetadataPluginsTableCompanion
this.apis = const Value.absent(),
this.abilities = const Value.absent(),
this.selected = const Value.absent(),
this.repository = const Value.absent(),
this.pluginApiVersion = const Value.absent(),
});
MetadataPluginsTableCompanion.insert({
this.id = const Value.absent(),
@ -3306,13 +3351,16 @@ class MetadataPluginsTableCompanion
required String apis,
required String abilities,
this.selected = const Value.absent(),
this.repository = const Value.absent(),
required String pluginApiVersion,
}) : name = Value(name),
description = Value(description),
version = Value(version),
author = Value(author),
entryPoint = Value(entryPoint),
apis = Value(apis),
abilities = Value(abilities);
abilities = Value(abilities),
pluginApiVersion = Value(pluginApiVersion);
static Insertable<MetadataPluginsTableData> custom({
Expression<int>? id,
Expression<String>? name,
@ -3323,6 +3371,8 @@ class MetadataPluginsTableCompanion
Expression<String>? apis,
Expression<String>? abilities,
Expression<bool>? selected,
Expression<String>? repository,
Expression<String>? pluginApiVersion,
}) {
return RawValuesInsertable({
if (id != null) 'id': id,
@ -3334,6 +3384,8 @@ class MetadataPluginsTableCompanion
if (apis != null) 'apis': apis,
if (abilities != null) 'abilities': abilities,
if (selected != null) 'selected': selected,
if (repository != null) 'repository': repository,
if (pluginApiVersion != null) 'plugin_api_version': pluginApiVersion,
});
}
@ -3346,7 +3398,9 @@ class MetadataPluginsTableCompanion
Value<String>? entryPoint,
Value<String>? apis,
Value<String>? abilities,
Value<bool>? selected}) {
Value<bool>? selected,
Value<String?>? repository,
Value<String>? pluginApiVersion}) {
return MetadataPluginsTableCompanion(
id: id ?? this.id,
name: name ?? this.name,
@ -3357,6 +3411,8 @@ class MetadataPluginsTableCompanion
apis: apis ?? this.apis,
abilities: abilities ?? this.abilities,
selected: selected ?? this.selected,
repository: repository ?? this.repository,
pluginApiVersion: pluginApiVersion ?? this.pluginApiVersion,
);
}
@ -3390,6 +3446,12 @@ class MetadataPluginsTableCompanion
if (selected.present) {
map['selected'] = Variable<bool>(selected.value);
}
if (repository.present) {
map['repository'] = Variable<String>(repository.value);
}
if (pluginApiVersion.present) {
map['plugin_api_version'] = Variable<String>(pluginApiVersion.value);
}
return map;
}
@ -3404,7 +3466,9 @@ class MetadataPluginsTableCompanion
..write('entryPoint: $entryPoint, ')
..write('apis: $apis, ')
..write('abilities: $abilities, ')
..write('selected: $selected')
..write('selected: $selected, ')
..write('repository: $repository, ')
..write('pluginApiVersion: $pluginApiVersion')
..write(')'))
.toString();
}