mirror of
https://github.com/zapstore/zapstore.git
synced 2026-10-05 12:38:24 +00:00
Fix user stuff and feedback form
This commit is contained in:
@@ -9,7 +9,6 @@ import 'package:zapstore/models/app.dart';
|
||||
import 'package:zapstore/screens/app_detail_screen.dart';
|
||||
import 'package:zapstore/screens/settings_screen.dart';
|
||||
import 'package:zapstore/screens/updates_screen.dart';
|
||||
import 'package:zapstore/utils/extensions.dart';
|
||||
import 'package:zapstore/widgets/app_drawer.dart';
|
||||
import 'package:zapstore/screens/search_screen.dart';
|
||||
|
||||
@@ -50,10 +49,6 @@ class ZapstoreApp extends StatelessWidget {
|
||||
useMaterial3: true,
|
||||
scaffoldBackgroundColor: kBackgroundColor,
|
||||
visualDensity: VisualDensity.adaptivePlatformDensity,
|
||||
|
||||
// textTheme: context.theme.textTheme.copyWith(
|
||||
// bodyLarge:
|
||||
// TextStyle(color: Colors.white, fontWeight: FontWeight.w300))
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -89,12 +84,6 @@ final goRouter = GoRouter(
|
||||
path: 'details',
|
||||
builder: (context, state) =>
|
||||
AppDetailScreen(app: state.extra as App),
|
||||
// pageBuilder: (context, state) =>
|
||||
// buildWithSlideTransition<void>(
|
||||
// context: context,
|
||||
// state: state,
|
||||
// child: AppDetailScreen(app: state.extra as App),
|
||||
// ),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -273,35 +262,3 @@ class ScaffoldWithNavigationRail extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
CustomTransitionPage buildWithSlideTransition<T>({
|
||||
required BuildContext context,
|
||||
required GoRouterState state,
|
||||
required Widget child,
|
||||
}) {
|
||||
return CustomTransitionPage<T>(
|
||||
key: state.pageKey,
|
||||
child: child,
|
||||
transitionsBuilder: (context, animation, secondaryAnimation, child) {
|
||||
return SlideTransition(
|
||||
position:
|
||||
Tween<Offset>(begin: const Offset(1, 0), end: Offset.zero).animate(
|
||||
CurvedAnimation(
|
||||
parent: animation,
|
||||
curve: Curves.fastOutSlowIn,
|
||||
),
|
||||
),
|
||||
child: AnimatedBuilder(
|
||||
animation: animation,
|
||||
builder: (context, child) {
|
||||
return Container(
|
||||
color: context.theme.colorScheme.background,
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
+12
-8
@@ -15,6 +15,8 @@ class User extends ZapstoreEvent<User> with BaseUser {
|
||||
late final HasMany<User> following;
|
||||
@DataRelationship(inverse: 'following')
|
||||
late final HasMany<User> followers = HasMany();
|
||||
|
||||
String get nameOrNpub => name ?? '${npub.substring(0, 10)}...';
|
||||
}
|
||||
|
||||
mixin UserAdapter on NostrAdapter<User> {
|
||||
@@ -40,14 +42,16 @@ mixin UserAdapter on NostrAdapter<User> {
|
||||
final k3 = sl.first;
|
||||
final contactMaps = [];
|
||||
for (final [_, id, ..._] in k3['tags'] as Iterable) {
|
||||
contactMaps.add({
|
||||
'id': id,
|
||||
'content': '',
|
||||
'pubkey': id,
|
||||
'created_at': DateTime.now().millisecondsSinceEpoch ~/ 1000,
|
||||
'kind': 0,
|
||||
'tags': [],
|
||||
});
|
||||
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;
|
||||
|
||||
@@ -8,6 +8,7 @@ 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';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:zapstore/main.data.dart';
|
||||
import 'package:zapstore/models/app.dart';
|
||||
@@ -243,12 +244,13 @@ class AppDetailScreen extends HookConsumerWidget {
|
||||
}
|
||||
|
||||
class ReleaseCard extends StatelessWidget {
|
||||
const ReleaseCard({
|
||||
ReleaseCard({
|
||||
super.key,
|
||||
required this.release,
|
||||
});
|
||||
|
||||
final Release release;
|
||||
final formatter = DateFormat('dd MMM yyyy');
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -274,7 +276,7 @@ class ReleaseCard extends StatelessWidget {
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [Text('Version'), Text(release.version)],
|
||||
children: [Text('Version'), Text(metadata.version!)],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
@@ -283,7 +285,7 @@ class ReleaseCard extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('Date'),
|
||||
Text(release.createdAt.toIso8601String())
|
||||
Text(formatter.format(release.createdAt)),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -151,7 +151,7 @@ final searchStateProvider = StateNotifierProvider.autoDispose<
|
||||
for (final app in apps) app.signer.id,
|
||||
for (final app in apps) app.developer.id
|
||||
}.nonNulls;
|
||||
ref.users.findAll(params: {'ids': userIds});
|
||||
await ref.users.findAll(params: {'ids': userIds});
|
||||
n.updateWith(isLoading: false);
|
||||
} catch (e) {
|
||||
n.updateWith(isLoading: false);
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:async_button_builder/async_button_builder.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:purplebase/purplebase.dart';
|
||||
import 'package:zapstore/main.data.dart';
|
||||
import 'package:zapstore/models/app.dart';
|
||||
import 'package:zapstore/services/session_service.dart';
|
||||
import 'package:zapstore/utils/extensions.dart';
|
||||
|
||||
class SettingsScreen extends HookConsumerWidget {
|
||||
@@ -12,11 +18,14 @@ class SettingsScreen extends HookConsumerWidget {
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final controller = useTextEditingController();
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Share your feedback with us',
|
||||
'Share your feedback',
|
||||
style: context.theme.textTheme.headlineLarge,
|
||||
),
|
||||
Gap(10),
|
||||
Text('Comments, suggestions and error reports welcome here.'),
|
||||
Gap(20),
|
||||
TextField(
|
||||
controller: controller,
|
||||
@@ -24,10 +33,21 @@ class SettingsScreen extends HookConsumerWidget {
|
||||
maxLines: 10,
|
||||
),
|
||||
Gap(20),
|
||||
ElevatedButton(
|
||||
AsyncButtonBuilder(
|
||||
loadingWidget: SizedBox(
|
||||
width: 14, height: 14, child: CircularProgressIndicator()),
|
||||
onPressed: () async {
|
||||
ref.apps.logLevel = 2;
|
||||
await ref.apps.clearLocal();
|
||||
final user = ref.read(loggedInUser);
|
||||
final text = '${controller.text.trim()} [from ${user?.npub}]';
|
||||
final event = BaseEvent.partial(content: text).sign(kI);
|
||||
await ref.apps.nostrAdapter.notifier.publish(event);
|
||||
controller.clear();
|
||||
},
|
||||
builder: (context, child, callback, buttonState) {
|
||||
return ElevatedButton(
|
||||
onPressed: callback,
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
child: Text('Send'),
|
||||
),
|
||||
|
||||
+33
-12
@@ -1,3 +1,4 @@
|
||||
import 'package:async_button_builder/async_button_builder.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
@@ -27,35 +28,55 @@ class AppDrawer extends HookConsumerWidget {
|
||||
children: [
|
||||
CircularImage(url: user?.avatarUrl, size: 46),
|
||||
Gap(10),
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (user != null)
|
||||
Text(
|
||||
user.name,
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
if (user != null)
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
user.nameOrNpub,
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
Gap(4),
|
||||
Icon(Icons.verified,
|
||||
color: Colors.lightBlue, size: 18),
|
||||
],
|
||||
),
|
||||
if (user != null)
|
||||
Text('${user.following.length} contacts'),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (user == null)
|
||||
TextField(
|
||||
autofocus: true,
|
||||
autocorrect: false,
|
||||
controller: controller,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Input your NIP-05 address',
|
||||
),
|
||||
),
|
||||
Gap(5),
|
||||
if (user == null)
|
||||
ElevatedButton(
|
||||
AsyncButtonBuilder(
|
||||
loadingWidget: SizedBox(
|
||||
width: 14,
|
||||
height: 14,
|
||||
child: CircularProgressIndicator()),
|
||||
onPressed: () async {
|
||||
ref.read(loggedInUser.notifier).state = await ref.users
|
||||
.findOne(controller.text.trim(),
|
||||
params: {'contacts': true});
|
||||
},
|
||||
builder: (context, child, callback, buttonState) {
|
||||
return ElevatedButton(
|
||||
onPressed: callback,
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
child: Text('Log in'),
|
||||
),
|
||||
if (user != null)
|
||||
|
||||
@@ -103,6 +103,7 @@ class AuthorContainer extends StatelessWidget {
|
||||
final User user;
|
||||
final String text;
|
||||
final bool oneLine;
|
||||
|
||||
const AuthorContainer({
|
||||
super.key,
|
||||
required this.user,
|
||||
@@ -121,7 +122,7 @@ class AuthorContainer extends StatelessWidget {
|
||||
if (oneLine)
|
||||
Expanded(
|
||||
child: Text(
|
||||
'$text ${user.name}',
|
||||
'$text ${user.nameOrNpub}',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
@@ -135,7 +136,7 @@ class AuthorContainer extends StatelessWidget {
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 1),
|
||||
child: Text(
|
||||
user.name,
|
||||
user.nameOrNpub,
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
|
||||
@@ -6,26 +6,14 @@
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <handy_window/handy_window_plugin.h>
|
||||
#include <screen_retriever/screen_retriever_plugin.h>
|
||||
#include <sqlite3_flutter_libs/sqlite3_flutter_libs_plugin.h>
|
||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||
#include <window_manager/window_manager_plugin.h>
|
||||
|
||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) handy_window_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "HandyWindowPlugin");
|
||||
handy_window_plugin_register_with_registrar(handy_window_registrar);
|
||||
g_autoptr(FlPluginRegistrar) screen_retriever_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverPlugin");
|
||||
screen_retriever_plugin_register_with_registrar(screen_retriever_registrar);
|
||||
g_autoptr(FlPluginRegistrar) sqlite3_flutter_libs_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "Sqlite3FlutterLibsPlugin");
|
||||
sqlite3_flutter_libs_plugin_register_with_registrar(sqlite3_flutter_libs_registrar);
|
||||
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
||||
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
||||
g_autoptr(FlPluginRegistrar) window_manager_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "WindowManagerPlugin");
|
||||
window_manager_plugin_register_with_registrar(window_manager_registrar);
|
||||
}
|
||||
|
||||
@@ -3,11 +3,8 @@
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
handy_window
|
||||
screen_retriever
|
||||
sqlite3_flutter_libs
|
||||
url_launcher_linux
|
||||
window_manager
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
|
||||
@@ -6,17 +6,13 @@ import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import path_provider_foundation
|
||||
import screen_retriever
|
||||
import sqflite
|
||||
import sqlite3_flutter_libs
|
||||
import url_launcher_macos
|
||||
import window_manager
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin"))
|
||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||
Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin"))
|
||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||
WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin"))
|
||||
}
|
||||
|
||||
+1
-41
@@ -282,14 +282,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.5"
|
||||
expansion_tile_card:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: expansion_tile_card
|
||||
sha256: "27ce4cb518f00e21d0f2309aaa6462b26b148e93cee2029a73088cecf42b1eb0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -453,22 +445,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.1"
|
||||
gtk_window:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: gtk_window
|
||||
sha256: "2760fda48314e4f38a0f4f7056cbb4885e230de4aa6a2905ca6345067e4109f4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.1"
|
||||
handy_window:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: handy_window
|
||||
sha256: "21a68a08e227c9fa6508cfebb57b81745a53e61c1b97e5029602f602f492c749"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.1"
|
||||
hooks_riverpod:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -518,7 +494,7 @@ packages:
|
||||
source: hosted
|
||||
version: "0.5.3+2"
|
||||
intl:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: intl
|
||||
sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
|
||||
@@ -836,14 +812,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.27.7"
|
||||
screen_retriever:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: screen_retriever
|
||||
sha256: "6ee02c8a1158e6dae7ca430da79436e3b1c9563c8cf02f524af997c201ac2b90"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.9"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1129,14 +1097,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.5.0"
|
||||
window_manager:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: window_manager
|
||||
sha256: b3c895bdf936c77b83c5254bec2e6b3f066710c1f89c38b20b8acc382b525494
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.8"
|
||||
ws:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -49,6 +49,7 @@ dependencies:
|
||||
cached_network_image: ^3.3.1
|
||||
gap: ^3.0.1
|
||||
auto_size_text: ^3.0.0
|
||||
intl: ^0.18.1
|
||||
|
||||
dependency_overrides:
|
||||
android_package_installer:
|
||||
|
||||
Reference in New Issue
Block a user