💄 Optimize styles
This commit is contained in:
		| @@ -1,5 +1,6 @@ | ||||
| { | ||||
|   "login": "Login", | ||||
|   "loginDescription": "Existing user? We're welcome you back!", | ||||
|   "forgotPassword": "Forgot password", | ||||
|   "loginPickFactor": "Pick a factor", | ||||
|   "loginMultiFactor": { | ||||
| @@ -19,6 +20,7 @@ | ||||
|   "password": "Password", | ||||
|   "next": "Next", | ||||
|   "createAccount": "Create an Account", | ||||
|   "createAccountDescription": "New to here? We got you covered!", | ||||
|   "nickname": "Nickname", | ||||
|   "email": "Email", | ||||
|   "bio": "Bio", | ||||
| @@ -252,5 +254,9 @@ | ||||
|   "leaveChatRoom": "Leave Chat Room", | ||||
|   "leaveChatRoomHint": "Are you sure to leave this chat room?", | ||||
|   "leaveRealm": "Leave Realm", | ||||
|   "leaveRealmHint": "Are you sure to leave this realm?" | ||||
|   "leaveRealmHint": "Are you sure to leave this realm?", | ||||
|   "walletNotFound": "Wallet not found", | ||||
|   "walletCreateHint": "You don't have a wallet yet. Create one to start using the Solar Network eWallet.", | ||||
|   "walletCreate": "Create a Wallet", | ||||
|   "settingsServerUrl": "Server URL" | ||||
| } | ||||
|   | ||||
| @@ -5,7 +5,7 @@ import 'package:shared_preferences/shared_preferences.dart'; | ||||
|  | ||||
| const kTokenPairStoreKey = 'dyn_user_tk'; | ||||
|  | ||||
| const kNetworkServerDefault = 'http://localhost:5071'; | ||||
| const kNetworkServerDefault = 'https://ppa.solian.app'; | ||||
| const kNetworkServerStoreKey = 'app_server_url'; | ||||
|  | ||||
| const kAppbarTransparentStoreKey = 'app_bar_transparent'; | ||||
|   | ||||
| @@ -267,30 +267,66 @@ class _UnauthorizedAccountScreen extends StatelessWidget { | ||||
|   Widget build(BuildContext context) { | ||||
|     return AppScaffold( | ||||
|       appBar: AppBar(title: const Text('Account')), | ||||
|       body: Column( | ||||
|         children: <Widget>[ | ||||
|           ListTile( | ||||
|             leading: const Icon(Symbols.person_add), | ||||
|             trailing: const Icon(Symbols.chevron_right), | ||||
|             title: Text('createAccount').tr(), | ||||
|             subtitle: Text('New to here? We got you covered!'), | ||||
|             contentPadding: EdgeInsets.symmetric(horizontal: 24), | ||||
|             onTap: () { | ||||
|               context.router.push(CreateAccountRoute()); | ||||
|             }, | ||||
|           ), | ||||
|           ListTile( | ||||
|             leading: const Icon(Symbols.login), | ||||
|             trailing: const Icon(Symbols.chevron_right), | ||||
|             subtitle: Text('Existing user? We\'re welcome you back!'), | ||||
|             contentPadding: EdgeInsets.symmetric(horizontal: 24), | ||||
|             title: Text('login').tr(), | ||||
|             onTap: () { | ||||
|               context.router.push(LoginRoute()); | ||||
|             }, | ||||
|           ), | ||||
|         ], | ||||
|       ), | ||||
|       body: | ||||
|           ConstrainedBox( | ||||
|             constraints: const BoxConstraints(maxWidth: 360), | ||||
|             child: Column( | ||||
|               crossAxisAlignment: CrossAxisAlignment.stretch, | ||||
|               mainAxisAlignment: MainAxisAlignment.center, | ||||
|               children: <Widget>[ | ||||
|                 Padding( | ||||
|                   padding: const EdgeInsets.symmetric(horizontal: 24), | ||||
|                   child: Card( | ||||
|                     child: InkWell( | ||||
|                       onTap: () { | ||||
|                         context.router.push(CreateAccountRoute()); | ||||
|                       }, | ||||
|                       child: Padding( | ||||
|                         padding: const EdgeInsets.all(16), | ||||
|                         child: Column( | ||||
|                           children: [ | ||||
|                             Icon(Symbols.person_add, size: 48), | ||||
|                             const SizedBox(height: 8), | ||||
|                             Text('createAccount').tr().bold(), | ||||
|                             Text('createAccountDescription').tr(), | ||||
|                           ], | ||||
|                         ), | ||||
|                       ), | ||||
|                     ), | ||||
|                   ), | ||||
|                 ), | ||||
|                 const Gap(8), | ||||
|                 Padding( | ||||
|                   padding: const EdgeInsets.symmetric(horizontal: 24), | ||||
|                   child: Card( | ||||
|                     child: InkWell( | ||||
|                       onTap: () { | ||||
|                         context.router.push(LoginRoute()); | ||||
|                       }, | ||||
|                       child: Padding( | ||||
|                         padding: const EdgeInsets.all(16), | ||||
|                         child: Column( | ||||
|                           children: [ | ||||
|                             Icon(Symbols.login, size: 48), | ||||
|                             const SizedBox(height: 8), | ||||
|                             Text('login').tr().bold(), | ||||
|                             Text('loginDescription').tr(), | ||||
|                           ], | ||||
|                         ), | ||||
|                       ), | ||||
|                     ), | ||||
|                   ), | ||||
|                 ), | ||||
|                 const Gap(8), | ||||
|                 TextButton( | ||||
|                   onPressed: () { | ||||
|                     context.router.push(SettingsRoute()); | ||||
|                   }, | ||||
|                   child: Text('appSettings').tr(), | ||||
|                 ).center(), | ||||
|               ], | ||||
|             ), | ||||
|           ).center(), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -146,6 +146,8 @@ class TabsNavigationWidget extends HookConsumerWidget { | ||||
|       bottomNavigationBar: | ||||
|           !useHorizontalLayout && isTabRoute | ||||
|               ? NavigationBar( | ||||
|                 height: 56, | ||||
|                 labelBehavior: NavigationDestinationLabelBehavior.alwaysHide, | ||||
|                 selectedIndex: activeIndex, | ||||
|                 onDestinationSelected: (index) { | ||||
|                   router.replace(routes[index]); | ||||
|   | ||||
| @@ -16,6 +16,7 @@ import 'package:island/services/file.dart'; | ||||
| import 'package:island/widgets/alert.dart'; | ||||
| import 'package:island/widgets/app_scaffold.dart'; | ||||
| import 'package:island/widgets/content/cloud_files.dart'; | ||||
| import 'package:island/widgets/response.dart'; | ||||
| import 'package:material_symbols_icons/symbols.dart'; | ||||
| import 'package:riverpod_annotation/riverpod_annotation.dart'; | ||||
| import 'package:styled_widget/styled_widget.dart'; | ||||
| @@ -480,7 +481,11 @@ class _RealmInviteSheet extends HookConsumerWidget { | ||||
|                             }, | ||||
|                           ), | ||||
|               loading: () => const Center(child: CircularProgressIndicator()), | ||||
|               error: (error, stack) => Center(child: Text('Error: $error')), | ||||
|               error: | ||||
|                   (error, _) => ResponseErrorWidget( | ||||
|                     error: error, | ||||
|                     onRetry: () => ref.invalidate(realmInvitesProvider), | ||||
|                   ), | ||||
|             ), | ||||
|           ), | ||||
|         ], | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| import 'package:island/widgets/app_scaffold.dart'; | ||||
| import 'package:material_symbols_icons/symbols.dart'; | ||||
| import 'package:styled_widget/styled_widget.dart'; | ||||
| import 'package:island/pods/config.dart'; | ||||
|  | ||||
| @RoutePage() | ||||
| class SettingsScreen extends HookConsumerWidget { | ||||
| @@ -14,6 +15,10 @@ class SettingsScreen extends HookConsumerWidget { | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|     final serverUrl = ref.watch(serverUrlProvider); | ||||
|     final prefs = ref.watch(sharedPreferencesProvider); | ||||
|     final controller = TextEditingController(text: serverUrl); | ||||
|  | ||||
|     return AppScaffold( | ||||
|       appBar: AppBar(title: const Text('Settings')), | ||||
|       body: SingleChildScrollView( | ||||
| @@ -61,6 +66,43 @@ class SettingsScreen extends HookConsumerWidget { | ||||
|                 ), | ||||
|               ), | ||||
|             ), | ||||
|             ListTile( | ||||
|               isThreeLine: true, | ||||
|               minLeadingWidth: 48, | ||||
|               title: Text('settingsServerUrl').tr(), | ||||
|               contentPadding: const EdgeInsets.only(left: 24, right: 17), | ||||
|               leading: const Icon(Symbols.link), | ||||
|               subtitle: Padding( | ||||
|                 padding: const EdgeInsets.only(top: 6), | ||||
|                 child: TextField( | ||||
|                   controller: controller, | ||||
|                   decoration: InputDecoration( | ||||
|                     hintText: kNetworkServerDefault, | ||||
|                     suffixIcon: IconButton( | ||||
|                       icon: const Icon(Symbols.restart_alt), | ||||
|                       onPressed: () { | ||||
|                         controller.text = kNetworkServerDefault; | ||||
|                         prefs.setString( | ||||
|                           kNetworkServerStoreKey, | ||||
|                           kNetworkServerDefault, | ||||
|                         ); | ||||
|                         ref.invalidate(serverUrlProvider); | ||||
|                       }, | ||||
|                     ), | ||||
|                     border: OutlineInputBorder( | ||||
|                       borderRadius: BorderRadius.circular(8), | ||||
|                     ), | ||||
|                     isDense: true, | ||||
|                   ), | ||||
|                   onSubmitted: (value) { | ||||
|                     if (value.isNotEmpty) { | ||||
|                       prefs.setString(kNetworkServerStoreKey, value); | ||||
|                       ref.invalidate(serverUrlProvider); | ||||
|                     } | ||||
|                   }, | ||||
|                 ), | ||||
|               ), | ||||
|             ), | ||||
|           ], | ||||
|         ), | ||||
|       ), | ||||
|   | ||||
| @@ -1,10 +1,12 @@ | ||||
| import 'package:auto_route/annotations.dart'; | ||||
| import 'package:dio/dio.dart'; | ||||
| import 'package:easy_localization/easy_localization.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| import 'package:island/models/wallet.dart'; | ||||
| import 'package:island/pods/network.dart'; | ||||
| import 'package:island/widgets/app_scaffold.dart'; | ||||
| import 'package:island/widgets/alert.dart'; | ||||
| import 'package:island/widgets/response.dart'; | ||||
| import 'package:material_symbols_icons/symbols.dart'; | ||||
| import 'package:riverpod_annotation/riverpod_annotation.dart'; | ||||
| @@ -14,10 +16,17 @@ import 'package:styled_widget/styled_widget.dart'; | ||||
| part 'wallet.g.dart'; | ||||
|  | ||||
| @riverpod | ||||
| Future<SnWallet> walletCurrent(Ref ref) async { | ||||
|   final apiClient = ref.watch(apiClientProvider); | ||||
|   final resp = await apiClient.get('/wallets'); | ||||
|   return SnWallet.fromJson(resp.data); | ||||
| Future<SnWallet?> walletCurrent(Ref ref) async { | ||||
|   try { | ||||
|     final apiClient = ref.watch(apiClientProvider); | ||||
|     final resp = await apiClient.get('/wallets'); | ||||
|     return SnWallet.fromJson(resp.data); | ||||
|   } catch (err) { | ||||
|     if (err is DioException && err.response?.statusCode == 404) { | ||||
|       return null; | ||||
|     } | ||||
|     rethrow; | ||||
|   } | ||||
| } | ||||
|  | ||||
| const Map<String, IconData> kCurrencyIconData = { | ||||
| @@ -71,6 +80,16 @@ class WalletScreen extends HookConsumerWidget { | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|     final wallet = ref.watch(walletCurrentProvider); | ||||
|  | ||||
|     Future<void> createWallet() async { | ||||
|       final client = ref.read(apiClientProvider); | ||||
|       try { | ||||
|         await client.post('/wallets'); | ||||
|         ref.invalidate(walletCurrentProvider); | ||||
|       } catch (err) { | ||||
|         showErrorAlert(err); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     String getCurrencyTranslationKey(String currency, {bool isShort = false}) { | ||||
|       return 'walletCurrency${isShort ? 'Short' : ''}${currency[0].toUpperCase()}${currency.substring(1).toLowerCase()}'; | ||||
|     } | ||||
| @@ -79,6 +98,19 @@ class WalletScreen extends HookConsumerWidget { | ||||
|       appBar: AppBar(title: Text('wallet').tr()), | ||||
|       body: wallet.when( | ||||
|         data: (data) { | ||||
|           if (data == null) { | ||||
|             return Column( | ||||
|               children: [ | ||||
|                 Text('walletNotFound').tr(), | ||||
|                 Text('walletCreateHint').tr(), | ||||
|                 TextButton( | ||||
|                   onPressed: createWallet, | ||||
|                   child: Text('walletCreate').tr(), | ||||
|                 ), | ||||
|               ], | ||||
|             ); | ||||
|           } | ||||
|  | ||||
|           return Column( | ||||
|             children: [ | ||||
|               Column( | ||||
|   | ||||
| @@ -6,11 +6,11 @@ part of 'wallet.dart'; | ||||
| // RiverpodGenerator | ||||
| // ************************************************************************** | ||||
|  | ||||
| String _$walletCurrentHash() => r'9123af148c4a27e079bbe90c7d4e41d08e408a39'; | ||||
| String _$walletCurrentHash() => r'94e6f3776ce15679d17238e372660c365c9b1028'; | ||||
|  | ||||
| /// See also [walletCurrent]. | ||||
| @ProviderFor(walletCurrent) | ||||
| final walletCurrentProvider = AutoDisposeFutureProvider<SnWallet>.internal( | ||||
| final walletCurrentProvider = AutoDisposeFutureProvider<SnWallet?>.internal( | ||||
|   walletCurrent, | ||||
|   name: r'walletCurrentProvider', | ||||
|   debugGetCreateSourceHash: | ||||
| @@ -23,7 +23,7 @@ final walletCurrentProvider = AutoDisposeFutureProvider<SnWallet>.internal( | ||||
|  | ||||
| @Deprecated('Will be removed in 3.0. Use Ref instead') | ||||
| // ignore: unused_element | ||||
| typedef WalletCurrentRef = AutoDisposeFutureProviderRef<SnWallet>; | ||||
| typedef WalletCurrentRef = AutoDisposeFutureProviderRef<SnWallet?>; | ||||
| String _$transactionListNotifierHash() => | ||||
|     r'148ffb0ee9e3be3b92de432f314d8ee2f09e9a24'; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user