mirror of
https://github.com/zapstore/zapstore.git
synced 2026-10-06 04:58:23 +00:00
Fix user loading and apps without latest release pointer
This commit is contained in:
+18
-6
@@ -173,15 +173,27 @@ mixin AppAdapter on Adapter<App> {
|
||||
);
|
||||
// Find all appid@version ($3) as we need to pick one tag to query on
|
||||
// (filters by kind ($1) and pubkey ($2) done locally)
|
||||
final latestReleaseIdentifiers =
|
||||
apps.map((app) => app.linkedReplaceableEvents.firstOrNull?.$3).nonNulls;
|
||||
final releases = await ref.releases.findAll(
|
||||
params: {'#d': latestReleaseIdentifiers},
|
||||
);
|
||||
// TODO: Deprecated
|
||||
// Some developers without access to the latest zapstore-cli
|
||||
// have not published their apps with latest release identifiers
|
||||
// so load as usual
|
||||
final oldApps =
|
||||
apps.where((app) => !latestReleaseIdentifiers.contains(app.identifier));
|
||||
final oldReleases = await ref.releases.findAll(
|
||||
params: {
|
||||
'#d': apps
|
||||
.map((app) => app.linkedReplaceableEvents.firstOrNull?.$3)
|
||||
.nonNulls
|
||||
'#a': oldApps.map((app) => app.getReplaceableEventLink().formatted)
|
||||
},
|
||||
);
|
||||
final metadataIds =
|
||||
releases.map((r) => r.tagMap['e']).nonNulls.expand((_) => _);
|
||||
|
||||
final metadataIds = [...releases, ...oldReleases]
|
||||
.map((r) => r.tagMap['e'])
|
||||
.nonNulls
|
||||
.expand((_) => _);
|
||||
|
||||
await ref.fileMetadata.findAll(params: {
|
||||
'ids': metadataIds,
|
||||
@@ -277,7 +289,7 @@ mixin AppAdapter on Adapter<App> {
|
||||
map['id'] =
|
||||
(map['kind'] as int, map['pubkey'].toString(), appId).formatted;
|
||||
map['signer'] = map['pubkey'];
|
||||
map['developer'] = tagMap['zap']?.firstOrNull?[1];
|
||||
map['developer'] = tagMap['zap']?.firstOrNull;
|
||||
map['localApp'] = appId;
|
||||
}
|
||||
|
||||
|
||||
+29
-22
@@ -43,34 +43,41 @@ mixin LocalAppAdapter on Adapter<LocalApp> {
|
||||
if (!Platform.isAndroid) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// NOTE: Using packageManager.getPackageInfo(packageName: appId)
|
||||
// throws an uncatchable error every time it queries a non-installed package
|
||||
final infos = await packageManager.getInstalledPackages();
|
||||
|
||||
final infos = appId != null
|
||||
? [await packageManager.getPackageInfo(packageName: appId)].nonNulls
|
||||
: await packageManager.getInstalledPackages();
|
||||
final installedPackageInfos = infos!.where((i) =>
|
||||
!kExcludedAppIdNamespaces.any((e) => i.packageName!.startsWith(e)));
|
||||
|
||||
final installedPackageInfos = infos!.where((i) =>
|
||||
!kExcludedAppIdNamespaces.any((e) => i.packageName!.startsWith(e)));
|
||||
final ids = appId != null
|
||||
? [appId]
|
||||
: installedPackageInfos.map((i) => i.packageName).nonNulls;
|
||||
|
||||
final localApps = findManyLocalByIds(
|
||||
installedPackageInfos.map((i) => i.packageName).nonNulls);
|
||||
final localApps = findManyLocalByIds(ids);
|
||||
|
||||
for (final i in installedPackageInfos) {
|
||||
final appId = i.packageName!;
|
||||
final localApp = localApps.firstWhereOrNull((app) => appId == app.id) ??
|
||||
LocalApp(id: i.packageName!);
|
||||
final installedVersion = i.versionName;
|
||||
final installedVersionCode = i.versionCode;
|
||||
for (final i in installedPackageInfos) {
|
||||
final appId = i.packageName!;
|
||||
final localApp = localApps.firstWhereOrNull((app) => appId == app.id) ??
|
||||
LocalApp(id: i.packageName!);
|
||||
final installedVersion = i.versionName;
|
||||
final installedVersionCode = i.versionCode;
|
||||
|
||||
final app = ref.apps.appAdapter.findWhereIdInLocal([appId]).firstOrNull;
|
||||
final status =
|
||||
determineInstallStatus(app, installedVersion, installedVersionCode);
|
||||
final app = ref.apps.appAdapter.findWhereIdInLocal([appId]).firstOrNull;
|
||||
final status =
|
||||
determineInstallStatus(app, installedVersion, installedVersionCode);
|
||||
|
||||
localApp
|
||||
.copyWith(
|
||||
installedVersion: installedVersion,
|
||||
installedVersionCode: installedVersionCode,
|
||||
status: status)
|
||||
.saveLocal();
|
||||
localApp
|
||||
.copyWith(
|
||||
installedVersion: installedVersion,
|
||||
installedVersionCode: installedVersionCode,
|
||||
status: status)
|
||||
.saveLocal();
|
||||
}
|
||||
} catch (e) {
|
||||
// TODO DEAL WITH
|
||||
// print(e);
|
||||
}
|
||||
|
||||
// Update number of apps
|
||||
|
||||
+6
-58
@@ -1,6 +1,5 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter_data/flutter_data.dart';
|
||||
import 'package:purplebase/purplebase.dart';
|
||||
import 'package:zapstore/models/nostr_adapter.dart';
|
||||
@@ -32,66 +31,15 @@ class User extends BaseUser with DataModelMixin<User> {
|
||||
}
|
||||
|
||||
mixin UserAdapter on NostrAdapter<User> {
|
||||
// TODO: All this still necessary with purplebase?
|
||||
@override
|
||||
DeserializedData<User> deserialize(Object? data, {String? key}) {
|
||||
final Iterable<Map<String, dynamic>> list =
|
||||
(data is Iterable ? data : [data as Map]).cast();
|
||||
final list = data is Iterable ? data : [data as Map];
|
||||
|
||||
final k0s = list
|
||||
.where((e) {
|
||||
// filter shitty kind 0s
|
||||
if (e['kind'] != 0 || !e['content'].toString().startsWith('{')) {
|
||||
return false;
|
||||
}
|
||||
final map = Map<String, dynamic>.from(jsonDecode(e['content']));
|
||||
final name = map['name'] ?? map['display_name'] ?? map['displayName'];
|
||||
return name != null;
|
||||
})
|
||||
.toList()
|
||||
.groupSetsBy((e) => e['pubkey'] as String);
|
||||
final k3s = list
|
||||
.where((e) => e['kind'] == 3)
|
||||
.toList()
|
||||
.groupSetsBy((e) => e['pubkey'] as String);
|
||||
|
||||
// collect contacts and then assign them to user
|
||||
final included = <String, List<DataModelMixin>>{};
|
||||
for (final _ in k3s.entries) {
|
||||
final sl = _.value.sorted(
|
||||
(a, b) => (b['created_at'] as int).compareTo(a['created_at']));
|
||||
final k3 = sl.first;
|
||||
final contactMaps = [];
|
||||
for (final [_, id, ..._] in k3['tags'] as Iterable) {
|
||||
if (!existsId(id)) {
|
||||
contactMaps.add({
|
||||
'id': id,
|
||||
'content': '',
|
||||
'pubkey': id,
|
||||
'created_at': DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
||||
'kind': 0,
|
||||
'tags': [],
|
||||
});
|
||||
}
|
||||
}
|
||||
final data = super.deserialize(contactMaps);
|
||||
included[k3['pubkey']] = data.models;
|
||||
for (final Map<String, dynamic> map in list) {
|
||||
map['id'] = map['pubkey'];
|
||||
}
|
||||
|
||||
final users = <User>[];
|
||||
for (final _ in k0s.entries) {
|
||||
final sl = _.value.sorted(
|
||||
(a, b) => (b['created_at'] as int).compareTo(a['created_at']));
|
||||
final k0 = sl.first;
|
||||
final id = k0['id'] = k0['pubkey'];
|
||||
if (included.containsKey(id)) {
|
||||
k0['following'] = included[id]!.map((e) => e.id).toList();
|
||||
}
|
||||
users.addAll(super.deserialize(k0).models);
|
||||
}
|
||||
|
||||
return DeserializedData<User>(users,
|
||||
included: included.values.expand((_) => _).toList());
|
||||
return super.deserialize(data);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -110,7 +58,7 @@ mixin UserAdapter on NostrAdapter<User> {
|
||||
}
|
||||
|
||||
final result = await socialRelays.queryRaw(RelayRequest(
|
||||
kinds: {0, 3},
|
||||
kinds: {0}, // 3
|
||||
authors: {...authors},
|
||||
));
|
||||
|
||||
@@ -166,7 +114,7 @@ mixin UserAdapter on NostrAdapter<User> {
|
||||
}
|
||||
|
||||
final result = await socialRelays.queryRaw(RelayRequest(
|
||||
kinds: {0, 3},
|
||||
kinds: {0}, // 3
|
||||
tags: params ?? {},
|
||||
authors: {publicKey},
|
||||
));
|
||||
|
||||
@@ -2,7 +2,6 @@ import 'package:auto_size_text/auto_size_text.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
@@ -31,17 +30,10 @@ class AppDetailScreen extends HookConsumerWidget {
|
||||
alsoWatch: (_) =>
|
||||
{_.releases, _.releases.artifacts, _.signer, _.developer});
|
||||
|
||||
// TODO: Workaround for bug in watchAll (when remote=true)
|
||||
// TODO: Just fetch the signer, no need to refetch again??
|
||||
useFuture(useMemoized(() {
|
||||
return ref.apps
|
||||
.findOne(model.identifier!, remote: true, params: {'includes': true});
|
||||
}));
|
||||
|
||||
final app = state.model ?? model;
|
||||
|
||||
return RefreshIndicator(
|
||||
onRefresh: () => ref.apps.findOne(model.id!),
|
||||
onRefresh: () => ref.apps.findOne(model.identifier!, remote: true),
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
|
||||
Reference in New Issue
Block a user