Update purplebase, better modelling

This commit is contained in:
franzap
2024-05-28 12:45:24 -03:00
parent a921bcbcb4
commit eb144190ab
13 changed files with 202 additions and 115 deletions
+23 -8
View File
@@ -26,9 +26,20 @@ part 'app.g.dart';
@JsonSerializable()
@DataAdapter([NostrAdapter, AppAdapter])
class App extends BaseApp with DataModelMixin<App> {
late final HasMany<Release> releases;
late final BelongsTo<User> signer;
late final BelongsTo<User> developer;
final HasMany<Release> releases;
final BelongsTo<User> signer;
final BelongsTo<User> developer;
App(
{super.id,
super.pubkey,
super.createdAt,
super.content,
super.tags,
super.signature,
required this.developer,
required this.releases,
required this.signer});
String? get installedVersion =>
DataModel.adapterFor(this).ref.read(installedAppProvider)[id!.toString()];
@@ -277,11 +288,15 @@ mixin AppAdapter on Adapter<App> {
@override
DeserializedData<App> deserialize(Object? data, {String? key}) {
// map['signer'] = map['pubkey'];
// final zapTags = (map['tags'] as Iterable).where((t) => t[0] == 'zap');
// if (zapTags.length == 1) {
// map['developer'] = (zapTags.first as List)[1];
// }
final list = data is Iterable ? data : [data as Map];
for (final e in list) {
final map = e as Map<String, dynamic>;
map['signer'] = map['pubkey'];
final zapTags = (map['tags'] as Iterable).where((t) => t[0] == 'zap');
if (zapTags.length == 1) {
map['developer'] = (zapTags.first as List)[1];
}
}
return super.deserialize(data);
}
}
+19 -16
View File
@@ -87,21 +87,25 @@ extension AppRelationshipGraphNodeX on RelationshipGraphNode<App> {
// JsonSerializableGenerator
// **************************************************************************
App _$AppFromJson(Map<String, dynamic> json) => App()
..id = json['id']
..pubkey = json['pubkey'] as String
..createdAt = DateTime.parse(json['createdAt'] as String)
..content = json['content'] as String
..tags = (json['tags'] as List<dynamic>)
.map((e) => (e as List<dynamic>).map((e) => e as String).toList())
.toList()
..signature = json['signature'] as String?
..kind = (json['kind'] as num).toInt()
..releases =
HasMany<Release>.fromJson(json['releases'] as Map<String, dynamic>)
..signer = BelongsTo<User>.fromJson(json['signer'] as Map<String, dynamic>)
..developer =
BelongsTo<User>.fromJson(json['developer'] as Map<String, dynamic>);
App _$AppFromJson(Map<String, dynamic> json) => App(
id: json['id'],
pubkey: json['pubkey'] as String?,
createdAt: json['createdAt'] == null
? null
: DateTime.parse(json['createdAt'] as String),
content: json['content'] as String? ?? '',
tags: (json['tags'] as List<dynamic>?)
?.map(
(e) => (e as List<dynamic>).map((e) => e as String).toList())
.toList() ??
const [],
signature: json['signature'] as String?,
developer:
BelongsTo<User>.fromJson(json['developer'] as Map<String, dynamic>),
releases:
HasMany<Release>.fromJson(json['releases'] as Map<String, dynamic>),
signer: BelongsTo<User>.fromJson(json['signer'] as Map<String, dynamic>),
);
Map<String, dynamic> _$AppToJson(App instance) => <String, dynamic>{
'id': instance.id,
@@ -110,7 +114,6 @@ Map<String, dynamic> _$AppToJson(App instance) => <String, dynamic>{
'content': instance.content,
'tags': instance.tags,
'signature': instance.signature,
'kind': instance.kind,
'releases': instance.releases,
'signer': instance.signer,
'developer': instance.developer,
+10 -1
View File
@@ -10,7 +10,16 @@ part 'app_curation_set.g.dart';
@DataAdapter([NostrAdapter, AppCurationSetAdapter])
class AppCurationSet extends BaseAppCurationSet
with DataModelMixin<AppCurationSet> {
late final HasMany<App> apps;
final HasMany<App> apps;
AppCurationSet(
{super.id,
super.pubkey,
super.createdAt,
super.content,
super.tags,
super.signature,
required this.apps});
}
mixin AppCurationSetAdapter on Adapter<AppCurationSet> {
+15 -12
View File
@@ -70,17 +70,21 @@ extension AppCurationSetRelationshipGraphNodeX
// **************************************************************************
AppCurationSet _$AppCurationSetFromJson(Map<String, dynamic> json) =>
AppCurationSet()
..id = json['id']
..pubkey = json['pubkey'] as String
..createdAt = DateTime.parse(json['createdAt'] as String)
..content = json['content'] as String
..kind = (json['kind'] as num).toInt()
..tags = (json['tags'] as List<dynamic>)
.map((e) => (e as List<dynamic>).map((e) => e as String).toList())
.toList()
..signature = json['signature'] as String?
..apps = HasMany<App>.fromJson(json['apps'] as Map<String, dynamic>);
AppCurationSet(
id: json['id'],
pubkey: json['pubkey'] as String?,
createdAt: json['createdAt'] == null
? null
: DateTime.parse(json['createdAt'] as String),
content: json['content'] as String? ?? '',
tags: (json['tags'] as List<dynamic>?)
?.map(
(e) => (e as List<dynamic>).map((e) => e as String).toList())
.toList() ??
const [],
signature: json['signature'] as String?,
apps: HasMany<App>.fromJson(json['apps'] as Map<String, dynamic>),
);
Map<String, dynamic> _$AppCurationSetToJson(AppCurationSet instance) =>
<String, dynamic>{
@@ -88,7 +92,6 @@ Map<String, dynamic> _$AppCurationSetToJson(AppCurationSet instance) =>
'pubkey': instance.pubkey,
'createdAt': instance.createdAt.toIso8601String(),
'content': instance.content,
'kind': instance.kind,
'tags': instance.tags,
'signature': instance.signature,
'apps': instance.apps,
+14 -3
View File
@@ -10,9 +10,20 @@ part 'file_metadata.g.dart';
@JsonSerializable()
@DataAdapter([NostrAdapter, FileMetadataAdapter])
class FileMetadata extends BaseFileMetadata with DataModelMixin<FileMetadata> {
late final BelongsTo<User> author;
late final BelongsTo<Release> release = BelongsTo();
late final BelongsTo<User> signer;
final BelongsTo<User> author;
final BelongsTo<Release> release;
final BelongsTo<User> signer;
FileMetadata(
{super.id,
super.pubkey,
super.createdAt,
super.content,
super.tags,
super.signature,
required this.author,
required this.release,
required this.signer});
}
mixin FileMetadataAdapter on Adapter<FileMetadata> {
+19 -13
View File
@@ -91,18 +91,24 @@ extension FileMetadataRelationshipGraphNodeX
// JsonSerializableGenerator
// **************************************************************************
FileMetadata _$FileMetadataFromJson(Map<String, dynamic> json) => FileMetadata()
..id = json['id']
..pubkey = json['pubkey'] as String
..createdAt = DateTime.parse(json['createdAt'] as String)
..content = json['content'] as String
..kind = (json['kind'] as num).toInt()
..tags = (json['tags'] as List<dynamic>)
.map((e) => (e as List<dynamic>).map((e) => e as String).toList())
.toList()
..signature = json['signature'] as String?
..author = BelongsTo<User>.fromJson(json['author'] as Map<String, dynamic>)
..signer = BelongsTo<User>.fromJson(json['signer'] as Map<String, dynamic>);
FileMetadata _$FileMetadataFromJson(Map<String, dynamic> json) => FileMetadata(
id: json['id'],
pubkey: json['pubkey'] as String?,
createdAt: json['createdAt'] == null
? null
: DateTime.parse(json['createdAt'] as String),
content: json['content'] as String? ?? '',
tags: (json['tags'] as List<dynamic>?)
?.map(
(e) => (e as List<dynamic>).map((e) => e as String).toList())
.toList() ??
const [],
signature: json['signature'] as String?,
author: BelongsTo<User>.fromJson(json['author'] as Map<String, dynamic>),
release:
BelongsTo<Release>.fromJson(json['release'] as Map<String, dynamic>),
signer: BelongsTo<User>.fromJson(json['signer'] as Map<String, dynamic>),
);
Map<String, dynamic> _$FileMetadataToJson(FileMetadata instance) =>
<String, dynamic>{
@@ -110,9 +116,9 @@ Map<String, dynamic> _$FileMetadataToJson(FileMetadata instance) =>
'pubkey': instance.pubkey,
'createdAt': instance.createdAt.toIso8601String(),
'content': instance.content,
'kind': instance.kind,
'tags': instance.tags,
'signature': instance.signature,
'author': instance.author,
'release': instance.release,
'signer': instance.signer,
};
+14 -28
View File
@@ -5,15 +5,9 @@ mixin NostrAdapter<T extends DataModelMixin<T>> on Adapter<T> {
late final RelayMessageNotifier notifier =
ref.read(relayMessageNotifierProvider.notifier);
// TODO rethink this
Map<int, String> kindType = {
0: 'users',
3: 'users',
1063: 'fileMetadata',
30063: 'releases',
30267: 'appCurationSets',
32267: 'apps'
};
int get kind {
return BaseEvent.kindForType(internalType)!;
}
@override
DeserializedData<T> deserialize(Object? data, {String? key}) {
@@ -23,40 +17,32 @@ mixin NostrAdapter<T extends DataModelMixin<T>> on Adapter<T> {
for (final e in list) {
final map = e as Map<String, dynamic>;
// Convert nostr-specific timestamp into a DateTime
map['createdAt'] =
DateTime.fromMillisecondsSinceEpoch(map['created_at'] * 1000)
.toIso8601String();
final kind = map['kind'] as int;
// ID should be the identifier in PREs
final dTags = (map['tags'] as Iterable).where((t) => t[0] == 'd');
if (dTags.length == 1) {
map['id'] = (dTags.first as List)[1];
}
// TODO remove
map['signer'] = map['pubkey'];
final zapTags = (map['tags'] as Iterable).where((t) => t[0] == 'zap');
if (zapTags.length == 1) {
map['developer'] = (zapTags.first as List)[1];
}
final xType = kindType[kind];
if (xType != null) {
if (xType == internalType) {
final newData = super.deserialize(map);
models.addAll(newData.models as Iterable<T>);
} else {
final newData = adapters[xType]!.deserialize(map);
included.addAll(newData.models as Iterable<DataModelMixin>);
}
// Collect models for current kind and included for others
final eventType = BaseEvent.kinds[kind]!;
if (eventType == internalType) {
final newData = super.deserialize(map);
models.addAll(newData.models as Iterable<T>);
} else {
final newData = adapters[eventType]!.deserialize(map);
included.addAll(newData.models as Iterable<DataModelMixin>);
}
}
return DeserializedData<T>(models, included: included);
}
// TODO remove
int get kind =>
kindType.entries.firstWhere((e) => e.value == internalType).key;
@override
Future<List<T>> findAll(
{bool? remote,
+14 -3
View File
@@ -12,9 +12,20 @@ part 'release.g.dart';
@JsonSerializable()
@DataAdapter([NostrAdapter, ReleaseAdapter])
class Release extends BaseRelease with DataModelMixin<Release> {
late final HasMany<FileMetadata> artifacts;
late final BelongsTo<App> app;
late final BelongsTo<User> signer;
final HasMany<FileMetadata> artifacts;
final BelongsTo<App> app;
final BelongsTo<User> signer;
Release(
{super.id,
super.pubkey,
super.createdAt,
super.content,
super.tags,
super.signature,
required this.artifacts,
required this.app,
required this.signer});
}
mixin ReleaseAdapter on Adapter<Release> {
+18 -15
View File
@@ -89,27 +89,30 @@ extension ReleaseRelationshipGraphNodeX on RelationshipGraphNode<Release> {
// JsonSerializableGenerator
// **************************************************************************
Release _$ReleaseFromJson(Map<String, dynamic> json) => Release()
..id = json['id']
..pubkey = json['pubkey'] as String
..createdAt = DateTime.parse(json['createdAt'] as String)
..content = json['content'] as String
..kind = (json['kind'] as num).toInt()
..tags = (json['tags'] as List<dynamic>)
.map((e) => (e as List<dynamic>).map((e) => e as String).toList())
.toList()
..signature = json['signature'] as String?
..artifacts =
HasMany<FileMetadata>.fromJson(json['artifacts'] as Map<String, dynamic>)
..app = BelongsTo<App>.fromJson(json['app'] as Map<String, dynamic>)
..signer = BelongsTo<User>.fromJson(json['signer'] as Map<String, dynamic>);
Release _$ReleaseFromJson(Map<String, dynamic> json) => Release(
id: json['id'],
pubkey: json['pubkey'] as String?,
createdAt: json['createdAt'] == null
? null
: DateTime.parse(json['createdAt'] as String),
content: json['content'] as String? ?? '',
tags: (json['tags'] as List<dynamic>?)
?.map(
(e) => (e as List<dynamic>).map((e) => e as String).toList())
.toList() ??
const [],
signature: json['signature'] as String?,
artifacts: HasMany<FileMetadata>.fromJson(
json['artifacts'] as Map<String, dynamic>),
app: BelongsTo<App>.fromJson(json['app'] as Map<String, dynamic>),
signer: BelongsTo<User>.fromJson(json['signer'] as Map<String, dynamic>),
);
Map<String, dynamic> _$ReleaseToJson(Release instance) => <String, dynamic>{
'id': instance.id,
'pubkey': instance.pubkey,
'createdAt': instance.createdAt.toIso8601String(),
'content': instance.content,
'kind': instance.kind,
'tags': instance.tags,
'signature': instance.signature,
'artifacts': instance.artifacts,
+12 -2
View File
@@ -11,10 +11,20 @@ part 'user.g.dart';
@JsonSerializable()
@DataAdapter([NostrAdapter, UserAdapter])
class User extends BaseUser with DataModelMixin<User> {
User(
{super.id,
super.pubkey,
super.createdAt,
super.content,
super.tags,
super.signature,
required this.followers,
required this.following});
@DataRelationship(inverse: 'followers')
late final HasMany<User> following;
final HasMany<User> following;
@DataRelationship(inverse: 'following')
late final HasMany<User> followers = HasMany();
final HasMany<User> followers;
String get nameOrNpub => name ?? '${npub.substring(0, 10)}...';
}
+19 -13
View File
@@ -76,26 +76,32 @@ extension UserRelationshipGraphNodeX on RelationshipGraphNode<User> {
// JsonSerializableGenerator
// **************************************************************************
User _$UserFromJson(Map<String, dynamic> json) => User()
..id = json['id']
..pubkey = json['pubkey'] as String
..createdAt = DateTime.parse(json['createdAt'] as String)
..content = json['content'] as String
..kind = (json['kind'] as num).toInt()
..tags = (json['tags'] as List<dynamic>)
.map((e) => (e as List<dynamic>).map((e) => e as String).toList())
.toList()
..signature = json['signature'] as String?
..following =
HasMany<User>.fromJson(json['following'] as Map<String, dynamic>);
User _$UserFromJson(Map<String, dynamic> json) => User(
id: json['id'],
pubkey: json['pubkey'] as String?,
createdAt: json['createdAt'] == null
? null
: DateTime.parse(json['createdAt'] as String),
content: json['content'] as String? ?? '',
tags: (json['tags'] as List<dynamic>?)
?.map(
(e) => (e as List<dynamic>).map((e) => e as String).toList())
.toList() ??
const [],
signature: json['signature'] as String?,
followers:
HasMany<User>.fromJson(json['followers'] as Map<String, dynamic>),
following:
HasMany<User>.fromJson(json['following'] as Map<String, dynamic>),
);
Map<String, dynamic> _$UserToJson(User instance) => <String, dynamic>{
'id': instance.id,
'pubkey': instance.pubkey,
'createdAt': instance.createdAt.toIso8601String(),
'content': instance.content,
'kind': instance.kind,
'tags': instance.tags,
'signature': instance.signature,
'following': instance.following,
'followers': instance.followers,
};
+1 -1
View File
@@ -56,7 +56,7 @@ class SettingsScreen extends HookConsumerWidget {
onPressed: () async {
final text =
'${controller.text.trim()} [from ${user.npub} on ${DateFormat('MMMM d, y').format(DateTime.now())}]';
final event = BaseEvent.partial(content: text).sign(kI);
final event = BaseEvent(content: text).sign(kI);
await ref.apps.nostrAdapter.notifier
.publish(event, relayUrls: ['wss://relay.zap.store']);
controller.clear();
+24
View File
@@ -257,6 +257,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.3.6"
decimal:
dependency: transitive
description:
name: decimal
sha256: "24a261d5d5c87e86c7651c417a5dbdf8bcd7080dd592533910e8d0505a279f21"
url: "https://pub.dev"
source: hosted
version: "2.3.3"
device_apps:
dependency: "direct main"
description:
@@ -508,6 +516,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.0.2"
humanizer:
dependency: transitive
description:
name: humanizer
sha256: "08728a4b6d62accd7d09e668bd54e81e6e09a82c8cfda30553224b3eb868d4f2"
url: "https://pub.dev"
source: hosted
version: "2.2.0"
image:
dependency: transitive
description:
@@ -851,6 +867,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.2.1"
rational:
dependency: transitive
description:
name: rational
sha256: ba58e9e18df9abde280e8b10051e4bce85091e41e8e7e411b6cde2e738d357cf
url: "https://pub.dev"
source: hosted
version: "2.2.2"
riverpod:
dependency: transitive
description: