diff --git a/app/lib/main.dart b/app/lib/main.dart index 76d793c9a..b268c74b9 100644 --- a/app/lib/main.dart +++ b/app/lib/main.dart @@ -34,6 +34,10 @@ extension ColorSchemeExtension on ColorScheme { : const Color.fromARGB(255, 10, 10, 10); } +Color _blendColors(Color base, Color tint, double ratio) { + return Color.lerp(base, tint, ratio) ?? base; +} + final GlobalKey navigatorKey = GlobalKey(); final lastPausedProvider = @@ -109,6 +113,15 @@ class MyApp extends ConsumerWidget { brightness: Brightness.light, seedColor: const Color.fromARGB(255, 26, 161, 143), ); + + kColorScheme = kColorScheme.copyWith( + primaryContainer: _blendColors( + kColorScheme.surfaceContainer, + kColorScheme.primary, + 0.08, + ), + onPrimaryContainer: kColorScheme.primary, + ); var kDarkColorScheme = ColorScheme.fromSeed( brightness: Brightness.dark, @@ -121,13 +134,17 @@ class MyApp extends ConsumerWidget { return AppLifecycleObserver( child: MaterialApp( navigatorKey: navigatorKey, - theme: ThemeData().copyWith( + theme: ThemeData( + useMaterial3: true, + ).copyWith( colorScheme: kColorScheme, brightness: Brightness.light, + scaffoldBackgroundColor: kColorScheme.surfaceContainerHighest, textTheme: textTheme, appBarTheme: const AppBarTheme().copyWith( - backgroundColor: kColorScheme.primary, - foregroundColor: kColorScheme.onPrimary, + backgroundColor: kColorScheme.surfaceContainerHighest, + foregroundColor: kColorScheme.onSurface, + elevation: 0, ), cardTheme: CardThemeData( color: kColorScheme.surfaceContainer, @@ -135,26 +152,31 @@ class MyApp extends ConsumerWidget { elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5)), - backgroundColor: kColorScheme.primaryContainer), + borderRadius: BorderRadius.circular(12)), + backgroundColor: kColorScheme.primaryContainer, + foregroundColor: kColorScheme.onPrimaryContainer), ), expansionTileTheme: const ExpansionTileThemeData().copyWith( - backgroundColor: kColorScheme.backgroundDarker, - collapsedBackgroundColor: ThemeData().colorScheme.surface), + backgroundColor: kColorScheme.surfaceContainerHighest, + collapsedBackgroundColor: kColorScheme.surfaceContainerHighest), bottomNavigationBarTheme: const BottomNavigationBarThemeData().copyWith( + backgroundColor: kColorScheme.surfaceContainerHighest, selectedItemColor: kColorScheme.primary, unselectedItemColor: kColorScheme.secondary, + elevation: 0, ), ), darkTheme: ThemeData( useMaterial3: true, colorScheme: kDarkColorScheme, brightness: Brightness.dark, + scaffoldBackgroundColor: kDarkColorScheme.surfaceContainerHighest, textTheme: textTheme, appBarTheme: const AppBarTheme().copyWith( - backgroundColor: kDarkColorScheme.primaryContainer, - foregroundColor: kDarkColorScheme.onPrimaryContainer, + backgroundColor: kDarkColorScheme.surfaceContainerHighest, + foregroundColor: kDarkColorScheme.onSurface, + elevation: 0, ), cardTheme: CardThemeData( color: kDarkColorScheme.surfaceContainer, @@ -162,16 +184,19 @@ class MyApp extends ConsumerWidget { elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5)), - backgroundColor: kDarkColorScheme.primaryContainer), + borderRadius: BorderRadius.circular(12)), + backgroundColor: kDarkColorScheme.primaryContainer, + foregroundColor: kDarkColorScheme.onPrimaryContainer), ), expansionTileTheme: const ExpansionTileThemeData().copyWith( - backgroundColor: kDarkColorScheme.backgroundDarker, - collapsedBackgroundColor: kDarkColorScheme.surface), + backgroundColor: kDarkColorScheme.surfaceContainerHighest, + collapsedBackgroundColor: kDarkColorScheme.surfaceContainerHighest), bottomNavigationBarTheme: const BottomNavigationBarThemeData().copyWith( + backgroundColor: kDarkColorScheme.surfaceContainerHighest, selectedItemColor: kDarkColorScheme.primary, unselectedItemColor: kDarkColorScheme.secondary, + elevation: 0, ), ), themeMode: themeMode, diff --git a/app/lib/screens/farm_screen.dart b/app/lib/screens/farm_screen.dart index dd88a7fe7..00c04b2a1 100644 --- a/app/lib/screens/farm_screen.dart +++ b/app/lib/screens/farm_screen.dart @@ -267,38 +267,64 @@ class _FarmScreenState extends ConsumerState Widget build(BuildContext context) { Widget mainWidget; if (loading) { - mainWidget = Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 16), - Text( - 'Loading Farms...', - style: Theme.of(context).textTheme.bodyLarge!.copyWith( - color: Theme.of(context).colorScheme.onSurface, - fontWeight: FontWeight.bold), - ), - ], - )); - } else if (failed) { mainWidget = Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ - ElevatedButton.icon( - icon: const Icon(Icons.refresh), - label: const Text('Try Again'), - onPressed: () { - listFarms(); - }, + const CircularProgressIndicator(), + const SizedBox(height: 24), + Text( + 'Loading Farms...', + style: Theme.of(context).textTheme.bodyLarge!.copyWith( + color: Theme.of(context).colorScheme.onSurfaceVariant, + fontWeight: FontWeight.w500, + ), ), - const SizedBox(height: 16), ], ), ); + } else if (failed) { + mainWidget = Center( + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.error_outline, + size: 64, + color: Theme.of(context).colorScheme.error, + ), + const SizedBox(height: 16), + Text( + 'Failed to load farms', + style: Theme.of(context).textTheme.titleLarge!.copyWith( + color: Theme.of(context).colorScheme.onSurface, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 8), + Text( + 'Please check your connection and try again', + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.bodyMedium!.copyWith( + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + const SizedBox(height: 32), + ElevatedButton.icon( + icon: const Icon(Icons.refresh), + label: const Text('Try Again'), + onPressed: () { + listFarms(); + }, + ), + ], + ), + ), + ); } else { mainWidget = Column( children: [ diff --git a/app/lib/screens/home_screen.dart b/app/lib/screens/home_screen.dart index 9a9440205..6c87ec322 100644 --- a/app/lib/screens/home_screen.dart +++ b/app/lib/screens/home_screen.dart @@ -206,8 +206,11 @@ class _HomeScreenState extends ConsumerState Widget build(BuildContext context) { ProviderScope.containerOf(context, listen: false) .read(walletsNotifier.notifier); + final colorScheme = Theme.of(context).colorScheme; + return Scaffold( resizeToAvoidBottomInset: false, + backgroundColor: colorScheme.surfaceContainerHighest, appBar: PreferredSize( preferredSize: const Size.fromHeight(0), child: AppBar( diff --git a/app/lib/screens/market/overview.dart b/app/lib/screens/market/overview.dart index 7603e0247..e3e925de4 100644 --- a/app/lib/screens/market/overview.dart +++ b/app/lib/screens/market/overview.dart @@ -410,11 +410,15 @@ class _OverviewWidgetState extends ConsumerState { child: Column( children: [ Card( + margin: const EdgeInsets.symmetric(horizontal: 16), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5), + borderRadius: BorderRadius.circular(12), side: BorderSide( - color: Theme.of(context).colorScheme.primary), + color: Theme.of(context).colorScheme.outline.withOpacity(0.5), + width: 1, + ), ), + elevation: 0, child: Padding( padding: const EdgeInsets.all(16.0), child: Column( @@ -426,10 +430,10 @@ class _OverviewWidgetState extends ConsumerState { .textTheme .titleLarge! .copyWith( - fontWeight: FontWeight.bold, + fontWeight: FontWeight.w600, color: Theme.of(context) .colorScheme - .onSecondaryContainer), + .onSurface), ), Row( crossAxisAlignment: @@ -471,13 +475,15 @@ class _OverviewWidgetState extends ConsumerState { SizedBox( width: double.infinity, child: Card( + margin: const EdgeInsets.symmetric(horizontal: 16), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5), + borderRadius: BorderRadius.circular(12), side: BorderSide( - color: Theme.of(context) - .colorScheme - .primary), + color: Theme.of(context).colorScheme.outline.withOpacity(0.5), + width: 1, + ), ), + elevation: 0, child: Padding( padding: const EdgeInsets.all(16.0), child: Column( @@ -490,10 +496,10 @@ class _OverviewWidgetState extends ConsumerState { .textTheme .titleLarge! .copyWith( - fontWeight: FontWeight.bold, + fontWeight: FontWeight.w600, color: Theme.of(context) .colorScheme - .onSecondaryContainer), + .onSurface), ), Column( crossAxisAlignment: diff --git a/app/lib/screens/preference_screen.dart b/app/lib/screens/preference_screen.dart index d61a7038b..a3d15bb56 100644 --- a/app/lib/screens/preference_screen.dart +++ b/app/lib/screens/preference_screen.dart @@ -97,9 +97,18 @@ class _PreferenceScreenState extends ConsumerState { return LayoutDrawer( titleText: 'Settings', content: ListView( + padding: const EdgeInsets.symmetric(vertical: 8), children: [ - const ListTile( - title: Text('Global settings'), + Padding( + padding: const EdgeInsets.fromLTRB(16, 24, 16, 8), + child: Text( + 'Global settings', + style: Theme.of(context).textTheme.titleSmall!.copyWith( + color: Theme.of(context).colorScheme.onSurfaceVariant, + fontWeight: FontWeight.w600, + letterSpacing: 0.5, + ), + ), ), FutureBuilder( future: checkBiometrics(), @@ -212,6 +221,18 @@ class _PreferenceScreenState extends ConsumerState { ), ), ), + const Divider(height: 1), + Padding( + padding: const EdgeInsets.fromLTRB(16, 24, 16, 8), + child: Text( + 'About', + style: Theme.of(context).textTheme.titleSmall!.copyWith( + color: Theme.of(context).colorScheme.onSurfaceVariant, + fontWeight: FontWeight.w600, + letterSpacing: 0.5, + ), + ), + ), ListTile( leading: const Icon(Icons.perm_device_information), title: Text('Version: $version - $buildNumber'), @@ -224,6 +245,18 @@ class _PreferenceScreenState extends ConsumerState { title: const Text('Terms and conditions'), onTap: () async => {await _showTermsAndConds()}, ), + const Divider(height: 1), + Padding( + padding: const EdgeInsets.fromLTRB(16, 24, 16, 8), + child: Text( + 'Account', + style: Theme.of(context).textTheme.titleSmall!.copyWith( + color: Theme.of(context).colorScheme.onSurfaceVariant, + fontWeight: FontWeight.w600, + letterSpacing: 0.5, + ), + ), + ), ListTile( leading: const Icon(Icons.logout_outlined), title: Text( diff --git a/app/lib/screens/registered_screen.dart b/app/lib/screens/registered_screen.dart index c443412f4..40b6bc9ae 100644 --- a/app/lib/screens/registered_screen.dart +++ b/app/lib/screens/registered_screen.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:threebotlogin/widgets/chat_widget.dart'; import 'package:threebotlogin/widgets/home_card.dart'; import 'package:threebotlogin/widgets/home_logo.dart'; @@ -10,138 +11,144 @@ class RegisteredScreen extends StatefulWidget { return _singleton; } - RegisteredScreen._internal() { - //init - } + RegisteredScreen._internal(); @override State createState() => _RegisteredScreenState(); } -class _RegisteredScreenState extends State - with WidgetsBindingObserver { - // We will treat this error as a singleton - - bool showSettings = false; - bool showPreference = false; +class _RegisteredScreenState extends State { + static const List> _quickAccessCards = [ + {'name': 'Wallet', 'icon': Icons.account_balance_wallet, 'page': 2}, + {'name': 'Farming', 'icon': Icons.storage, 'page': 3}, + {'name': 'Market', 'icon': Icons.show_chart_sharp, 'page': 6}, + {'name': 'Dao', 'icon': Icons.how_to_vote_outlined, 'page': 4}, + {'name': 'Sign', 'icon': Icons.draw_sharp, 'page': 9}, + {'name': 'News', 'icon': Icons.article, 'page': 1}, + {'name': 'Identity', 'icon': Icons.person, 'page': 5}, + {'name': 'Settings', 'icon': Icons.settings, 'page': 7}, + ]; @override Widget build(BuildContext context) { - return Scaffold( - body: SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - SizedBox( - height: MediaQuery.of(context).size.height * 0.3, - width: MediaQuery.of(context).size.width, - child: Stack( - alignment: Alignment.center, - children: [ - Image.asset( - 'assets/map.png', - fit: BoxFit.cover, - ), - const Hero( - tag: 'logo', - child: HomeLogoWidget( - animate: false, + final colorScheme = Theme.of(context).colorScheme; + final screenHeight = MediaQuery.of(context).size.height; + + return AnnotatedRegion( + value: SystemUiOverlayStyle( + statusBarColor: colorScheme.surfaceContainerHighest, + statusBarIconBrightness: colorScheme.brightness == Brightness.light + ? Brightness.dark + : Brightness.light, + ), + child: Scaffold( + backgroundColor: colorScheme.surfaceContainerHighest, + body: Column( + children: [ + _buildHeroSection(colorScheme, screenHeight), + Expanded( + child: Container( + color: colorScheme.surfaceContainerHighest, + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 24), + _buildDescription(colorScheme), + const SizedBox(height: 24), + _buildSectionHeader(colorScheme), + _buildCardGrid(), + const SizedBox(height: 24), + Padding( + padding: const EdgeInsets.only(bottom: 8), + child: Align( + alignment: Alignment.centerRight, + child: CrispChatbot(), + ), + ), + ], ), ), - ], + ), ), ), - Container( - padding: const EdgeInsets.only(left: 10, right: 10, top: 50), - height: MediaQuery.of(context).size.height * 0.6, - width: MediaQuery.of(context).size.width, - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - SizedBox( - width: MediaQuery.of(context).size.width / 1.2, - child: RichText( - textAlign: TextAlign.center, - text: TextSpan( - style: Theme.of(context) - .textTheme - .titleMedium! - .copyWith( - color: Theme.of(context).colorScheme.onSurface, - ), - children: const [ - TextSpan( - text: - 'Your portal to ThreeFold: access your wallets, your digital identity, your farms, and ThreeFold updates with ease.'), - ]), - ), - ), - const Spacer(), - const Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - HomeCardWidget( - name: 'Wallet', - icon: Icons.account_balance_wallet, - pageNumber: 2), - HomeCardWidget( - name: 'Farming', icon: Icons.storage, pageNumber: 3), - ], - ), - const Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - HomeCardWidget( - name: 'Market', - icon: Icons.show_chart_sharp, - pageNumber: 6), - HomeCardWidget( - name: 'Dao', - icon: Icons.how_to_vote_outlined, - pageNumber: 4), - ], - ), - const Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - HomeCardWidget( - name: 'Sign', icon: Icons.draw_sharp, pageNumber: 9), - HomeCardWidget( - name: 'News', icon: Icons.article, pageNumber: 1), - ], - ), - const Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - HomeCardWidget( - name: 'Identity', icon: Icons.person, pageNumber: 5), - HomeCardWidget( - name: 'Settings', icon: Icons.settings, pageNumber: 7), - // HomeCardWidget( - // name: 'Notifications', - // icon: Icons.notifications, - // pageNumber: 9), - ], - ), - const SizedBox(height: 40), - const Row( - children: [Spacer(), CrispChatbot(), SizedBox(width: 20)], - ) - ], - ), - ) ], ), - )); + ), + ); + } + + Widget _buildHeroSection(ColorScheme colorScheme, double screenHeight) { + return Container( + height: screenHeight * 0.20, + width: double.infinity, + decoration: BoxDecoration( + image: const DecorationImage( + image: AssetImage('assets/map.png'), + fit: BoxFit.cover, + ), + ), + child: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Colors.transparent, + colorScheme.surfaceContainerHighest.withOpacity(0.4), + colorScheme.surfaceContainerHighest, + ], + stops: const [0.0, 0.7, 1.0], + ), + ), + child: Center( + child: Hero( + tag: 'logo', + child: HomeLogoWidget(animate: false), + ), + ), + ), + ); + } + + Widget _buildDescription(ColorScheme colorScheme) { + return Text( + 'Your portal to ThreeFold: access your wallets, your digital identity, your farms, and ThreeFold updates with ease.', + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.bodyMedium!.copyWith( + color: colorScheme.onSurfaceVariant, + height: 1.4, + ), + ); + } + + Widget _buildSectionHeader(ColorScheme colorScheme) { + return Padding( + padding: const EdgeInsets.only(left: 4, bottom: 12), + child: Text( + 'Quick Access', + style: Theme.of(context).textTheme.titleMedium!.copyWith( + color: colorScheme.onSurface, + fontWeight: FontWeight.w600, + ), + ), + ); } - void updatePreference(bool preference) { - setState(() { - showPreference = preference; - }); + Widget _buildCardGrid() { + return Wrap( + alignment: WrapAlignment.start, + spacing: 8, + runSpacing: 8, + children: _quickAccessCards.map((card) { + return HomeCardWidget( + name: card['name'] as String, + icon: card['icon'] as IconData, + pageNumber: card['page'] as int, + ); + }).toList(), + ); } } diff --git a/app/lib/screens/signing/sign_with_link.dart b/app/lib/screens/signing/sign_with_link.dart index 4d1f765d6..6f3a12d70 100644 --- a/app/lib/screens/signing/sign_with_link.dart +++ b/app/lib/screens/signing/sign_with_link.dart @@ -208,7 +208,7 @@ class _SignWithLinkScreenState extends ConsumerState hintText: 'Paste your link here...', errorText: linkError, border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), + borderRadius: BorderRadius.circular(12), ), suffixIcon: IconButton( icon: const Icon(Icons.paste), @@ -253,7 +253,7 @@ class _SignWithLinkScreenState extends ConsumerState hintText: 'Processed data will appear here...', errorText: dataError, border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), + borderRadius: BorderRadius.circular(12), ), suffixIcon: _dataController.text.isNotEmpty ? IconButton( @@ -284,7 +284,7 @@ class _SignWithLinkScreenState extends ConsumerState style: ElevatedButton.styleFrom( padding: const EdgeInsets.all(16), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), + borderRadius: BorderRadius.circular(12), ), ), child: isLoading diff --git a/app/lib/screens/signing/sign_with_qrcode.dart b/app/lib/screens/signing/sign_with_qrcode.dart index a33c5c2bb..efe51a980 100644 --- a/app/lib/screens/signing/sign_with_qrcode.dart +++ b/app/lib/screens/signing/sign_with_qrcode.dart @@ -197,7 +197,7 @@ class _SignWithQRCodeScreenState extends ConsumerState hintText: 'Scan a QR code to see the data here...', errorText: scannedDataError, border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), + borderRadius: BorderRadius.circular(12), ), suffixIcon: textController.text.isNotEmpty ? IconButton( @@ -228,7 +228,7 @@ class _SignWithQRCodeScreenState extends ConsumerState style: ElevatedButton.styleFrom( padding: const EdgeInsets.all(16), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), + borderRadius: BorderRadius.circular(12), ), ), child: isLoading diff --git a/app/lib/screens/signing/sign_with_text.dart b/app/lib/screens/signing/sign_with_text.dart index adcce41d8..a3e2699f2 100644 --- a/app/lib/screens/signing/sign_with_text.dart +++ b/app/lib/screens/signing/sign_with_text.dart @@ -73,7 +73,7 @@ class _SignWithTextScreenState extends ConsumerState errorText: textError, enabled: !isLoadingWallets, border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), + borderRadius: BorderRadius.circular(12), ), ), ), @@ -89,7 +89,7 @@ class _SignWithTextScreenState extends ConsumerState style: ElevatedButton.styleFrom( padding: const EdgeInsets.all(16), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), + borderRadius: BorderRadius.circular(12), ), ), child: isLoading diff --git a/app/lib/screens/signing/signing.dart b/app/lib/screens/signing/signing.dart index 02e6e7656..a30547cec 100644 --- a/app/lib/screens/signing/signing.dart +++ b/app/lib/screens/signing/signing.dart @@ -23,7 +23,7 @@ class _SigningState extends State { style: ElevatedButton.styleFrom( minimumSize: const Size.fromHeight(60), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), + borderRadius: BorderRadius.circular(12), ), backgroundColor: Theme.of(context).colorScheme.primaryContainer, ), diff --git a/app/lib/screens/signing/signing_mixin.dart b/app/lib/screens/signing/signing_mixin.dart index 420774ee1..19b011735 100644 --- a/app/lib/screens/signing/signing_mixin.dart +++ b/app/lib/screens/signing/signing_mixin.dart @@ -276,7 +276,7 @@ mixin SigningMixin on ConsumerState { height: 56, padding: const EdgeInsets.symmetric(horizontal: 16), decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), + borderRadius: BorderRadius.circular(12), border: Border.all( color: Theme.of(context).colorScheme.outline), ), @@ -299,7 +299,7 @@ mixin SigningMixin on ConsumerState { value: selectedWallet, decoration: InputDecoration( border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), + borderRadius: BorderRadius.circular(12), ), hintText: 'Select a wallet', errorText: walletError, @@ -351,7 +351,7 @@ mixin SigningMixin on ConsumerState { style: IconButton.styleFrom( backgroundColor: Theme.of(context).colorScheme.surfaceVariant, shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), + borderRadius: BorderRadius.circular(12), ), ), ), @@ -372,7 +372,7 @@ mixin SigningMixin on ConsumerState { errorText: destUrlError, hintText: 'https://example.com/api/signatures', border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), + borderRadius: BorderRadius.circular(12), ), ), onChanged: (value) { @@ -420,7 +420,7 @@ mixin SigningMixin on ConsumerState { border: Border.all( color: Theme.of(context).colorScheme.outline, ), - borderRadius: BorderRadius.circular(8), + borderRadius: BorderRadius.circular(12), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, diff --git a/app/lib/screens/wallets/wallet_screen.dart b/app/lib/screens/wallets/wallet_screen.dart index 879b41438..f8c3cea7a 100644 --- a/app/lib/screens/wallets/wallet_screen.dart +++ b/app/lib/screens/wallets/wallet_screen.dart @@ -48,52 +48,113 @@ class _WalletScreenState extends ConsumerState { wallets = ref.watch(walletsNotifier); Widget mainWidget; if (loading) { - mainWidget = Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const CircularProgressIndicator(), - const SizedBox(height: 15), - Text( - 'Loading Wallets...', - style: Theme.of(context).textTheme.bodyLarge!.copyWith( - color: Theme.of(context).colorScheme.onSurface, - fontWeight: FontWeight.bold), - ), - ], - )); - } else if (failed) { mainWidget = Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - const SizedBox(height: 15), - ElevatedButton.icon( - icon: const Icon(Icons.refresh), - label: const Text('Try Again'), - onPressed: () { - setState(() { - walletRef.clear(); - failed = false; - loading = true; - }); - listMyWallets(); - }, + const CircularProgressIndicator(), + const SizedBox(height: 24), + Text( + 'Loading Wallets...', + style: Theme.of(context).textTheme.bodyLarge!.copyWith( + color: Theme.of(context).colorScheme.onSurfaceVariant, + fontWeight: FontWeight.w500, + ), ), ], ), ); + } else if (failed) { + mainWidget = Center( + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.error_outline, + size: 64, + color: Theme.of(context).colorScheme.error, + ), + const SizedBox(height: 16), + Text( + 'Failed to load wallets', + style: Theme.of(context).textTheme.titleLarge!.copyWith( + color: Theme.of(context).colorScheme.onSurface, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 8), + Text( + 'Please check your connection and try again', + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.bodyMedium!.copyWith( + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + const SizedBox(height: 32), + ElevatedButton.icon( + icon: const Icon(Icons.refresh), + label: const Text('Try Again'), + onPressed: () { + setState(() { + walletRef.clear(); + failed = false; + loading = true; + }); + listMyWallets(); + }, + ), + ], + ), + ), + ); } else { - mainWidget = RefreshIndicator( - onRefresh: handleRefresh, - child: ListView.builder( - itemCount: wallets.length, - itemBuilder: (context, i) { - final wallet = wallets[i]; - return WalletCardWidget( - wallet: wallet, - ); - })); + mainWidget = wallets.isEmpty + ? Center( + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.account_balance_wallet_outlined, + size: 64, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + const SizedBox(height: 16), + Text( + 'No wallets yet', + style: Theme.of(context).textTheme.titleLarge!.copyWith( + color: Theme.of(context).colorScheme.onSurface, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 8), + Text( + 'Add your first wallet to get started', + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.bodyMedium!.copyWith( + color: Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ], + ), + ), + ) + : RefreshIndicator( + onRefresh: handleRefresh, + child: ListView.builder( + padding: const EdgeInsets.symmetric(vertical: 8), + itemCount: wallets.length, + itemBuilder: (context, i) { + final wallet = wallets[i]; + return WalletCardWidget( + wallet: wallet, + ); + }, + ), + ); } return LayoutDrawer( diff --git a/app/lib/widgets/dao/show_result_dialog.dart b/app/lib/widgets/dao/show_result_dialog.dart index 0ef763926..ec77be98c 100644 --- a/app/lib/widgets/dao/show_result_dialog.dart +++ b/app/lib/widgets/dao/show_result_dialog.dart @@ -132,7 +132,7 @@ class _ShowResultDialogState extends State color: Theme.of(context).colorScheme.primaryContainer, backgroundColor: Theme.of(context).colorScheme.surfaceContainerHigh, - borderRadius: const BorderRadius.all(Radius.circular(5)), + borderRadius: const BorderRadius.all(Radius.circular(12)), ); }, ), diff --git a/app/lib/widgets/farm_item.dart b/app/lib/widgets/farm_item.dart index 01c48c9d6..a07a8d397 100644 --- a/app/lib/widgets/farm_item.dart +++ b/app/lib/widgets/farm_item.dart @@ -29,71 +29,82 @@ class _FarmItemWidgetState extends State { Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; - return GestureDetector( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => FarmDetails( - farm: widget.farm, - wallets: widget.wallets, - isV4: widget.isV4, - ), - ), - ); - }, - child: Card( - margin: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 6.0), - elevation: 2.0, + return Card( + margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + elevation: 0, shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), + borderRadius: BorderRadius.circular(12), + side: BorderSide( + color: colorScheme.outline.withOpacity(0.5), + width: 1, + ), ), - clipBehavior: Clip.antiAlias, - color: colorScheme.surfaceVariant, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0), - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.only(right: 16.0), - child: Icon( - Icons.storage, - color: colorScheme.onSurfaceVariant.withOpacity(0.7), + child: InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => FarmDetails( + farm: widget.farm, + wallets: widget.wallets, + isV4: widget.isV4, ), ), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Text( - widget.farm.name, - style: Theme.of(context).textTheme.titleMedium?.copyWith( - color: colorScheme.onSurfaceVariant, - ), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ...[ - const SizedBox(height: 4.0), + ); + }, + borderRadius: BorderRadius.circular(12), + child: Padding( + padding: const EdgeInsets.all(16), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: colorScheme.primaryContainer.withOpacity(0.3), + borderRadius: BorderRadius.circular(12), + ), + child: Icon( + Icons.storage, + color: colorScheme.primary, + size: 24, + ), + ), + const SizedBox(width: 16), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + widget.farm.name, + style: Theme.of(context).textTheme.titleMedium?.copyWith( + color: colorScheme.onSurface, + fontWeight: FontWeight.w600, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 4), Text( '${widget.farm.nodes.length} Node${widget.farm.nodes.length == 1 ? '' : 's'}', style: Theme.of(context).textTheme.bodyMedium?.copyWith( - color: - colorScheme.onSurfaceVariant.withOpacity(0.7), + color: colorScheme.onSurfaceVariant, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ], - ], + ), ), - ), - ], + Icon( + Icons.chevron_right, + color: colorScheme.onSurfaceVariant, + ), + ], + ), ), ), - ), ); } } diff --git a/app/lib/widgets/home_card.dart b/app/lib/widgets/home_card.dart index a5fd2e711..62f5cdc35 100644 --- a/app/lib/widgets/home_card.dart +++ b/app/lib/widgets/home_card.dart @@ -17,44 +17,46 @@ class HomeCardWidget extends StatelessWidget { @override Widget build(BuildContext context) { - Globals globals = Globals(); - final size = MediaQuery.of(context).size.width; - const double margin = 3; + final colorScheme = Theme.of(context).colorScheme; + final textTheme = Theme.of(context).textTheme; + final screenWidth = MediaQuery.of(context).size.width; + final cardWidth = fullWidth ? double.infinity : (screenWidth - 32 - 8) / 2; + return Card( - color: Theme.of(context).colorScheme.primaryContainer, - margin: const EdgeInsets.all(margin), - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)), - clipBehavior: Clip.hardEdge, - elevation: 2, + margin: EdgeInsets.zero, + elevation: 0, + color: colorScheme.surface, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + side: BorderSide( + color: colorScheme.outline.withOpacity(0.2), + width: 1, + ), + ), child: InkWell( - onTap: () { - globals.tabController.animateTo(pageNumber); - }, - child: Column( - children: [ - Container( - padding: const EdgeInsets.all(10), - height: size / 7, - width: fullWidth ? size * 2 / 2.5 + 2 * margin : size / 2.5, - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - icon, - color: Theme.of(context).colorScheme.onPrimaryContainer, - ), - const SizedBox(width: 7), - Text( - name, - style: Theme.of(context).textTheme.titleMedium!.copyWith( - color: Theme.of(context).colorScheme.onPrimaryContainer, - fontWeight: FontWeight.bold), - ) - ], + onTap: () => Globals().tabController.animateTo(pageNumber), + borderRadius: BorderRadius.circular(12), + child: Container( + width: cardWidth, + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 12), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(icon, size: 22, color: colorScheme.primary), + const SizedBox(height: 6), + Text( + name, + textAlign: TextAlign.center, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: textTheme.bodySmall!.copyWith( + color: colorScheme.onSurface, + fontWeight: FontWeight.w600, + ), ), - ) - ], + ], + ), ), ), ); diff --git a/app/lib/widgets/home_logo.dart b/app/lib/widgets/home_logo.dart index 8c25640b9..2b5b8a513 100644 --- a/app/lib/widgets/home_logo.dart +++ b/app/lib/widgets/home_logo.dart @@ -7,65 +7,71 @@ class HomeLogoWidget extends StatelessWidget { const HomeLogoWidget({super.key, required this.animate}); @override -Widget build(BuildContext context) { - return Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Center( - child: animate - ? Column( - mainAxisSize: MainAxisSize.min, - children: [ - SizedBox( - width: 45, - height: 45, - child: Lottie.asset( - 'assets/tfloading.json', - repeat: true, - animate: true, + Widget build(BuildContext context) { + final colorScheme = Theme.of(context).colorScheme; + final textTheme = Theme.of(context).textTheme; + final screenWidth = MediaQuery.of(context).size.width; + + return Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Center( + child: animate + ? Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + width: 40, + height: 40, + child: Lottie.asset( + 'assets/tfloading.json', + repeat: true, + animate: true, + ), + ), + const SizedBox(height: 8), + Text( + 'THREEFOLD', + style: textTheme.titleLarge!.copyWith( + color: colorScheme.onSurface, + fontWeight: FontWeight.bold, + ), + ), + ], + ) + : SizedBox( + height: 50, + child: SvgPicture.asset( + 'assets/TF_logo.svg', + alignment: Alignment.center, + colorFilter: ColorFilter.mode( + colorScheme.onSurface, + BlendMode.srcIn, ), - ), - const SizedBox(height: 10), - Text( - 'THREEFOLD', - style: Theme.of(context).textTheme.headlineLarge!.copyWith( - color: Theme.of(context).colorScheme.onSurface, - fontWeight: FontWeight.bold, - ), - ), - ], - ) - : SizedBox( - height: 90, - child: SvgPicture.asset( - 'assets/TF_logo.svg', - alignment: Alignment.center, - colorFilter: ColorFilter.mode( - Theme.of(context).colorScheme.onSurface, - BlendMode.srcIn, ), ), - ), - ), - SizedBox( - height: MediaQuery.of(context).size.height * 0.04, - width: MediaQuery.of(context).size.width * 0.6, - child: Divider( - thickness: 2, - color: Theme.of(context).colorScheme.primary, ), - ), - Text( - 'CONNECT', - style: Theme.of(context).textTheme.titleLarge!.copyWith( - color: Theme.of(context).colorScheme.onSurface, - letterSpacing: 10, - fontWeight: FontWeight.bold, - ), - ), - ], - ); -} - + const SizedBox(height: 6), + SizedBox( + height: 1.5, + width: screenWidth * 0.45, + child: Divider( + thickness: 1.5, + color: colorScheme.primary, + ), + ), + const SizedBox(height: 4), + Text( + 'CONNECT', + style: textTheme.bodyLarge!.copyWith( + color: colorScheme.onSurface, + letterSpacing: 4, + fontWeight: FontWeight.bold, + ), + ), + ], + ); + } } diff --git a/app/lib/widgets/layout_drawer.dart b/app/lib/widgets/layout_drawer.dart index 457467766..03189e279 100644 --- a/app/lib/widgets/layout_drawer.dart +++ b/app/lib/widgets/layout_drawer.dart @@ -70,28 +70,40 @@ class _LayoutDrawerState extends State { actions: widget.appBarActions ?? [], title: Text(widget.titleText), toolbarHeight: 60, + elevation: 0, ), body: widget.content, drawer: Drawer( - elevation: 5, + elevation: 0, width: MediaQuery.of(context).size.width * 2 / 3, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topRight: Radius.circular(0), + bottomRight: Radius.circular(0), + ), + ), // space to fit everything. child: Column( children: [ - SizedBox( - height: 70, - child: DrawerHeader( - decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - color: Theme.of(context).colorScheme.primary), - ), + DrawerHeader( + padding: EdgeInsets.zero, + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surfaceContainerHighest, + border: Border( + bottom: BorderSide( + color: Theme.of(context).colorScheme.outline.withOpacity(0.2), + width: 1), ), - child: SvgPicture.asset( - 'assets/TF_log_horizontal.svg', - colorFilter: ColorFilter.mode( - Theme.of(context).colorScheme.onSurface, - BlendMode.srcIn), + ), + child: Center( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: SvgPicture.asset( + 'assets/TF_log_horizontal.svg', + colorFilter: ColorFilter.mode( + Theme.of(context).colorScheme.onSurface, + BlendMode.srcIn), + ), ), ), ), @@ -232,6 +244,8 @@ class _LayoutDrawerState extends State { unselectedFontSize: 12, currentIndex: currentScreenIndex, type: BottomNavigationBarType.fixed, + backgroundColor: Theme.of(context).colorScheme.surfaceContainerHighest, + elevation: 0, items: const [ BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'), BottomNavigationBarItem( diff --git a/app/lib/widgets/pin_code.dart b/app/lib/widgets/pin_code.dart index 4135237ee..c7204ae01 100644 --- a/app/lib/widgets/pin_code.dart +++ b/app/lib/widgets/pin_code.dart @@ -91,9 +91,10 @@ class _PincodeWidgetState extends State { @override Widget build(BuildContext context) { - final focusedBorderColor = Theme.of(context).colorScheme.primary; - final fillColor = Theme.of(context).colorScheme.secondaryContainer; - final borderColor = Theme.of(context).colorScheme.primaryContainer; + final colorScheme = Theme.of(context).colorScheme; + final focusedBorderColor = colorScheme.primary; + final fillColor = colorScheme.secondaryContainer; + final borderColor = colorScheme.outline.withOpacity(0.3); final defaultPinTheme = PinTheme( width: 56, @@ -167,7 +168,7 @@ class _PincodeWidgetState extends State { ), focusedPinTheme: defaultPinTheme.copyWith( decoration: defaultPinTheme.decoration!.copyWith( - borderRadius: BorderRadius.circular(8), + borderRadius: BorderRadius.circular(12), border: Border.all(color: focusedBorderColor), ), ), diff --git a/app/lib/widgets/wallets/balance_tile.dart b/app/lib/widgets/wallets/balance_tile.dart index e55b87e00..c518408f1 100644 --- a/app/lib/widgets/wallets/balance_tile.dart +++ b/app/lib/widgets/wallets/balance_tile.dart @@ -21,7 +21,7 @@ class WalletBalanceTileWidget extends StatelessWidget { side: BorderSide( color: Theme.of(context).colorScheme.primary, ), - borderRadius: BorderRadius.circular(5), + borderRadius: BorderRadius.circular(12), ), leading: SizedBox( width: 25, diff --git a/app/lib/widgets/wallets/contact_card.dart b/app/lib/widgets/wallets/contact_card.dart index 1deffe796..179809a2a 100644 --- a/app/lib/widgets/wallets/contact_card.dart +++ b/app/lib/widgets/wallets/contact_card.dart @@ -64,7 +64,7 @@ class _ContactCardWidgetState extends State { Widget build(BuildContext context) { return Card( shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5), + borderRadius: BorderRadius.circular(12), side: BorderSide(color: Theme.of(context).colorScheme.primary)), child: Padding( padding: const EdgeInsets.all(16), diff --git a/app/lib/widgets/wallets/select_chain_widget.dart b/app/lib/widgets/wallets/select_chain_widget.dart index 43a247b85..ea4779447 100644 --- a/app/lib/widgets/wallets/select_chain_widget.dart +++ b/app/lib/widgets/wallets/select_chain_widget.dart @@ -18,14 +18,17 @@ class SelectChainWidget extends StatelessWidget { onPressed: onPressed, style: ElevatedButton.styleFrom( maximumSize: Size.fromWidth(width), - backgroundColor: - active ? colorScheme.primaryContainer : colorScheme.surface, + backgroundColor: active + ? colorScheme.primaryContainer + : colorScheme.surfaceContainerHighest, + elevation: 0, shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5), + borderRadius: BorderRadius.circular(12), side: BorderSide( color: active - ? colorScheme.primaryContainer - : colorScheme.secondaryContainer))), + ? colorScheme.primary + : colorScheme.outline.withOpacity(0.2), + width: active ? 1.5 : 1))), child: Text( label, style: Theme.of(context).textTheme.titleMedium!.copyWith( diff --git a/app/lib/widgets/wallets/wallet_card.dart b/app/lib/widgets/wallets/wallet_card.dart index c5f239fab..b7c34bee6 100644 --- a/app/lib/widgets/wallets/wallet_card.dart +++ b/app/lib/widgets/wallets/wallet_card.dart @@ -165,9 +165,15 @@ class _WalletCardWidgetState extends ConsumerState { ]; } return Card( + margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(5), - side: BorderSide(color: Theme.of(context).colorScheme.primary)), + borderRadius: BorderRadius.circular(12), + side: BorderSide( + color: Theme.of(context).colorScheme.outline.withOpacity(0.5), + width: 1, + ), + ), + elevation: 0, child: InkWell( onTap: () { if (widget.wallet.type == WalletType.NATIVE && @@ -180,6 +186,7 @@ class _WalletCardWidgetState extends ConsumerState { ), )); }, + borderRadius: BorderRadius.circular(12), child: Padding( padding: const EdgeInsets.all(16), child: Column( @@ -187,38 +194,43 @@ class _WalletCardWidgetState extends ConsumerState { children: [ Row( children: [ - Text( - widget.wallet.name, - style: Theme.of(context).textTheme.titleLarge!.copyWith( - color: Theme.of(context) - .colorScheme - .onSecondaryContainer, - ), + Expanded( + child: Text( + widget.wallet.name, + style: Theme.of(context).textTheme.titleLarge!.copyWith( + color: Theme.of(context).colorScheme.onSurface, + fontWeight: FontWeight.w600, + ), + ), ), - const Spacer(), Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( - border: Border.all( - color: wallet!.verificationStatus == - VerificationState.VERIFIED - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.error, - ), - borderRadius: BorderRadius.circular(20), + color: wallet!.verificationStatus == + VerificationState.VERIFIED + ? Theme.of(context).colorScheme.primaryContainer + : Theme.of(context).colorScheme.errorContainer, + borderRadius: BorderRadius.circular(16), + ), + child: Text( + capitalize(wallet.verificationStatus.name), + style: Theme.of(context).textTheme.bodySmall!.copyWith( + color: wallet.verificationStatus == + VerificationState.VERIFIED + ? Theme.of(context) + .colorScheme + .onPrimaryContainer + : Theme.of(context).colorScheme.onErrorContainer, + fontWeight: FontWeight.w600, + ), ), - child: Text(capitalize(wallet.verificationStatus.name), - style: Theme.of(context).textTheme.bodySmall!.copyWith( - color: wallet.verificationStatus == - VerificationState.VERIFIED - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.error, - )), ), ], ), - const SizedBox(height: 10), + const SizedBox(height: 16), + const Divider(height: 1), + const SizedBox(height: 16), ...cardContent, ], ),