Skip to content
Snippets Groups Projects
Commit c2042f21 authored by vjrj's avatar vjrj
Browse files

Search duniter users from contacts too

parent 87b45991
No related branches found
No related tags found
No related merge requests found
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
"g1_amount_hint": "Amount to send in {currency}", "g1_amount_hint": "Amount to send in {currency}",
"g1_form_pay_send": "Send", "g1_form_pay_send": "Send",
"search_user_title": "User to pay", "search_user_title": "User to pay",
"search_user_title_in_contacts": "Search for users",
"search_user": "Search (user or public key)", "search_user": "Search (user or public key)",
"search_user_btn": "Search user", "search_user_btn": "Search user",
"g1_form_pay_desc": "Comment", "g1_form_pay_desc": "Comment",
......
...@@ -12,7 +12,8 @@ ...@@ -12,7 +12,8 @@
"g1_amount": "Monto a enviar", "g1_amount": "Monto a enviar",
"g1_amount_hint": "Monto a enviar en {currency}", "g1_amount_hint": "Monto a enviar en {currency}",
"g1_form_pay_send": "Enviar", "g1_form_pay_send": "Enviar",
"search_user_title": "Usuario a pagar", "search_user_title": "Usuari@ a pagar",
"search_user_title_in_contacts": "Busca usuari@",
"search_user": "Buscar (usuari@ o clave pública)", "search_user": "Buscar (usuari@ o clave pública)",
"search_user_btn": "Buscar usuari@", "search_user_btn": "Buscar usuari@",
"g1_form_pay_desc": "Comentario", "g1_form_pay_desc": "Comentario",
......
...@@ -46,7 +46,7 @@ import 'ui/notification_controller.dart'; ...@@ -46,7 +46,7 @@ import 'ui/notification_controller.dart';
import 'ui/screens/skeleton_screen.dart'; import 'ui/screens/skeleton_screen.dart';
import 'ui/ui_helpers.dart'; import 'ui/ui_helpers.dart';
import 'ui/widgets/connectivity_widget_wrapper_wrapper.dart'; import 'ui/widgets/connectivity_widget_wrapper_wrapper.dart';
import 'ui/widgets/first_screen/pay_contact_search_page.dart'; import 'ui/widgets/first_screen/contact_search_page.dart';
void main() async { void main() async {
await NotificationController.initializeLocalNotifications(); await NotificationController.initializeLocalNotifications();
...@@ -82,7 +82,7 @@ void main() async { ...@@ -82,7 +82,7 @@ void main() async {
final Box<dynamic> box = await Hive.openBox('hydrated_box', final Box<dynamic> box = await Hive.openBox('hydrated_box',
path: HydratedStorage.webStorageDirectory.path); path: HydratedStorage.webStorageDirectory.path);
final List<dynamic> keysToDelete = final List<dynamic> keysToDelete =
box.keys.where((dynamic key) => '$key'.startsWith('minified')).toList(); box.keys.where((dynamic key) => '$key'.startsWith('minified')).toList();
box.deleteAll(keysToDelete); box.deleteAll(keysToDelete);
// This should we done after init // This should we done after init
// await HydratedBloc.storage.clear(); // await HydratedBloc.storage.clear();
...@@ -96,7 +96,7 @@ void main() async { ...@@ -96,7 +96,7 @@ void main() async {
final Directory tmpDir = await getTemporaryDirectory(); final Directory tmpDir = await getTemporaryDirectory();
Hive.init(tmpDir.toString()); Hive.init(tmpDir.toString());
HydratedBloc.storage = HydratedBloc.storage =
await HydratedStorage.build(storageDirectory: tmpDir); await HydratedStorage.build(storageDirectory: tmpDir);
} }
PWAInstall().setup(installCallback: () { PWAInstall().setup(installCallback: () {
...@@ -105,8 +105,7 @@ void main() async { ...@@ -105,8 +105,7 @@ void main() async {
Bloc.observer = AppBlocObserver(); Bloc.observer = AppBlocObserver();
void appRunner() => void appRunner() => runApp(
runApp(
EasyLocalization( EasyLocalization(
path: 'assets/translations', path: 'assets/translations',
supportedLocales: const <Locale>[ supportedLocales: const <Locale>[
...@@ -150,7 +149,9 @@ void main() async { ...@@ -150,7 +149,9 @@ void main() async {
if (kReleaseMode) { if (kReleaseMode) {
// Only use sentry in production // Only use sentry in production
await SentryFlutter.init((SentryFlutterOptions options,) { await SentryFlutter.init((
SentryFlutterOptions options,
) {
options.tracesSampleRate = 1.0; options.tracesSampleRate = 1.0;
options.reportPackages = false; options.reportPackages = false;
// options.addInAppInclude('sentry_flutter_example'); // options.addInAppInclude('sentry_flutter_example');
...@@ -197,7 +198,7 @@ class AppIntro extends StatefulWidget { ...@@ -197,7 +198,7 @@ class AppIntro extends StatefulWidget {
class _AppIntro extends State<AppIntro> { class _AppIntro extends State<AppIntro> {
final GlobalKey<IntroductionScreenState> introKey = final GlobalKey<IntroductionScreenState> introKey =
GlobalKey<IntroductionScreenState>(); GlobalKey<IntroductionScreenState>();
void _onIntroEnd(BuildContext context, AppCubit cubit) { void _onIntroEnd(BuildContext context, AppCubit cubit) {
cubit.introViewed(); cubit.introViewed();
...@@ -211,43 +212,40 @@ class _AppIntro extends State<AppIntro> { ...@@ -211,43 +212,40 @@ class _AppIntro extends State<AppIntro> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<AppCubit, AppState>( return BlocBuilder<AppCubit, AppState>(
builder: (BuildContext buildContext, AppState state) { builder: (BuildContext buildContext, AppState state) {
final AppCubit cubit = context.read<AppCubit>(); final AppCubit cubit = context.read<AppCubit>();
return IntroductionScreen( return IntroductionScreen(
key: introKey, key: introKey,
pages: <PageViewModel>[ pages: <PageViewModel>[
for (int i = 1; i <= 5; i++) for (int i = 1; i <= 5; i++)
createPageViewModel( createPageViewModel('intro_${i}_title', 'intro_${i}_description',
'intro_${i}_title', 'intro_${i}_description', 'assets/img/undraw_intro_$i.png', context),
'assets/img/undraw_intro_$i.png', context), ],
], onDone: () => _onIntroEnd(buildContext, cubit),
onDone: () => _onIntroEnd(buildContext, cubit), showSkipButton: true,
showSkipButton: true, skipOrBackFlex: 0,
skipOrBackFlex: 0, onSkip: () => _onIntroEnd(buildContext, cubit),
onSkip: () => _onIntroEnd(buildContext, cubit), nextFlex: 0,
nextFlex: 0, skip: Text(tr('skip')),
skip: Text(tr('skip')), next: const Icon(Icons.arrow_forward),
next: const Icon(Icons.arrow_forward), done: Text(tr('start'),
done: Text(tr('start'), style: const TextStyle(fontWeight: FontWeight.w600)),
style: const TextStyle(fontWeight: FontWeight.w600)), dotsDecorator: const DotsDecorator(
dotsDecorator: const DotsDecorator( size: Size(10.0, 10.0),
size: Size(10.0, 10.0), color: Color(0xFFBDBDBD),
color: Color(0xFFBDBDBD), activeColor: Colors.blueAccent,
activeColor: Colors.blueAccent, activeSize: Size(22.0, 10.0),
activeSize: Size(22.0, 10.0), activeShape: RoundedRectangleBorder(
activeShape: RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(25.0)),
borderRadius: BorderRadius.all(Radius.circular(25.0)), ),
), ),
), );
); });
});
} }
} }
PageViewModel createPageViewModel(String title, String body, String imageAsset, PageViewModel createPageViewModel(
BuildContext context) { String title, String body, String imageAsset, BuildContext context) {
final ColorScheme colorScheme = Theme final ColorScheme colorScheme = Theme.of(context).colorScheme;
.of(context)
.colorScheme;
final TextStyle titleStyle = TextStyle( final TextStyle titleStyle = TextStyle(
color: colorScheme.primary, color: colorScheme.primary,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
...@@ -275,7 +273,7 @@ class GinkgoApp extends StatefulWidget { ...@@ -275,7 +273,7 @@ class GinkgoApp extends StatefulWidget {
// The navigator key is necessary to navigate using static methods // The navigator key is necessary to navigate using static methods
static final GlobalKey<NavigatorState> navigatorKey = static final GlobalKey<NavigatorState> navigatorKey =
GlobalKey<NavigatorState>(); GlobalKey<NavigatorState>();
@override @override
State<GinkgoApp> createState() => _GinkgoAppState(); State<GinkgoApp> createState() => _GinkgoAppState();
...@@ -291,16 +289,10 @@ class _GinkgoAppState extends State<GinkgoApp> { ...@@ -291,16 +289,10 @@ class _GinkgoAppState extends State<GinkgoApp> {
} }
void _printNodeStatus({String prefix = 'Starting'}) { void _printNodeStatus({String prefix = 'Starting'}) {
final int nDuniterNodes = NodeManager() final int nDuniterNodes = NodeManager().nodeList(NodeType.duniter).length;
.nodeList(NodeType.duniter)
.length;
final int nCesiumPlusNodes = final int nCesiumPlusNodes =
NodeManager() NodeManager().nodeList(NodeType.cesiumPlus).length;
.nodeList(NodeType.cesiumPlus) final int nGvaNodes = NodeManager().nodeList(NodeType.gva).length;
.length;
final int nGvaNodes = NodeManager()
.nodeList(NodeType.gva)
.length;
logger( logger(
'$prefix with $nDuniterNodes duniter nodes, $nCesiumPlusNodes c+ nodes, and $nGvaNodes gva nodes'); '$prefix with $nDuniterNodes duniter nodes, $nCesiumPlusNodes c+ nodes, and $nGvaNodes gva nodes');
if (!kReleaseMode) { if (!kReleaseMode) {
...@@ -320,7 +312,7 @@ class _GinkgoAppState extends State<GinkgoApp> { ...@@ -320,7 +312,7 @@ class _GinkgoAppState extends State<GinkgoApp> {
NotificationController.startListeningNotificationEvents(); NotificationController.startListeningNotificationEvents();
Once.runHourly('load_nodes', callback: () async { Once.runHourly('load_nodes', callback: () async {
final bool isConnected = final bool isConnected =
await ConnectivityWidgetWrapperWrapper.isConnected; await ConnectivityWidgetWrapperWrapper.isConnected;
if (isConnected) { if (isConnected) {
logger('Load nodes via once'); logger('Load nodes via once');
_loadNodes(); _loadNodes();
...@@ -335,10 +327,7 @@ class _GinkgoAppState extends State<GinkgoApp> { ...@@ -335,10 +327,7 @@ class _GinkgoAppState extends State<GinkgoApp> {
Once.runDaily('clear_cache', callback: () { Once.runDaily('clear_cache', callback: () {
logger('clear cache via once'); logger('clear cache via once');
ContactsCache().clear(); ContactsCache().clear();
ContactsCache().addContacts(context ContactsCache().addContacts(context.read<ContactsCubit>().state.contacts);
.read<ContactsCubit>()
.state
.contacts);
}); });
Once.runOnce('resize_avatars', callback: () { Once.runOnce('resize_avatars', callback: () {
logger('resize avatar via once'); logger('resize avatar via once');
...@@ -366,8 +355,7 @@ class _GinkgoAppState extends State<GinkgoApp> { ...@@ -366,8 +355,7 @@ class _GinkgoAppState extends State<GinkgoApp> {
showDialog( showDialog(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return return ContactSearchPage(uri: link);
PayContactSearchPage(uri: link);
}, },
); );
} }
...@@ -391,104 +379,94 @@ class _GinkgoAppState extends State<GinkgoApp> { ...@@ -391,104 +379,94 @@ class _GinkgoAppState extends State<GinkgoApp> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<NodeListCubit, NodeListState>( return BlocBuilder<NodeListCubit, NodeListState>(
builder: (BuildContext nodeContext, NodeListState state) { builder: (BuildContext nodeContext, NodeListState state) {
return ConnectivityAppWrapper( return ConnectivityAppWrapper(
app: FilesystemPickerDefaultOptions( app: FilesystemPickerDefaultOptions(
fileTileSelectMode: FileTileSelectMode.wholeTile, fileTileSelectMode: FileTileSelectMode.wholeTile,
theme: FilesystemPickerTheme( theme: FilesystemPickerTheme(
topBar: FilesystemPickerTopBarThemeData( topBar: FilesystemPickerTopBarThemeData(
backgroundColor: Theme backgroundColor: Theme.of(context).colorScheme.primary,
.of(context) ),
.colorScheme ),
.primary, child: MaterialApp(
), /// Localization is not available for the title.
), title: 'Ğ1nkgo',
child: MaterialApp( theme: ThemeData(
useMaterial3: true, colorScheme: lightColorScheme),
/// Localization is not available for the title. darkTheme:
title: 'Ğ1nkgo',
theme: ThemeData(
useMaterial3: true, colorScheme: lightColorScheme),
darkTheme:
ThemeData(useMaterial3: true, colorScheme: darkColorScheme), ThemeData(useMaterial3: true, colorScheme: darkColorScheme),
navigatorKey: GinkgoApp.navigatorKey, navigatorKey: GinkgoApp.navigatorKey,
scaffoldMessengerKey: globalMessengerKey, scaffoldMessengerKey: globalMessengerKey,
/// Theme stuff /// Theme stuff
themeMode: context themeMode: context.watch<ThemeCubit>().state.themeMode,
.watch<ThemeCubit>()
.state /// Localization stuff
.themeMode, localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales,
/// Localization stuff locale: context.locale,
localizationsDelegates: context.localizationDelegates, debugShowCheckedModeBanner: false,
supportedLocales: context.supportedLocales, home: context.read<AppCubit>().isIntroViewed
locale: context.locale, ? BetterFeedback(
debugShowCheckedModeBanner: false,
home: context
.read<AppCubit>()
.isIntroViewed
? BetterFeedback(
localizationsDelegates: context.localizationDelegates localizationsDelegates: context.localizationDelegates
..add(CustomFeedbackLocalizationsDelegate()), ..add(CustomFeedbackLocalizationsDelegate()),
child: const SkeletonScreen()) child: const SkeletonScreen())
: const AppIntro(), : const AppIntro(),
builder: (BuildContext buildContext, Widget? widget) { builder: (BuildContext buildContext, Widget? widget) {
NotificationController.locale = context.locale; NotificationController.locale = context.locale;
return ResponsiveWrapper.builder( return ResponsiveWrapper.builder(
BouncingScrollWrapper.builder( BouncingScrollWrapper.builder(
context, context,
ConnectivityWidgetWrapperWrapper( ConnectivityWidgetWrapperWrapper(
//message: tr('offline'), //message: tr('offline'),
//height: 18, //height: 18,
offlineWidget: /* Container( offlineWidget: /* Container(
color: Colors.transparent, color: Colors.transparent,
child: Center( child: Center(
child: */ child: */
Column( Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
const Icon( const Icon(
Icons.cloud_off, Icons.cloud_off,
size: 48, size: 48,
color: Colors.grey,
),
const SizedBox(height: 6),
Container(
padding: const EdgeInsets.all(5.0),
decoration: const BoxDecoration(
color: Colors.grey, color: Colors.grey,
), borderRadius:
const SizedBox(height: 6),
Container(
padding: const EdgeInsets.all(5.0),
decoration: const BoxDecoration(
color: Colors.grey,
borderRadius:
BorderRadius.all(Radius.circular(10.0)), BorderRadius.all(Radius.circular(10.0)),
), ),
child: Text( child: Text(
tr('offline'), tr('offline'),
style: const TextStyle( style: const TextStyle(
color: Colors.white, color: Colors.white,
decoration: TextDecoration.none, decoration: TextDecoration.none,
fontSize: 14, fontSize: 14,
), ),
)), )),
const SizedBox(height: 110), const SizedBox(height: 110),
], ],
), ),
child: widget!, child: widget!,
)), )),
maxWidth: 480, maxWidth: 480,
minWidth: 480, minWidth: 480,
// defaultScale: true, // defaultScale: true,
breakpoints: <ResponsiveBreakpoint>[ breakpoints: <ResponsiveBreakpoint>[
const ResponsiveBreakpoint.resize(200, name: MOBILE), const ResponsiveBreakpoint.resize(200, name: MOBILE),
const ResponsiveBreakpoint.resize(480, name: TABLET), const ResponsiveBreakpoint.resize(480, name: TABLET),
const ResponsiveBreakpoint.resize( const ResponsiveBreakpoint.resize(1000, name: DESKTOP),
1000, name: DESKTOP), ],
], background: Container(color: const Color(0xFFF5F5F5)),
background: Container(color: const Color(0xFFF5F5F5)), );
); },
}, )));
))); });
});
} }
} }
...@@ -11,6 +11,7 @@ import '../qr_manager.dart'; ...@@ -11,6 +11,7 @@ import '../qr_manager.dart';
import '../tutorial.dart'; import '../tutorial.dart';
import '../tutorial_keys.dart'; import '../tutorial_keys.dart';
import '../widgets/card_drawer.dart'; import '../widgets/card_drawer.dart';
import '../widgets/first_screen/contact_search_page.dart';
import '../widgets/third_screen/contact_form_dialog.dart'; import '../widgets/third_screen/contact_form_dialog.dart';
import '../widgets/third_screen/contacts_page.dart'; import '../widgets/third_screen/contacts_page.dart';
import '../widgets/third_screen/third_tutorial.dart'; import '../widgets/third_screen/third_tutorial.dart';
...@@ -38,6 +39,16 @@ class _ThirdScreenState extends State<ThirdScreen> { ...@@ -38,6 +39,16 @@ class _ThirdScreenState extends State<ThirdScreen> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar(title: Text(tr('bottom_nav_trd')), actions: <Widget>[ appBar: AppBar(title: Text(tr('bottom_nav_trd')), actions: <Widget>[
IconButton(
icon: const Icon(Icons.travel_explore),
onPressed: () async {
showDialog(
context: context,
builder: (BuildContext context) {
return const ContactSearchPage(forPayment: false);
},
);
}),
IconButton( IconButton(
key: contactsQrKey, key: contactsQrKey,
icon: const Icon(Icons.qr_code), icon: const Icon(Icons.qr_code),
......
...@@ -24,16 +24,17 @@ import '../loading_box.dart'; ...@@ -24,16 +24,17 @@ import '../loading_box.dart';
import '../third_screen/contacts_page.dart'; import '../third_screen/contacts_page.dart';
import 'contact_fav_icon.dart'; import 'contact_fav_icon.dart';
class PayContactSearchPage extends StatefulWidget { class ContactSearchPage extends StatefulWidget {
const PayContactSearchPage({super.key, this.uri}); const ContactSearchPage({super.key, this.uri, this.forPayment = true});
final String? uri; final String? uri;
final bool forPayment;
@override @override
State<PayContactSearchPage> createState() => _PayContactSearchPageState(); State<ContactSearchPage> createState() => _ContactSearchPageState();
} }
class _PayContactSearchPageState extends State<PayContactSearchPage> { class _ContactSearchPageState extends State<ContactSearchPage> {
final TextEditingController _searchController = TextEditingController(); final TextEditingController _searchController = TextEditingController();
String _searchTerm = ''; String _searchTerm = '';
...@@ -135,7 +136,9 @@ class _PayContactSearchPageState extends State<PayContactSearchPage> { ...@@ -135,7 +136,9 @@ class _PayContactSearchPageState extends State<PayContactSearchPage> {
final PaymentCubit paymentCubit = context.read<PaymentCubit>(); final PaymentCubit paymentCubit = context.read<PaymentCubit>();
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text(tr('search_user_title')), title: Text(widget.forPayment
? tr('search_user_title')
: tr('search_user_title_in_contacts')),
backgroundColor: Theme.of(context).colorScheme.primary, backgroundColor: Theme.of(context).colorScheme.primary,
foregroundColor: Theme.of(context).colorScheme.inversePrimary, foregroundColor: Theme.of(context).colorScheme.inversePrimary,
actions: <Widget>[ actions: <Widget>[
...@@ -241,6 +244,9 @@ class _PayContactSearchPageState extends State<PayContactSearchPage> { ...@@ -241,6 +244,9 @@ class _PayContactSearchPageState extends State<PayContactSearchPage> {
Future<void> _onKeyScanned( Future<void> _onKeyScanned(
String scannedKey, PaymentCubit paymentCubit) async { String scannedKey, PaymentCubit paymentCubit) async {
if (!widget.forPayment) {
return;
}
final PaymentState? pay = parseScannedUri(scannedKey); final PaymentState? pay = parseScannedUri(scannedKey);
if (pay != null) { if (pay != null) {
logger('Scanned $pay'); logger('Scanned $pay');
......
...@@ -4,7 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; ...@@ -4,7 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../data/models/payment_cubit.dart'; import '../../../data/models/payment_cubit.dart';
import '../../../data/models/payment_state.dart'; import '../../../data/models/payment_state.dart';
import 'pay_contact_search_page.dart'; import 'contact_search_page.dart';
import 'pay_recipient_widget.dart'; import 'pay_recipient_widget.dart';
class PayContactSearchButton extends StatefulWidget { class PayContactSearchButton extends StatefulWidget {
...@@ -25,7 +25,7 @@ class _PayContactSearchButtonState extends State<PayContactSearchButton> { ...@@ -25,7 +25,7 @@ class _PayContactSearchButtonState extends State<PayContactSearchButton> {
showDialog( showDialog(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return const PayContactSearchPage(); return const ContactSearchPage();
}, },
); );
}, },
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment