mirror of
https://github.com/zapstore/zapstore.git
synced 2026-10-05 20:48:24 +00:00
Refactor WoT related widgets
This commit is contained in:
@@ -133,7 +133,7 @@ mixin UserAdapter on NostrAdapter<User> {
|
||||
}
|
||||
|
||||
Future<List<User>> getTrusted(String npub1, String npub2) async {
|
||||
final url = 'https://trustgraph.live/api/trust/$npub1/$npub2';
|
||||
final url = 'https://trustgraph.live/api/fwf/$npub1/$npub2';
|
||||
final users = await sendRequest(
|
||||
Uri.parse(url),
|
||||
onSuccess: (response, label) async {
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:zapstore/main.data.dart';
|
||||
import 'package:zapstore/models/app.dart';
|
||||
import 'package:zapstore/models/settings.dart';
|
||||
import 'package:zapstore/models/user.dart';
|
||||
import 'package:zapstore/widgets/app_drawer.dart';
|
||||
import 'package:zapstore/widgets/author_container.dart';
|
||||
import 'package:zapstore/widgets/wot_container.dart';
|
||||
|
||||
class InstallAlertDialog extends ConsumerWidget {
|
||||
const InstallAlertDialog({
|
||||
super.key,
|
||||
required this.app,
|
||||
});
|
||||
|
||||
final App app;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final user = ref.settings
|
||||
.watchOne('_', alsoWatch: (_) => {_.user})
|
||||
.model!
|
||||
.user
|
||||
.value;
|
||||
|
||||
return AlertDialog(
|
||||
elevation: 10,
|
||||
title: Text(
|
||||
'Are you sure you want to install ${app.name}?',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
content: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'By installing this app you are trusting the signer now and for all future updates. Make sure you know who they are.'),
|
||||
Gap(20),
|
||||
if (app.signer.value != null)
|
||||
AuthorContainer(
|
||||
user: app.signer.value!, text: 'Signed by', oneLine: true),
|
||||
Gap(20),
|
||||
if (app.signer.value != null)
|
||||
WebOfTrustContainer(
|
||||
fromNpub: user?.npub ?? kFranzapNpub,
|
||||
toNpub: app.signer.value!.npub,
|
||||
),
|
||||
if (user == null)
|
||||
LoginContainer(
|
||||
minimal: true,
|
||||
labelText: 'Log in to view your own web of trust',
|
||||
),
|
||||
if (app.latestMetadata?.urls.isNotEmpty ?? false)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 16, bottom: 16),
|
||||
child: RichText(
|
||||
text: WidgetSpan(
|
||||
child: Wrap(
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
Text('This app will be downloaded from '),
|
||||
Text(
|
||||
Uri.parse(app.latestMetadata!.urls.first).host,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
),
|
||||
Text(' and verified.'),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: TextButton(
|
||||
onPressed: () {
|
||||
app.install();
|
||||
// NOTE: can't use context.pop()
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: user != null
|
||||
? Text('Install', style: TextStyle(fontWeight: FontWeight.bold))
|
||||
: Text(
|
||||
'I trust the signer, install the app',
|
||||
textAlign: TextAlign.right,
|
||||
),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
// NOTE: can't use context.pop()
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text('Go back'),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import 'package:zapstore/utils/extensions.dart';
|
||||
import 'package:zapstore/utils/system_info.dart';
|
||||
import 'package:zapstore/widgets/app_drawer.dart';
|
||||
import 'package:zapstore/widgets/author_container.dart';
|
||||
import 'package:zapstore/widgets/install_alert_dialog.dart';
|
||||
import 'package:zapstore/widgets/spinning_logo.dart';
|
||||
import 'package:zapstore/widgets/wot_container.dart';
|
||||
|
||||
@@ -138,102 +139,4 @@ class InstallButton extends HookConsumerWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class InstallAlertDialog extends ConsumerWidget {
|
||||
const InstallAlertDialog({
|
||||
super.key,
|
||||
required this.app,
|
||||
});
|
||||
|
||||
final App app;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final user = ref.settings
|
||||
.watchOne('_', alsoWatch: (_) => {_.user})
|
||||
.model!
|
||||
.user
|
||||
.value;
|
||||
return AlertDialog(
|
||||
elevation: 10,
|
||||
title: Text(
|
||||
'Are you sure you want to install ${app.name}?',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
content: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'By installing this app you are trusting the signer now and for all future updates. Make sure you know who they are.'),
|
||||
Gap(20),
|
||||
// SignerAndDeveloperRow(app: app),
|
||||
if (app.signer.value != null)
|
||||
AuthorContainer(
|
||||
user: app.signer.value!, text: 'Signed by', oneLine: true),
|
||||
Gap(20),
|
||||
if (app.signer.value != null)
|
||||
WebOfTrustContainer(
|
||||
fromNpub: user?.npub ?? kFranzapNpub,
|
||||
toNpub: app.signer.value!.npub,
|
||||
),
|
||||
if (user == null)
|
||||
LoginContainer(
|
||||
minimal: true,
|
||||
labelText: 'Log in to view your own web of trust',
|
||||
),
|
||||
if (app.latestMetadata?.urls.isNotEmpty ?? false)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 16, bottom: 16),
|
||||
child: RichText(
|
||||
text: WidgetSpan(
|
||||
child: Wrap(
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
Text('This app will be downloaded from '),
|
||||
Text(
|
||||
Uri.parse(app.latestMetadata!.urls.first).host,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
),
|
||||
Text(' and verified.'),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: TextButton(
|
||||
onPressed: () {
|
||||
app.install();
|
||||
// NOTE: can't use context.pop()
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: user != null
|
||||
? Text('Install', style: TextStyle(fontWeight: FontWeight.bold))
|
||||
: Text(
|
||||
'I trust the signer, install the app',
|
||||
textAlign: TextAlign.right,
|
||||
),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
// NOTE: can't use context.pop()
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text('Go back'),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final kUpdateColor = Colors.blue[700]!;
|
||||
|
||||
@@ -19,8 +19,10 @@ class WebOfTrustContainer extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return switch (
|
||||
ref.watch(followsWhoFollowProvider((from: fromNpub, to: toNpub)))) {
|
||||
final data =
|
||||
ref.watch(followsWhoFollowProvider((from: fromNpub, to: toNpub)));
|
||||
|
||||
return switch (data) {
|
||||
AsyncData<List<User>>(value: final trustedUsers) => Builder(
|
||||
builder: (context) {
|
||||
final hasUser =
|
||||
@@ -32,39 +34,12 @@ class WebOfTrustContainer extends HookConsumerWidget {
|
||||
return Text(
|
||||
'No trusted users between you and the signer. (This may be a service error)');
|
||||
}
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
if (hasUser && fromNpub != kFranzapNpub)
|
||||
TextSpan(text: 'You, '),
|
||||
for (final trustedUser in trustedUsersWithoutLoggedInUser)
|
||||
TextSpan(
|
||||
style: TextStyle(height: 1.6),
|
||||
children: [
|
||||
WidgetSpan(
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
child: Wrap(
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
RoundedImage(
|
||||
url: trustedUser.avatarUrl, size: 20),
|
||||
Text(
|
||||
' ${trustedUser.nameOrNpub}${trustedUsersWithoutLoggedInUser.indexOf(trustedUser) == trustedUsersWithoutLoggedInUser.length - 1 ? '' : ', '}',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (trustedUsersWithoutLoggedInUser
|
||||
.indexOf(trustedUser) ==
|
||||
trustedUsersWithoutLoggedInUser.length - 1)
|
||||
TextSpan(
|
||||
text: ' and others follow this signer on nostr.',
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
return UsersRichText(
|
||||
preSpan: hasUser && fromNpub != kFranzapNpub
|
||||
? TextSpan(text: 'You, ')
|
||||
: null,
|
||||
users: trustedUsersWithoutLoggedInUser,
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -91,6 +66,51 @@ class WebOfTrustContainer extends HookConsumerWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class UsersRichText extends StatelessWidget {
|
||||
const UsersRichText({
|
||||
super.key,
|
||||
this.preSpan,
|
||||
required this.users,
|
||||
});
|
||||
|
||||
final TextSpan? preSpan;
|
||||
final List<User> users;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
if (preSpan != null) preSpan!,
|
||||
for (final user in users)
|
||||
TextSpan(
|
||||
style: TextStyle(height: 1.6),
|
||||
children: [
|
||||
WidgetSpan(
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
child: Wrap(
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
RoundedImage(url: user.avatarUrl, size: 20),
|
||||
Text(
|
||||
' ${user.nameOrNpub}${users.indexOf(user) == users.length - 1 ? '' : ', '}',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (users.indexOf(user) == users.length - 1)
|
||||
TextSpan(
|
||||
text: ' and others follow this signer on nostr.',
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final followsWhoFollowProvider = FutureProvider.autoDispose
|
||||
.family<List<User>, ({String from, String to})>((ref, arg) async {
|
||||
final _ =
|
||||
|
||||
Reference in New Issue
Block a user