mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55: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 'track.dart';
|
||||
part 'user.dart';
|
||||
|
||||
part 'plugin.dart';
|
||||
|
@ -2430,3 +2430,241 @@ abstract class _SpotubeUserObject implements SpotubeUserObject {
|
||||
_$$SpotubeUserObjectImplCopyWith<_$SpotubeUserObjectImpl> get copyWith =>
|
||||
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,
|
||||
'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/xhr.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/services/logger/logger.dart';
|
||||
import 'package:spotube/services/metadata/apis/localstorage.dart';
|
||||
|
||||
const defaultMetadataLimit = "20";
|
||||
|
||||
@ -13,10 +15,12 @@ const defaultMetadataLimit = "20";
|
||||
/// objects e.g. SpotubeTrack, SpotubePlaylist, etc.
|
||||
class MetadataApiSignature {
|
||||
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();
|
||||
runtime.enableHandlePromises();
|
||||
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() {
|
||||
|
Loading…
Reference in New Issue
Block a user