mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-12 23:45:18 +00:00
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:
parent
2f304fa943
commit
cdc64e4bb0
@ -1,3 +1,3 @@
|
||||
{
|
||||
"flutterSdkVersion": "3.32.5"
|
||||
"flutterSdkVersion": "3.32.7"
|
||||
}
|
2
.github/workflows/pr-lint.yml
vendored
2
.github/workflows/pr-lint.yml
vendored
@ -4,7 +4,7 @@ on:
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
FLUTTER_VERSION: 3.32.5
|
||||
FLUTTER_VERSION: 3.32.7
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
|
2
.github/workflows/spotube-release-binary.yml
vendored
2
.github/workflows/spotube-release-binary.yml
vendored
@ -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:
|
||||
|
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@ -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
@ -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)))
|
||||
|
@ -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,
|
||||
|
@ -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()();
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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 = {
|
||||
|
@ -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) =>
|
||||
|
@ -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,
|
||||
|
@ -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) =>
|
||||
|
162
lib/modules/metadata_plugins/installed_plugin.dart
Normal file
162
lib/modules/metadata_plugins/installed_plugin.dart
Normal 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"),
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
174
lib/modules/metadata_plugins/plugin_repository.dart
Normal file
174
lib/modules/metadata_plugins/plugin_repository.dart
Normal 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"),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -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 = 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,6 +130,7 @@ class SettingsMetadataProviderPage extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
const SliverGap(12),
|
||||
if (plugins.asData?.value.plugins.isNotEmpty ?? false)
|
||||
SliverToBoxAdapter(
|
||||
child: Row(
|
||||
children: [
|
||||
@ -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(
|
||||
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];
|
||||
final host = Uri.parse(pluginRepo.repoUrl).host;
|
||||
|
||||
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"),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -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),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user