From 7e73496ee9b5e258445d469dc9b244c58ac86ea3 Mon Sep 17 00:00:00 2001 From: franzap <_@franzap.com> Date: Sat, 4 May 2024 00:30:43 -0300 Subject: [PATCH] Fix user stuff and feedback form --- lib/main.dart | 43 ------------------ lib/models/user.dart | 20 +++++---- lib/screens/app_detail_screen.dart | 8 ++-- lib/screens/search_screen.dart | 2 +- lib/screens/settings_screen.dart | 28 ++++++++++-- lib/widgets/app_drawer.dart | 45 ++++++++++++++----- lib/widgets/card.dart | 5 ++- linux/flutter/generated_plugin_registrant.cc | 12 ----- linux/flutter/generated_plugins.cmake | 3 -- macos/Flutter/GeneratedPluginRegistrant.swift | 4 -- pubspec.lock | 42 +---------------- pubspec.yaml | 1 + 12 files changed, 80 insertions(+), 133 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 9a78568..3bcf4e4 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -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( - // context: context, - // state: state, - // child: AppDetailScreen(app: state.extra as App), - // ), ), ], ), @@ -273,35 +262,3 @@ class ScaffoldWithNavigationRail extends StatelessWidget { ); } } - -CustomTransitionPage buildWithSlideTransition({ - required BuildContext context, - required GoRouterState state, - required Widget child, -}) { - return CustomTransitionPage( - key: state.pageKey, - child: child, - transitionsBuilder: (context, animation, secondaryAnimation, child) { - return SlideTransition( - position: - Tween(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, - ), - ); - }, - ); -} diff --git a/lib/models/user.dart b/lib/models/user.dart index 7ffd2a4..6157308 100644 --- a/lib/models/user.dart +++ b/lib/models/user.dart @@ -15,6 +15,8 @@ class User extends ZapstoreEvent with BaseUser { late final HasMany following; @DataRelationship(inverse: 'following') late final HasMany followers = HasMany(); + + String get nameOrNpub => name ?? '${npub.substring(0, 10)}...'; } mixin UserAdapter on NostrAdapter { @@ -40,14 +42,16 @@ mixin UserAdapter on NostrAdapter { 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; diff --git a/lib/screens/app_detail_screen.dart b/lib/screens/app_detail_screen.dart index bb8ff5e..9ce857a 100644 --- a/lib/screens/app_detail_screen.dart +++ b/lib/screens/app_detail_screen.dart @@ -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)), ], ), ), diff --git a/lib/screens/search_screen.dart b/lib/screens/search_screen.dart index ba18ece..ecd9e94 100644 --- a/lib/screens/search_screen.dart +++ b/lib/screens/search_screen.dart @@ -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); diff --git a/lib/screens/settings_screen.dart b/lib/screens/settings_screen.dart index 9d69297..5d1794e 100644 --- a/lib/screens/settings_screen.dart +++ b/lib/screens/settings_screen.dart @@ -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'), ), diff --git a/lib/widgets/app_drawer.dart b/lib/widgets/app_drawer.dart index 2fb36c1..39786d3 100644 --- a/lib/widgets/app_drawer.dart +++ b/lib/widgets/app_drawer.dart @@ -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) diff --git a/lib/widgets/card.dart b/lib/widgets/card.dart index 63413b4..f2adecc 100644 --- a/lib/widgets/card.dart +++ b/lib/widgets/card.dart @@ -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, diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 854280a..4c0025f 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -6,26 +6,14 @@ #include "generated_plugin_registrant.h" -#include -#include #include #include -#include 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); } diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index ab7d522..ad279a8 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -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 diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 92d0ff2..f93e892 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -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")) } diff --git a/pubspec.lock b/pubspec.lock index 2b3d59c..585ee6e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -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: diff --git a/pubspec.yaml b/pubspec.yaml index e3ac9f0..7e6926f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -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: