mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 16:05:18 +00:00
feat(metadata-plugin): add local storage api
This commit is contained in:
parent
8ac30c0031
commit
abe04b28b2
@ -14,3 +14,5 @@ part 'playlist.dart';
|
|||||||
part 'search.dart';
|
part 'search.dart';
|
||||||
part 'track.dart';
|
part 'track.dart';
|
||||||
part 'user.dart';
|
part 'user.dart';
|
||||||
|
|
||||||
|
part 'plugin.dart';
|
||||||
|
@ -2430,3 +2430,241 @@ abstract class _SpotubeUserObject implements SpotubeUserObject {
|
|||||||
_$$SpotubeUserObjectImplCopyWith<_$SpotubeUserObjectImpl> get copyWith =>
|
_$$SpotubeUserObjectImplCopyWith<_$SpotubeUserObjectImpl> get copyWith =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PluginConfiguration _$PluginConfigurationFromJson(Map<String, dynamic> json) {
|
||||||
|
return _PluginConfiguration.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$PluginConfiguration {
|
||||||
|
PluginType get type => throw _privateConstructorUsedError;
|
||||||
|
String get name => throw _privateConstructorUsedError;
|
||||||
|
String get description => throw _privateConstructorUsedError;
|
||||||
|
String get version => throw _privateConstructorUsedError;
|
||||||
|
String get author => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Serializes this PluginConfiguration to a JSON map.
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Create a copy of PluginConfiguration
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
$PluginConfigurationCopyWith<PluginConfiguration> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $PluginConfigurationCopyWith<$Res> {
|
||||||
|
factory $PluginConfigurationCopyWith(
|
||||||
|
PluginConfiguration value, $Res Function(PluginConfiguration) then) =
|
||||||
|
_$PluginConfigurationCopyWithImpl<$Res, PluginConfiguration>;
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{PluginType type,
|
||||||
|
String name,
|
||||||
|
String description,
|
||||||
|
String version,
|
||||||
|
String author});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$PluginConfigurationCopyWithImpl<$Res, $Val extends PluginConfiguration>
|
||||||
|
implements $PluginConfigurationCopyWith<$Res> {
|
||||||
|
_$PluginConfigurationCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of PluginConfiguration
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? type = null,
|
||||||
|
Object? name = null,
|
||||||
|
Object? description = null,
|
||||||
|
Object? version = null,
|
||||||
|
Object? author = null,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
type: null == type
|
||||||
|
? _value.type
|
||||||
|
: type // ignore: cast_nullable_to_non_nullable
|
||||||
|
as PluginType,
|
||||||
|
name: null == name
|
||||||
|
? _value.name
|
||||||
|
: name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
description: null == description
|
||||||
|
? _value.description
|
||||||
|
: description // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
version: null == version
|
||||||
|
? _value.version
|
||||||
|
: version // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
author: null == author
|
||||||
|
? _value.author
|
||||||
|
: author // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
) as $Val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$PluginConfigurationImplCopyWith<$Res>
|
||||||
|
implements $PluginConfigurationCopyWith<$Res> {
|
||||||
|
factory _$$PluginConfigurationImplCopyWith(_$PluginConfigurationImpl value,
|
||||||
|
$Res Function(_$PluginConfigurationImpl) then) =
|
||||||
|
__$$PluginConfigurationImplCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{PluginType type,
|
||||||
|
String name,
|
||||||
|
String description,
|
||||||
|
String version,
|
||||||
|
String author});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$PluginConfigurationImplCopyWithImpl<$Res>
|
||||||
|
extends _$PluginConfigurationCopyWithImpl<$Res, _$PluginConfigurationImpl>
|
||||||
|
implements _$$PluginConfigurationImplCopyWith<$Res> {
|
||||||
|
__$$PluginConfigurationImplCopyWithImpl(_$PluginConfigurationImpl _value,
|
||||||
|
$Res Function(_$PluginConfigurationImpl) _then)
|
||||||
|
: super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of PluginConfiguration
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? type = null,
|
||||||
|
Object? name = null,
|
||||||
|
Object? description = null,
|
||||||
|
Object? version = null,
|
||||||
|
Object? author = null,
|
||||||
|
}) {
|
||||||
|
return _then(_$PluginConfigurationImpl(
|
||||||
|
type: null == type
|
||||||
|
? _value.type
|
||||||
|
: type // ignore: cast_nullable_to_non_nullable
|
||||||
|
as PluginType,
|
||||||
|
name: null == name
|
||||||
|
? _value.name
|
||||||
|
: name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
description: null == description
|
||||||
|
? _value.description
|
||||||
|
: description // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
version: null == version
|
||||||
|
? _value.version
|
||||||
|
: version // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
author: null == author
|
||||||
|
? _value.author
|
||||||
|
: author // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$PluginConfigurationImpl extends _PluginConfiguration {
|
||||||
|
_$PluginConfigurationImpl(
|
||||||
|
{required this.type,
|
||||||
|
required this.name,
|
||||||
|
required this.description,
|
||||||
|
required this.version,
|
||||||
|
required this.author})
|
||||||
|
: super._();
|
||||||
|
|
||||||
|
factory _$PluginConfigurationImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$PluginConfigurationImplFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final PluginType type;
|
||||||
|
@override
|
||||||
|
final String name;
|
||||||
|
@override
|
||||||
|
final String description;
|
||||||
|
@override
|
||||||
|
final String version;
|
||||||
|
@override
|
||||||
|
final String author;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'PluginConfiguration(type: $type, name: $name, description: $description, version: $version, author: $author)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$PluginConfigurationImpl &&
|
||||||
|
(identical(other.type, type) || other.type == type) &&
|
||||||
|
(identical(other.name, name) || other.name == name) &&
|
||||||
|
(identical(other.description, description) ||
|
||||||
|
other.description == description) &&
|
||||||
|
(identical(other.version, version) || other.version == version) &&
|
||||||
|
(identical(other.author, author) || other.author == author));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
Object.hash(runtimeType, type, name, description, version, author);
|
||||||
|
|
||||||
|
/// Create a copy of PluginConfiguration
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$PluginConfigurationImplCopyWith<_$PluginConfigurationImpl> get copyWith =>
|
||||||
|
__$$PluginConfigurationImplCopyWithImpl<_$PluginConfigurationImpl>(
|
||||||
|
this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$$PluginConfigurationImplToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _PluginConfiguration extends PluginConfiguration {
|
||||||
|
factory _PluginConfiguration(
|
||||||
|
{required final PluginType type,
|
||||||
|
required final String name,
|
||||||
|
required final String description,
|
||||||
|
required final String version,
|
||||||
|
required final String author}) = _$PluginConfigurationImpl;
|
||||||
|
_PluginConfiguration._() : super._();
|
||||||
|
|
||||||
|
factory _PluginConfiguration.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$PluginConfigurationImpl.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
PluginType get type;
|
||||||
|
@override
|
||||||
|
String get name;
|
||||||
|
@override
|
||||||
|
String get description;
|
||||||
|
@override
|
||||||
|
String get version;
|
||||||
|
@override
|
||||||
|
String get author;
|
||||||
|
|
||||||
|
/// Create a copy of PluginConfiguration
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$PluginConfigurationImplCopyWith<_$PluginConfigurationImpl> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
@ -223,3 +223,26 @@ Map<String, dynamic> _$$SpotubeUserObjectImplToJson(
|
|||||||
'externalUrl': instance.externalUrl,
|
'externalUrl': instance.externalUrl,
|
||||||
'displayName': instance.displayName,
|
'displayName': instance.displayName,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_$PluginConfigurationImpl _$$PluginConfigurationImplFromJson(Map json) =>
|
||||||
|
_$PluginConfigurationImpl(
|
||||||
|
type: $enumDecode(_$PluginTypeEnumMap, json['type']),
|
||||||
|
name: json['name'] as String,
|
||||||
|
description: json['description'] as String,
|
||||||
|
version: json['version'] as String,
|
||||||
|
author: json['author'] as String,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$PluginConfigurationImplToJson(
|
||||||
|
_$PluginConfigurationImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'type': _$PluginTypeEnumMap[instance.type]!,
|
||||||
|
'name': instance.name,
|
||||||
|
'description': instance.description,
|
||||||
|
'version': instance.version,
|
||||||
|
'author': instance.author,
|
||||||
|
};
|
||||||
|
|
||||||
|
const _$PluginTypeEnumMap = {
|
||||||
|
PluginType.metadata: 'metadata',
|
||||||
|
};
|
||||||
|
21
lib/models/metadata/plugin.dart
Normal file
21
lib/models/metadata/plugin.dart
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
part of 'metadata.dart';
|
||||||
|
|
||||||
|
enum PluginType { metadata }
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class PluginConfiguration with _$PluginConfiguration {
|
||||||
|
const PluginConfiguration._();
|
||||||
|
|
||||||
|
factory PluginConfiguration({
|
||||||
|
required PluginType type,
|
||||||
|
required String name,
|
||||||
|
required String description,
|
||||||
|
required String version,
|
||||||
|
required String author,
|
||||||
|
}) = _PluginConfiguration;
|
||||||
|
|
||||||
|
factory PluginConfiguration.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$PluginConfigurationFromJson(json);
|
||||||
|
|
||||||
|
String get slug => name.toLowerCase().replaceAll(RegExp(r'[^a-z0-9]+'), '-');
|
||||||
|
}
|
60
lib/services/metadata/apis/localstorage.dart
Normal file
60
lib/services/metadata/apis/localstorage.dart
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import 'package:flutter_js/flutter_js.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
class PluginLocalStorageApi {
|
||||||
|
final JavascriptRuntime runtime;
|
||||||
|
final SharedPreferences sharedPreferences;
|
||||||
|
|
||||||
|
final String pluginName;
|
||||||
|
|
||||||
|
PluginLocalStorageApi({
|
||||||
|
required this.runtime,
|
||||||
|
required this.sharedPreferences,
|
||||||
|
required this.pluginName,
|
||||||
|
}) {
|
||||||
|
runtime.onMessage("LocalStorage.getItem", (args) {
|
||||||
|
final key = args[0];
|
||||||
|
final value = getItem(key);
|
||||||
|
runtime.evaluate(
|
||||||
|
"""
|
||||||
|
eventEmitter.emit('LocalStorage.getItem', ${value != null ? "'$value'" : "null"});
|
||||||
|
""",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
runtime.onMessage("LocalStorage.setItem", (args) {
|
||||||
|
final map = args[0] as Map<String, dynamic>;
|
||||||
|
setItem(map["key"], map["value"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
runtime.onMessage("LocalStorage.removeItem", (args) {
|
||||||
|
final map = args[0];
|
||||||
|
removeItem(map["key"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
runtime.onMessage("LocalStorage.clear", (args) {
|
||||||
|
clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void setItem(String key, String value) async {
|
||||||
|
await sharedPreferences.setString("plugin.$pluginName.$key", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
String? getItem(String key) {
|
||||||
|
return sharedPreferences.getString("plugin.$pluginName.$key");
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeItem(String key) async {
|
||||||
|
await sharedPreferences.remove("plugin.$pluginName.$key");
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() async {
|
||||||
|
final keys = sharedPreferences.getKeys();
|
||||||
|
for (String key in keys) {
|
||||||
|
if (key.startsWith("plugin.$pluginName.")) {
|
||||||
|
await sharedPreferences.remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,8 +4,10 @@ import 'dart:convert';
|
|||||||
import 'package:flutter_js/extensions/fetch.dart';
|
import 'package:flutter_js/extensions/fetch.dart';
|
||||||
import 'package:flutter_js/extensions/xhr.dart';
|
import 'package:flutter_js/extensions/xhr.dart';
|
||||||
import 'package:flutter_js/flutter_js.dart';
|
import 'package:flutter_js/flutter_js.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:spotube/models/metadata/metadata.dart';
|
import 'package:spotube/models/metadata/metadata.dart';
|
||||||
import 'package:spotube/services/logger/logger.dart';
|
import 'package:spotube/services/logger/logger.dart';
|
||||||
|
import 'package:spotube/services/metadata/apis/localstorage.dart';
|
||||||
|
|
||||||
const defaultMetadataLimit = "20";
|
const defaultMetadataLimit = "20";
|
||||||
|
|
||||||
@ -13,10 +15,12 @@ const defaultMetadataLimit = "20";
|
|||||||
/// objects e.g. SpotubeTrack, SpotubePlaylist, etc.
|
/// objects e.g. SpotubeTrack, SpotubePlaylist, etc.
|
||||||
class MetadataApiSignature {
|
class MetadataApiSignature {
|
||||||
final JavascriptRuntime runtime;
|
final JavascriptRuntime runtime;
|
||||||
|
final PluginLocalStorageApi localStorageApi;
|
||||||
|
|
||||||
MetadataApiSignature._(this.runtime);
|
MetadataApiSignature._(this.runtime, this.localStorageApi);
|
||||||
|
|
||||||
static Future<MetadataApiSignature> init(String libraryCode) async {
|
static Future<MetadataApiSignature> init(
|
||||||
|
String libraryCode, PluginConfiguration config) async {
|
||||||
final runtime = getJavascriptRuntime(xhr: true).enableXhr();
|
final runtime = getJavascriptRuntime(xhr: true).enableXhr();
|
||||||
runtime.enableHandlePromises();
|
runtime.enableHandlePromises();
|
||||||
await runtime.enableFetch();
|
await runtime.enableFetch();
|
||||||
@ -41,7 +45,17 @@ class MetadataApiSignature {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return MetadataApiSignature._(runtime);
|
// Create all the PluginAPIs after library code is evaluated
|
||||||
|
final localStorageApi = PluginLocalStorageApi(
|
||||||
|
runtime: runtime,
|
||||||
|
sharedPreferences: await SharedPreferences.getInstance(),
|
||||||
|
pluginName: config.slug,
|
||||||
|
);
|
||||||
|
|
||||||
|
return MetadataApiSignature._(
|
||||||
|
runtime,
|
||||||
|
localStorageApi,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
Loading…
Reference in New Issue
Block a user